diff --git a/convert.go b/convert.go index 8489f62..bcccbcc 100644 --- a/convert.go +++ b/convert.go @@ -28,9 +28,10 @@ func Translate(c *Config) error { } var knownFuncs = make(map[string]int) + var visitedPaths = make(map[string]bool) // Locate all the assets. for _, input := range c.Input { - err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore, knownFuncs) + err = findFiles(input.Path, c.Prefix, input.Recursive, &toc, c.Ignore, knownFuncs, visitedPaths) if err != nil { return err } @@ -96,7 +97,7 @@ func (v ByName) Less(i, j int) bool { return v[i].Name() < v[j].Name() } // findFiles recursively finds all the file paths in the given directory tree. // They are added to the given map as keys. Values will be safe function names // for each file, which will be used when generating the output code. -func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp, knownFuncs map[string]int) error { +func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regexp.Regexp, knownFuncs map[string]int, visitedPaths map[string]bool) error { if len(prefix) > 0 { dir, _ = filepath.Abs(dir) prefix, _ = filepath.Abs(prefix) @@ -114,6 +115,7 @@ func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regex dir = "" list = []os.FileInfo{fi} } else { + visitedPaths[dir] = true fd, err := os.Open(dir) if err != nil { return err @@ -148,7 +150,23 @@ func findFiles(dir, prefix string, recursive bool, toc *[]Asset, ignore []*regex if file.IsDir() { if recursive { - findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs) + visitedPaths[asset.Path] = true + findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) + } + continue + } else if file.Mode()&os.ModeSymlink == os.ModeSymlink { + var linkPath string + if linkPath, err = os.Readlink(asset.Path); err != nil { + return err + } + if !filepath.IsAbs(linkPath) { + if linkPath, err = filepath.Abs(dir + "/" + linkPath); err != nil { + return err + } + } + if _, ok := visitedPaths[linkPath]; !ok { + visitedPaths[linkPath] = true + findFiles(asset.Path, prefix, recursive, toc, ignore, knownFuncs, visitedPaths) } continue } diff --git a/convert_test.go b/convert_test.go index 4bfa9db..5908adc 100644 --- a/convert_test.go +++ b/convert_test.go @@ -2,6 +2,7 @@ package bindata import ( "regexp" + "strings" "testing" ) @@ -17,7 +18,8 @@ func TestSafeFunctionName(t *testing.T) { func TestFindFiles(t *testing.T) { var toc []Asset var knownFuncs = make(map[string]int) - err := findFiles("testdata/dupname", "testdata/dupname", true, &toc, []*regexp.Regexp{}, knownFuncs) + var visitedPaths = make(map[string]bool) + err := findFiles("testdata/dupname", "testdata/dupname", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) if err != nil { t.Errorf("expected to be no error: %+v", err) } @@ -25,3 +27,63 @@ func TestFindFiles(t *testing.T) { t.Errorf("name collision") } } + +func TestFindFilesWithSymlinks(t *testing.T) { + var tocSrc []Asset + var tocTarget []Asset + + var knownFuncs = make(map[string]int) + var visitedPaths = make(map[string]bool) + err := findFiles("testdata/symlinkSrc", "testdata/symlinkSrc", true, &tocSrc, []*regexp.Regexp{}, knownFuncs, visitedPaths) + if err != nil { + t.Errorf("expected to be no error: %+v", err) + } + + knownFuncs = make(map[string]int) + visitedPaths = make(map[string]bool) + err = findFiles("testdata/symlinkParent", "testdata/symlinkParent", true, &tocTarget, []*regexp.Regexp{}, knownFuncs, visitedPaths) + if err != nil { + t.Errorf("expected to be no error: %+v", err) + } + + if len(tocSrc) != len(tocTarget) { + t.Errorf("Symlink source and target should have the same number of assets. Expected %d got %d", len(tocTarget), len(tocSrc)) + } else { + for i, _ := range tocSrc { + targetFunc := strings.TrimPrefix(tocTarget[i].Func, "symlinktarget_") + if tocSrc[i].Func != targetFunc { + t.Errorf("Symlink source and target produced different function lists. Expected %s to be %s", targetFunc, tocSrc[i].Func) + } + } + } +} + +func TestFindFilesWithRecursiveSymlinks(t *testing.T) { + var toc []Asset + + var knownFuncs = make(map[string]int) + var visitedPaths = make(map[string]bool) + err := findFiles("testdata/symlinkRecursiveParent", "testdata/symlinkRecursiveParent", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) + if err != nil { + t.Errorf("expected to be no error: %+v", err) + } + + if len(toc) != 1 { + t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) + } +} + +func TestFindFilesWithSymlinkedFile(t *testing.T) { + var toc []Asset + + var knownFuncs = make(map[string]int) + var visitedPaths = make(map[string]bool) + err := findFiles("testdata/symlinkFile", "testdata/symlinkFile", true, &toc, []*regexp.Regexp{}, knownFuncs, visitedPaths) + if err != nil { + t.Errorf("expected to be no error: %+v", err) + } + + if len(toc) != 1 { + t.Errorf("Only one asset should have been found. Got %d: %v", len(toc), toc) + } +} diff --git a/testdata/symlinkFile/file1 b/testdata/symlinkFile/file1 new file mode 120000 index 0000000..6e09272 --- /dev/null +++ b/testdata/symlinkFile/file1 @@ -0,0 +1 @@ +../symlinkSrc/file1 \ No newline at end of file diff --git a/testdata/symlinkParent/symlinkTarget b/testdata/symlinkParent/symlinkTarget new file mode 120000 index 0000000..ccb1f73 --- /dev/null +++ b/testdata/symlinkParent/symlinkTarget @@ -0,0 +1 @@ +../symlinkSrc/ \ No newline at end of file diff --git a/testdata/symlinkRecursiveParent/file1 b/testdata/symlinkRecursiveParent/file1 new file mode 100644 index 0000000..91ea38d --- /dev/null +++ b/testdata/symlinkRecursiveParent/file1 @@ -0,0 +1 @@ +// test file 1 diff --git a/testdata/symlinkRecursiveParent/symlinkTarget b/testdata/symlinkRecursiveParent/symlinkTarget new file mode 120000 index 0000000..2ee9371 --- /dev/null +++ b/testdata/symlinkRecursiveParent/symlinkTarget @@ -0,0 +1 @@ +../symlinkRecursiveParent/ \ No newline at end of file diff --git a/testdata/symlinkSrc/file1 b/testdata/symlinkSrc/file1 new file mode 100644 index 0000000..5161fce --- /dev/null +++ b/testdata/symlinkSrc/file1 @@ -0,0 +1 @@ +// symlink file 1 diff --git a/testdata/symlinkSrc/file2 b/testdata/symlinkSrc/file2 new file mode 100644 index 0000000..dfa589a --- /dev/null +++ b/testdata/symlinkSrc/file2 @@ -0,0 +1 @@ +// symlink file 2 diff --git a/testdata/symlinkSrc/file3 b/testdata/symlinkSrc/file3 new file mode 100644 index 0000000..9096fe8 --- /dev/null +++ b/testdata/symlinkSrc/file3 @@ -0,0 +1 @@ +// symlink file 3 diff --git a/testdata/symlinkSrc/file4 b/testdata/symlinkSrc/file4 new file mode 100644 index 0000000..49e0302 --- /dev/null +++ b/testdata/symlinkSrc/file4 @@ -0,0 +1 @@ +// symlink file 4