diff --git a/cmd/lsif-go/main.go b/cmd/lsif-go/main.go index 4d6784a3..951d4e84 100644 --- a/cmd/lsif-go/main.go +++ b/cmd/lsif-go/main.go @@ -2,11 +2,13 @@ package main import ( + "errors" "fmt" "log" "os" "os/exec" "path/filepath" + "strings" "time" "github.com/alecthomas/kingpin" @@ -15,7 +17,7 @@ import ( "github.com/sourcegraph/lsif-go/protocol" ) -const version = "0.4.1" +const version = "0.5.0" const versionString = version + ", protocol version " + protocol.Version func init() { @@ -36,6 +38,7 @@ func realMain() error { outFile string moduleVersion string repositoryRoot string + moduleRoot string addContents bool ) @@ -47,6 +50,7 @@ func realMain() error { app.Flag("out", "The output file.").Short('o').Default("dump.lsif").StringVar(&outFile) app.Flag("moduleVersion", "Specifies the version of the module defined by this project.").PlaceHolder("version").StringVar(&moduleVersion) app.Flag("repositoryRoot", "Specifies the path of the current repository (inferred automatically via git).").PlaceHolder("root").StringVar(&repositoryRoot) + app.Flag("moduleRoot", "Specifies the module root directory relative to the repository").Default(".").StringVar(&moduleRoot) app.Flag("addContents", "Embed file contents into the dump.").Default("false").BoolVar(&addContents) _, err := app.Parse(os.Args[1:]) @@ -59,10 +63,10 @@ func realMain() error { if err != nil { return fmt.Errorf("get git root: %v", err) } - repositoryRoot = string(toplevel) + repositoryRoot = strings.TrimSpace(string(toplevel)) } - projectRoot, err := filepath.Abs(".") + projectRoot, err := filepath.Abs(moduleRoot) if err != nil { return fmt.Errorf("get abspath of project root: %v", err) } @@ -72,6 +76,16 @@ func realMain() error { return fmt.Errorf("get abspath of repository root: %v", err) } + // Sanity check: Ensure the module root is inside the repository. + if !strings.HasPrefix(projectRoot, repositoryRoot) { + return errors.New("module root is outside the repository") + } + + // Ensure all the dependencies of the specified module are cached. + if err := gomod.Download(projectRoot); err != nil { + return fmt.Errof("fetching dependencies: %v", err) + } + moduleName, dependencies, err := gomod.ListModules(projectRoot) if err != nil { return err @@ -96,6 +110,9 @@ func realMain() error { Args: os.Args[1:], } + // TODO(@creachadair): With cgo enabled, the indexer cannot handle packages + // that include assembly (.s) files. To index such a package you need to + // set CGO_ENABLED=0. Consider maybe doing this explicitly, always. indexer := index.NewIndexer( projectRoot, repositoryRoot, diff --git a/internal/gomod/module.go b/internal/gomod/module.go index fe5560d4..7a091d10 100644 --- a/internal/gomod/module.go +++ b/internal/gomod/module.go @@ -60,7 +60,7 @@ func ListModules(projectRoot string) (string, map[string]string, error) { return "", nil, nil } - out, err := run(projectRoot, "go", "list", "-m", "all") + out, err := run(projectRoot, "go", "list", "-mod=readonly", "-m", "all") if err != nil { return "", nil, fmt.Errorf("failed to list modules: %v", err) } @@ -81,6 +81,13 @@ func ListModules(projectRoot string) (string, map[string]string, error) { return lines[0], dependencies, nil } +// Download fetches all the dependencies of the module in projectRoot. +func Download(projectRoot string) error { + cmd := exec.Command("go", "mod", "download") + cmd.Dir = projectRoot + return cmd.Run() +} + // versionPattern matches the form vX.Y.Z.-yyyymmddhhmmss-abcdefabcdef var versionPattern = regexp.MustCompile(`^(.*)-(\d{14})-([a-f0-9]{12})$`)