github.com/ianfoo/lab@v0.9.5-0.20180123060006-5ed79f2ccfc7/cmd/snippetCreate.go (about) 1 package cmd 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "runtime" 10 "strconv" 11 "strings" 12 "text/template" 13 14 "github.com/pkg/errors" 15 "github.com/spf13/cobra" 16 "github.com/xanzy/go-gitlab" 17 "github.com/zaquestion/lab/internal/git" 18 lab "github.com/zaquestion/lab/internal/gitlab" 19 ) 20 21 var ( 22 name string 23 file string 24 private bool 25 public bool 26 ) 27 28 // mrCmd represents the mr command 29 var snippetCreateCmd = &cobra.Command{ 30 Use: "create [remote]", 31 Short: "Create a personal or project snippet", 32 Long: ` 33 Source snippets from stdin, file, or in editor from scratch 34 Optionally add a title & description with -m`, 35 Run: func(cmd *cobra.Command, args []string) { 36 msgs, err := cmd.Flags().GetStringSlice("message") 37 if err != nil { 38 log.Fatal(err) 39 } 40 remote := forkedFromRemote 41 if len(args) > 0 { 42 ok, err := git.IsRemote(args[0]) 43 if err != nil { 44 log.Fatal(err) 45 } 46 if ok { 47 remote = args[0] 48 } else { 49 file = args[0] 50 } 51 if ok && len(args) > 1 { 52 file = args[1] 53 } 54 } 55 code, err := snipCode(file) 56 if err != nil { 57 log.Fatal(err) 58 } 59 if strings.TrimSpace(code) == "" { 60 log.Fatal("aborting snippet due to empty contents") 61 } 62 title, body := snipMsg(msgs) 63 if title == "" { 64 log.Fatal("aborting snippet due to empty msg") 65 } 66 67 visibility := gitlab.InternalVisibility 68 switch { 69 case private: 70 visibility = gitlab.PrivateVisibility 71 case public: 72 visibility = gitlab.PublicVisibility 73 } 74 // See if we're in a git repo or if global is set to determine 75 // if this should be a personal snippet 76 rn, _ := git.PathWithNameSpace(remote) 77 if global || rn == "" { 78 opts := gitlab.CreateSnippetOptions{ 79 Title: gitlab.String(title), 80 Description: gitlab.String(body), 81 Content: gitlab.String(code), 82 FileName: gitlab.String(name), 83 Visibility: &visibility, 84 } 85 snip, err := lab.SnippetCreate(&opts) 86 if err != nil || snip == nil { 87 log.Fatal(errors.Wrap(err, "failed to create snippet")) 88 } 89 fmt.Println(snip.WebURL) 90 return 91 } 92 93 project, err := lab.FindProject(rn) 94 if err != nil { 95 log.Fatal(err) 96 } 97 opts := gitlab.CreateProjectSnippetOptions{ 98 Title: gitlab.String(title), 99 Description: gitlab.String(body), 100 Code: gitlab.String(code), 101 FileName: gitlab.String(name), 102 Visibility: &visibility, 103 } 104 snip, err := lab.ProjectSnippetCreate(project.ID, &opts) 105 if err != nil || snip == nil { 106 log.Fatal(errors.Wrap(err, "failed to create snippet")) 107 } 108 fmt.Println(snip.WebURL) 109 }, 110 } 111 112 func snipMsg(msgs []string) (string, string) { 113 return msgs[0], strings.Join(msgs[1:], "\n\n") 114 } 115 116 func snipCode(path string) (string, error) { 117 b, err := ioutil.ReadFile(path) 118 if !os.IsNotExist(err) && err != nil { 119 return "", err 120 } 121 if len(b) > 0 { 122 return string(b), nil 123 } 124 125 if stat, _ := os.Stdin.Stat(); (stat.Mode() & os.ModeCharDevice) == 0 { 126 b, err = ioutil.ReadAll(os.Stdin) 127 if err != nil { 128 return "", err 129 } 130 if len(b) > 0 { 131 return string(b), nil 132 } 133 } 134 135 var tmpl = ` 136 {{.CommentChar}} In this mode you are writing a snippet from scratch 137 {{.CommentChar}} The first block is the title and the rest is the contents.` 138 139 text, err := snipText(tmpl) 140 if err != nil { 141 log.Fatal(err) 142 } 143 title, body, err := git.Edit("SNIPCODE", text) 144 if err != nil { 145 _, f, l, _ := runtime.Caller(0) 146 log.Fatal(f+":"+strconv.Itoa(l)+" ", err) 147 } 148 return fmt.Sprintf("%s\n\n%s", title, body), nil 149 } 150 151 func snipText(tmpl string) (string, error) { 152 t, err := template.New("tmpl").Parse(tmpl) 153 if err != nil { 154 return "", err 155 } 156 157 cc := git.CommentChar() 158 msg := &struct{ CommentChar string }{CommentChar: cc} 159 var b bytes.Buffer 160 err = t.Execute(&b, msg) 161 if err != nil { 162 return "", err 163 } 164 165 return b.String(), nil 166 } 167 168 func init() { 169 snippetCreateCmd.Flags().BoolVarP(&private, "private", "p", false, "Make snippet private; visible only to project members (default: internal)") 170 snippetCreateCmd.Flags().BoolVar(&public, "public", false, "Make snippet public; can be accessed without any authentication (default: internal)") 171 snippetCreateCmd.Flags().StringVarP(&name, "name", "n", "", "(optional) Name snippet to add code highlighting, e.g. potato.go for GoLang") 172 snippetCreateCmd.Flags().StringSliceP("message", "m", []string{"-"}, "Use the given <msg>; multiple -m are concatenated as seperate paragraphs") 173 snippetCmd.Flags().AddFlagSet(snippetCreateCmd.Flags()) 174 snippetCmd.AddCommand(snippetCreateCmd) 175 }