feat: update go.mod

main
sudo pacman -Syu 2022-07-22 21:09:34 +07:00
commit afb1ad6256
No known key found for this signature in database
GPG Key ID: D6CB5C6C567C47B0
10 changed files with 374 additions and 0 deletions

2
.deps Normal file
View File

@ -0,0 +1,2 @@
github.com/make-go-great/color-go
github.com/urfave/cli/v2

17
.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
# macOS
.DS_Store
# Window
*.exe
# IntelliJ
.idea
# VSCode
.vscode
# Go
coverage.out
# GoReleaser
dist

74
.golangci.yml Normal file
View File

@ -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

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# update-go-mod
## Thanks
- [Managing dependencies](https://go.dev/doc/modules/managing-dependencies)

View File

@ -0,0 +1,8 @@
package main
import "github.com/haunt98/update-go-mod/internal/cli"
func main() {
app := cli.NewApp()
app.Run()
}

18
go.mod Normal file
View File

@ -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
)

21
go.sum Normal file
View File

@ -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=

33
internal/cli/action.go Normal file
View File

@ -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...)
}
}

121
internal/cli/action_run.go Normal file
View File

@ -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
}

75
internal/cli/app.go Normal file
View File

@ -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())
}
}