mirror of https://gitlab.com/gitlab-org/cli.git
147 lines
4.3 KiB
Go
147 lines
4.3 KiB
Go
package create
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/spf13/cobra"
|
|
"github.com/xanzy/go-gitlab"
|
|
"gitlab.com/gitlab-org/cli/api"
|
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
|
"gitlab.com/gitlab-org/cli/internal/glrepo"
|
|
"gitlab.com/gitlab-org/cli/pkg/iostreams"
|
|
)
|
|
|
|
type CreateOpts struct {
|
|
Title string
|
|
Description string
|
|
DisplayFilename string
|
|
Visibility string
|
|
|
|
ForUser bool
|
|
FilePath string
|
|
|
|
IO *iostreams.IOStreams
|
|
Lab func() (*gitlab.Client, error)
|
|
BaseRepo func() (glrepo.Interface, error)
|
|
}
|
|
|
|
func (opts CreateOpts) isSnippetFromFile() bool {
|
|
return opts.FilePath != ""
|
|
}
|
|
|
|
func NewCmdCreate(f *cmdutils.Factory) *cobra.Command {
|
|
opts := &CreateOpts{}
|
|
var snippetCreateCmd = &cobra.Command{
|
|
Use: "create [path]",
|
|
Short: `Create new snippet`,
|
|
Long: ``,
|
|
Aliases: []string{"new"},
|
|
Example: heredoc.Doc(`
|
|
glab snippet create script.py --title "Title of the snippet"
|
|
echo "package main" | glab snippet new --title "Title of the snippet" --filename "main.go"
|
|
glab snippet create main.go -t Title -f "different.go" -d Description
|
|
`),
|
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
|
opts.IO = f.IO
|
|
opts.BaseRepo = f.BaseRepo
|
|
opts.Lab = f.HttpClient
|
|
if opts.Title == "" {
|
|
return &cmdutils.FlagError{
|
|
Err: errors.New("--title required for snippets"),
|
|
}
|
|
}
|
|
if len(args) == 0 {
|
|
if opts.DisplayFilename == "" {
|
|
return &cmdutils.FlagError{Err: errors.New("if path is not provided filename is required")}
|
|
}
|
|
} else {
|
|
if opts.DisplayFilename == "" {
|
|
opts.DisplayFilename = args[0]
|
|
}
|
|
opts.FilePath = args[0]
|
|
}
|
|
|
|
return nil
|
|
},
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
client, err := opts.Lab()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
repo, err := opts.BaseRepo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return runCreate(client, repo, opts)
|
|
},
|
|
}
|
|
|
|
snippetCreateCmd.Flags().StringVarP(&opts.Title, "title", "t", "", "Title of the snippet")
|
|
snippetCreateCmd.Flags().StringVarP(&opts.DisplayFilename, "filename", "f", "", "Filename of the snippet in GitLab")
|
|
snippetCreateCmd.Flags().StringVarP(&opts.Description, "description", "d", "", "Description of the snippet")
|
|
snippetCreateCmd.Flags().StringVarP(&opts.Visibility, "visibility", "v", "private", "Limit by visibility {public, internal, or private}")
|
|
|
|
return snippetCreateCmd
|
|
}
|
|
|
|
func runCreate(client *gitlab.Client, repo glrepo.Interface, opts *CreateOpts) error {
|
|
content, err := readSnippetsContent(opts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(opts.IO.StdErr, "- Creating snippet in", repo.FullName())
|
|
snippet, err := api.CreateProjectSnippet(client, repo.FullName(), &gitlab.CreateProjectSnippetOptions{
|
|
Title: &opts.Title,
|
|
Description: &opts.Description,
|
|
Content: gitlab.String(string(content)),
|
|
FileName: &opts.DisplayFilename,
|
|
Visibility: gitlab.Visibility(gitlab.VisibilityValue(opts.Visibility)),
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create snippet. %w", err)
|
|
}
|
|
snippetID := opts.IO.Color().Green(fmt.Sprintf("$%d", snippet.ID))
|
|
if opts.IO.IsaTTY {
|
|
fmt.Fprintf(opts.IO.StdOut, "%s %s (%s)\n %s\n", snippetID, snippet.Title, snippet.FileName, snippet.WebURL)
|
|
} else {
|
|
fmt.Fprintln(opts.IO.StdOut, snippet.WebURL)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// FIXME: Adding more then one file can't be done right now because the GitLab API library
|
|
//
|
|
// Doesn't support it yet.
|
|
//
|
|
// See for the API reference: https://docs.gitlab.com/ee/api/snippets.html#create-new-snippet
|
|
// See for the library docs : https://pkg.go.dev/github.com/xanzy/go-gitlab#CreateSnippetOptions
|
|
// See for GitHub issue : https://github.com/xanzy/go-gitlab/issues/1372
|
|
func readSnippetsContent(opts *CreateOpts) (string, error) {
|
|
if opts.isSnippetFromFile() {
|
|
return readFromFile(opts.FilePath)
|
|
}
|
|
return readFromSTDIN(opts.IO)
|
|
}
|
|
|
|
func readFromSTDIN(ioStream *iostreams.IOStreams) (string, error) {
|
|
content, err := io.ReadAll(ioStream.In)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Failed to read snippet from STDIN. %w", err)
|
|
}
|
|
return string(content), nil
|
|
}
|
|
|
|
func readFromFile(filename string) (string, error) {
|
|
content, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return "", fmt.Errorf("Failed to read snippet from file '%s'. %w", filename, err)
|
|
}
|
|
return string(content), nil
|
|
}
|