feat: update go.mod
commit
afb1ad6256
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/make-go-great/color-go
|
||||||
|
github.com/urfave/cli/v2
|
|
@ -0,0 +1,17 @@
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Window
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# Go
|
||||||
|
coverage.out
|
||||||
|
|
||||||
|
# GoReleaser
|
||||||
|
dist
|
|
@ -0,0 +1,74 @@
|
||||||
|
run:
|
||||||
|
tests: false
|
||||||
|
skip-dirs:
|
||||||
|
- ".*test.*"
|
||||||
|
- ".*mock.*"
|
||||||
|
- ".*generated.*"
|
||||||
|
- ".*example.*"
|
||||||
|
skip-files:
|
||||||
|
- ".*Mock.*"
|
||||||
|
- ".*_mock.*"
|
||||||
|
- ".*_generated.*"
|
||||||
|
go: "1.18"
|
||||||
|
|
||||||
|
output:
|
||||||
|
sort-results: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- deadcode
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- staticcheck
|
||||||
|
- typecheck
|
||||||
|
- unused
|
||||||
|
- varcheck
|
||||||
|
- errname
|
||||||
|
- errorlint
|
||||||
|
- execinquery
|
||||||
|
- goerr113
|
||||||
|
- gofumpt
|
||||||
|
- gosec
|
||||||
|
- ifshort
|
||||||
|
- importas
|
||||||
|
- makezero
|
||||||
|
- nilnil
|
||||||
|
- prealloc
|
||||||
|
- unconvert
|
||||||
|
fast: true
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
gosec:
|
||||||
|
excludes:
|
||||||
|
- G402
|
||||||
|
- G501
|
||||||
|
- G505
|
||||||
|
exclude-generated: true
|
||||||
|
govet:
|
||||||
|
check-shadowing: false
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- assign
|
||||||
|
- atomic
|
||||||
|
- bools
|
||||||
|
- buildtag
|
||||||
|
- composites
|
||||||
|
- copylocks
|
||||||
|
- fieldalignment
|
||||||
|
- httpresponse
|
||||||
|
- loopclosure
|
||||||
|
- lostcancel
|
||||||
|
- nilfunc
|
||||||
|
- printf
|
||||||
|
- unmarshal
|
||||||
|
- unreachable
|
||||||
|
- unusedresult
|
||||||
|
staticcheck:
|
||||||
|
go: "1.18"
|
||||||
|
checks: ["all", "-SA1019"]
|
||||||
|
|
||||||
|
issues:
|
||||||
|
new: true
|
||||||
|
fix: true
|
|
@ -0,0 +1,5 @@
|
||||||
|
# update-go-mod
|
||||||
|
|
||||||
|
## Thanks
|
||||||
|
|
||||||
|
- [Managing dependencies](https://go.dev/doc/modules/managing-dependencies)
|
|
@ -0,0 +1,8 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/haunt98/update-go-mod/internal/cli"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Run()
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
module github.com/haunt98/update-go-mod
|
||||||
|
|
||||||
|
go 1.18
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/make-go-great/color-go v0.4.1
|
||||||
|
github.com/urfave/cli/v2 v2.11.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||||
|
)
|
|
@ -0,0 +1,21 @@
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
|
github.com/make-go-great/color-go v0.4.1 h1:4HIat5r1oQneu5BSDUjHKN/9x4Ay2qEEkswdOgk/VRY=
|
||||||
|
github.com/make-go-great/color-go v0.4.1/go.mod h1:G5G8IJ3PUo+vSQ+UvnfaswF8O/piVIhFJKv1mQjBGpI=
|
||||||
|
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/urfave/cli/v2 v2.11.1 h1:UKK6SP7fV3eKOefbS87iT9YHefv7iB/53ih6e+GNAsE=
|
||||||
|
github.com/urfave/cli/v2 v2.11.1/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||||
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
@ -0,0 +1,33 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type action struct {
|
||||||
|
flags struct {
|
||||||
|
depsFile string
|
||||||
|
verbose bool
|
||||||
|
dryRun bool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *action) RunHelp(c *cli.Context) error {
|
||||||
|
return cli.ShowAppHelp(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *action) getFlags(c *cli.Context) {
|
||||||
|
a.flags.verbose = c.Bool(flagVerbose)
|
||||||
|
a.flags.depsFile = c.String(flagDepsFile)
|
||||||
|
a.flags.dryRun = c.Bool(flagDryRun)
|
||||||
|
|
||||||
|
a.log("flags %+v", a.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *action) log(format string, v ...interface{}) {
|
||||||
|
if a.flags.verbose {
|
||||||
|
log.Printf(format, v...)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/make-go-great/color-go"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrInvalidModuleVersion = errors.New("invalid module version")
|
||||||
|
|
||||||
|
// See https://pkg.go.dev/cmd/go#hdr-List_packages_or_modules
|
||||||
|
type Module struct {
|
||||||
|
Update *Module
|
||||||
|
Path string
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *action) Run(c *cli.Context) error {
|
||||||
|
a.getFlags(c)
|
||||||
|
|
||||||
|
// Get all imported modules
|
||||||
|
goListAllArgs := []string{"list", "-m", "-json", "all"}
|
||||||
|
goOutput, err := exec.CommandContext(c.Context, "go", goListAllArgs...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to run go %+v: %w", strings.Join(goListAllArgs, " "), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// goAllOutput is like {...}\n{...}\n{...}
|
||||||
|
// Missing [] and , for json
|
||||||
|
goOutputStr := strings.ReplaceAll(strings.TrimSpace(string(goOutput)), "\n", "")
|
||||||
|
goOutputStr = strings.ReplaceAll(goOutputStr, "}{", "},{")
|
||||||
|
goOutputStr = "[" + goOutputStr + "]"
|
||||||
|
|
||||||
|
importedModules := make([]Module, 0, 100)
|
||||||
|
if err := json.Unmarshal([]byte(goOutputStr), &importedModules); err != nil {
|
||||||
|
return fmt.Errorf("failed to json unmarshal: %w", err)
|
||||||
|
}
|
||||||
|
a.log("go output: %s", string(goOutput))
|
||||||
|
|
||||||
|
mapImportedModules := make(map[string]struct{})
|
||||||
|
for _, importedModule := range importedModules {
|
||||||
|
mapImportedModules[importedModule.Path] = struct{}{}
|
||||||
|
}
|
||||||
|
a.log("imported modules: %+v\n", importedModules)
|
||||||
|
|
||||||
|
// Read pkg from file
|
||||||
|
depsFileBytes, err := os.ReadFile(a.flags.depsFile)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
color.PrintAppWarning(name, fmt.Sprintf("deps file [%s] not found", a.flags.depsFile))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("failed to read file %s: %w", a.flags.depsFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
depsFileStr := strings.TrimSpace(string(depsFileBytes))
|
||||||
|
lines := strings.Split(depsFileStr, "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
a.log("line: %s", line)
|
||||||
|
|
||||||
|
// Check if line is imported module, otherwise skip
|
||||||
|
if _, ok := mapImportedModules[line]; !ok {
|
||||||
|
a.log("%s is not imported module", line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get module latest version
|
||||||
|
goListArgs := []string{"list", "-m", "-u", "-json", line}
|
||||||
|
goOutput, err = exec.CommandContext(c.Context, "go", goListArgs...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to run go %+v: %w", strings.Join(goListArgs, " "), err)
|
||||||
|
}
|
||||||
|
a.log("go output: %s", string(goOutput))
|
||||||
|
|
||||||
|
module := Module{}
|
||||||
|
if err := json.Unmarshal(goOutput, &module); err != nil {
|
||||||
|
return fmt.Errorf("failed to json unmarshal: %w", err)
|
||||||
|
}
|
||||||
|
a.log("module: %+v", module)
|
||||||
|
|
||||||
|
if module.Update == nil {
|
||||||
|
color.PrintAppOK(name, fmt.Sprintf("You already have latest [%s] version [%s]", module.Path, module.Version))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upgrade module
|
||||||
|
if a.flags.dryRun {
|
||||||
|
color.PrintAppOK(name, fmt.Sprintf("Will upgrade [%s] version [%s] to [%s]", module.Path, module.Version, module.Update.Version))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
goGetArgs := []string{"get", "-d", line + "@" + module.Update.Version}
|
||||||
|
goOutput, err = exec.CommandContext(c.Context, "go", goGetArgs...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to run go %+v: %w", strings.Join(goGetArgs, " "), err)
|
||||||
|
}
|
||||||
|
a.log("go output: %s", string(goOutput))
|
||||||
|
|
||||||
|
color.PrintAppOK(name, fmt.Sprintf("Upgraded [%s] version [%s] to [%s] success", module.Path, module.Version, module.Update.Version))
|
||||||
|
}
|
||||||
|
|
||||||
|
goModArgs := []string{"mod", "tidy"}
|
||||||
|
goOutput, err = exec.CommandContext(c.Context, "go", goModArgs...).CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to run go %+v: %w", strings.Join(goModArgs, " "), err)
|
||||||
|
}
|
||||||
|
a.log("go output: %s", string(goOutput))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/make-go-great/color-go"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
name = "update-go-mod"
|
||||||
|
usage = "excatly like the name says"
|
||||||
|
|
||||||
|
flagVerbose = "verbose"
|
||||||
|
flagDepsFile = "deps-file"
|
||||||
|
flagDryRun = "dry-run"
|
||||||
|
|
||||||
|
commandRun = "run"
|
||||||
|
|
||||||
|
usageCommandRun = "run the program"
|
||||||
|
usageFlagVerbose = "show what is going on"
|
||||||
|
usageDepsFile = "show what deps need to upgrade"
|
||||||
|
usageDryRun = "demo what would be done"
|
||||||
|
|
||||||
|
defaultDepsFile = ".deps"
|
||||||
|
)
|
||||||
|
|
||||||
|
var aliasFlagVerbose = []string{"v"}
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
cliApp *cli.App
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApp() *App {
|
||||||
|
a := &action{}
|
||||||
|
|
||||||
|
cliApp := &cli.App{
|
||||||
|
Name: name,
|
||||||
|
Usage: usage,
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
{
|
||||||
|
Name: commandRun,
|
||||||
|
Usage: usageCommandRun,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: flagVerbose,
|
||||||
|
Aliases: aliasFlagVerbose,
|
||||||
|
Usage: usageFlagVerbose,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: flagDepsFile,
|
||||||
|
Usage: usageDepsFile,
|
||||||
|
Value: defaultDepsFile,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: flagDryRun,
|
||||||
|
Usage: usageDryRun,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: a.Run,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: a.RunHelp,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &App{
|
||||||
|
cliApp: cliApp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) Run() {
|
||||||
|
if err := a.cliApp.Run(os.Args); err != nil {
|
||||||
|
color.PrintAppError(name, err.Error())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue