Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit c460889

Browse files
committed
internal/gps: refactor filesystemState and functions
This commit moves filesystemState from being a test struct to become part of gps. It'll beused to optimize the prune functions by calculating the filesystem state and determining the files to prune in-memory. Signed-off-by: Ibrahim AshShohail <[email protected]>
1 parent ceb67da commit c460889

File tree

2 files changed

+107
-55
lines changed

2 files changed

+107
-55
lines changed

internal/gps/filesystem.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2017 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package gps
6+
7+
import (
8+
"os"
9+
"path/filepath"
10+
)
11+
12+
// filesystemState represents the state of a file system.
13+
type filesystemState struct {
14+
root string
15+
dirs []string
16+
files []string
17+
links []fsLink
18+
}
19+
20+
// fsLink represents a symbolic link.
21+
type fsLink struct {
22+
path string
23+
to string
24+
}
25+
26+
// deriveFilesystemState returns a filesystemState based on the state of
27+
// the filesystem on root.
28+
func deriveFilesystemState(root string) (filesystemState, error) {
29+
fs := filesystemState{
30+
root: root,
31+
}
32+
33+
err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
34+
if err != nil {
35+
return err
36+
}
37+
38+
if path == fs.root {
39+
return nil
40+
}
41+
42+
relPath, err := filepath.Rel(fs.root, path)
43+
if err != nil {
44+
return err
45+
}
46+
47+
if (info.Mode() & os.ModeSymlink) != 0 {
48+
eval, err := filepath.EvalSymlinks(path)
49+
if err != nil {
50+
return err
51+
}
52+
53+
fs.links = append(fs.links, fsLink{
54+
path: relPath,
55+
to: eval,
56+
})
57+
58+
return nil
59+
}
60+
61+
if info.IsDir() {
62+
fs.dirs = append(fs.dirs, relPath)
63+
64+
return nil
65+
}
66+
67+
fs.files = append(fs.files, relPath)
68+
69+
return nil
70+
})
71+
72+
if err != nil {
73+
return filesystemState{}, err
74+
}
75+
76+
return fs, nil
77+
}

internal/gps/filesystem_test.go

Lines changed: 30 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,34 @@ import (
1212

1313
// This file contains utilities for running tests around file system state.
1414

15-
// fspath represents a file system path in an OS-agnostic way.
16-
type fsPath []string
17-
18-
func (f fsPath) String() string { return filepath.Join(f...) }
19-
20-
func (f fsPath) prepend(prefix string) fsPath {
21-
p := fsPath{filepath.FromSlash(prefix)}
22-
return append(p, f...)
23-
}
24-
2515
type fsTestCase struct {
2616
before, after filesystemState
2717
}
2818

29-
// filesystemState represents the state of a file system. It has a setup method
30-
// which inflates its state to the actual host file system, and an assert
31-
// method which checks that the actual file system matches the described state.
32-
type filesystemState struct {
33-
root string
34-
dirs []fsPath
35-
files []fsPath
36-
links []fsLink
37-
}
38-
39-
// assert makes sure that the fs state matches the state of the actual host
40-
// file system
41-
func (fs filesystemState) assert(t *testing.T) {
19+
// assert makes sure that the tc.after state matches the state of the actual host
20+
// file system at tc.after.root.
21+
func (tc fsTestCase) assert(t *testing.T) {
4222
dirMap := make(map[string]bool)
4323
fileMap := make(map[string]bool)
4424
linkMap := make(map[string]bool)
4525

46-
for _, d := range fs.dirs {
47-
dirMap[d.prepend(fs.root).String()] = true
26+
for _, d := range tc.after.dirs {
27+
dirMap[filepath.Join(tc.after.root, d)] = true
4828
}
49-
for _, f := range fs.files {
50-
fileMap[f.prepend(fs.root).String()] = true
29+
for _, f := range tc.after.files {
30+
fileMap[filepath.Join(tc.after.root, f)] = true
5131
}
52-
for _, l := range fs.links {
53-
linkMap[l.path.prepend(fs.root).String()] = true
32+
for _, l := range tc.after.links {
33+
linkMap[filepath.Join(tc.after.root, l.path)] = true
5434
}
5535

56-
err := filepath.Walk(fs.root, func(path string, info os.FileInfo, err error) error {
36+
err := filepath.Walk(tc.after.root, func(path string, info os.FileInfo, err error) error {
5737
if err != nil {
5838
t.Errorf("filepath.Walk path=%q err=%q", path, err)
5939
return err
6040
}
6141

62-
if path == fs.root {
42+
if path == tc.after.root {
6343
return nil
6444
}
6545

@@ -106,32 +86,27 @@ func (fs filesystemState) assert(t *testing.T) {
10686
}
10787
}
10888

109-
// fsLink represents a symbolic link.
110-
type fsLink struct {
111-
path fsPath
112-
to string
113-
}
114-
115-
// setup inflates fs onto the actual host file system
116-
func (fs filesystemState) setup(t *testing.T) {
117-
fs.setupDirs(t)
118-
fs.setupFiles(t)
119-
fs.setupLinks(t)
89+
// setup inflates fs onto the actual host file system at tc.before.root.
90+
// It doesn't delete existing files and should be used on empty roots only.
91+
func (tc fsTestCase) setup(t *testing.T) {
92+
tc.setupDirs(t)
93+
tc.setupFiles(t)
94+
tc.setupLinks(t)
12095
}
12196

122-
func (fs filesystemState) setupDirs(t *testing.T) {
123-
for _, dir := range fs.dirs {
124-
p := dir.prepend(fs.root)
125-
if err := os.MkdirAll(p.String(), 0777); err != nil {
97+
func (tc fsTestCase) setupDirs(t *testing.T) {
98+
for _, dir := range tc.before.dirs {
99+
p := filepath.Join(tc.before.root, dir)
100+
if err := os.MkdirAll(p, 0777); err != nil {
126101
t.Fatalf("os.MkdirAll(%q, 0777) err=%q", p, err)
127102
}
128103
}
129104
}
130105

131-
func (fs filesystemState) setupFiles(t *testing.T) {
132-
for _, file := range fs.files {
133-
p := file.prepend(fs.root)
134-
f, err := os.Create(p.String())
106+
func (tc fsTestCase) setupFiles(t *testing.T) {
107+
for _, file := range tc.before.files {
108+
p := filepath.Join(tc.before.root, file)
109+
f, err := os.Create(p)
135110
if err != nil {
136111
t.Fatalf("os.Create(%q) err=%q", p, err)
137112
}
@@ -141,17 +116,17 @@ func (fs filesystemState) setupFiles(t *testing.T) {
141116
}
142117
}
143118

144-
func (fs filesystemState) setupLinks(t *testing.T) {
145-
for _, link := range fs.links {
146-
p := link.path.prepend(fs.root)
119+
func (tc fsTestCase) setupLinks(t *testing.T) {
120+
for _, link := range tc.before.links {
121+
p := filepath.Join(tc.before.root, link.path)
147122

148123
// On Windows, relative symlinks confuse filepath.Walk. This is golang/go
149124
// issue 17540. So, we'll just sigh and do absolute links, assuming they are
150125
// relative to the directory of link.path.
151-
dir := filepath.Dir(p.String())
126+
dir := filepath.Dir(p)
152127
to := filepath.Join(dir, link.to)
153128

154-
if err := os.Symlink(to, p.String()); err != nil {
129+
if err := os.Symlink(to, p); err != nil {
155130
t.Fatalf("os.Symlink(%q, %q) err=%q", to, p, err)
156131
}
157132
}

0 commit comments

Comments
 (0)