diff --git a/internal/servegit/serve.go b/internal/servegit/serve.go index f5a6597bc7..ea8d022dcf 100644 --- a/internal/servegit/serve.go +++ b/internal/servegit/serve.go @@ -125,7 +125,13 @@ func (s *Serve) Repos() ([]Repo, error) { var repos []Repo var reposRootIsRepo bool - err := filepath.Walk(s.Root, func(path string, fi os.FileInfo, fileErr error) error { + root, err := filepath.EvalSymlinks(s.Root) + if err != nil { + s.Info.Printf("WARN: ignoring error searching %s: %v", root, err) + return nil, nil + } + + err = filepath.Walk(root, func(path string, fi os.FileInfo, fileErr error) error { if fileErr != nil { s.Info.Printf("WARN: ignoring error searching %s: %v", path, fileErr) return nil @@ -150,11 +156,11 @@ func (s *Serve) Repos() ([]Repo, error) { return nil } - subpath, err := filepath.Rel(s.Root, path) + subpath, err := filepath.Rel(root, path) if err != nil { // According to WalkFunc docs, path is always filepath.Join(root, // subpath). So Rel should always work. - s.Info.Fatalf("filepath.Walk returned %s which is not relative to %s: %v", path, s.Root, err) + s.Info.Fatalf("filepath.Walk returned %s which is not relative to %s: %v", path, root, err) } name := filepath.ToSlash(subpath) @@ -190,7 +196,7 @@ func (s *Serve) Repos() ([]Repo, error) { // Update all names to be relative to the parent of reposRoot. This is to // give a better name than "." for repos root - abs, err := filepath.Abs(s.Root) + abs, err := filepath.Abs(root) if err != nil { return nil, fmt.Errorf("failed to get the absolute path of reposRoot: %w", err) } diff --git a/internal/servegit/serve_test.go b/internal/servegit/serve_test.go index ab7a169beb..ce1c2e063c 100644 --- a/internal/servegit/serve_test.go +++ b/internal/servegit/serve_test.go @@ -80,6 +80,39 @@ func TestReposHandler(t *testing.T) { } testReposHandler(t, h, want) }) + + // Ensure everything still works if root is a symlink + t.Run("rooted-"+tc.name, func(t *testing.T) { + root := gitInitRepos(t, tc.repos...) + + // This is the difference, we create a symlink for root + { + tmp, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { os.RemoveAll(tmp) }) + + symlink := filepath.Join(tmp, "symlink-root") + if err := os.Symlink(root, symlink); err != nil { + t.Fatal(err) + } + root = symlink + } + + h := (&Serve{ + Info: testLogger(t), + Debug: discardLogger, + Addr: testAddress, + Root: root, + }).handler() + + var want []Repo + for _, name := range tc.repos { + want = append(want, Repo{Name: name, URI: path.Join("/repos", name)}) + } + testReposHandler(t, h, want) + }) } }