package rename import ( "bytes" "encoding/json" "errors" "fmt" "net/http" "strings" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/pkg/cmd/gist/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" "github.com/spf13/cobra" ) type RenameOptions struct { IO *iostreams.IOStreams Config func() (config.Config, error) HttpClient func() (*http.Client, error) Selector string OldFileName string NewFileName string } func NewCmdRename(f *cmdutil.Factory, runf func(*RenameOptions) error) *cobra.Command { opts := &RenameOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, Config: f.Config, } cmd := &cobra.Command{ Use: "rename { | } ", Short: "Rename a file in a gist", Long: heredoc.Doc(`Rename a file in the given gist ID / URL.`), Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error { opts.Selector = args[0] opts.OldFileName = args[1] opts.NewFileName = args[2] if runf != nil { return runf(opts) } return renameRun(opts) }, } return cmd } func renameRun(opts *RenameOptions) error { gistID := opts.Selector if strings.Contains(gistID, "/") { id, err := shared.GistIDFromURL(gistID) if err != nil { return err } gistID = id } client, err := opts.HttpClient() if err != nil { return err } apiClient := api.NewClientFromHTTP(client) cfg, err := opts.Config() if err != nil { return err } host, _ := cfg.Authentication().DefaultHost() gist, err := shared.GetGist(client, host, gistID) if err != nil { if errors.Is(err, shared.NotFoundErr) { return fmt.Errorf("gist not found: %s", gistID) } return err } username, err := api.CurrentLoginName(apiClient, host) if err != nil { return err } if username != gist.Owner.Login { return errors.New("you do not own this gist") } _, ok := gist.Files[opts.OldFileName] if !ok { return fmt.Errorf("File %s not found in gist", opts.OldFileName) } _, ok = gist.Files[opts.NewFileName] if ok { return fmt.Errorf("File %s already exists in gist", opts.NewFileName) } gist.Files[opts.NewFileName] = gist.Files[opts.OldFileName] gist.Files[opts.NewFileName].Filename = opts.NewFileName gist.Files[opts.OldFileName] = &shared.GistFile{} return updateGist(apiClient, host, gist) } func updateGist(apiClient *api.Client, hostname string, gist *shared.Gist) error { body := shared.Gist{ Description: gist.Description, Files: gist.Files, } path := "gists/" + gist.ID requestByte, err := json.Marshal(body) if err != nil { return err } requestBody := bytes.NewReader(requestByte) result := shared.Gist{} err = apiClient.REST(hostname, "POST", path, requestBody, &result) if err != nil { return err } return nil }