gps: refactor the filesystemState struct

Signed-off-by: Ibrahim AshShohail <ibra.sho@gmail.com>
This commit is contained in:
Ibrahim AshShohail 2017-11-29 09:37:45 +04:00
Родитель 4e4925d382
Коммит 869f2d711a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F9188F2C77217B32
2 изменённых файлов: 107 добавлений и 55 удалений

77
gps/filesystem.go Normal file
Просмотреть файл

@ -0,0 +1,77 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gps
import (
"os"
"path/filepath"
)
// filesystemState represents the state of a file system.
type filesystemState struct {
root string
dirs []string
files []string
links []fsLink
}
// fsLink represents a symbolic link.
type fsLink struct {
path string
to string
}
// deriveFilesystemState returns a filesystemState based on the state of
// the filesystem on root.
func deriveFilesystemState(root string) (filesystemState, error) {
fs := filesystemState{
root: root,
}
err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == fs.root {
return nil
}
relPath, err := filepath.Rel(fs.root, path)
if err != nil {
return err
}
if (info.Mode() & os.ModeSymlink) != 0 {
eval, err := filepath.EvalSymlinks(path)
if err != nil {
return err
}
fs.links = append(fs.links, fsLink{
path: relPath,
to: eval,
})
return nil
}
if info.IsDir() {
fs.dirs = append(fs.dirs, relPath)
return nil
}
fs.files = append(fs.files, relPath)
return nil
})
if err != nil {
return filesystemState{}, err
}
return fs, nil
}

Просмотреть файл

@ -12,54 +12,34 @@ import (
// This file contains utilities for running tests around file system state. // This file contains utilities for running tests around file system state.
// fspath represents a file system path in an OS-agnostic way.
type fsPath []string
func (f fsPath) String() string { return filepath.Join(f...) }
func (f fsPath) prepend(prefix string) fsPath {
p := fsPath{filepath.FromSlash(prefix)}
return append(p, f...)
}
type fsTestCase struct { type fsTestCase struct {
before, after filesystemState before, after filesystemState
} }
// filesystemState represents the state of a file system. It has a setup method // assert makes sure that the tc.after state matches the state of the actual host
// which inflates its state to the actual host file system, and an assert // file system at tc.after.root.
// method which checks that the actual file system matches the described state. func (tc fsTestCase) assert(t *testing.T) {
type filesystemState struct {
root string
dirs []fsPath
files []fsPath
links []fsLink
}
// assert makes sure that the fs state matches the state of the actual host
// file system
func (fs filesystemState) assert(t *testing.T) {
dirMap := make(map[string]bool) dirMap := make(map[string]bool)
fileMap := make(map[string]bool) fileMap := make(map[string]bool)
linkMap := make(map[string]bool) linkMap := make(map[string]bool)
for _, d := range fs.dirs { for _, d := range tc.after.dirs {
dirMap[d.prepend(fs.root).String()] = true dirMap[filepath.Join(tc.after.root, d)] = true
} }
for _, f := range fs.files { for _, f := range tc.after.files {
fileMap[f.prepend(fs.root).String()] = true fileMap[filepath.Join(tc.after.root, f)] = true
} }
for _, l := range fs.links { for _, l := range tc.after.links {
linkMap[l.path.prepend(fs.root).String()] = true linkMap[filepath.Join(tc.after.root, l.path)] = true
} }
err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error { err := filepath.Walk(tc.after.root, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
t.Errorf("filepath.Walk path=%q err=%q", path, err) t.Errorf("filepath.Walk path=%q err=%q", path, err)
return err return err
} }
if path == fs.root { if path == tc.after.root {
return nil return nil
} }
@ -106,32 +86,27 @@ func (fs filesystemState) assert(t *testing.T) {
} }
} }
// fsLink represents a symbolic link. // setup inflates fs onto the actual host file system at tc.before.root.
type fsLink struct { // It doesn't delete existing files and should be used on empty roots only.
path fsPath func (tc fsTestCase) setup(t *testing.T) {
to string tc.setupDirs(t)
tc.setupFiles(t)
tc.setupLinks(t)
} }
// setup inflates fs onto the actual host file system func (tc fsTestCase) setupDirs(t *testing.T) {
func (fs filesystemState) setup(t *testing.T) { for _, dir := range tc.before.dirs {
fs.setupDirs(t) p := filepath.Join(tc.before.root, dir)
fs.setupFiles(t) if err := os.MkdirAll(p, 0777); err != nil {
fs.setupLinks(t)
}
func (fs filesystemState) setupDirs(t *testing.T) {
for _, dir := range fs.dirs {
p := dir.prepend(fs.root)
if err := os.MkdirAll(p.String(), 0777); err != nil {
t.Fatalf("os.MkdirAll(%q, 0777) err=%q", p, err) t.Fatalf("os.MkdirAll(%q, 0777) err=%q", p, err)
} }
} }
} }
func (fs filesystemState) setupFiles(t *testing.T) { func (tc fsTestCase) setupFiles(t *testing.T) {
for _, file := range fs.files { for _, file := range tc.before.files {
p := file.prepend(fs.root) p := filepath.Join(tc.before.root, file)
f, err := os.Create(p.String()) f, err := os.Create(p)
if err != nil { if err != nil {
t.Fatalf("os.Create(%q) err=%q", p, err) t.Fatalf("os.Create(%q) err=%q", p, err)
} }
@ -141,17 +116,17 @@ func (fs filesystemState) setupFiles(t *testing.T) {
} }
} }
func (fs filesystemState) setupLinks(t *testing.T) { func (tc fsTestCase) setupLinks(t *testing.T) {
for _, link := range fs.links { for _, link := range tc.before.links {
p := link.path.prepend(fs.root) p := filepath.Join(tc.before.root, link.path)
// On Windows, relative symlinks confuse filepath.Walk. This is golang/go // On Windows, relative symlinks confuse filepath.Walk. This is golang/go
// issue 17540. So, we'll just sigh and do absolute links, assuming they are // issue 17540. So, we'll just sigh and do absolute links, assuming they are
// relative to the directory of link.path. // relative to the directory of link.path.
dir := filepath.Dir(p.String()) dir := filepath.Dir(p)
to := filepath.Join(dir, link.to) to := filepath.Join(dir, link.to)
if err := os.Symlink(to, p.String()); err != nil { if err := os.Symlink(to, p); err != nil {
t.Fatalf("os.Symlink(%q, %q) err=%q", to, p, err) t.Fatalf("os.Symlink(%q, %q) err=%q", to, p, err)
} }
} }