From db82cc8424f80d23fa4f1cfd8a8b2d4689a1dd7a Mon Sep 17 00:00:00 2001 From: Keegan Carruthers-Smith Date: Thu, 23 Jul 2020 11:00:26 +0200 Subject: [PATCH] servegit: list flag to list found repositories This is useful functionality when setting up serve-git to understand what it does. --- cmd/src/servegit.go | 19 ++++++++- internal/servegit/serve.go | 68 ++++++++++++++++----------------- internal/servegit/serve_test.go | 7 +++- 3 files changed, 56 insertions(+), 38 deletions(-) diff --git a/cmd/src/servegit.go b/cmd/src/servegit.go index 4fd3caa672..794cb3180e 100644 --- a/cmd/src/servegit.go +++ b/cmd/src/servegit.go @@ -17,13 +17,17 @@ func init() { fmt.Fprintf(flag.CommandLine.Output(), `'src serve-git' serves your local git repositories over HTTP for Sourcegraph to pull. USAGE - src [-v] serve-git [-addr :3434] [path/to/dir] + src [-v] serve-git [-list] [-addr :3434] [path/to/dir] By default 'src serve-git' will recursively serve your current directory on the address ':3434'. + +'src serve-git -list' will not start up the server. Instead it will write to stdout a list of +repository names it would serve. `) } var ( addrFlag = flagSet.String("addr", ":3434", "Address on which to serve (end with : for unused port)") + listFlag = flagSet.Bool("list", false, "list found repository names") ) handler := func(args []string) error { @@ -58,11 +62,24 @@ By default 'src serve-git' will recursively serve your current directory on the Info: log.New(os.Stderr, "serve-git: ", log.LstdFlags), Debug: dbug, } + + if *listFlag { + repos, err := s.Repos() + if err != nil { + return err + } + for _, r := range repos { + fmt.Println(r.Name) + } + return nil + } + return s.Start() } // Register the command. commands = append(commands, &command{ + aliases: []string{"servegit"}, flagSet: flagSet, handler: handler, usageFunc: usageFunc, diff --git a/internal/servegit/serve.go b/internal/servegit/serve.go index bc38334ff0..3590bb17a0 100644 --- a/internal/servegit/serve.go +++ b/internal/servegit/serve.go @@ -9,7 +9,7 @@ import ( "net/http" "os" "os/exec" - "path" + pathpkg "path" "path/filepath" "strings" @@ -79,32 +79,10 @@ func (s *Serve) handler() http.Handler { }) mux.HandleFunc("/v1/list-repos", func(w http.ResponseWriter, r *http.Request) { - var repos []Repo - var reposRootIsRepo bool - for _, name := range s.repos() { - if name == "." { - reposRootIsRepo = true - } - - repos = append(repos, Repo{ - Name: name, - URI: path.Join("/repos", name), - }) - } - - if reposRootIsRepo { - // 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) - if err != nil { - http.Error(w, "failed to get the absolute path of reposRoot: "+err.Error(), http.StatusInternalServerError) - return - } - rootName := filepath.Base(abs) - for i := range repos { - repos[i].Name = path.Join(rootName, repos[i].Name) - } + repos, err := s.Repos() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } resp := struct { @@ -142,10 +120,10 @@ func (s *Serve) handler() http.Handler { }) } -// repos returns a slice of all the git directories it finds. The paths are -// relative to root. -func (s *Serve) repos() []string { - var gitDirs []string +// Repos returns a slice of all the git repositories it finds. +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 { if fileErr != nil { @@ -178,7 +156,13 @@ func (s *Serve) repos() []string { // subpath). So Rel should always work. s.Info.Fatalf("filepath.Walk returned %s which is not relative to %s: %v", path, s.Root, err) } - gitDirs = append(gitDirs, filepath.ToSlash(subpath)) + + name := filepath.ToSlash(subpath) + reposRootIsRepo = reposRootIsRepo || name == "." + repos = append(repos, Repo{ + Name: name, + URI: pathpkg.Join("/repos", name), + }) // Check whether a repository is a bare repository or not. // @@ -197,11 +181,25 @@ func (s *Serve) repos() []string { }) if err != nil { - // Our WalkFunc doesn't return any errors, so neither should filepath.Walk - panic(err) + return nil, err + } + + if !reposRootIsRepo { + return repos, nil + } + + // 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) + if err != nil { + return nil, fmt.Errorf("failed to get the absolute path of reposRoot: %w", err) + } + rootName := filepath.Base(abs) + for i := range repos { + repos[i].Name = pathpkg.Join(rootName, repos[i].Name) } - return gitDirs + return repos, nil } func explainAddr(addr string) string { diff --git a/internal/servegit/serve_test.go b/internal/servegit/serve_test.go index 1ec0328600..ab7a169beb 100644 --- a/internal/servegit/serve_test.go +++ b/internal/servegit/serve_test.go @@ -175,11 +175,14 @@ func TestIgnoreGitSubmodules(t *testing.T) { t.Fatal(err) } - repos := (&Serve{ + repos, err := (&Serve{ Info: testLogger(t), Debug: discardLogger, Root: root, - }).repos() + }).Repos() + if err != nil { + t.Fatal(err) + } if len(repos) != 0 { t.Fatalf("expected no repos, got %v", repos) }