-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathcmd.go
173 lines (160 loc) · 5.76 KB
/
cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (c) Bartłomiej Płotka @bwplotka
// Licensed under the Apache License 2.0.
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"path/filepath"
"regexp"
"syscall"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/bwplotka/bingo/pkg/bingo"
"github.com/bwplotka/bingo/pkg/runner"
"github.com/bwplotka/bingo/pkg/version"
)
func NewBingoGetCommand(logger *log.Logger) *cobra.Command {
var (
goCmd string
rename string
name string
insecure bool
link bool
timeOut uint
)
cmd := &cobra.Command{
Use: "get [flags] [<package or binary>[@version1 or none,version2,version3...]]",
Example: "bingo get github.com/fatih/faillint\n" +
"bingo get github.com/fatih/faillint@latest\n" +
"bingo get github.com/fatih/[email protected]\n" +
"bingo get github.com/fatih/[email protected],v1.5.0\n" +
"bingo get github.com/fatih/faillint@none // this will be deleted ",
Short: "add development tools to the current project (e.g: bingo get github.com/fatih/faillint@latest)",
Long: "go get like, simple CLI that allows automated versioning of Go package level \n" +
"binaries(e.g required as dev tools by your project!) built on top of Go Modules, allowing reproducible dev environments.",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if len(goCmd) == 0 {
return errors.New("'go' flag cannot be empty")
}
if len(args) > 1 {
return errors.New("too many arguments except none or binary/package")
}
if len(rename) > 0 && len(name) > 0 {
return errors.New("Both -n and -r were specified. You can either rename or create new one.")
}
if len(name) > 0 && !regexp.MustCompile(`[a-zA-Z0-9.-_]+`).MatchString(name) {
return errors.New("-n name contains not allowed characters")
}
if len(rename) > 0 && !regexp.MustCompile(`[a-zA-Z0-9.-_]+`).MatchString(rename) {
return errors.New("-r name contains not allowed characters")
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
modDirAbs, err := filepath.Abs(moddir)
if err != nil {
return errors.Wrap(err, "abs")
}
defer func() {
if err == nil {
// Leave tmp files on error for debug purposes.
if cerr := cleanGoGetTmpFiles(modDirAbs); cerr != nil {
logger.Println("cannot clean tmp files", err)
}
}
}()
r, err := runner.NewRunner(ctx, logger, insecure, goCmd)
if err != nil {
return err
}
if verbose {
r.Verbose()
}
cfg := getConfig{
runner: r,
modDir: modDirAbs,
relModDir: moddir,
name: name,
rename: rename,
link: link,
timeOut: timeOut,
verbose: verbose,
}
var target string
if len(args) > 0 {
target = args[0]
}
if err := get(ctx, logger, cfg, target); err != nil {
return errors.Wrap(err, "get")
}
pkgs, err := bingo.ListPinnedMainPackages(logger, modDirAbs, true)
if err != nil {
return errors.Wrap(err, "list pinned")
}
if len(pkgs) == 0 {
return bingo.RemoveHelpers(modDirAbs)
}
return bingo.GenHelpers(moddir, version.Version, pkgs)
},
}
flags := cmd.Flags()
flags.StringVarP(&name, "name", "n", "", "The -n flag instructs to get binary and name it with given name instead of default,\n"+
"so the last element of package directory. Allowed characters [A-z0-9._-]. If -n is used and no package/binary is specified,\n"+
"bingo get will return error. If -n is used with existing binary name, copy of this binary will be done. Cannot be used with -r")
flags.StringVarP(&rename, "rename", "r", "", "The -r flag instructs to get existing binary and rename it with given name. Allowed characters [A-z0-9._-]. \n"+
"If -r is used and no package/binary is specified or non existing binary name is used, bingo will return error. Cannot be used with -n.")
flags.StringVar(&goCmd, "go", "go", "Path to the go command.")
flags.BoolVar(&insecure, "insecure", insecure, `Use -insecure flag when using 'go get'`)
flags.BoolVarP(&link, "link", "l", link, "If enabled, bingo will also create soft link called <tool> that links to the current <tool>-<version> binary.\n"+
"Use Variables.mk and variables.env if you want to be sure that what you are invoking is what is pinned.")
flags.UintVarP(&timeOut, "timeout", "t", 5, "The maximum time (in minutes) to wait for each go command before killing it.\n"+
"Set this flag to 0 to indefinitely wait on them.")
return cmd
}
func NewBingoListCommand(logger *log.Logger) *cobra.Command {
cmd := &cobra.Command{
Use: "list <flags> [<package or binary>]",
Version: version.Version,
Short: "List enumerates all or one binary that are/is currently pinned in this project. ",
Long: "List enumerates all or one binary that are/is currently pinned in this project. It will print exact path, Version and immutable output.",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return errors.New("too many arguments except none or binary/package")
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
modDir, err := filepath.Abs(moddir)
if err != nil {
return errors.Wrap(err, "abs")
}
pkgs, err := bingo.ListPinnedMainPackages(logger, modDir, false)
if err != nil {
return err
}
var target string
if len(args) > 0 {
target = args[0]
}
bingo.SortRenderables(pkgs)
return pkgs.PrintTab(target, os.Stdout)
},
}
return cmd
}
func NewBingoVersionCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Prints bingo Version.",
Long: `Prints bingo Version.`,
Run: func(cmd *cobra.Command, args []string) {
_, _ = fmt.Fprintln(os.Stdout, version.Version)
},
}
return cmd
}