Skip to content

Commit dae3f65

Browse files
peterguytrly
authored andcommitted
Fix linter issues. Add support for job id numbers (#1151)
1 parent f46b05a commit dae3f65

File tree

9 files changed

+231
-182
lines changed

9 files changed

+231
-182
lines changed

cmd/src/format.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ func parseTemplate(text string) (*template.Template, error) {
8080
}
8181
return humanize.Time(t), nil
8282
},
83+
"searchJobIDNumber": func(id string) string {
84+
sjid, err := ParseSearchJobID(id)
85+
if err != nil {
86+
return id
87+
}
88+
return fmt.Sprintf("%d", sjid.Number())
89+
},
90+
"searchJobIDCanonical": func(id string) string {
91+
sjid, err := ParseSearchJobID(id)
92+
if err != nil {
93+
return id
94+
}
95+
return sjid.Canonical()
96+
},
8397

8498
// Register search-specific template functions
8599
"searchSequentialLineNumber": searchTemplateFuncs["searchSequentialLineNumber"],

cmd/src/search_jobs.go

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package main
22

33
import (
4+
"encoding/base64"
45
"flag"
56
"fmt"
6-
"text/template"
7-
"os"
7+
"regexp"
8+
"strconv"
9+
10+
"github.com/sourcegraph/src-cli/internal/cmderrors"
811
)
912

1013
// searchJobFragment is a GraphQL fragment that defines the fields to be queried
@@ -51,6 +54,8 @@ The commands are:
5154
delete deletes a search job by ID
5255
get gets a search job by ID
5356
list lists search jobs
57+
logs outputs the logs for a search job by ID
58+
results outputs the results for a search job by ID
5459
5560
Use "src search-jobs [command] -h" for more information about a command.
5661
`
@@ -71,22 +76,12 @@ Use "src search-jobs [command] -h" for more information about a command.
7176
})
7277
}
7378

74-
// printSearchJob formats and prints a search job to stdout using the provided format template.
75-
// Returns an error if the template parsing or execution fails.
76-
func printSearchJob(job *SearchJob, format string) error {
77-
tmpl, err := template.New("searchJob").Parse(format)
78-
if err != nil {
79-
return err
80-
}
81-
return tmpl.Execute(os.Stdout, job)
82-
}
83-
8479
// SearchJob represents a search job with its metadata, including the search query,
8580
// execution state, creator information, timestamps, URLs, and repository statistics.
8681
type SearchJob struct {
87-
ID string
88-
Query string
89-
State string
82+
ID string
83+
Query string
84+
State string
9085
Creator struct {
9186
Username string
9287
}
@@ -96,9 +91,55 @@ type SearchJob struct {
9691
URL string
9792
LogURL string
9893
RepoStats struct {
99-
Total int
100-
Completed int
101-
Failed int
102-
InProgress int
94+
Total int
95+
Completed int
96+
Failed int
97+
InProgress int
98+
}
99+
}
100+
101+
type SearchJobID struct {
102+
number uint64
103+
}
104+
105+
func ParseSearchJobID(input string) (*SearchJobID, error) {
106+
// accept either:
107+
// - the numeric job id (non-negative integer)
108+
// - the plain text SearchJob:<integer> form of the id
109+
// - the base64-encoded "SearchJob:<integer>" string
110+
111+
if input == "" {
112+
return nil, cmderrors.Usage("must provide a search job ID")
113+
}
114+
115+
// Try to decode if it's base64 first
116+
if decoded, err := base64.StdEncoding.DecodeString(input); err == nil {
117+
input = string(decoded)
103118
}
119+
120+
// Match either "SearchJob:<integer>" or "<integer>"
121+
re := regexp.MustCompile(`^(?:SearchJob:)?(\d+)$`)
122+
matches := re.FindStringSubmatch(input)
123+
if matches == nil {
124+
return nil, fmt.Errorf("invalid ID format: must be a non-negative integer, 'SearchJob:<integer>', or that string base64-encoded")
125+
}
126+
127+
number, err := strconv.ParseUint(matches[1], 10, 64)
128+
if err != nil {
129+
return nil, fmt.Errorf("invalid ID format: must be a 64-bit non-negative integer")
130+
}
131+
132+
return &SearchJobID{number: number}, nil
133+
}
134+
135+
func (id *SearchJobID) String() string {
136+
return fmt.Sprintf("SearchJob:%d", id.Number())
137+
}
138+
139+
func (id *SearchJobID) Canonical() string {
140+
return base64.StdEncoding.EncodeToString([]byte(id.String()))
141+
}
142+
143+
func (id *SearchJobID) Number() uint64 {
144+
return id.number
104145
}

cmd/src/search_jobs_cancel.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"context"
55
"flag"
66
"fmt"
7+
78
"github.com/sourcegraph/src-cli/internal/api"
8-
"github.com/sourcegraph/src-cli/internal/cmderrors"
99
)
1010

1111
const CancelSearchJobMutation = `mutation CancelSearchJob($id: ID!) {
@@ -23,7 +23,7 @@ Examples:
2323
2424
Cancel a search job:
2525
26-
$ src search-jobs cancel --id U2VhcmNoSm9iOjY5
26+
$ src search-jobs cancel -id 999
2727
`
2828
flagSet := flag.NewFlagSet("cancel", flag.ExitOnError)
2929
usageFunc := func() {
@@ -33,8 +33,8 @@ Examples:
3333
}
3434

3535
var (
36-
idFlag = flagSet.String("id", "", "ID of the search job to cancel")
37-
apiFlags = api.NewFlags(flagSet)
36+
idFlag = flagSet.String("id", "", "ID of the search job to cancel")
37+
apiFlags = api.NewFlags(flagSet)
3838
)
3939

4040
handler := func(args []string) error {
@@ -49,8 +49,9 @@ Examples:
4949
Flags: apiFlags,
5050
})
5151

52-
if *idFlag == "" {
53-
return cmderrors.Usage("must provide a search job ID")
52+
jobID, err := ParseSearchJobID(*idFlag)
53+
if err != nil {
54+
return err
5455
}
5556

5657
query := CancelSearchJobMutation
@@ -62,7 +63,7 @@ Examples:
6263
}
6364

6465
if ok, err := client.NewRequest(query, map[string]interface{}{
65-
"id": *idFlag,
66+
"id": api.NullString(jobID.Canonical()),
6667
}).Do(context.Background(), &result); err != nil || !ok {
6768
return err
6869
}

cmd/src/search_jobs_create.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"flag"
66
"fmt"
7+
78
"github.com/sourcegraph/src-cli/internal/api"
89
"github.com/sourcegraph/src-cli/internal/cmderrors"
910
)
@@ -43,9 +44,9 @@ Examples:
4344
}
4445

4546
var (
46-
queryFlag = flagSet.String("query", "", "Search query")
47-
formatFlag = flagSet.String("f", "{{.ID}}: {{.Creator.Username}} {{.State}} ({{.Query}})", `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Creator.Username}} ({{.Query}})" or "{{.|json}}")`)
48-
apiFlags = api.NewFlags(flagSet)
47+
queryFlag = flagSet.String("query", "", "Search query")
48+
formatFlag = flagSet.String("f", "{{searchJobIDNumber .ID}}: {{.Creator.Username}} {{.State}} ({{.Query}})", `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Creator.Username}} ({{.Query}})" or "{{.|json}}")`)
49+
apiFlags = api.NewFlags(flagSet)
4950
)
5051

