Skip to content

Commit 5df0445

Browse files
authored
codeintel: Update codeintel/upload package (#541)
1 parent c670e13 commit 5df0445

File tree

8 files changed

+502
-361
lines changed

8 files changed

+502
-361
lines changed

cmd/src/lsif_upload.go

Lines changed: 151 additions & 318 deletions
Large diffs are not rendered by default.

cmd/src/lsif_upload_flags.go

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"flag"
6+
"fmt"
7+
"os"
8+
"strings"
9+
10+
"github.com/sourcegraph/sourcegraph/lib/codeintel/upload"
11+
"github.com/sourcegraph/src-cli/internal/codeintel"
12+
)
13+
14+
var lsifUploadFlags struct {
15+
file string
16+
17+
// UploadRecordOptions
18+
repo string
19+
commit string
20+
root string
21+
indexer string
22+
associatedIndexID int
23+
24+
// SourcegraphInstanceOptions
25+
uploadRoute string
26+
gitHubToken string
27+
maxPayloadSizeMb int64
28+
29+
// Output and error behavior
30+
ignoreUploadFailures bool
31+
noProgress bool
32+
verbosity int
33+
json bool
34+
open bool
35+
}
36+
37+
var lsifUploadFlagSet = flag.NewFlagSet("upload", flag.ExitOnError)
38+
39+
func init() {
40+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.file, "file", "./dump.lsif", `The path to the LSIF dump file.`)
41+
42+
// UploadRecordOptions
43+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.repo, "repo", "", `The name of the repository (e.g. github.com/gorilla/mux). By default, derived from the origin remote.`)
44+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.commit, "commit", "", `The 40-character hash of the commit. Defaults to the currently checked-out commit.`)
45+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.root, "root", "", `The path in the repository that matches the LSIF projectRoot (e.g. cmd/project1). Defaults to the directory where the dump file is located.`)
46+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.indexer, "indexer", "", `The name of the indexer that generated the dump. This will override the 'toolInfo.name' field in the metadata vertex of the LSIF dump file. This must be supplied if the indexer does not set this field (in which case the upload will fail with an explicit message).`)
47+
lsifUploadFlagSet.IntVar(&lsifUploadFlags.associatedIndexID, "associated-index-id", -1, "ID of the associated index record for this upload. For internal use only.")
48+
49+
// SourcegraphInstanceOptions
50+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.uploadRoute, "upload-route", "/.api/lsif/upload", "The path of the upload route. For internal use only.")
51+
lsifUploadFlagSet.StringVar(&lsifUploadFlags.gitHubToken, "github-token", "", `A GitHub access token with 'public_repo' scope that Sourcegraph uses to verify you have access to the repository.`)
52+
lsifUploadFlagSet.Int64Var(&lsifUploadFlags.maxPayloadSizeMb, "max-payload-size", 100, `The maximum upload size (in megabytes). Indexes exceeding this limit will be uploaded over multiple HTTP requests.`)
53+
54+
// Output and error behavior
55+
lsifUploadFlagSet.BoolVar(&lsifUploadFlags.ignoreUploadFailures, "ignore-upload-failure", false, `Exit with status code zero on upload failure.`)
56+
lsifUploadFlagSet.BoolVar(&lsifUploadFlags.noProgress, "no-progress", false, `Do not display progress updates.`)
57+
lsifUploadFlagSet.IntVar(&lsifUploadFlags.verbosity, "trace", 0, "-trace=0 shows no logs; -trace=1 shows requests and response metadata; -trace=2 shows headers, -trace=3 shows response body")
58+
lsifUploadFlagSet.BoolVar(&lsifUploadFlags.json, "json", false, `Output relevant state in JSON on success.`)
59+
lsifUploadFlagSet.BoolVar(&lsifUploadFlags.open, "open", false, `Open the LSIF upload page in your browser.`)
60+
}
61+
62+
// parseAndValidateLSIFUploadFlags calls lsifUploadFlagSet.Parse, then infers values for
63+
// missing flags, normalizes supplied values, and validates the state of the lsifUploadFlags
64+
// object.
65+
//
66+
// On success, the global lsifUploadFlags object will be populated with valid values. An
67+
// error is returned on failure.
68+
func parseAndValidateLSIFUploadFlags(args []string) error {
69+
if err := lsifUploadFlagSet.Parse(args); err != nil {
70+
return err
71+
}
72+
73+
if inferenceErrors := inferMissingLSIFUploadFlags(); len(inferenceErrors) > 0 {
74+
return errorWithHint{
75+
err: inferenceErrors[0].err, hint: strings.Join([]string{
76+
fmt.Sprintf(
77+
"Unable to determine %s from environment. Check your working directory or supply -%s={value} explicitly",
78+
inferenceErrors[0].argument,
79+
inferenceErrors[0].argument,
80+
),
81+
}, "\n"),
82+
}
83+
}
84+
85+
if err := validateLSIFUploadFlags(); err != nil {
86+
return err
87+
}
88+
89+
return nil
90+
}
91+
92+
type argumentInferenceError struct {
93+
argument string
94+
err error
95+
}
96+
97+
// inferMissingLSIFUploadFlags updates the flags values which were not explicitly
98+
// supplied by the user with default values inferred from the current git state and
99+
// filesystem.
100+
//
101+
// Note: This function must not be called before lsifUploadFlagSet.Parse.
102+
func inferMissingLSIFUploadFlags() (inferErrors []argumentInferenceError) {
103+
if _, err := os.Stat(lsifUploadFlags.file); os.IsNotExist(err) {
104+
inferErrors = append(inferErrors, argumentInferenceError{"file", err})
105+
}
106+
107+
if err := inferUnsetFlag("repo", &lsifUploadFlags.repo, codeintel.InferRepo); err != nil {
108+
inferErrors = append(inferErrors, *err)
109+
}
110+
if err := inferUnsetFlag("commit", &lsifUploadFlags.commit, codeintel.InferCommit); err != nil {
111+
inferErrors = append(inferErrors, *err)
112+
}
113+
if err := inferUnsetFlag("root", &lsifUploadFlags.root, inferIndexRoot); err != nil {
114+
inferErrors = append(inferErrors, *err)
115+
}
116+
if err := inferUnsetFlag("indexer", &lsifUploadFlags.indexer, readIndexerName); err != nil {
117+
inferErrors = append(inferErrors, *err)
118+
}
119+
120+
return inferErrors
121+
}
122+
123+
// inferUnsetFlag conditionally updates the value of the given pointer with the
124+
// return value of the given function. If the flag with the given name was supplied
125+
// by the user, then this function no-ops. An argumentInferenceError is returned if
126+
// the given function returns an error.
127+
//
128+
// Note: This function must not be called before lsifUploadFlagSet.Parse.
129+
func inferUnsetFlag(name string, target *string, f func() (string, error)) *argumentInferenceError {
130+
if isFlagSet(lsifUploadFlagSet, name) {
131+
return nil
132+
}
133+
134+
value, err := f()
135+
if err != nil {
136+
return &argumentInferenceError{name, err}
137+
}
138+
139+
*target = value
140+
return nil
141+
}
142+
143+
// isFlagSet returns true if the flag with the given name was supplied by the user.
144+
// This lets us distinguish between zero-values (empty strings) and void values without
145+
// requiring pointers and adding a layer of indirection deeper in the program.
146+
func isFlagSet(fs *flag.FlagSet, name string) (found bool) {
147+
fs.Visit(func(f *flag.Flag) {
148+
if f.Name == name {
149+
found = true
150+
}
151+
})
152+
153+
return found
154+
}
155+
156+
// inferIndexRoot returns the root directory based on the configured index file path.
157+
//
158+
// Note: This function must not be called before lsifUploadFlagSet.Parse.
159+
func inferIndexRoot() (string, error) {
160+
return codeintel.InferRoot(lsifUploadFlags.file)
161+
}
162+
163+
// readIndexerName returns the indexer name read from the configured index file.
164+
//
165+
// Note: This function must not be called before lsifUploadFlagSet.Parse.
166+
func readIndexerName() (string, error) {
167+
file, err := os.Open(lsifUploadFlags.file)
168+
if err != nil {
169+
return "", err
170+
}
171+
defer file.Close()
172+
173+
return upload.ReadIndexerName(file)
174+
}
175+
176+
// validateLSIFUploadFlags returns an error if any of the parsed flag values are illegal.
177+
//
178+
// Note: This function must not be called before lsifUploadFlagSet.Parse.
179+
func validateLSIFUploadFlags() error {
180+
lsifUploadFlags.root = codeintel.SanitizeRoot(lsifUploadFlags.root)
181+
182+
if strings.HasPrefix(lsifUploadFlags.root, "..") {
183+
return errors.New("root must not be outside of repository")
184+
}
185+
186+
if lsifUploadFlags.maxPayloadSizeMb < 25 {
187+
return errors.New("max-payload-size must be at least 25 (MB)")
188+
}
189+
190+
return nil
191+
}

