New upstream version 1.0.0
Dr. Tobias Quathamer
6 years ago
15 | 15 | fast_finish: true |
16 | 16 | |
17 | 17 | script: |
18 | - go test -v ./... | |
19 | 18 | - go build |
19 | - go test -race -v ./... | |
20 |
60 | 60 | |
61 | 61 | First define a package variable and set it to a pointer to a filesystem. |
62 | 62 | ```go |
63 | var AppFs afero.Fs = afero.NewMemMapFs() | |
63 | var AppFs = afero.NewMemMapFs() | |
64 | 64 | |
65 | 65 | or |
66 | 66 | |
67 | var AppFs afero.Fs = afero.NewOsFs() | |
67 | var AppFs = afero.NewOsFs() | |
68 | 68 | ``` |
69 | 69 | It is important to note that if you repeat the composite literal you |
70 | 70 | will be using a completely new and isolated filesystem. In the case of |
80 | 80 | ```go |
81 | 81 | os.Open('/tmp/foo') |
82 | 82 | ``` |
83 | We would replace it with a call to `AppFs.Open('/tmp/foo')`. | |
83 | We would replace it with: | |
84 | ```go | |
85 | AppFs.Open('/tmp/foo') | |
86 | ``` | |
84 | 87 | |
85 | 88 | `AppFs` being the variable we defined above. |
86 | 89 | |
165 | 168 | ### Calling via Afero |
166 | 169 | |
167 | 170 | ```go |
168 | fs := afero.NewMemMapFs | |
169 | afs := &Afero{Fs: fs} | |
171 | fs := afero.NewMemMapFs() | |
172 | afs := &afero.Afero{Fs: fs} | |
170 | 173 | f, err := afs.TempFile("", "ioutil-test") |
171 | 174 | ``` |
172 | 175 |
11 | 11 | |
12 | 12 | go build github.com/spf13/afero |
13 | 13 | test_script: |
14 | - cmd: go test -v github.com/spf13/afero | |
14 | - cmd: go test -race -v github.com/spf13/afero/... |
63 | 63 | return cacheHit, lfi, nil |
64 | 64 | } |
65 | 65 | |
66 | if err == syscall.ENOENT { | |
66 | if err == syscall.ENOENT || os.IsNotExist(err) { | |
67 | 67 | return cacheMiss, nil, nil |
68 | 68 | } |
69 | var ok bool | |
70 | if err, ok = err.(*os.PathError); ok { | |
71 | if err == os.ErrNotExist { | |
72 | return cacheMiss, nil, nil | |
73 | } | |
74 | } | |
69 | ||
75 | 70 | return cacheMiss, nil, err |
76 | 71 | } |
77 | 72 |
0 | 0 | package afero |
1 | 1 | |
2 | 2 | import ( |
3 | "bytes" | |
3 | 4 | "fmt" |
4 | 5 | "io/ioutil" |
5 | 6 | "os" |
365 | 366 | t.Errorf("cache time failed: <%s>", data) |
366 | 367 | } |
367 | 368 | } |
369 | ||
370 | func TestCacheOnReadFsNotInLayer(t *testing.T) { | |
371 | base := NewMemMapFs() | |
372 | layer := NewMemMapFs() | |
373 | fs := NewCacheOnReadFs(base, layer, 0) | |
374 | ||
375 | fh, err := base.Create("/file.txt") | |
376 | if err != nil { | |
377 | t.Fatal("unable to create file: ", err) | |
378 | } | |
379 | ||
380 | txt := []byte("This is a test") | |
381 | fh.Write(txt) | |
382 | fh.Close() | |
383 | ||
384 | fh, err = fs.Open("/file.txt") | |
385 | if err != nil { | |
386 | t.Fatal("could not open file: ", err) | |
387 | } | |
388 | ||
389 | b, err := ReadAll(fh) | |
390 | fh.Close() | |
391 | ||
392 | if err != nil { | |
393 | t.Fatal("could not read file: ", err) | |
394 | } else if !bytes.Equal(txt, b) { | |
395 | t.Fatalf("wanted file text %q, got %q", txt, b) | |
396 | } | |
397 | ||
398 | fh, err = layer.Open("/file.txt") | |
399 | if err != nil { | |
400 | t.Fatal("could not open file from layer: ", err) | |
401 | } | |
402 | fh.Close() | |
403 | } |
79 | 79 | if e, ok := err.(*os.PathError); ok { |
80 | 80 | err = e.Err |
81 | 81 | } |
82 | if err == syscall.ENOENT || err == syscall.ENOTDIR { | |
82 | if err == os.ErrNotExist || err == syscall.ENOENT || err == syscall.ENOTDIR { | |
83 | 83 | return u.base.Stat(name) |
84 | 84 | } |
85 | 85 | return nil, origErr |
20 | 20 | } |
21 | 21 | |
22 | 22 | } |
23 | ||
24 | func TestCopyOnWriteFileInMemMapBase(t *testing.T) { | |
25 | base := &MemMapFs{} | |
26 | layer := &MemMapFs{} | |
27 | ||
28 | if err := WriteFile(base, "base.txt", []byte("base"), 0755); err != nil { | |
29 | t.Fatalf("Failed to write file: %s", err) | |
30 | } | |
31 | ||
32 | ufs := NewCopyOnWriteFs(base, layer) | |
33 | ||
34 | _, err := ufs.Stat("base.txt") | |
35 | if err != nil { | |
36 | t.Fatal(err) | |
37 | } | |
38 | } |
73 | 73 | } |
74 | 74 | |
75 | 75 | func ChangeFileName(f *FileData, newname string) { |
76 | f.Lock() | |
76 | 77 | f.name = newname |
78 | f.Unlock() | |
77 | 79 | } |
78 | 80 | |
79 | 81 | func SetMode(f *FileData, mode os.FileMode) { |
82 | f.Lock() | |
80 | 83 | f.mode = mode |
84 | f.Unlock() | |
81 | 85 | } |
82 | 86 | |
83 | 87 | func SetModTime(f *FileData, mtime time.Time) { |
88 | f.Lock() | |
89 | setModTime(f, mtime) | |
90 | f.Unlock() | |
91 | } | |
92 | ||
93 | func setModTime(f *FileData, mtime time.Time) { | |
84 | 94 | f.modtime = mtime |
85 | 95 | } |
86 | 96 | |
101 | 111 | f.fileData.Lock() |
102 | 112 | f.closed = true |
103 | 113 | if !f.readOnly { |
104 | SetModTime(f.fileData, time.Now()) | |
114 | setModTime(f.fileData, time.Now()) | |
105 | 115 | } |
106 | 116 | f.fileData.Unlock() |
107 | 117 | return nil |
196 | 206 | } else { |
197 | 207 | f.fileData.data = f.fileData.data[0:size] |
198 | 208 | } |
199 | SetModTime(f.fileData, time.Now()) | |
209 | setModTime(f.fileData, time.Now()) | |
200 | 210 | return nil |
201 | 211 | } |
202 | 212 | |
235 | 245 | f.fileData.data = append(f.fileData.data[:cur], b...) |
236 | 246 | f.fileData.data = append(f.fileData.data, tail...) |
237 | 247 | } |
238 | SetModTime(f.fileData, time.Now()) | |
248 | setModTime(f.fileData, time.Now()) | |
239 | 249 | |
240 | 250 | atomic.StoreInt64(&f.at, int64(len(f.fileData.data))) |
241 | 251 | return |
260 | 270 | |
261 | 271 | // Implements os.FileInfo |
262 | 272 | func (s *FileInfo) Name() string { |
273 | s.Lock() | |
263 | 274 | _, name := filepath.Split(s.name) |
275 | s.Unlock() | |
264 | 276 | return name |
265 | 277 | } |
266 | func (s *FileInfo) Mode() os.FileMode { return s.mode } | |
267 | func (s *FileInfo) ModTime() time.Time { return s.modtime } | |
268 | func (s *FileInfo) IsDir() bool { return s.dir } | |
269 | func (s *FileInfo) Sys() interface{} { return nil } | |
278 | func (s *FileInfo) Mode() os.FileMode { | |
279 | s.Lock() | |
280 | defer s.Unlock() | |
281 | return s.mode | |
282 | } | |
283 | func (s *FileInfo) ModTime() time.Time { | |
284 | s.Lock() | |
285 | defer s.Unlock() | |
286 | return s.modtime | |
287 | } | |
288 | func (s *FileInfo) IsDir() bool { | |
289 | s.Lock() | |
290 | defer s.Unlock() | |
291 | return s.dir | |
292 | } | |
293 | func (s *FileInfo) Sys() interface{} { return nil } | |
270 | 294 | func (s *FileInfo) Size() int64 { |
271 | 295 | if s.IsDir() { |
272 | 296 | return int64(42) |
273 | 297 | } |
298 | s.Lock() | |
299 | defer s.Unlock() | |
274 | 300 | return int64(len(s.data)) |
275 | 301 | } |
276 | 302 |
0 | package mem | |
1 | ||
2 | import ( | |
3 | "testing" | |
4 | "time" | |
5 | ) | |
6 | ||
7 | func TestFileDataNameRace(t *testing.T) { | |
8 | t.Parallel() | |
9 | const someName = "someName" | |
10 | const someOtherName = "someOtherName" | |
11 | d := FileData{ | |
12 | name: someName, | |
13 | } | |
14 | ||
15 | if d.Name() != someName { | |
16 | t.Errorf("Failed to read correct Name, was %v", d.Name()) | |
17 | } | |
18 | ||
19 | ChangeFileName(&d, someOtherName) | |
20 | if d.Name() != someOtherName { | |
21 | t.Errorf("Failed to set Name, was %v", d.Name()) | |
22 | } | |
23 | ||
24 | go func() { | |
25 | ChangeFileName(&d, someName) | |
26 | }() | |
27 | ||
28 | if d.Name() != someName && d.Name() != someOtherName { | |
29 | t.Errorf("Failed to read either Name, was %v", d.Name()) | |
30 | } | |
31 | } | |
32 | ||
33 | func TestFileDataModTimeRace(t *testing.T) { | |
34 | t.Parallel() | |
35 | someTime := time.Now() | |
36 | someOtherTime := someTime.Add(1 * time.Minute) | |
37 | ||
38 | d := FileData{ | |
39 | modtime: someTime, | |
40 | } | |
41 | ||
42 | s := FileInfo{ | |
43 | FileData: &d, | |
44 | } | |
45 | ||
46 | if s.ModTime() != someTime { | |
47 | t.Errorf("Failed to read correct value, was %v", s.ModTime()) | |
48 | } | |
49 | ||
50 | SetModTime(&d, someOtherTime) | |
51 | if s.ModTime() != someOtherTime { | |
52 | t.Errorf("Failed to set ModTime, was %v", s.ModTime()) | |
53 | } | |
54 | ||
55 | go func() { | |
56 | SetModTime(&d, someTime) | |
57 | }() | |
58 | ||
59 | if s.ModTime() != someTime && s.ModTime() != someOtherTime { | |
60 | t.Errorf("Failed to read either modtime, was %v", s.ModTime()) | |
61 | } | |
62 | } | |
63 | ||
64 | func TestFileDataModeRace(t *testing.T) { | |
65 | t.Parallel() | |
66 | const someMode = 0777 | |
67 | const someOtherMode = 0660 | |
68 | ||
69 | d := FileData{ | |
70 | mode: someMode, | |
71 | } | |
72 | ||
73 | s := FileInfo{ | |
74 | FileData: &d, | |
75 | } | |
76 | ||
77 | if s.Mode() != someMode { | |
78 | t.Errorf("Failed to read correct value, was %v", s.Mode()) | |
79 | } | |
80 | ||
81 | SetMode(&d, someOtherMode) | |
82 | if s.Mode() != someOtherMode { | |
83 | t.Errorf("Failed to set Mode, was %v", s.Mode()) | |
84 | } | |
85 | ||
86 | go func() { | |
87 | SetMode(&d, someMode) | |
88 | }() | |
89 | ||
90 | if s.Mode() != someMode && s.Mode() != someOtherMode { | |
91 | t.Errorf("Failed to read either mode, was %v", s.Mode()) | |
92 | } | |
93 | } | |
94 | ||
95 | func TestFileDataIsDirRace(t *testing.T) { | |
96 | t.Parallel() | |
97 | ||
98 | d := FileData{ | |
99 | dir: true, | |
100 | } | |
101 | ||
102 | s := FileInfo{ | |
103 | FileData: &d, | |
104 | } | |
105 | ||
106 | if s.IsDir() != true { | |
107 | t.Errorf("Failed to read correct value, was %v", s.IsDir()) | |
108 | } | |
109 | ||
110 | go func() { | |
111 | s.Lock() | |
112 | d.dir = false | |
113 | s.Unlock() | |
114 | }() | |
115 | ||
116 | //just logging the value to trigger a read: | |
117 | t.Logf("Value is %v", s.IsDir()) | |
118 | } | |
119 | ||
120 | func TestFileDataSizeRace(t *testing.T) { | |
121 | t.Parallel() | |
122 | ||
123 | const someData = "Hello" | |
124 | const someOtherDataSize = "Hello World" | |
125 | ||
126 | d := FileData{ | |
127 | data: []byte(someData), | |
128 | dir: false, | |
129 | } | |
130 | ||
131 | s := FileInfo{ | |
132 | FileData: &d, | |
133 | } | |
134 | ||
135 | if s.Size() != int64(len(someData)) { | |
136 | t.Errorf("Failed to read correct value, was %v", s.Size()) | |
137 | } | |
138 | ||
139 | go func() { | |
140 | s.Lock() | |
141 | d.data = []byte(someOtherDataSize) | |
142 | s.Unlock() | |
143 | }() | |
144 | ||
145 | //just logging the value to trigger a read: | |
146 | t.Logf("Value is %v", s.Size()) | |
147 | ||
148 | //Testing the Dir size case | |
149 | d.dir = true | |
150 | if s.Size() != int64(42) { | |
151 | t.Errorf("Failed to read correct value for dir, was %v", s.Size()) | |
152 | } | |
153 | } |
140 | 140 | m.registerWithParent(item) |
141 | 141 | m.mu.Unlock() |
142 | 142 | |
143 | m.Chmod(name, perm) | |
143 | m.Chmod(name, perm|os.ModeDir) | |
144 | 144 | |
145 | 145 | return nil |
146 | 146 | } |
150 | 150 | if err != nil { |
151 | 151 | if err.(*os.PathError).Err == ErrFileExists { |
152 | 152 | return nil |
153 | } else { | |
154 | return err | |
155 | } | |
153 | } | |
154 | return err | |
156 | 155 | } |
157 | 156 | return nil |
158 | 157 | } |
109 | 109 | const dirPathAll = "/my/path/to/dir" |
110 | 110 | |
111 | 111 | const fileMode = os.FileMode(0765) |
112 | // directories will also have the directory bit set | |
113 | const dirMode = fileMode | os.ModeDir | |
112 | 114 | |
113 | 115 | fs := NewMemMapFs() |
114 | 116 | |
131 | 133 | } |
132 | 134 | |
133 | 135 | // Test Mkdir |
134 | err = fs.Mkdir(dirPath, fileMode) | |
136 | err = fs.Mkdir(dirPath, dirMode) | |
135 | 137 | if err != nil { |
136 | 138 | t.Errorf("MkDir Create failed: %s", err) |
137 | 139 | return |
141 | 143 | t.Errorf("Stat failed: %s", err) |
142 | 144 | return |
143 | 145 | } |
144 | if s.Mode().String() != fileMode.String() { | |
145 | t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), fileMode.String()) | |
146 | // sets File | |
147 | if s.Mode().String() != dirMode.String() { | |
148 | t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String()) | |
146 | 149 | return |
147 | 150 | } |
148 | 151 | |
149 | 152 | // Test MkdirAll |
150 | err = fs.MkdirAll(dirPathAll, fileMode) | |
153 | err = fs.MkdirAll(dirPathAll, dirMode) | |
151 | 154 | if err != nil { |
152 | 155 | t.Errorf("MkDir Create failed: %s", err) |
153 | 156 | return |
157 | 160 | t.Errorf("Stat failed: %s", err) |
158 | 161 | return |
159 | 162 | } |
160 | if s.Mode().String() != fileMode.String() { | |
161 | t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), fileMode.String()) | |
163 | if s.Mode().String() != dirMode.String() { | |
164 | t.Errorf("Permissions Incorrect: %s != %s", s.Mode().String(), dirMode.String()) | |
162 | 165 | return |
163 | 166 | } |
164 | 167 | } |
383 | 386 | } |
384 | 387 | } |
385 | 388 | } |
389 | ||
390 | func TestMemFsDirMode(t *testing.T) { | |
391 | fs := NewMemMapFs() | |
392 | err := fs.Mkdir("/testDir1", 0644) | |
393 | if err != nil { | |
394 | t.Error(err) | |
395 | } | |
396 | err = fs.MkdirAll("/sub/testDir2", 0644) | |
397 | if err != nil { | |
398 | t.Error(err) | |
399 | } | |
400 | info, err := fs.Stat("/testDir1") | |
401 | if err != nil { | |
402 | t.Error(err) | |
403 | } | |
404 | if !info.IsDir() { | |
405 | t.Error("should be a directory") | |
406 | } | |
407 | if !info.Mode().IsDir() { | |
408 | t.Error("FileMode is not directory") | |
409 | } | |
410 | info, err = fs.Stat("/sub/testDir2") | |
411 | if err != nil { | |
412 | t.Error(err) | |
413 | } | |
414 | if !info.IsDir() { | |
415 | t.Error("should be a directory") | |
416 | } | |
417 | if !info.Mode().IsDir() { | |
418 | t.Error("FileMode is not directory") | |
419 | } | |
420 | } |
0 | // Copyright © 2014 Steve Francia <spf@spf13.com>. | |
1 | // | |
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | // you may not use this file except in compliance with the License. | |
4 | // You may obtain a copy of the License at | |
5 | // http://www.apache.org/licenses/LICENSE-2.0 | |
6 | // | |
7 | // Unless required by applicable law or agreed to in writing, software | |
8 | // distributed under the License is distributed on an "AS IS" BASIS, | |
9 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
10 | // See the License for the specific language governing permissions and | |
11 | // limitations under the License. | |
12 | ||
13 | package afero |
156 | 156 | return string(target) |
157 | 157 | } |
158 | 158 | |
159 | // Transform characters with accents into plan forms | |
159 | // Transform characters with accents into plain forms. | |
160 | 160 | func NeuterAccents(s string) string { |
161 | 161 | t := transform.Chain(norm.NFD, transform.RemoveFunc(isMn), norm.NFC) |
162 | 162 | result, _, _ := transform.String(t, string(s)) |