diff --git a/cmd/src/doc.go b/cmd/src/doc.go index 43ea72944d..d433aa24cb 100644 --- a/cmd/src/doc.go +++ b/cmd/src/doc.go @@ -57,15 +57,13 @@ Examples: } commanders := map[string]*commander{ - "": &commands, - "batch": &batchCommands, - "config": &configCommands, - "extsvc": &extsvcCommands, - "code-intel": &codeintelCommands, - "orgs": &orgsCommands, - "orgs members": &orgsMembersCommands, - "repos": &reposCommands, - "users": &usersCommands, + "": &commands, + "batch": &batchCommands, + "config": &configCommands, + "extsvc": &extsvcCommands, + "code-intel": &codeintelCommands, + "repos": &reposCommands, + "users": &usersCommands, } pending := out.Pending(output.Line("", output.StylePending, "Rendering Markdown...")) diff --git a/cmd/src/orgs.go b/cmd/src/orgs.go index 755fe5615c..b5c4ed473e 100644 --- a/cmd/src/orgs.go +++ b/cmd/src/orgs.go @@ -1,14 +1,27 @@ package main import ( - "flag" - "fmt" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -var orgsCommands commander - -func init() { - usage := `'src orgs' is a tool that manages organizations on a Sourcegraph instance. +var orgsCommand = clicompat.Wrap(&cli.Command{ + Name: "orgs", + Aliases: []string{"org"}, + Usage: "manages organizations", + UsageText: "src orgs [command options]", + Description: orgsExamples, + HideVersion: true, + Commands: []*cli.Command{ + orgsListCommand, + orgsGetCommand, + orgsCreateCommand, + orgsDeleteCommand, + orgsMembersCommand, + }, +}) + +const orgsExamples = `'src orgs' is a tool that manages organizations on a Sourcegraph instance. Usage: @@ -25,23 +38,6 @@ The commands are: Use "src orgs [command] -h" for more information about a command. ` - flagSet := flag.NewFlagSet("orgs", flag.ExitOnError) - handler := func(args []string) error { - orgsCommands.run(flagSet, "src orgs", usage, args) - return nil - } - - // Register the command. - commands = append(commands, &command{ - flagSet: flagSet, - aliases: []string{"org"}, - handler: handler, - usageFunc: func() { - fmt.Println(usage) - }, - }) -} - const orgFragment = ` fragment OrgFields on Org { id diff --git a/cmd/src/orgs_create.go b/cmd/src/orgs_create.go index af00c0fd38..ced6e9fd92 100644 --- a/cmd/src/orgs_create.go +++ b/cmd/src/orgs_create.go @@ -2,14 +2,13 @@ package main import ( "context" - "flag" "fmt" - "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsCreateExamples = ` Examples: Create an organization: @@ -18,24 +17,27 @@ Examples: ` - flagSet := flag.NewFlagSet("create", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - nameFlag = flagSet.String("name", "", `The new organization's name. (required)`) - displayNameFlag = flagSet.String("display-name", "", `The new organization's display name. Defaults to organization name if unspecified.`) - apiFlags = api.NewFlags(flagSet) - ) +var orgsCreateCommand = clicompat.Wrap(&cli.Command{ + Name: "create", + Usage: "creates an organization", + UsageText: "src orgs create [options]", + Description: orgsCreateExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.StringFlag{ + Name: "name", + Usage: "The new organization's name. (required)", + }, + &cli.StringFlag{ + Name: "display-name", + Usage: "The new organization's display name. Defaults to organization name if unspecified.", + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + name := cmd.String("name") + displayName := cmd.String("display-name") - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) query := `mutation CreateOrg( $name: String!, @@ -53,20 +55,13 @@ Examples: CreateOrg Org } if ok, err := client.NewRequest(query, map[string]any{ - "name": *nameFlag, - "displayName": *displayNameFlag, - }).Do(context.Background(), &result); err != nil || !ok { + "name": name, + "displayName": displayName, + }).Do(ctx, &result); err != nil || !ok { return err } - fmt.Printf("Organization %q created.\n", *nameFlag) - return nil - } - - // Register the command. - orgsCommands = append(orgsCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + _, err := fmt.Fprintf(cmd.Writer, "Organization %q created.\n", name) + return err + }, +}) diff --git a/cmd/src/orgs_delete.go b/cmd/src/orgs_delete.go index 7a00aa4478..49a3d6201f 100644 --- a/cmd/src/orgs_delete.go +++ b/cmd/src/orgs_delete.go @@ -2,14 +2,13 @@ package main import ( "context" - "flag" "fmt" - "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsDeleteExamples = ` Examples: Delete an organization by ID: @@ -26,23 +25,21 @@ Examples: ` - flagSet := flag.NewFlagSet("delete", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - orgIDFlag = flagSet.String("id", "", `The ID of the organization to delete.`) - apiFlags = api.NewFlags(flagSet) - ) - - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) +var orgsDeleteCommand = clicompat.Wrap(&cli.Command{ + Name: "delete", + Usage: "deletes an organization", + UsageText: "src orgs delete [options]", + Description: orgsDeleteExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.StringFlag{ + Name: "id", + Usage: "The ID of the organization to delete.", + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + orgID := cmd.String("id") + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) query := `mutation DeleteOrganization( $organization: ID! @@ -58,19 +55,12 @@ Examples: DeleteOrganization struct{} } if ok, err := client.NewRequest(query, map[string]any{ - "organization": *orgIDFlag, - }).Do(context.Background(), &result); err != nil || !ok { + "organization": orgID, + }).Do(ctx, &result); err != nil || !ok { return err } - fmt.Printf("Organization with ID %q deleted.\n", *orgIDFlag) - return nil - } - - // Register the command. - orgsCommands = append(orgsCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + _, err := fmt.Fprintf(cmd.Writer, "Organization with ID %q deleted.\n", orgID) + return err + }, +}) diff --git a/cmd/src/orgs_get.go b/cmd/src/orgs_get.go index 39a1f508db..3a5a9189c2 100644 --- a/cmd/src/orgs_get.go +++ b/cmd/src/orgs_get.go @@ -2,14 +2,12 @@ package main import ( "context" - "flag" - "fmt" - "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsGetExamples = ` Examples: Get organization named abc-org: @@ -22,26 +20,30 @@ Examples: ` - flagSet := flag.NewFlagSet("get", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - nameFlag = flagSet.String("name", "", `Look up organization by name. (e.g. "abc-org")`) - formatFlag = flagSet.String("f", "{{.|json}}", `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Name}} ({{.DisplayName}})")`) - apiFlags = api.NewFlags(flagSet) - ) - - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) - - tmpl, err := parseTemplate(*formatFlag) +var orgsGetCommand = clicompat.Wrap(&cli.Command{ + Name: "get", + Usage: "gets an organization", + UsageText: "src orgs get [options]", + Description: orgsGetExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.StringFlag{ + Name: "name", + Usage: `Look up organization by name. (e.g. "abc-org")`, + }, + &cli.StringFlag{ + Name: "f", + Value: "{{.|json}}", + Usage: `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Name}} ({{.DisplayName}})")`, + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + name := cmd.String("name") + format := cmd.String("f") + + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) + + tmpl, err := parseTemplate(format) if err != nil { return err } @@ -60,18 +62,11 @@ Examples: Organization *Org } if ok, err := client.NewRequest(query, map[string]any{ - "name": *nameFlag, - }).Do(context.Background(), &result); err != nil || !ok { + "name": name, + }).Do(ctx, &result); err != nil || !ok { return err } return execTemplate(tmpl, result.Organization) - } - - // Register the command. - orgsCommands = append(orgsCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + }, +}) diff --git a/cmd/src/orgs_list.go b/cmd/src/orgs_list.go index 3ad611b473..a4b643ef8d 100644 --- a/cmd/src/orgs_list.go +++ b/cmd/src/orgs_list.go @@ -2,14 +2,13 @@ package main import ( "context" - "flag" - "fmt" "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsListExamples = ` Examples: List organizations: @@ -22,27 +21,36 @@ Examples: ` - flagSet := flag.NewFlagSet("list", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - firstFlag = flagSet.Int("first", 1000, "Returns the first n organizations from the list.") - queryFlag = flagSet.String("query", "", `Returns organizations whose names match the query. (e.g. "alice")`) - formatFlag = flagSet.String("f", "{{.Name}}", `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Name}} ({{.DisplayName}})" or "{{.|json}}")`) - apiFlags = api.NewFlags(flagSet) - ) - - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) - - tmpl, err := parseTemplate(*formatFlag) +var orgsListCommand = clicompat.Wrap(&cli.Command{ + Name: "list", + Usage: "lists organizations", + UsageText: "src orgs list [options]", + Description: orgsListExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.IntFlag{ + Name: "first", + Value: 1000, + Usage: "Returns the first n organizations from the list.", + }, + &cli.StringFlag{ + Name: "query", + Usage: `Returns organizations whose names match the query. (e.g. "alice")`, + }, + &cli.StringFlag{ + Name: "f", + Value: "{{.Name}}", + Usage: `Format for the output, using the syntax of Go package text/template. (e.g. "{{.ID}}: {{.Name}} ({{.DisplayName}})" or "{{.|json}}")`, + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + first := cmd.Int("first") + queryValue := cmd.String("query") + format := cmd.String("f") + + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) + + tmpl, err := parseTemplate(format) if err != nil { return err } @@ -67,9 +75,9 @@ Examples: } } if ok, err := client.NewRequest(query, map[string]any{ - "first": api.NullInt(*firstFlag), - "query": api.NullString(*queryFlag), - }).Do(context.Background(), &result); err != nil || !ok { + "first": api.NullInt(first), + "query": api.NullString(queryValue), + }).Do(ctx, &result); err != nil || !ok { return err } @@ -79,12 +87,5 @@ Examples: } } return nil - } - - // Register the command. - orgsCommands = append(orgsCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + }, +}) diff --git a/cmd/src/orgs_members.go b/cmd/src/orgs_members.go index 443c5b01ad..bf033644ff 100644 --- a/cmd/src/orgs_members.go +++ b/cmd/src/orgs_members.go @@ -1,14 +1,24 @@ package main import ( - "flag" - "fmt" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -var orgsMembersCommands commander - -func init() { - usage := `'src orgs members' is a tool that manages organization members on a Sourcegraph instance. +var orgsMembersCommand = clicompat.Wrap(&cli.Command{ + Name: "members", + Aliases: []string{"member"}, + Usage: "manages organization members", + UsageText: "src orgs members [command options]", + Description: orgsMembersExamples, + HideVersion: true, + Commands: []*cli.Command{ + orgsMembersAddCommand, + orgsMembersRemoveCommand, + }, +}) + +const orgsMembersExamples = `'src orgs members' is a tool that manages organization members on a Sourcegraph instance. Usage: @@ -21,20 +31,3 @@ The commands are: Use "src orgs members [command] -h" for more information about a command. ` - - flagSet := flag.NewFlagSet("members", flag.ExitOnError) - handler := func(args []string) error { - orgsMembersCommands.run(flagSet, "src orgs members", usage, args) - return nil - } - - // Register the command. - orgsCommands = append(orgsCommands, &command{ - flagSet: flagSet, - aliases: []string{"member"}, - handler: handler, - usageFunc: func() { - fmt.Println(usage) - }, - }) -} diff --git a/cmd/src/orgs_members_add.go b/cmd/src/orgs_members_add.go index cf09f5c0d1..f6fa691f87 100644 --- a/cmd/src/orgs_members_add.go +++ b/cmd/src/orgs_members_add.go @@ -2,14 +2,13 @@ package main import ( "context" - "flag" "fmt" - "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsMembersAddExamples = ` Examples: Add a member (alice) to an organization (abc-org): @@ -18,24 +17,27 @@ Examples: ` - flagSet := flag.NewFlagSet("add", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs members %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - orgIDFlag = flagSet.String("org-id", "", "ID of organization to which to add member. (required)") - usernameFlag = flagSet.String("username", "", "Username of user to add as member. (required)") - apiFlags = api.NewFlags(flagSet) - ) +var orgsMembersAddCommand = clicompat.Wrap(&cli.Command{ + Name: "add", + Usage: "adds a user as a member to an organization", + UsageText: "src orgs members add [options]", + Description: orgsMembersAddExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.StringFlag{ + Name: "org-id", + Usage: "ID of organization to which to add member. (required)", + }, + &cli.StringFlag{ + Name: "username", + Usage: "Username of user to add as member. (required)", + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + orgID := cmd.String("org-id") + username := cmd.String("username") - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) query := `mutation AddUserToOrganization( $organization: ID!, @@ -53,20 +55,13 @@ Examples: AddUserToOrganization struct{} } if ok, err := client.NewRequest(query, map[string]any{ - "organization": *orgIDFlag, - "username": *usernameFlag, - }).Do(context.Background(), &result); err != nil || !ok { + "organization": orgID, + "username": username, + }).Do(ctx, &result); err != nil || !ok { return err } - fmt.Printf("User %q added as member to organization with ID %q.\n", *usernameFlag, *orgIDFlag) - return nil - } - - // Register the command. - orgsMembersCommands = append(orgsMembersCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + _, err := fmt.Fprintf(cmd.Writer, "User %q added as member to organization with ID %q.\n", username, orgID) + return err + }, +}) diff --git a/cmd/src/orgs_members_remove.go b/cmd/src/orgs_members_remove.go index 6f6eb3171f..9eac9f0fd0 100644 --- a/cmd/src/orgs_members_remove.go +++ b/cmd/src/orgs_members_remove.go @@ -2,14 +2,13 @@ package main import ( "context" - "flag" "fmt" - "github.com/sourcegraph/src-cli/internal/api" + "github.com/sourcegraph/src-cli/internal/clicompat" + "github.com/urfave/cli/v3" ) -func init() { - usage := ` +const orgsMembersRemoveExamples = ` Examples: Remove a member (alice) from an organization (abc-org): @@ -17,24 +16,27 @@ Examples: $ src orgs members remove -org-id=$(src org get -f '{{.ID}}' -name=abc-org) -user-id=$(src users get -f '{{.ID}}' -username=alice) ` - flagSet := flag.NewFlagSet("remove", flag.ExitOnError) - usageFunc := func() { - fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src orgs members %s':\n", flagSet.Name()) - flagSet.PrintDefaults() - fmt.Println(usage) - } - var ( - orgIDFlag = flagSet.String("org-id", "", "ID of organization from which to remove member. (required)") - userIDFlag = flagSet.String("user-id", "", "ID of user to remove as member. (required)") - apiFlags = api.NewFlags(flagSet) - ) +var orgsMembersRemoveCommand = clicompat.Wrap(&cli.Command{ + Name: "remove", + Usage: "removes a user as a member from an organization", + UsageText: "src orgs members remove [options]", + Description: orgsMembersRemoveExamples, + HideVersion: true, + Flags: clicompat.WithAPIFlags( + &cli.StringFlag{ + Name: "org-id", + Usage: "ID of organization from which to remove member. (required)", + }, + &cli.StringFlag{ + Name: "user-id", + Usage: "ID of user to remove as member. (required)", + }, + ), + Action: func(ctx context.Context, cmd *cli.Command) error { + orgID := cmd.String("org-id") + userID := cmd.String("user-id") - handler := func(args []string) error { - if err := flagSet.Parse(args); err != nil { - return err - } - - client := cfg.apiClient(apiFlags, flagSet.Output()) + client := cfg.apiClient(clicompat.APIFlagsFromCmd(cmd), cmd.Writer) query := `mutation RemoveUserFromOrg( $orgID: ID!, @@ -52,20 +54,13 @@ Examples: RemoveUserFromOrg struct{} } if ok, err := client.NewRequest(query, map[string]any{ - "orgID": *orgIDFlag, - "userID": *userIDFlag, - }).Do(context.Background(), &result); err != nil || !ok { + "orgID": orgID, + "userID": userID, + }).Do(ctx, &result); err != nil || !ok { return err } - fmt.Printf("User %q removed as member from organization with ID %q.\n", *userIDFlag, *orgIDFlag) - return nil - } - - // Register the command. - orgsMembersCommands = append(orgsMembersCommands, &command{ - flagSet: flagSet, - handler: handler, - usageFunc: usageFunc, - }) -} + _, err := fmt.Fprintf(cmd.Writer, "User %q removed as member from organization with ID %q.\n", userID, orgID) + return err + }, +}) diff --git a/cmd/src/run_migration_compat.go b/cmd/src/run_migration_compat.go index 52baca0fc5..1a6c624d40 100644 --- a/cmd/src/run_migration_compat.go +++ b/cmd/src/run_migration_compat.go @@ -20,6 +20,8 @@ var migratedCommands = map[string]*cli.Command{ "api": apiCommand, "auth": authCommand, "login": loginCommand, + "orgs": orgsCommand, + "org": orgsCommand, "version": versionCommand, }