go.mod

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ go 1.13
55
require (
66
github.com/Masterminds/semver v1.5.0
77
github.com/dustin/go-humanize v1.0.0
8-
github.com/efritz/pentimento v0.0.0-20190429011147-ade47d831101
98
github.com/gobwas/glob v0.2.3
109
github.com/google/go-cmp v0.5.5
1110
github.com/hashicorp/go-multierror v1.1.1
1211
github.com/jig/teereadcloser v0.0.0-20181016160506-953720c48e05
13-
github.com/json-iterator/go v1.1.10
12+
github.com/json-iterator/go v1.1.11
1413
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
1514
github.com/mattn/go-isatty v0.0.12
1615
github.com/neelance/parallel v0.0.0-20160708114440-4de9ce63d14c
@@ -22,11 +21,11 @@ require (
2221
github.com/sourcegraph/batch-change-utils v0.0.0-20210309183117-206c057cc03e
2322
github.com/sourcegraph/go-diff v0.6.1
2423
github.com/sourcegraph/jsonx v0.0.0-20200629203448-1a936bd500cf
25-
github.com/sourcegraph/sourcegraph/lib v0.0.0-20210425142047-b8f4790093e5
24+
github.com/sourcegraph/sourcegraph/lib v0.0.0-20210520231824-520a2ae26af0
2625
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
2726
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
28-
golang.org/x/net v0.0.0-20200625001655-4c5254603344
29-
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
27+
golang.org/x/net v0.0.0-20201021035429-f5854403a974
28+
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
3029
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 // indirect
3130
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
3231
jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7

0 commit comments

Comments
 (0)