Compare commits

...

4 Commits

4 changed files with 116 additions and 39 deletions

7
go.mod
View File

@ -3,6 +3,7 @@ module github.com/haunt98/update-go-mod
go 1.22
require (
github.com/bytedance/sonic v1.12.3
github.com/google/go-github/v65 v65.0.0
github.com/make-go-great/color-go v0.5.0
github.com/make-go-great/netrc-go v0.0.2
@ -13,14 +14,20 @@ require (
)
require (
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/sys v0.18.0 // indirect
)

25
go.sum
View File

@ -1,3 +1,12 @@
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -14,6 +23,9 @@ github.com/google/go-github/v65 v65.0.0 h1:pQ7BmO3DZivvFk92geC0jB0q2m3gyn8vnYPgV
github.com/google/go-github/v65 v65.0.0/go.mod h1:DvrqWo5hvsdhJvHd4WyVF9ttANN3BniqjP8uTFMNb60=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -38,9 +50,17 @@ github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIK
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
@ -49,11 +69,16 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

View File

@ -1,7 +1,6 @@
package cli
import (
"encoding/json"
"errors"
"fmt"
"io"
@ -11,6 +10,7 @@ import (
"os/exec"
"strings"
"github.com/bytedance/sonic"
"github.com/urfave/cli/v2"
"github.com/make-go-great/color-go"
@ -30,18 +30,9 @@ const (
var (
ErrInvalidModuleVersion = errors.New("invalid module version")
ErrFailedStatusCode = errors.New("failed status code")
ErrGoModExistToolchain = errors.New("go mod exist toolchain")
)
// See https://pkg.go.dev/cmd/go#hdr-List_packages_or_modules
type Module struct {
Update *Module
Replace *Module
Path string
Version string
Main bool
Indirect bool
}
func (a *action) Run(c *cli.Context) error {
a.getFlags(c)
@ -66,7 +57,7 @@ func (a *action) Run(c *cli.Context) error {
}
// Read deps file line by line to upgrade
successUpgradedModules := make([]Module, 0, defaultCountModule)
successUpgradedModules := make([]*Module, 0, defaultCountModule)
modulePaths := strings.Split(depsStr, "\n")
for _, modulePath := range modulePaths {
successUpgradedModules, err = a.runUpgradeModule(
@ -92,11 +83,11 @@ func (a *action) Run(c *cli.Context) error {
}
// Get all imported modules
func (a *action) runGetImportedModules(c *cli.Context) (map[string]Module, error) {
func (a *action) runGetImportedModules(c *cli.Context) (map[string]*Module, error) {
goListAllArgs := []string{"list", "-m", "-json", "-mod=readonly", "all"}
goOutput, err := exec.CommandContext(c.Context, "go", goListAllArgs...).CombinedOutput()
if err != nil {
return nil, fmt.Errorf("failed to run go %s: %w", strings.Join(goListAllArgs, " "), err)
return nil, fmt.Errorf("exec: failed to run go %s: %w", strings.Join(goListAllArgs, " "), err)
}
// goAllOutput is like {...}\n{...}\n{...}
@ -105,13 +96,13 @@ func (a *action) runGetImportedModules(c *cli.Context) (map[string]Module, error
goOutputStr = strings.ReplaceAll(goOutputStr, "}{", "},{")
goOutputStr = "[" + goOutputStr + "]"
importedModules := make([]Module, 0, defaultCountModule)
if err := json.Unmarshal([]byte(goOutputStr), &importedModules); err != nil {
return nil, fmt.Errorf("failed to json unmarshal: %w", err)
importedModules := make([]*Module, 0, defaultCountModule)
if err := sonic.UnmarshalString(goOutputStr, &importedModules); err != nil {
return nil, fmt.Errorf("sonic: failed to unmarshal: %w", err)
}
a.log("Go output: %s\n", string(goOutput))
mapImportedModules := make(map[string]Module)
mapImportedModules := make(map[string]*Module)
for _, importedModule := range importedModules {
// Ignore main module
if importedModule.Main {
@ -141,23 +132,23 @@ func (a *action) runReadDepsFile() (depsStr string, useDepFile bool, err error)
if a.flags.depsURL != "" {
depsURL, err := url.Parse(a.flags.depsURL)
if err != nil {
return "", false, fmt.Errorf("failed to parse deps file url %s: %w", a.flags.depsURL, err)
return "", false, fmt.Errorf("url: failed to parse %s: %w", a.flags.depsURL, err)
}
// nolint:noctx
httpRsp, err := http.Get(depsURL.String())
if err != nil {
return "", false, fmt.Errorf("failed to http get %s: %w", depsURL.String(), err)
return "", false, fmt.Errorf("http: failed to get %s: %w", depsURL.String(), err)
}
defer httpRsp.Body.Close()
if httpRsp.StatusCode != http.StatusOK {
return "", false, fmt.Errorf("http status code not ok %d: %w", httpRsp.StatusCode, ErrFailedStatusCode)
return "", false, fmt.Errorf("http: status code not ok %d: %w", httpRsp.StatusCode, ErrFailedStatusCode)
}
depsBytes, err := io.ReadAll(httpRsp.Body)
if err != nil {
return "", false, fmt.Errorf("failed to read http response body: %w", err)
return "", false, fmt.Errorf("io: failed to read all: %w", err)
}
return strings.TrimSpace(string(depsBytes)), false, nil
@ -167,11 +158,11 @@ func (a *action) runReadDepsFile() (depsStr string, useDepFile bool, err error)
depsBytes, 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))
color.PrintAppWarning(name, fmt.Sprintf("[%s] not found", a.flags.depsFile))
return "", false, nil
}
return "", false, fmt.Errorf("failed to read file %s: %w", a.flags.depsFile, err)
return "", false, fmt.Errorf("os: failed to read file %s: %w", a.flags.depsFile, err)
}
return strings.TrimSpace(string(depsBytes)), true, nil
@ -179,10 +170,10 @@ func (a *action) runReadDepsFile() (depsStr string, useDepFile bool, err error)
func (a *action) runUpgradeModule(
c *cli.Context,
mapImportedModules map[string]Module,
successUpgradedModules []Module,
mapImportedModules map[string]*Module,
successUpgradedModules []*Module,
modulePath string,
) ([]Module, error) {
) ([]*Module, error) {
modulePath = strings.TrimSpace(modulePath)
// Ignore empty
@ -207,13 +198,13 @@ func (a *action) runUpgradeModule(
goListArgs := []string{"list", "-m", "-u", "-json", "-mod=readonly", modulePath}
goOutput, err := exec.CommandContext(c.Context, "go", goListArgs...).CombinedOutput()
if err != nil {
return successUpgradedModules, fmt.Errorf("failed to run go %+v: %w", strings.Join(goListArgs, " "), err)
return successUpgradedModules, fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goListArgs, " "), err)
}
a.log("Go output: %s\n", string(goOutput))
module := Module{}
if err := json.Unmarshal(goOutput, &module); err != nil {
return successUpgradedModules, fmt.Errorf("failed to json unmarshal: %w", err)
module := &Module{}
if err := sonic.Unmarshal(goOutput, module); err != nil {
return successUpgradedModules, fmt.Errorf("sonic: failed to unmarshal: %w", err)
}
a.log("Module: %+v\n", module)
@ -233,7 +224,7 @@ func (a *action) runUpgradeModule(
goGetArgs := []string{"get", "-d", modulePath + "@" + module.Update.Version}
goOutput, err = exec.CommandContext(c.Context, "go", goGetArgs...).CombinedOutput()
if err != nil {
return successUpgradedModules, fmt.Errorf("failed to run go %+v: %w", strings.Join(goGetArgs, " "), err)
return successUpgradedModules, fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goGetArgs, " "), err)
}
a.log("Go output: %s\n", string(goOutput))
@ -249,11 +240,17 @@ func (a *action) runGoMod(c *cli.Context, existVendor bool) error {
return nil
}
// go mod edit -toolchain=none
goModArgs := []string{"mod", "edit", "-toolchain=none"}
if _, err := exec.CommandContext(c.Context, "go", goModArgs...).CombinedOutput(); err != nil {
return fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goModArgs, " "), err)
}
// go mod tidy
goModArgs := []string{"mod", "tidy"}
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)
return fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goModArgs, " "), err)
}
a.log("Go output: %s\n", string(goOutput))
@ -262,15 +259,40 @@ func (a *action) runGoMod(c *cli.Context, existVendor bool) error {
goModArgs = []string{"mod", "vendor"}
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)
return fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goModArgs, " "), err)
}
a.log("Go output: %s\n", string(goOutput))
}
goMod, err := a.runReadGoMod()
if err != nil {
return err
}
if goMod.Toolchain != "" {
return ErrGoModExistToolchain
}
return nil
}
func (a *action) runGitCommit(c *cli.Context, successUpgradedModules []Module, existVendor, useDepFile bool) error {
func (a *action) runReadGoMod() (*GoMod, error) {
goModArgs := []string{"mod", "edit", "-json"}
goOutput, err := exec.Command("go", goModArgs...).CombinedOutput()
if err != nil {
return nil, fmt.Errorf("exec: failed to run go %+v: %w", strings.Join(goModArgs, " "), err)
}
goMod := &GoMod{}
if err := sonic.Unmarshal(goOutput, goMod); err != nil {
return nil, fmt.Errorf("sonic: failed to unmarshal: %w", err)
}
a.log("Go output: %s\n", string(goOutput))
return goMod, nil
}
func (a *action) runGitCommit(c *cli.Context, successUpgradedModules []*Module, existVendor, useDepFile bool) error {
if a.flags.dryRun {
return nil
}
@ -281,7 +303,7 @@ func (a *action) runGitCommit(c *cli.Context, successUpgradedModules []Module, e
return nil
}
return fmt.Errorf("failed to stat %s: %w", gitDirectory, err)
return fmt.Errorf("os: failed to stat %s: %w", gitDirectory, err)
}
// If there is no upgrade module, stop
@ -300,7 +322,7 @@ func (a *action) runGitCommit(c *cli.Context, successUpgradedModules []Module, e
gitOutput, err := exec.CommandContext(c.Context, "git", gitAddArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to run git %+v: %w", strings.Join(gitAddArgs, " "), err)
return fmt.Errorf("exec: failed to run git %+v: %w", strings.Join(gitAddArgs, " "), err)
}
a.log("Git output: %s\n", string(gitOutput))
@ -312,7 +334,7 @@ func (a *action) runGitCommit(c *cli.Context, successUpgradedModules []Module, e
gitCommitArgs := []string{"commit", "-m", gitCommitMessage}
gitOutput, err = exec.CommandContext(c.Context, "git", gitCommitArgs...).CombinedOutput()
if err != nil {
return fmt.Errorf("failed to run git %+v: %w", strings.Join(gitCommitArgs, " "), err)
return fmt.Errorf("exec: failed to run git %+v: %w", strings.Join(gitCommitArgs, " "), err)
}
a.log("Git output: %s\n", string(gitOutput))

23
internal/cli/models.go Normal file
View File

@ -0,0 +1,23 @@
package cli
// See https://pkg.go.dev/cmd/go#hdr-List_packages_or_modules
type Module struct {
Update *Module
Replace *Module
Path string
Version string
Main bool
Indirect bool
}
// https://pkg.go.dev/cmd/go#hdr-Edit_go_mod_from_tools_or_scripts
type GoMod struct {
Module ModPath
Go string
Toolchain string
}
type ModPath struct {
Path string
Deprecated string
}