Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Commit

Permalink
Add a flag to specify an alternate module root. (#51)
Browse files Browse the repository at this point in the history
Although it is common practice, not all Go repositories have the go.mod file at
the repo root. Add a --moduleRoot flag that allows the caller to specify a path
relative to the repository root, that should be used as the module root for the
purpose of indexing.

To handle vendored dependencies, we now use go list -mod=readonly.
To preserve the existing assumption that dependencies are fetched, do an
explicit go mod download before listing the module.
  • Loading branch information
M. J. Fromberger authored Mar 30, 2020
1 parent ad3507c commit b5af0ba
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 4 deletions.
23 changes: 20 additions & 3 deletions cmd/lsif-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
package main

import (
"errors"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
"time"

"github.com/alecthomas/kingpin"
Expand All @@ -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() {
Expand All @@ -36,6 +38,7 @@ func realMain() error {
outFile string
moduleVersion string
repositoryRoot string
moduleRoot string
addContents bool
)

Expand All @@ -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:])
Expand All @@ -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)
}
Expand All @@ -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
Expand All @@ -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,
Expand Down
9 changes: 8 additions & 1 deletion internal/gomod/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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})$`)

Expand Down

0 comments on commit b5af0ba

Please sign in to comment.