Skip to content

Commit b1d5ba0

Browse files
authored
add CRUD support for repo key-value pairs (#896)
* add CRUD support for repo key-value pairs - Add field KeyValuePairs to the Repository type so it will be part of the response object for repo read requests - Add commands `src repos add-kvp`, `src repos update-kvp`, and `src repos delete-kvp` * go imports * rename added files for consistency
1 parent dcab97d commit b1d5ba0

File tree

4 files changed

+295
-0
lines changed

4 files changed

+295
-0
lines changed

cmd/src/repos.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ The commands are:
2323
get gets a repository
2424
list lists repositories
2525
delete deletes repositories
26+
add-kvp adds a key-value pair to a repository
27+
update-kvp updates a key-value pair on a repository
28+
delete-kvp deletes a key-value pair from a repository
2629
2730
Use "src repos [command] -h" for more information about a command.
2831
`
@@ -63,6 +66,10 @@ fragment RepositoryFields on Repository {
6366
displayName
6467
}
6568
viewerCanAdminister
69+
keyValuePairs {
70+
key
71+
value
72+
}
6673
}
6774
`
6875

@@ -77,6 +84,12 @@ type Repository struct {
7784
ExternalRepository ExternalRepository `json:"externalRepository"`
7885
DefaultBranch GitRef `json:"defaultBranch"`
7986
ViewerCanAdminister bool `json:"viewerCanAdminister"`
87+
KeyValuePairs []KeyValuePair `json:"keyValuePairs"`
88+
}
89+
90+
type KeyValuePair struct {
91+
Key string `json:"key"`
92+
Value *string `json:"value"`
8093
}
8194

8295
type ExternalRepository struct {

cmd/src/repos_add_kvp.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
8+
"github.com/sourcegraph/sourcegraph/lib/errors"
9+
"github.com/sourcegraph/src-cli/internal/api"
10+
)
11+
12+
func init() {
13+
usage := `
14+
Examples:
15+
16+
Add a key-value pair to a repository:
17+
18+
$ src repos add-kvp -repo=repoID -key=mykey -value=myvalue
19+
20+
Omitting -value will create a tag (a key with a null value).
21+
`
22+
23+
flagSet := flag.NewFlagSet("add-kvp", flag.ExitOnError)
24+
usageFunc := func() {
25+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
26+
flagSet.PrintDefaults()
27+
fmt.Println(usage)
28+
}
29+
var (
30+
repoFlag = flagSet.String("repo", "", `The ID of the repo to add the key-value pair to (required)`)
31+
keyFlag = flagSet.String("key", "", `The name of the key to add (required)`)
32+
valueFlag = flagSet.String("value", "", `The value associated with the key. Defaults to null.`)
33+
apiFlags = api.NewFlags(flagSet)
34+
)
35+
36+
handler := func(args []string) error {
37+
if err := flagSet.Parse(args); err != nil {
38+
return err
39+
}
40+
if *repoFlag == "" {
41+
return errors.New("error: repo is required")
42+
}
43+
44+
keyFlag = nil
45+
valueFlag = nil
46+
flagSet.Visit(func(f *flag.Flag) {
47+
if f.Name == "key" {
48+
key := f.Value.String()
49+
keyFlag = &key
50+
}
51+
52+
if f.Name == "value" {
53+
value := f.Value.String()
54+
valueFlag = &value
55+
}
56+
})
57+
if keyFlag == nil {
58+
return errors.New("error: key is required")
59+
}
60+
61+
client := cfg.apiClient(apiFlags, flagSet.Output())
62+
63+
query := `mutation addKVP(
64+
$repo: ID!,
65+
$key: String!,
66+
$value: String,
67+
) {
68+
addRepoKeyValuePair(
69+
repo: $repo,
70+
key: $key,
71+
value: $value,
72+
) {
73+
alwaysNil
74+
}
75+
}`
76+
77+
if ok, err := client.NewRequest(query, map[string]interface{}{
78+
"repo": *repoFlag,
79+
"key": *keyFlag,
80+
"value": valueFlag,
81+
}).Do(context.Background(), nil); err != nil || !ok {
82+
return err
83+
}
84+
85+
if valueFlag != nil {
86+
fmt.Printf("Key-value pair '%s:%v' created.\n", *keyFlag, *valueFlag)
87+
} else {
88+
fmt.Printf("Key-value pair '%s:<nil>' created.\n", *keyFlag)
89+
}
90+
return nil
91+
}
92+
93+
// Register the command.
94+
reposCommands = append(reposCommands, &command{
95+
flagSet: flagSet,
96+
handler: handler,
97+
usageFunc: usageFunc,
98+
})
99+
}

cmd/src/repos_delete_kvp.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
8+
"github.com/sourcegraph/sourcegraph/lib/errors"
9+
"github.com/sourcegraph/src-cli/internal/api"
10+
)
11+
12+
func init() {
13+
usage := `
14+
Examples:
15+
16+
Delete a key-value pair from a repository:
17+
18+
$ src repos delete-kvp -repo=repoID -key=mykey
19+
20+
`
21+
22+
flagSet := flag.NewFlagSet("delete-kvp", flag.ExitOnError)
23+
usageFunc := func() {
24+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
25+
flagSet.PrintDefaults()
26+
fmt.Println(usage)
27+
}
28+
var (
29+
repoFlag = flagSet.String("repo", "", `The ID of the repo with the key-value pair to be deleted (required)`)
30+
keyFlag = flagSet.String("key", "", `The name of the key to be deleted (required)`)
31+
apiFlags = api.NewFlags(flagSet)
32+
)
33+
34+
handler := func(args []string) error {
35+
if err := flagSet.Parse(args); err != nil {
36+
return err
37+
}
38+
if *repoFlag == "" {
39+
return errors.New("error: repo is required")
40+
}
41+
42+
keyFlag = nil
43+
flagSet.Visit(func(f *flag.Flag) {
44+
if f.Name == "key" {
45+
key := f.Value.String()
46+
keyFlag = &key
47+
}
48+
})
49+
if keyFlag == nil {
50+
return errors.New("error: key is required")
51+
}
52+
53+
client := cfg.apiClient(apiFlags, flagSet.Output())
54+
55+
query := `mutation deleteKVP(
56+
$repo: ID!,
57+
$key: String!,
58+
) {
59+
deleteRepoKeyValuePair(
60+
repo: $repo,
61+
key: $key,
62+
) {
63+
alwaysNil
64+
}
65+
}`
66+
67+
if ok, err := client.NewRequest(query, map[string]interface{}{
68+
"repo": *repoFlag,
69+
"key": *keyFlag,
70+
}).Do(context.Background(), nil); err != nil || !ok {
71+
return err
72+
}
73+
74+
fmt.Printf("Key-value pair with key '%s' deleted.\n", *keyFlag)
75+
return nil
76+
}
77+
78+
// Register the command.
79+
reposCommands = append(reposCommands, &command{
80+
flagSet: flagSet,
81+
handler: handler,
82+
usageFunc: usageFunc,
83+
})
84+
}