5152
handler := func(args []string) error {

cmd/src/search_jobs_delete.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"context"
55
"flag"
66
"fmt"
7+
78
"github.com/sourcegraph/src-cli/internal/api"
8-
"github.com/sourcegraph/src-cli/internal/cmderrors"
99
)
1010

1111
const DeleteSearchJobQuery = `mutation DeleteSearchJob($id: ID!) {
@@ -23,7 +23,7 @@ Examples:
2323
2424
Delete a search job by ID:
2525
26-
$ src search-jobs delete U2VhcmNoSm9iOjY5
26+
$ src search-jobs delete -id 999
2727
`
2828

2929
flagSet := flag.NewFlagSet("delete", flag.ExitOnError)
@@ -34,7 +34,7 @@ Examples:
3434
}
3535

3636
var (
37-
idFlag = flagSet.String("id", "", "ID of the search job to delete")
37+
idFlag = flagSet.String("id", "", "ID of the search job to delete")
3838
apiFlags = api.NewFlags(flagSet)
3939
)
4040

@@ -50,8 +50,9 @@ Examples:
5050
Flags: apiFlags,
5151
})
5252

53-
if *idFlag == "" {
54-
return cmderrors.Usage("must provide a search job ID")
53+
jobID, err := ParseSearchJobID(*idFlag)
54+
if err != nil {
55+
return err
5556
}
5657

5758
var result struct {
@@ -61,7 +62,7 @@ Examples:
6162
}
6263

6364
if ok, err := client.NewRequest(DeleteSearchJobQuery, map[string]interface{}{
64-
"id": *idFlag,
65+
"id": api.NullString(jobID.Canonical()),
6566
}).Do(context.Background(), &result); err != nil || !ok {
6667
return err
6768
}

0 commit comments

Comments
 (0)