rootmapping_fs_test.go (18029B)
1 // Copyright 2019 The Hugo Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 package hugofs
15
16 import (
17 "fmt"
18 "io/ioutil"
19 "path/filepath"
20 "sort"
21 "testing"
22
23 "github.com/gohugoio/hugo/config"
24 "github.com/gohugoio/hugo/hugofs/glob"
25
26 qt "github.com/frankban/quicktest"
27 "github.com/gohugoio/hugo/htesting"
28 "github.com/spf13/afero"
29 )
30
31 func TestLanguageRootMapping(t *testing.T) {
32 c := qt.New(t)
33 v := config.NewWithTestDefaults()
34 v.Set("contentDir", "content")
35
36 fs := NewBaseFileDecorator(afero.NewMemMapFs())
37
38 c.Assert(afero.WriteFile(fs, filepath.Join("content/sv/svdir", "main.txt"), []byte("main sv"), 0755), qt.IsNil)
39
40 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mysvblogcontent", "sv-f.txt"), []byte("some sv blog content"), 0755), qt.IsNil)
41 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/myenblogcontent", "en-f.txt"), []byte("some en blog content in a"), 0755), qt.IsNil)
42 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mysvblogcontent/d1", "sv-d1-f.txt"), []byte("some sv blog content"), 0755), qt.IsNil)
43 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/myenblogcontent/d1", "en-d1-f.txt"), []byte("some en blog content in a"), 0755), qt.IsNil)
44
45 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/myotherenblogcontent", "en-f2.txt"), []byte("some en content"), 0755), qt.IsNil)
46 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mysvdocs", "sv-docs.txt"), []byte("some sv docs content"), 0755), qt.IsNil)
47 c.Assert(afero.WriteFile(fs, filepath.Join("themes/b/myenblogcontent", "en-b-f.txt"), []byte("some en content"), 0755), qt.IsNil)
48
49 rfs, err := NewRootMappingFs(fs,
50 RootMapping{
51 From: "content/blog", // Virtual path, first element is one of content, static, layouts etc.
52 To: "themes/a/mysvblogcontent", // Real path
53 Meta: &FileMeta{Lang: "sv"},
54 },
55 RootMapping{
56 From: "content/blog",
57 To: "themes/a/myenblogcontent",
58 Meta: &FileMeta{Lang: "en"},
59 },
60 RootMapping{
61 From: "content/blog",
62 To: "content/sv",
63 Meta: &FileMeta{Lang: "sv"},
64 },
65 RootMapping{
66 From: "content/blog",
67 To: "themes/a/myotherenblogcontent",
68 Meta: &FileMeta{Lang: "en"},
69 },
70 RootMapping{
71 From: "content/docs",
72 To: "themes/a/mysvdocs",
73 Meta: &FileMeta{Lang: "sv"},
74 },
75 )
76
77 c.Assert(err, qt.IsNil)
78
79 collected, err := collectFilenames(rfs, "content", "content")
80 c.Assert(err, qt.IsNil)
81 c.Assert(collected, qt.DeepEquals,
82 []string{"blog/d1/en-d1-f.txt", "blog/d1/sv-d1-f.txt", "blog/en-f.txt", "blog/en-f2.txt", "blog/sv-f.txt", "blog/svdir/main.txt", "docs/sv-docs.txt"}, qt.Commentf("%#v", collected))
83
84 dirs, err := rfs.Dirs(filepath.FromSlash("content/blog"))
85 c.Assert(err, qt.IsNil)
86 c.Assert(len(dirs), qt.Equals, 4)
87 for _, dir := range dirs {
88 f, err := dir.Meta().Open()
89 c.Assert(err, qt.IsNil)
90 f.Close()
91 }
92
93 blog, err := rfs.Open(filepath.FromSlash("content/blog"))
94 c.Assert(err, qt.IsNil)
95 fis, err := blog.Readdir(-1)
96 for _, fi := range fis {
97 f, err := fi.(FileMetaInfo).Meta().Open()
98 c.Assert(err, qt.IsNil)
99 f.Close()
100 }
101 blog.Close()
102
103 getDirnames := func(name string, rfs *RootMappingFs) []string {
104 c.Helper()
105 filename := filepath.FromSlash(name)
106 f, err := rfs.Open(filename)
107 c.Assert(err, qt.IsNil)
108 names, err := f.Readdirnames(-1)
109
110 f.Close()
111 c.Assert(err, qt.IsNil)
112
113 info, err := rfs.Stat(filename)
114 c.Assert(err, qt.IsNil)
115 f2, err := info.(FileMetaInfo).Meta().Open()
116 c.Assert(err, qt.IsNil)
117 names2, err := f2.Readdirnames(-1)
118 c.Assert(err, qt.IsNil)
119 c.Assert(names2, qt.DeepEquals, names)
120 f2.Close()
121
122 return names
123 }
124
125 rfsEn := rfs.Filter(func(rm RootMapping) bool {
126 return rm.Meta.Lang == "en"
127 })
128
129 c.Assert(getDirnames("content/blog", rfsEn), qt.DeepEquals, []string{"d1", "en-f.txt", "en-f2.txt"})
130
131 rfsSv := rfs.Filter(func(rm RootMapping) bool {
132 return rm.Meta.Lang == "sv"
133 })
134
135 c.Assert(getDirnames("content/blog", rfsSv), qt.DeepEquals, []string{"d1", "sv-f.txt", "svdir"})
136
137 // Make sure we have not messed with the original
138 c.Assert(getDirnames("content/blog", rfs), qt.DeepEquals, []string{"d1", "sv-f.txt", "en-f.txt", "svdir", "en-f2.txt"})
139
140 c.Assert(getDirnames("content", rfsSv), qt.DeepEquals, []string{"blog", "docs"})
141 c.Assert(getDirnames("content", rfs), qt.DeepEquals, []string{"blog", "docs"})
142 }
143
144 func TestRootMappingFsDirnames(t *testing.T) {
145 c := qt.New(t)
146 fs := NewBaseFileDecorator(afero.NewMemMapFs())
147
148 testfile := "myfile.txt"
149 c.Assert(fs.Mkdir("f1t", 0755), qt.IsNil)
150 c.Assert(fs.Mkdir("f2t", 0755), qt.IsNil)
151 c.Assert(fs.Mkdir("f3t", 0755), qt.IsNil)
152 c.Assert(afero.WriteFile(fs, filepath.Join("f2t", testfile), []byte("some content"), 0755), qt.IsNil)
153
154 rfs, err := newRootMappingFsFromFromTo("", fs, "static/bf1", "f1t", "static/cf2", "f2t", "static/af3", "f3t")
155 c.Assert(err, qt.IsNil)
156
157 fif, err := rfs.Stat(filepath.Join("static/cf2", testfile))
158 c.Assert(err, qt.IsNil)
159 c.Assert(fif.Name(), qt.Equals, "myfile.txt")
160 fifm := fif.(FileMetaInfo).Meta()
161 c.Assert(fifm.Filename, qt.Equals, filepath.FromSlash("f2t/myfile.txt"))
162
163 root, err := rfs.Open("static")
164 c.Assert(err, qt.IsNil)
165
166 dirnames, err := root.Readdirnames(-1)
167 c.Assert(err, qt.IsNil)
168 c.Assert(dirnames, qt.DeepEquals, []string{"af3", "bf1", "cf2"})
169 }
170
171 func TestRootMappingFsFilename(t *testing.T) {
172 c := qt.New(t)
173 workDir, clean, err := htesting.CreateTempDir(Os, "hugo-root-filename")
174 c.Assert(err, qt.IsNil)
175 defer clean()
176 fs := NewBaseFileDecorator(Os)
177
178 testfilename := filepath.Join(workDir, "f1t/foo/file.txt")
179
180 c.Assert(fs.MkdirAll(filepath.Join(workDir, "f1t/foo"), 0777), qt.IsNil)
181 c.Assert(afero.WriteFile(fs, testfilename, []byte("content"), 0666), qt.IsNil)
182
183 rfs, err := newRootMappingFsFromFromTo(workDir, fs, "static/f1", filepath.Join(workDir, "f1t"), "static/f2", filepath.Join(workDir, "f2t"))
184 c.Assert(err, qt.IsNil)
185
186 fi, err := rfs.Stat(filepath.FromSlash("static/f1/foo/file.txt"))
187 c.Assert(err, qt.IsNil)
188 fim := fi.(FileMetaInfo)
189 c.Assert(fim.Meta().Filename, qt.Equals, testfilename)
190 _, err = rfs.Stat(filepath.FromSlash("static/f1"))
191 c.Assert(err, qt.IsNil)
192 }
193
194 func TestRootMappingFsMount(t *testing.T) {
195 c := qt.New(t)
196 fs := NewBaseFileDecorator(afero.NewMemMapFs())
197
198 testfile := "test.txt"
199
200 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mynoblogcontent", testfile), []byte("some no content"), 0755), qt.IsNil)
201 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/myenblogcontent", testfile), []byte("some en content"), 0755), qt.IsNil)
202 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mysvblogcontent", testfile), []byte("some sv content"), 0755), qt.IsNil)
203 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/mysvblogcontent", "other.txt"), []byte("some sv content"), 0755), qt.IsNil)
204 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/singlefiles", "no.txt"), []byte("no text"), 0755), qt.IsNil)
205 c.Assert(afero.WriteFile(fs, filepath.Join("themes/a/singlefiles", "sv.txt"), []byte("sv text"), 0755), qt.IsNil)
206
207 bfs := afero.NewBasePathFs(fs, "themes/a").(*afero.BasePathFs)
208 rm := []RootMapping{
209 // Directories
210 {
211 From: "content/blog",
212 To: "mynoblogcontent",
213 Meta: &FileMeta{Lang: "no"},
214 },
215 {
216 From: "content/blog",
217 To: "myenblogcontent",
218 Meta: &FileMeta{Lang: "en"},
219 },
220 {
221 From: "content/blog",
222 To: "mysvblogcontent",
223 Meta: &FileMeta{Lang: "sv"},
224 },
225 // Files
226 {
227 From: "content/singles/p1.md",
228 To: "singlefiles/no.txt",
229 ToBasedir: "singlefiles",
230 Meta: &FileMeta{Lang: "no"},
231 },
232 {
233 From: "content/singles/p1.md",
234 To: "singlefiles/sv.txt",
235 ToBasedir: "singlefiles",
236 Meta: &FileMeta{Lang: "sv"},
237 },
238 }
239
240 rfs, err := NewRootMappingFs(bfs, rm...)
241 c.Assert(err, qt.IsNil)
242
243 blog, err := rfs.Stat(filepath.FromSlash("content/blog"))
244 c.Assert(err, qt.IsNil)
245 c.Assert(blog.IsDir(), qt.Equals, true)
246 blogm := blog.(FileMetaInfo).Meta()
247 c.Assert(blogm.Lang, qt.Equals, "no") // First match
248
249 f, err := blogm.Open()
250 c.Assert(err, qt.IsNil)
251 defer f.Close()
252 dirs1, err := f.Readdirnames(-1)
253 c.Assert(err, qt.IsNil)
254 // Union with duplicate dir names filtered.
255 c.Assert(dirs1, qt.DeepEquals, []string{"test.txt", "test.txt", "other.txt", "test.txt"})
256
257 files, err := afero.ReadDir(rfs, filepath.FromSlash("content/blog"))
258 c.Assert(err, qt.IsNil)
259 c.Assert(len(files), qt.Equals, 4)
260
261 testfilefi := files[1]
262 c.Assert(testfilefi.Name(), qt.Equals, testfile)
263
264 testfilem := testfilefi.(FileMetaInfo).Meta()
265 c.Assert(testfilem.Filename, qt.Equals, filepath.FromSlash("themes/a/mynoblogcontent/test.txt"))
266
267 tf, err := testfilem.Open()
268 c.Assert(err, qt.IsNil)
269 defer tf.Close()
270 b, err := ioutil.ReadAll(tf)
271 c.Assert(err, qt.IsNil)
272 c.Assert(string(b), qt.Equals, "some no content")
273
274 // Ambiguous
275 _, err = rfs.Stat(filepath.FromSlash("content/singles/p1.md"))
276 c.Assert(err, qt.Not(qt.IsNil))
277
278 singlesDir, err := rfs.Open(filepath.FromSlash("content/singles"))
279 c.Assert(err, qt.IsNil)
280 defer singlesDir.Close()
281 singles, err := singlesDir.Readdir(-1)
282 c.Assert(err, qt.IsNil)
283 c.Assert(singles, qt.HasLen, 2)
284 for i, lang := range []string{"no", "sv"} {
285 fi := singles[i].(FileMetaInfo)
286 c.Assert(fi.Meta().PathFile(), qt.Equals, filepath.FromSlash("themes/a/singlefiles/"+lang+".txt"))
287 c.Assert(fi.Meta().Lang, qt.Equals, lang)
288 c.Assert(fi.Name(), qt.Equals, "p1.md")
289 }
290 }
291
292 func TestRootMappingFsMountOverlap(t *testing.T) {
293 c := qt.New(t)
294 fs := NewBaseFileDecorator(afero.NewMemMapFs())
295
296 c.Assert(afero.WriteFile(fs, filepath.FromSlash("da/a.txt"), []byte("some no content"), 0755), qt.IsNil)
297 c.Assert(afero.WriteFile(fs, filepath.FromSlash("db/b.txt"), []byte("some no content"), 0755), qt.IsNil)
298 c.Assert(afero.WriteFile(fs, filepath.FromSlash("dc/c.txt"), []byte("some no content"), 0755), qt.IsNil)
299 c.Assert(afero.WriteFile(fs, filepath.FromSlash("de/e.txt"), []byte("some no content"), 0755), qt.IsNil)
300
301 rm := []RootMapping{
302 {
303 From: "static",
304 To: "da",
305 },
306 {
307 From: "static/b",
308 To: "db",
309 },
310 {
311 From: "static/b/c",
312 To: "dc",
313 },
314 {
315 From: "/static/e/",
316 To: "de",
317 },
318 }
319
320 rfs, err := NewRootMappingFs(fs, rm...)
321 c.Assert(err, qt.IsNil)
322
323 checkDirnames := func(name string, expect []string) {
324 c.Helper()
325 name = filepath.FromSlash(name)
326 f, err := rfs.Open(name)
327 c.Assert(err, qt.IsNil)
328 defer f.Close()
329 names, err := f.Readdirnames(-1)
330 c.Assert(err, qt.IsNil)
331 c.Assert(names, qt.DeepEquals, expect, qt.Commentf(fmt.Sprintf("%#v", names)))
332 }
333
334 checkDirnames("static", []string{"a.txt", "b", "e"})
335 checkDirnames("static/b", []string{"b.txt", "c"})
336 checkDirnames("static/b/c", []string{"c.txt"})
337
338 fi, err := rfs.Stat(filepath.FromSlash("static/b/b.txt"))
339 c.Assert(err, qt.IsNil)
340 c.Assert(fi.Name(), qt.Equals, "b.txt")
341 }
342
343 func TestRootMappingFsOs(t *testing.T) {
344 c := qt.New(t)
345 fs := NewBaseFileDecorator(afero.NewOsFs())
346
347 d, clean, err := htesting.CreateTempDir(fs, "hugo-root-mapping-os")
348 c.Assert(err, qt.IsNil)
349 defer clean()
350
351 testfile := "myfile.txt"
352 c.Assert(fs.Mkdir(filepath.Join(d, "f1t"), 0755), qt.IsNil)
353 c.Assert(fs.Mkdir(filepath.Join(d, "f2t"), 0755), qt.IsNil)
354 c.Assert(fs.Mkdir(filepath.Join(d, "f3t"), 0755), qt.IsNil)
355
356 // Deep structure
357 deepDir := filepath.Join(d, "d1", "d2", "d3", "d4", "d5")
358 c.Assert(fs.MkdirAll(deepDir, 0755), qt.IsNil)
359 for i := 1; i <= 3; i++ {
360 c.Assert(fs.MkdirAll(filepath.Join(d, "d1", "d2", "d3", "d4", fmt.Sprintf("d4-%d", i)), 0755), qt.IsNil)
361 c.Assert(afero.WriteFile(fs, filepath.Join(d, "d1", "d2", "d3", fmt.Sprintf("f-%d.txt", i)), []byte("some content"), 0755), qt.IsNil)
362 }
363
364 c.Assert(afero.WriteFile(fs, filepath.Join(d, "f2t", testfile), []byte("some content"), 0755), qt.IsNil)
365
366 // https://github.com/gohugoio/hugo/issues/6854
367 mystaticDir := filepath.Join(d, "mystatic", "a", "b", "c")
368 c.Assert(fs.MkdirAll(mystaticDir, 0755), qt.IsNil)
369 c.Assert(afero.WriteFile(fs, filepath.Join(mystaticDir, "ms-1.txt"), []byte("some content"), 0755), qt.IsNil)
370
371 rfs, err := newRootMappingFsFromFromTo(
372 d,
373 fs,
374 "static/bf1", filepath.Join(d, "f1t"),
375 "static/cf2", filepath.Join(d, "f2t"),
376 "static/af3", filepath.Join(d, "f3t"),
377 "static", filepath.Join(d, "mystatic"),
378 "static/a/b/c", filepath.Join(d, "d1", "d2", "d3"),
379 "layouts", filepath.Join(d, "d1"),
380 )
381
382 c.Assert(err, qt.IsNil)
383
384 fif, err := rfs.Stat(filepath.Join("static/cf2", testfile))
385 c.Assert(err, qt.IsNil)
386 c.Assert(fif.Name(), qt.Equals, "myfile.txt")
387
388 root, err := rfs.Open("static")
389 c.Assert(err, qt.IsNil)
390
391 dirnames, err := root.Readdirnames(-1)
392 c.Assert(err, qt.IsNil)
393 c.Assert(dirnames, qt.DeepEquals, []string{"a", "af3", "bf1", "cf2"}, qt.Commentf(fmt.Sprintf("%#v", dirnames)))
394
395 getDirnames := func(dirname string) []string {
396 dirname = filepath.FromSlash(dirname)
397 f, err := rfs.Open(dirname)
398 c.Assert(err, qt.IsNil)
399 defer f.Close()
400 dirnames, err := f.Readdirnames(-1)
401 c.Assert(err, qt.IsNil)
402 sort.Strings(dirnames)
403 return dirnames
404 }
405
406 c.Assert(getDirnames("static/a/b"), qt.DeepEquals, []string{"c"})
407 c.Assert(getDirnames("static/a/b/c"), qt.DeepEquals, []string{"d4", "f-1.txt", "f-2.txt", "f-3.txt", "ms-1.txt"})
408 c.Assert(getDirnames("static/a/b/c/d4"), qt.DeepEquals, []string{"d4-1", "d4-2", "d4-3", "d5"})
409
410 all, err := collectFilenames(rfs, "static", "static")
411 c.Assert(err, qt.IsNil)
412
413 c.Assert(all, qt.DeepEquals, []string{"a/b/c/f-1.txt", "a/b/c/f-2.txt", "a/b/c/f-3.txt", "a/b/c/ms-1.txt", "cf2/myfile.txt"})
414
415 fis, err := collectFileinfos(rfs, "static", "static")
416 c.Assert(err, qt.IsNil)
417
418 c.Assert(fis[9].Meta().PathFile(), qt.Equals, filepath.FromSlash("d1/d2/d3/f-1.txt"))
419
420 dirc := fis[3].Meta()
421
422 f, err := dirc.Open()
423 c.Assert(err, qt.IsNil)
424 defer f.Close()
425 fileInfos, err := f.Readdir(-1)
426 c.Assert(err, qt.IsNil)
427 sortFileInfos(fileInfos)
428 i := 0
429 for _, fi := range fileInfos {
430 if fi.IsDir() || fi.Name() == "ms-1.txt" {
431 continue
432 }
433 i++
434 meta := fi.(FileMetaInfo).Meta()
435 c.Assert(meta.Filename, qt.Equals, filepath.Join(d, fmt.Sprintf("/d1/d2/d3/f-%d.txt", i)))
436 c.Assert(meta.PathFile(), qt.Equals, filepath.FromSlash(fmt.Sprintf("d1/d2/d3/f-%d.txt", i)))
437 }
438
439 _, err = rfs.Stat(filepath.FromSlash("layouts/d2/d3/f-1.txt"))
440 c.Assert(err, qt.IsNil)
441 _, err = rfs.Stat(filepath.FromSlash("layouts/d2/d3"))
442 c.Assert(err, qt.IsNil)
443 }
444
445 func TestRootMappingFsOsBase(t *testing.T) {
446 c := qt.New(t)
447 fs := NewBaseFileDecorator(afero.NewOsFs())
448
449 d, clean, err := htesting.CreateTempDir(fs, "hugo-root-mapping-os-base")
450 c.Assert(err, qt.IsNil)
451 defer clean()
452
453 // Deep structure
454 deepDir := filepath.Join(d, "d1", "d2", "d3", "d4", "d5")
455 c.Assert(fs.MkdirAll(deepDir, 0755), qt.IsNil)
456 for i := 1; i <= 3; i++ {
457 c.Assert(fs.MkdirAll(filepath.Join(d, "d1", "d2", "d3", "d4", fmt.Sprintf("d4-%d", i)), 0755), qt.IsNil)
458 c.Assert(afero.WriteFile(fs, filepath.Join(d, "d1", "d2", "d3", fmt.Sprintf("f-%d.txt", i)), []byte("some content"), 0755), qt.IsNil)
459 }
460
461 mystaticDir := filepath.Join(d, "mystatic", "a", "b", "c")
462 c.Assert(fs.MkdirAll(mystaticDir, 0755), qt.IsNil)
463 c.Assert(afero.WriteFile(fs, filepath.Join(mystaticDir, "ms-1.txt"), []byte("some content"), 0755), qt.IsNil)
464
465 bfs := afero.NewBasePathFs(fs, d)
466
467 rfs, err := newRootMappingFsFromFromTo(
468 "",
469 bfs,
470 "static", "mystatic",
471 "static/a/b/c", filepath.Join("d1", "d2", "d3"),
472 )
473
474 getDirnames := func(dirname string) []string {
475 dirname = filepath.FromSlash(dirname)
476 f, err := rfs.Open(dirname)
477 c.Assert(err, qt.IsNil)
478 defer f.Close()
479 dirnames, err := f.Readdirnames(-1)
480 c.Assert(err, qt.IsNil)
481 sort.Strings(dirnames)
482 return dirnames
483 }
484
485 c.Assert(getDirnames("static/a/b/c"), qt.DeepEquals, []string{"d4", "f-1.txt", "f-2.txt", "f-3.txt", "ms-1.txt"})
486 }
487
488 func TestRootMappingFileFilter(t *testing.T) {
489 c := qt.New(t)
490 fs := NewBaseFileDecorator(afero.NewMemMapFs())
491
492 for _, lang := range []string{"no", "en", "fr"} {
493 for i := 1; i <= 3; i++ {
494 c.Assert(afero.WriteFile(fs, filepath.Join(lang, fmt.Sprintf("my%s%d.txt", lang, i)), []byte("some text file for"+lang), 0755), qt.IsNil)
495 }
496 }
497
498 for _, lang := range []string{"no", "en", "fr"} {
499 for i := 1; i <= 3; i++ {
500 c.Assert(afero.WriteFile(fs, filepath.Join(lang, "sub", fmt.Sprintf("mysub%s%d.txt", lang, i)), []byte("some text file for"+lang), 0755), qt.IsNil)
501 }
502 }
503
504 rm := []RootMapping{
505 {
506 From: "content",
507 To: "no",
508 Meta: &FileMeta{Lang: "no", InclusionFilter: glob.MustNewFilenameFilter(nil, []string{"**.txt"})},
509 },
510 {
511 From: "content",
512 To: "en",
513 Meta: &FileMeta{Lang: "en"},
514 },
515 {
516 From: "content",
517 To: "fr",
518 Meta: &FileMeta{Lang: "fr", InclusionFilter: glob.MustNewFilenameFilter(nil, []string{"**.txt"})},
519 },
520 }
521
522 rfs, err := NewRootMappingFs(fs, rm...)
523 c.Assert(err, qt.IsNil)
524
525 assertExists := func(filename string, shouldExist bool) {
526 c.Helper()
527 filename = filepath.Clean(filename)
528 _, err1 := rfs.Stat(filename)
529 f, err2 := rfs.Open(filename)
530 if shouldExist {
531 c.Assert(err1, qt.IsNil)
532 c.Assert(err2, qt.IsNil)
533 c.Assert(f.Close(), qt.IsNil)
534 } else {
535 c.Assert(err1, qt.Not(qt.IsNil))
536 c.Assert(err2, qt.Not(qt.IsNil))
537 }
538 }
539
540 assertExists("content/myno1.txt", false)
541 assertExists("content/myen1.txt", true)
542 assertExists("content/myfr1.txt", false)
543
544 dirEntriesSub, err := afero.ReadDir(rfs, filepath.Join("content", "sub"))
545 c.Assert(err, qt.IsNil)
546 c.Assert(len(dirEntriesSub), qt.Equals, 3)
547
548 dirEntries, err := afero.ReadDir(rfs, "content")
549
550 c.Assert(err, qt.IsNil)
551 c.Assert(len(dirEntries), qt.Equals, 4)
552
553 }