From 86f74558f0bd634b8fd13a11c3f841f6ded3d743 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Wed, 25 Jan 2017 15:45:46 +0900 Subject: [PATCH 01/15] Read the destination of named symbolic link FileInfo.IsDir() returns false if it is symlink. But package is sometime defined under symlink. So should follow the symlink. --- analysis.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/analysis.go b/analysis.go index 872456f..8b52a77 100644 --- a/analysis.go +++ b/analysis.go @@ -84,6 +84,19 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { if err != nil && err != filepath.SkipDir { return err } + + // Rewrite FileInfo if file is symlink + if fi.Mode()&os.ModeSymlink != 0 { + dst, err := os.Readlink(filepath.Join(fileRoot, fi.Name())) + if err != nil { + return err + } + fi, err = os.Stat(filepath.Join(fileRoot, dst)) + if err != nil { + return err + } + } + if !fi.IsDir() { return nil } From 60db13503b66ea3ebee4b03485a7f52ac7de95fc Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 14:35:00 +0900 Subject: [PATCH 02/15] Accept only if it is not absolute path or links to an outside of the root. --- _testdata/src/gosimple | 1 + _testdata/src/symlinks/gopkg | 1 + _testdata/src/symlinks/pkg/gopkg.go | 1 + _testdata/src/symlinks/symlinks.go | 6 ++++ analysis.go | 32 +++++++++++++++++--- analysis_test.go | 45 +++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 4 deletions(-) create mode 120000 _testdata/src/gosimple create mode 120000 _testdata/src/symlinks/gopkg create mode 100644 _testdata/src/symlinks/pkg/gopkg.go create mode 100644 _testdata/src/symlinks/symlinks.go diff --git a/_testdata/src/gosimple b/_testdata/src/gosimple new file mode 120000 index 0000000..8fd3246 --- /dev/null +++ b/_testdata/src/gosimple @@ -0,0 +1 @@ +simple \ No newline at end of file diff --git a/_testdata/src/symlinks/gopkg b/_testdata/src/symlinks/gopkg new file mode 120000 index 0000000..0c6117d --- /dev/null +++ b/_testdata/src/symlinks/gopkg @@ -0,0 +1 @@ +pkg \ No newline at end of file diff --git a/_testdata/src/symlinks/pkg/gopkg.go b/_testdata/src/symlinks/pkg/gopkg.go new file mode 100644 index 0000000..61db224 --- /dev/null +++ b/_testdata/src/symlinks/pkg/gopkg.go @@ -0,0 +1 @@ +package gopkg diff --git a/_testdata/src/symlinks/symlinks.go b/_testdata/src/symlinks/symlinks.go new file mode 100644 index 0000000..65ede6b --- /dev/null +++ b/_testdata/src/symlinks/symlinks.go @@ -0,0 +1,6 @@ +package symlinks + +import ( + _ "github.com/sdboyer/gps" + _ "symlinks/gopkg" +) diff --git a/analysis.go b/analysis.go index 8b52a77..724481b 100644 --- a/analysis.go +++ b/analysis.go @@ -85,16 +85,37 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { return err } - // Rewrite FileInfo if file is symlink - if fi.Mode()&os.ModeSymlink != 0 { - dst, err := os.Readlink(filepath.Join(fileRoot, fi.Name())) + // Read the destination of named symbolic link + // rules: + // 1. All absolute symlinks are disqualified; if one is encountered, it should be skipped. + // 2. Relative symlinks pointing to somewhere outside of the root (via ..) should also be skipped. + if !fi.IsDir() && fi.Mode()&os.ModeSymlink != 0 { + n := fi.Name() + if strings.HasPrefix(n, string(filepath.Separator)) { + return nil + } + dst, err := os.Readlink(wp) if err != nil { return err } - fi, err = os.Stat(filepath.Join(fileRoot, dst)) + // 1. + if strings.HasPrefix(dst, string(filepath.Separator)) { + return nil + } + d, _ := filepath.Split(wp) + rp, err := filepath.Abs(filepath.Join(d, dst)) if err != nil { return err } + // 2. + if !strings.HasPrefix(rp, fileRoot) { + return nil + } + rfi, err := os.Lstat(rp) + if err != nil { + return nil + } + fi = rfi } if !fi.IsDir() { @@ -120,6 +141,9 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { // paths are normalized to Unix separators, as import paths are expected // to be. ip := filepath.ToSlash(filepath.Join(importRoot, strings.TrimPrefix(wp, fileRoot))) + if ip == "" { + return filepath.SkipDir + } // Find all the imports, across all os/arch combos //p, err := fullPackageInDir(wp) diff --git a/analysis_test.go b/analysis_test.go index 4182ca4..9f9ba62 100644 --- a/analysis_test.go +++ b/analysis_test.go @@ -878,6 +878,51 @@ func TestListPackages(t *testing.T) { }, }, }, + // has symbolic link + "follow symlink": { + fileRoot: j("gosimple"), + importRoot: "gosimple", + out: PackageTree{ + ImportRoot: "gosimple", + Packages: map[string]PackageOrErr{}, + }, + }, + "follow symlinks inside of package": { + fileRoot: j("symlinks"), + importRoot: "symlinks", + out: PackageTree{ + ImportRoot: "symlinks", + Packages: map[string]PackageOrErr{ + "symlinks/gopkg": { + P: Package{ + ImportPath: "symlinks/gopkg", + CommentPath: "", + Name: "gopkg", + Imports: []string{}, + }, + }, + "symlinks/pkg": { + P: Package{ + ImportPath: "symlinks/pkg", + CommentPath: "", + Name: "gopkg", + Imports: []string{}, + }, + }, + "symlinks": { + P: Package{ + ImportPath: "symlinks", + CommentPath: "", + Name: "symlinks", + Imports: []string{ + "github.com/sdboyer/gps", + "symlinks/gopkg", + }, + }, + }, + }, + }, + }, } for name, fix := range table { From 02fe19e0eb91b84d63b0e8801a326f15a7a2581b Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 14:49:36 +0900 Subject: [PATCH 03/15] Remove blank import --- _testdata/src/symlinks/pkg/gopkg.go | 4 ++++ _testdata/src/symlinks/symlinks.go | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/_testdata/src/symlinks/pkg/gopkg.go b/_testdata/src/symlinks/pkg/gopkg.go index 61db224..9f6e647 100644 --- a/_testdata/src/symlinks/pkg/gopkg.go +++ b/_testdata/src/symlinks/pkg/gopkg.go @@ -1 +1,5 @@ package gopkg + +const ( + Foo = "foo" +) diff --git a/_testdata/src/symlinks/symlinks.go b/_testdata/src/symlinks/symlinks.go index 65ede6b..5629790 100644 --- a/_testdata/src/symlinks/symlinks.go +++ b/_testdata/src/symlinks/symlinks.go @@ -1,6 +1,11 @@ package symlinks import ( - _ "github.com/sdboyer/gps" - _ "symlinks/gopkg" + "github.com/sdboyer/gps" + "symlinks/gopkg" +) + +var ( + _ = gps.Solve + _ = gopkg.Foo ) From ff0894c955b6d01e920f4ab8956c30e997385f0d Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 14:54:25 +0900 Subject: [PATCH 04/15] Unexport const value --- _testdata/src/symlinks/pkg/gopkg.go | 2 +- _testdata/src/symlinks/symlinks.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/_testdata/src/symlinks/pkg/gopkg.go b/_testdata/src/symlinks/pkg/gopkg.go index 9f6e647..f275b83 100644 --- a/_testdata/src/symlinks/pkg/gopkg.go +++ b/_testdata/src/symlinks/pkg/gopkg.go @@ -1,5 +1,5 @@ package gopkg const ( - Foo = "foo" + foo = "foo" ) diff --git a/_testdata/src/symlinks/symlinks.go b/_testdata/src/symlinks/symlinks.go index 5629790..02ffc61 100644 --- a/_testdata/src/symlinks/symlinks.go +++ b/_testdata/src/symlinks/symlinks.go @@ -1,11 +1,12 @@ package symlinks import ( + gopkg "symlinks/gopkg" + "github.com/sdboyer/gps" - "symlinks/gopkg" ) var ( _ = gps.Solve - _ = gopkg.Foo + _ = gopkg.foo ) From bd7a18a4489ece8ab61abfc87ab4cb5e093b5cb6 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 15:00:29 +0900 Subject: [PATCH 05/15] Fix syntax error --- analysis_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/analysis_test.go b/analysis_test.go index 5667ceb..cf4e5eb 100644 --- a/analysis_test.go +++ b/analysis_test.go @@ -917,6 +917,12 @@ func TestListPackages(t *testing.T) { Imports: []string{ "github.com/sdboyer/gps", "symlinks/gopkg", + }, + }, + }, + }, + }, + }, "invalid buildtag like comments should be ignored": { fileRoot: j("buildtag"), importRoot: "buildtag", From 07ee8ad4fa154df1921bb9859c230c0f8bd67fe9 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 17:35:44 +0900 Subject: [PATCH 06/15] Refactor code of reading symlinks --- analysis.go | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/analysis.go b/analysis.go index 6caf03f..939ccfd 100644 --- a/analysis.go +++ b/analysis.go @@ -92,26 +92,16 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { if !fi.IsDir() && fi.Mode()&os.ModeSymlink != 0 { n := fi.Name() if strings.HasPrefix(n, string(filepath.Separator)) { - return nil - } - dst, err := os.Readlink(wp) - if err != nil { return err } - // 1. - if strings.HasPrefix(dst, string(filepath.Separator)) { - return nil - } - d, _ := filepath.Split(wp) - rp, err := filepath.Abs(filepath.Join(d, dst)) + dst, err := filepath.EvalSymlinks(wp) if err != nil { return err } - // 2. - if !strings.HasPrefix(rp, fileRoot) { + if !strings.HasPrefix(dst, fileRoot) { return nil } - rfi, err := os.Lstat(rp) + rfi, err := os.Lstat(dst) if err != nil { return nil } From 6e88f65bab1520ec77d06fb548830478f734a2a1 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 17:40:29 +0900 Subject: [PATCH 07/15] Remove unnecessary changes --- analysis.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/analysis.go b/analysis.go index 939ccfd..4d737a2 100644 --- a/analysis.go +++ b/analysis.go @@ -131,9 +131,6 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { // paths are normalized to Unix separators, as import paths are expected // to be. ip := filepath.ToSlash(filepath.Join(importRoot, strings.TrimPrefix(wp, fileRoot))) - if ip == "" { - return filepath.SkipDir - } // Find all the imports, across all os/arch combos //p, err := fullPackageInDir(wp) From 479c2294902d4e713e0582e2f17ebf9c0cc5212e Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 29 Jan 2017 17:57:20 +0900 Subject: [PATCH 08/15] Skip symlink test if it is run on windows --- analysis_test.go | 56 +++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/analysis_test.go b/analysis_test.go index cf4e5eb..bdd4324 100644 --- a/analysis_test.go +++ b/analysis_test.go @@ -8,6 +8,7 @@ import ( "os" "path/filepath" "reflect" + "runtime" "strings" "testing" ) @@ -878,16 +879,42 @@ func TestListPackages(t *testing.T) { }, }, }, - // has symbolic link - "follow symlink": { + "invalid buildtag like comments should be ignored": { + fileRoot: j("buildtag"), + importRoot: "buildtag", + out: PackageTree{ + ImportRoot: "buildtag", + Packages: map[string]PackageOrErr{ + "buildtag": { + P: Package{ + ImportPath: "buildtag", + CommentPath: "", + Name: "buildtag", + Imports: []string{ + "sort", + }, + }, + }, + }, + }, + }, + } + if runtime.GOOS != "windows" { + type t struct { + fileRoot string + importRoot string + out PackageTree + err error + } + table["follow_symlink"] = t{ fileRoot: j("gosimple"), importRoot: "gosimple", out: PackageTree{ ImportRoot: "gosimple", Packages: map[string]PackageOrErr{}, }, - }, - "follow symlinks inside of package": { + } + table["follow symlinks inside of package"] = t{ fileRoot: j("symlinks"), importRoot: "symlinks", out: PackageTree{ @@ -922,26 +949,7 @@ func TestListPackages(t *testing.T) { }, }, }, - }, - "invalid buildtag like comments should be ignored": { - fileRoot: j("buildtag"), - importRoot: "buildtag", - out: PackageTree{ - ImportRoot: "buildtag", - Packages: map[string]PackageOrErr{ - "buildtag": { - P: Package{ - ImportPath: "buildtag", - CommentPath: "", - Name: "buildtag", - Imports: []string{ - "sort", - }, - }, - }, - }, - }, - }, + } } for name, fix := range table { From 7c60dfb0c86255d361ee618f398be874ae8cd45e Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 5 Feb 2017 21:58:01 +0900 Subject: [PATCH 09/15] Use filepath.IsAbs instead of strings.HasPrefix --- analysis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis.go b/analysis.go index 4d737a2..54d0cf3 100644 --- a/analysis.go +++ b/analysis.go @@ -91,7 +91,7 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { // 2. Relative symlinks pointing to somewhere outside of the root (via ..) should also be skipped. if !fi.IsDir() && fi.Mode()&os.ModeSymlink != 0 { n := fi.Name() - if strings.HasPrefix(n, string(filepath.Separator)) { + if filepath.IsAbs(n) { return err } dst, err := filepath.EvalSymlinks(wp) From 14fc57e6819e35c6885530e191e44456a69dc1e5 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 5 Feb 2017 22:03:46 +0900 Subject: [PATCH 10/15] Read the link destination --- analysis.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/analysis.go b/analysis.go index 54d0cf3..478281a 100644 --- a/analysis.go +++ b/analysis.go @@ -90,11 +90,14 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { // 1. All absolute symlinks are disqualified; if one is encountered, it should be skipped. // 2. Relative symlinks pointing to somewhere outside of the root (via ..) should also be skipped. if !fi.IsDir() && fi.Mode()&os.ModeSymlink != 0 { - n := fi.Name() - if filepath.IsAbs(n) { + dst, err := os.Readlink(wp) + if err != nil { + return err + } + if filepath.IsAbs(dst) { return err } - dst, err := filepath.EvalSymlinks(wp) + dst, err = filepath.EvalSymlinks(wp) if err != nil { return err } From f8131086ef33262375aa0306548a0ce1f3c6278e Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 5 Feb 2017 22:10:08 +0900 Subject: [PATCH 11/15] Declare type `tc` before declaring `table` --- analysis_test.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/analysis_test.go b/analysis_test.go index bdd4324..c1163a2 100644 --- a/analysis_test.go +++ b/analysis_test.go @@ -232,12 +232,13 @@ func TestListPackages(t *testing.T) { return filepath.Join(srcdir, filepath.Join(s...)) } - table := map[string]struct { + type tc struct { fileRoot string importRoot string out PackageTree err error - }{ + } + table := map[string]tc{ "empty": { fileRoot: j("empty"), importRoot: "empty", @@ -900,13 +901,7 @@ func TestListPackages(t *testing.T) { }, } if runtime.GOOS != "windows" { - type t struct { - fileRoot string - importRoot string - out PackageTree - err error - } - table["follow_symlink"] = t{ + table["follow_symlink"] = tc{ fileRoot: j("gosimple"), importRoot: "gosimple", out: PackageTree{ @@ -914,7 +909,7 @@ func TestListPackages(t *testing.T) { Packages: map[string]PackageOrErr{}, }, } - table["follow symlinks inside of package"] = t{ + table["follow symlinks inside of package"] = tc{ fileRoot: j("symlinks"), importRoot: "symlinks", out: PackageTree{ From c72a3ac5724ca8b8c8e47c8d7455cb8cd59d6112 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 12 Feb 2017 22:43:53 +0900 Subject: [PATCH 12/15] Skip if symlink is broken --- _testdata/src/symlinks/broken | 1 + analysis.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 120000 _testdata/src/symlinks/broken diff --git a/_testdata/src/symlinks/broken b/_testdata/src/symlinks/broken new file mode 120000 index 0000000..d5bcc42 --- /dev/null +++ b/_testdata/src/symlinks/broken @@ -0,0 +1 @@ +nodest \ No newline at end of file diff --git a/analysis.go b/analysis.go index 478281a..0383a6d 100644 --- a/analysis.go +++ b/analysis.go @@ -99,7 +99,7 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { } dst, err = filepath.EvalSymlinks(wp) if err != nil { - return err + return nil } if !strings.HasPrefix(dst, fileRoot) { return nil From 23332881b92120ed3c21dd28aee5ebb134d1d03f Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 12 Feb 2017 23:11:25 +0900 Subject: [PATCH 13/15] Add non-sibling symlinking cases --- _testdata/src/symlinks/foo/bar | 1 + _testdata/src/symlinks/foo/foo.go | 7 +++++++ _testdata/src/symlinks/foobar | 1 + _testdata/src/symlinks/pkg/bar | 1 + analysis_test.go | 10 ++++++++++ 5 files changed, 20 insertions(+) create mode 120000 _testdata/src/symlinks/foo/bar create mode 100644 _testdata/src/symlinks/foo/foo.go create mode 120000 _testdata/src/symlinks/foobar create mode 120000 _testdata/src/symlinks/pkg/bar diff --git a/_testdata/src/symlinks/foo/bar b/_testdata/src/symlinks/foo/bar new file mode 120000 index 0000000..b49d704 --- /dev/null +++ b/_testdata/src/symlinks/foo/bar @@ -0,0 +1 @@ +../../pkg \ No newline at end of file diff --git a/_testdata/src/symlinks/foo/foo.go b/_testdata/src/symlinks/foo/foo.go new file mode 100644 index 0000000..bebff84 --- /dev/null +++ b/_testdata/src/symlinks/foo/foo.go @@ -0,0 +1,7 @@ +package foo + +import "github.com/sdboyer/gps" + +var ( + _ = gps.Solve +) diff --git a/_testdata/src/symlinks/foobar b/_testdata/src/symlinks/foobar new file mode 120000 index 0000000..337ca42 --- /dev/null +++ b/_testdata/src/symlinks/foobar @@ -0,0 +1 @@ +foo/bar \ No newline at end of file diff --git a/_testdata/src/symlinks/pkg/bar b/_testdata/src/symlinks/pkg/bar new file mode 120000 index 0000000..ba0e162 --- /dev/null +++ b/_testdata/src/symlinks/pkg/bar @@ -0,0 +1 @@ +bar \ No newline at end of file diff --git a/analysis_test.go b/analysis_test.go index c1163a2..572416c 100644 --- a/analysis_test.go +++ b/analysis_test.go @@ -942,6 +942,16 @@ func TestListPackages(t *testing.T) { }, }, }, + "symlinks/foo": { + P: Package{ + ImportPath: "symlinks/foo", + CommentPath: "", + Name: "foo", + Imports: []string{ + "github.com/sdboyer/gps", + }, + }, + }, }, }, } From 5f6939fbfa35dfa0832df38f3929f6816892faec Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sun, 12 Feb 2017 23:52:28 +0900 Subject: [PATCH 14/15] Ensure the existence of the gopath --- circle.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/circle.yml b/circle.yml index 8be1609..84e08b3 100644 --- a/circle.yml +++ b/circle.yml @@ -8,6 +8,7 @@ dependencies: - wget https://github.com/Masterminds/glide/releases/download/0.10.1/glide-0.10.1-linux-amd64.tar.gz - tar -vxz -C $HOME/bin --strip=1 -f glide-0.10.1-linux-amd64.tar.gz override: + - mkdir -p $HOME/.go_workspace/src - glide --home $HOME/.glide -y glide.yaml install --cache - mkdir -p $RD - rsync -azC --delete ./ $RD From 425722b6edff61fa71b059bb430158406e3733a9 Mon Sep 17 00:00:00 2001 From: ReSTARTR Date: Sat, 4 Mar 2017 11:12:18 +0900 Subject: [PATCH 15/15] Promote into readSymlink function --- analysis.go | 56 ++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/analysis.go b/analysis.go index 0383a6d..a8d5b4f 100644 --- a/analysis.go +++ b/analysis.go @@ -80,38 +80,16 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { if err != nil { return PackageTree{}, err } + err = filepath.Walk(fileRoot, func(wp string, fi os.FileInfo, err error) error { if err != nil && err != filepath.SkipDir { return err } // Read the destination of named symbolic link - // rules: - // 1. All absolute symlinks are disqualified; if one is encountered, it should be skipped. - // 2. Relative symlinks pointing to somewhere outside of the root (via ..) should also be skipped. - if !fi.IsDir() && fi.Mode()&os.ModeSymlink != 0 { - dst, err := os.Readlink(wp) - if err != nil { - return err - } - if filepath.IsAbs(dst) { - return err - } - dst, err = filepath.EvalSymlinks(wp) - if err != nil { - return nil - } - if !strings.HasPrefix(dst, fileRoot) { - return nil - } - rfi, err := os.Lstat(dst) - if err != nil { - return nil - } - fi = rfi - } - - if !fi.IsDir() { + if fi, err := readSymlink(wp, fileRoot, fi); err != nil { + return nil + } else if !fi.IsDir() { return nil } @@ -209,6 +187,32 @@ func ListPackages(fileRoot, importRoot string) (PackageTree, error) { return ptree, nil } +func readSymlink(wp, fileRoot string, fi os.FileInfo) (os.FileInfo, error) { + // read only symlink dir + if fi.IsDir() || fi.Mode()&os.ModeSymlink == 0 { + return fi, nil + } + + dst, err := os.Readlink(wp) + if err != nil { + return fi, err + } + + // All absolute symlinks are disqualified; if one is encountered, it should be skipped. + if filepath.IsAbs(dst) { + return fi, nil + } + + // Relative symlinks pointing to somewhere outside of the root (via ..) should also be skipped. + dst, err = filepath.EvalSymlinks(wp) + if err != nil { + return fi, nil + } else if !strings.HasPrefix(dst, fileRoot) { + return fi, nil + } + return os.Lstat(dst) +} + // fillPackage full of info. Assumes p.Dir is set at a minimum func fillPackage(p *build.Package) error { var buildPrefix = "// +build "