cmd/src/repos_update_kvp.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
8+
"github.com/sourcegraph/sourcegraph/lib/errors"
9+
"github.com/sourcegraph/src-cli/internal/api"
10+
)
11+
12+
func init() {
13+
usage := `
14+
Examples:
15+
16+
Update the value for a key on a repository:
17+
18+
$ src repos update-kvp -repo=repoID -key=my-key -value=new-value
19+
20+
Omitting -value will set the value of the key to null.
21+
`
22+
23+
flagSet := flag.NewFlagSet("update-kvp", flag.ExitOnError)
24+
usageFunc := func() {
25+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
26+
flagSet.PrintDefaults()
27+
fmt.Println(usage)
28+
}
29+
var (
30+
repoFlag = flagSet.String("repo", "", `The ID of the repo with the key to be updated (required)`)
31+
keyFlag = flagSet.String("key", "", `The name of the key to be updated (required)`)
32+
valueFlag = flagSet.String("value", "", `The new value of the key to be set. Defaults to null.`)
33+
apiFlags = api.NewFlags(flagSet)
34+
)
35+
36+
handler := func(args []string) error {
37+
if err := flagSet.Parse(args); err != nil {
38+
return err
39+
}
40+
if *repoFlag == "" {
41+
return errors.New("error: repo is required")
42+
}
43+
44+
keyFlag = nil
45+
valueFlag = nil
46+
flagSet.Visit(func(f *flag.Flag) {
47+
if f.Name == "key" {
48+
key := f.Value.String()
49+
keyFlag = &key
50+
}
51+
52+
if f.Name == "value" {
53+
value := f.Value.String()
54+
valueFlag = &value
55+
}
56+
})
57+
if keyFlag == nil {
58+
return errors.New("error: key is required")
59+
}
60+
61+
client := cfg.apiClient(apiFlags, flagSet.Output())
62+
63+
query := `mutation updateKVP(
64+
$repo: ID!,
65+
$key: String!,
66+
$value: String,
67+
) {
68+
updateRepoKeyValuePair(
69+
repo: $repo,
70+
key: $key,
71+
value: $value,
72+
) {
73+
alwaysNil
74+
}
75+
}`
76+
77+
if ok, err := client.NewRequest(query, map[string]interface{}{
78+
"repo": *repoFlag,
79+
"key": *keyFlag,
80+
"value": valueFlag,
81+
}).Do(context.Background(), nil); err != nil || !ok {
82+
return err
83+
}
84+
85+
if valueFlag != nil {
86+
fmt.Printf("Value of key '%s' updated to '%v'\n", *keyFlag, *valueFlag)
87+
} else {
88+
fmt.Printf("Value of key '%s' updated to <nil>\n", *keyFlag)
89+
}
90+
return nil
91+
}
92+
93+
// Register the command.
94+
reposCommands = append(reposCommands, &command{
95+
flagSet: flagSet,
96+
handler: handler,
97+
usageFunc: usageFunc,
98+
})
99+
}

0 commit comments

Comments
 (0)