Add version tags alongside commit hashes in output

- tools.json now has both "version" (tag) and "hash" (commit) fields
- Output format: toolname@version [hash] (in duration)
- Update tool fetches and stores both version and hash
- Fix .gitignore to not exclude cmd/update directory
This commit is contained in:
Jeffrey Paul 2025-12-18 05:58:39 -08:00
parent 49ba38602c
commit 998dc1d37b
4 changed files with 88 additions and 43 deletions

4
.gitignore vendored
View File

@ -1,6 +1,6 @@
# Binaries # Binaries
gosetup /gosetup
update /update
*.exe *.exe
# Test binaries # Test binaries

View File

@ -17,6 +17,7 @@ type Tool struct {
Name string `json:"name"` Name string `json:"name"`
Package string `json:"package"` Package string `json:"package"`
Version string `json:"version"` Version string `json:"version"`
Hash string `json:"hash"`
Date string `json:"date"` Date string `json:"date"`
} }
@ -85,11 +86,15 @@ func main() {
failed++ failed++
} else { } else {
updatedTools[r.idx] = r.updated updatedTools[r.idx] = r.updated
if r.tool.Version != r.updated.Version { oldHash := r.tool.Hash
fmt.Printf("↑ %s: %s -> %s\n", r.tool.Name, r.tool.Version, r.updated.Version) if oldHash == "" {
oldHash = r.tool.Version // migration from old format
}
if oldHash != r.updated.Hash {
fmt.Printf("↑ %s: %s [%s] -> %s [%s]\n", r.tool.Name, r.tool.Version, shortHash(oldHash), r.updated.Version, r.updated.Hash[:12])
changed++ changed++
} else { } else {
fmt.Printf("✓ %s: %s (unchanged)\n", r.tool.Name, r.tool.Version) fmt.Printf("✓ %s: %s [%s] (unchanged)\n", r.tool.Name, r.updated.Version, r.updated.Hash[:12])
} }
succeeded++ succeeded++
} }
@ -226,7 +231,8 @@ func fetchLatestVersion(tool Tool) (Tool, error) {
return Tool{ return Tool{
Name: tool.Name, Name: tool.Name,
Package: tool.Package, Package: tool.Package,
Version: fullHash, Version: info.Version,
Hash: fullHash,
Date: date, Date: date,
}, nil }, nil
} }
@ -243,7 +249,8 @@ func fetchLatestVersion(tool Tool) (Tool, error) {
return Tool{ return Tool{
Name: tool.Name, Name: tool.Name,
Package: tool.Package, Package: tool.Package,
Version: hash, Version: info.Version,
Hash: hash,
Date: date, Date: date,
}, nil }, nil
} }
@ -294,3 +301,10 @@ type result struct {
updated Tool updated Tool
err error err error
} }
func shortHash(h string) string {
if len(h) >= 12 {
return h[:12]
}
return h
}

13
main.go
View File

@ -18,6 +18,7 @@ type Tool struct {
Name string `json:"name"` Name string `json:"name"`
Package string `json:"package"` Package string `json:"package"`
Version string `json:"version"` Version string `json:"version"`
Hash string `json:"hash"`
Date string `json:"date"` Date string `json:"date"`
} }
@ -40,7 +41,7 @@ func main() {
if *list { if *list {
for _, t := range tf.Tools { for _, t := range tf.Tools {
fmt.Printf("%-20s %s (%s)\n", t.Name, t.Version, t.Date) fmt.Printf("%-20s %s [%s] (%s)\n", t.Name, t.Version, t.Hash[:12], t.Date)
} }
return return
} }
@ -49,7 +50,7 @@ func main() {
if *dryRun { if *dryRun {
for _, t := range tf.Tools { for _, t := range tf.Tools {
fmt.Printf("go install %s@%s\n", t.Package, t.Version) fmt.Printf("go install %s@%s\n", t.Package, t.Hash)
} }
return return
} }
@ -68,11 +69,11 @@ func main() {
defer func() { <-sem }() defer func() { <-sem }()
if *verbose { if *verbose {
fmt.Printf("Installing %s@%s...\n", tool.Name, tool.Version) fmt.Printf("Installing %s@%s...\n", tool.Name, tool.Hash)
} }
toolStart := time.Now() toolStart := time.Now()
pkg := fmt.Sprintf("%s@%s", tool.Package, tool.Version) pkg := fmt.Sprintf("%s@%s", tool.Package, tool.Hash)
cmd := exec.Command("go", "install", pkg) cmd := exec.Command("go", "install", pkg)
cmd.Env = os.Environ() cmd.Env = os.Environ()
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
@ -88,13 +89,13 @@ func main() {
var succeeded, failed int var succeeded, failed int
for r := range results { for r := range results {
if r.err != nil { if r.err != nil {
fmt.Printf("✗ %s@%s: %v (%s)\n", r.tool.Name, r.tool.Version, r.err, formatDuration(r.duration)) fmt.Printf("✗ %s@%s [%s]: %v (in %s)\n", r.tool.Name, r.tool.Version, r.tool.Hash[:12], r.err, formatDuration(r.duration))
if *verbose && r.output != "" { if *verbose && r.output != "" {
fmt.Printf(" %s\n", r.output) fmt.Printf(" %s\n", r.output)
} }
failed++ failed++
} else { } else {
fmt.Printf("✓ %s@%s (%s)\n", r.tool.Name, r.tool.Version, formatDuration(r.duration)) fmt.Printf("✓ %s@%s [%s] (in %s)\n", r.tool.Name, r.tool.Version, r.tool.Hash[:12], formatDuration(r.duration))
succeeded++ succeeded++
} }
} }

View File

@ -3,181 +3,211 @@
{ {
"name": "gopls", "name": "gopls",
"package": "golang.org/x/tools/gopls", "package": "golang.org/x/tools/gopls",
"version": "ecc727ef4e92b7170abe1881910c4c8773800196", "version": "v0.21.0",
"hash": "ecc727ef4e92b7170abe1881910c4c8773800196",
"date": "2025-12-05" "date": "2025-12-05"
}, },
{ {
"name": "gofumpt", "name": "gofumpt",
"package": "mvdan.cc/gofumpt", "package": "mvdan.cc/gofumpt",
"version": "5504461061294d4d80f5a7d2fdfa98d9a75ae69b", "version": "v0.9.2",
"hash": "5504461061294d4d80f5a7d2fdfa98d9a75ae69b",
"date": "2025-10-21" "date": "2025-10-21"
}, },
{ {
"name": "goimports", "name": "goimports",
"package": "golang.org/x/tools/cmd/goimports", "package": "golang.org/x/tools/cmd/goimports",
"version": "00b22d96a3616723b0ee0341fb34c40b73e19c96", "version": "v0.40.0",
"hash": "00b22d96a3616723b0ee0341fb34c40b73e19c96",
"date": "2025-12-08" "date": "2025-12-08"
}, },
{ {
"name": "godoc", "name": "godoc",
"package": "golang.org/x/tools/cmd/godoc", "package": "golang.org/x/tools/cmd/godoc",
"version": "ccfe399eae9bf60bad2b93ac1f9a37d08d3c46df", "version": "v0.1.0-deprecated",
"hash": "ccfe399eae9bf60bad2b93ac1f9a37d08d3c46df",
"date": "2025-09-04" "date": "2025-09-04"
}, },
{ {
"name": "golangci-lint", "name": "golangci-lint",
"package": "github.com/golangci/golangci-lint/cmd/golangci-lint", "package": "github.com/golangci/golangci-lint/cmd/golangci-lint",
"version": "8b37f14162043f908949f1b363d061dc9ba713c0", "version": "v1.64.8",
"hash": "8b37f14162043f908949f1b363d061dc9ba713c0",
"date": "2025-03-17" "date": "2025-03-17"
}, },
{ {
"name": "staticcheck", "name": "staticcheck",
"package": "honnef.co/go/tools/cmd/staticcheck", "package": "honnef.co/go/tools/cmd/staticcheck",
"version": "b7ae2809b76e7d4ab5a4cc907919fc80b7d84c68", "version": "v0.6.1",
"hash": "b7ae2809b76e7d4ab5a4cc907919fc80b7d84c68",
"date": "2025-03-05" "date": "2025-03-05"
}, },
{ {
"name": "errcheck", "name": "errcheck",
"package": "github.com/kisielk/errcheck", "package": "github.com/kisielk/errcheck",
"version": "11c27a7ce69d583465d80d808817d22d6653ee34", "version": "v1.9.0",
"hash": "11c27a7ce69d583465d80d808817d22d6653ee34",
"date": "2025-02-19" "date": "2025-02-19"
}, },
{ {
"name": "revive", "name": "revive",
"package": "github.com/mgechev/revive", "package": "github.com/mgechev/revive",
"version": "ac5f398440705ae79abf836674f46c24a2494949", "version": "v1.13.0",
"hash": "ac5f398440705ae79abf836674f46c24a2494949",
"date": "2025-11-13" "date": "2025-11-13"
}, },
{ {
"name": "godef", "name": "godef",
"package": "github.com/rogpeppe/godef", "package": "github.com/rogpeppe/godef",
"version": "8318a6814d22e99151760ac2fc890f55088a3192", "version": "v1.1.2",
"hash": "8318a6814d22e99151760ac2fc890f55088a3192",
"date": "2020-03-03" "date": "2020-03-03"
}, },
{ {
"name": "gotests", "name": "gotests",
"package": "github.com/cweill/gotests/gotests", "package": "github.com/cweill/gotests/gotests",
"version": "f6659a2f552227d25e79651377cddc1ffbd49006", "version": "v1.9.0",
"hash": "f6659a2f552227d25e79651377cddc1ffbd49006",
"date": "2025-10-23" "date": "2025-10-23"
}, },
{ {
"name": "gomodifytags", "name": "gomodifytags",
"package": "github.com/fatih/gomodifytags", "package": "github.com/fatih/gomodifytags",
"version": "0af24e19f5a325b1e6ef83692b8946b546491586", "version": "v1.17.0",
"hash": "0af24e19f5a325b1e6ef83692b8946b546491586",
"date": "2024-07-15" "date": "2024-07-15"
}, },
{ {
"name": "impl", "name": "impl",
"package": "github.com/josharian/impl", "package": "github.com/josharian/impl",
"version": "923c93ed5ade114ce3bb9e77c71e52e8b6724cf7", "version": "v1.5.0",
"hash": "923c93ed5ade114ce3bb9e77c71e52e8b6724cf7",
"date": "2025-12-09" "date": "2025-12-09"
}, },
{ {
"name": "fillstruct", "name": "fillstruct",
"package": "github.com/davidrjenni/reftools/cmd/fillstruct", "package": "github.com/davidrjenni/reftools/cmd/fillstruct",
"version": "34b10582faa4220d684a595b3e1237f244707e23", "version": "v0.0.0-20250907133731-34b10582faa4",
"hash": "34b10582faa4220d684a595b3e1237f244707e23",
"date": "2025-09-07" "date": "2025-09-07"
}, },
{ {
"name": "fillswitch", "name": "fillswitch",
"package": "github.com/davidrjenni/reftools/cmd/fillswitch", "package": "github.com/davidrjenni/reftools/cmd/fillswitch",
"version": "34b10582faa4220d684a595b3e1237f244707e23", "version": "v0.0.0-20250907133731-34b10582faa4",
"hash": "34b10582faa4220d684a595b3e1237f244707e23",
"date": "2025-09-07" "date": "2025-09-07"
}, },
{ {
"name": "fixplurals", "name": "fixplurals",
"package": "github.com/davidrjenni/reftools/cmd/fixplurals", "package": "github.com/davidrjenni/reftools/cmd/fixplurals",
"version": "34b10582faa4220d684a595b3e1237f244707e23", "version": "v0.0.0-20250907133731-34b10582faa4",
"hash": "34b10582faa4220d684a595b3e1237f244707e23",
"date": "2025-09-07" "date": "2025-09-07"
}, },
{ {
"name": "dlv", "name": "dlv",
"package": "github.com/go-delve/delve/cmd/dlv", "package": "github.com/go-delve/delve/cmd/dlv",
"version": "498ee9c27223fed032af8856f7a62590a63b9439", "version": "v1.25.2",
"hash": "498ee9c27223fed032af8856f7a62590a63b9439",
"date": "2025-08-27" "date": "2025-08-27"
}, },
{ {
"name": "gotags", "name": "gotags",
"package": "github.com/jstemmer/gotags", "package": "github.com/jstemmer/gotags",
"version": "4cd81528d803e5044b3732a5e7a1dfab5ddc1514", "version": "v1.4.1",
"hash": "4cd81528d803e5044b3732a5e7a1dfab5ddc1514",
"date": "2017-04-03" "date": "2017-04-03"
}, },
{ {
"name": "gogetdoc", "name": "gogetdoc",
"package": "github.com/zmb3/gogetdoc", "package": "github.com/zmb3/gogetdoc",
"version": "b37376c5da6aeb900611837098f40f81972e63e4", "version": "v0.0.0-20190228002656-b37376c5da6a",
"hash": "b37376c5da6aeb900611837098f40f81972e63e4",
"date": "2019-02-28" "date": "2019-02-28"
}, },
{ {
"name": "iferr", "name": "iferr",
"package": "github.com/koron/iferr", "package": "github.com/koron/iferr",
"version": "9c3e2fbe4bd19a7f0338e42bb483562ed4cf4d50", "version": "v0.0.0-20240122035601-9c3e2fbe4bd1",
"hash": "9c3e2fbe4bd19a7f0338e42bb483562ed4cf4d50",
"date": "2024-01-22" "date": "2024-01-22"
}, },
{ {
"name": "asmfmt", "name": "asmfmt",
"package": "github.com/klauspost/asmfmt/cmd/asmfmt", "package": "github.com/klauspost/asmfmt/cmd/asmfmt",
"version": "ef134b9cec704e2b7b336fb02153b7d1a58247da", "version": "v1.3.2",
"hash": "ef134b9cec704e2b7b336fb02153b7d1a58247da",
"date": "2022-03-30" "date": "2022-03-30"
}, },
{ {
"name": "motion", "name": "motion",
"package": "github.com/fatih/motion", "package": "github.com/fatih/motion",
"version": "3360433d74666f4e1250c857656bc7178d0f3933", "version": "v1.2.0",
"hash": "3360433d74666f4e1250c857656bc7178d0f3933",
"date": "2023-02-16" "date": "2023-02-16"
}, },
{ {
"name": "gojson", "name": "gojson",
"package": "github.com/ChimeraCoder/gojson/gojson", "package": "github.com/ChimeraCoder/gojson/gojson",
"version": "fa01aa3a208834638989d1255282988a4865629d", "version": "v1.1.0",
"hash": "fa01aa3a208834638989d1255282988a4865629d",
"date": "2018-08-18" "date": "2018-08-18"
}, },
{ {
"name": "golines", "name": "golines",
"package": "github.com/segmentio/golines", "package": "github.com/segmentio/golines",
"version": "8f32f0f7e89c30f572c7f2cd3b2a48016b9d8bbf", "version": "v0.13.0",
"hash": "8f32f0f7e89c30f572c7f2cd3b2a48016b9d8bbf",
"date": "2025-08-21" "date": "2025-08-21"
}, },
{ {
"name": "gocyclo", "name": "gocyclo",
"package": "github.com/fzipp/gocyclo/cmd/gocyclo", "package": "github.com/fzipp/gocyclo/cmd/gocyclo",
"version": "62aa1f84d9ea7d68ecc499a74e98f188f63b650e", "version": "v0.6.0",
"hash": "62aa1f84d9ea7d68ecc499a74e98f188f63b650e",
"date": "2022-06-15" "date": "2022-06-15"
}, },
{ {
"name": "ineffassign", "name": "ineffassign",
"package": "github.com/gordonklaus/ineffassign", "package": "github.com/gordonklaus/ineffassign",
"version": "cc8665bbd67af3cf6a54bc55bef821949f7ce0e9", "version": "v0.2.0",
"hash": "cc8665bbd67af3cf6a54bc55bef821949f7ce0e9",
"date": "2025-08-24" "date": "2025-08-24"
}, },
{ {
"name": "misspell", "name": "misspell",
"package": "github.com/client9/misspell/cmd/misspell", "package": "github.com/client9/misspell/cmd/misspell",
"version": "7888c6b6ce89353cd98e196bce3c3f9e4cdf31f6", "version": "v0.3.4",
"hash": "7888c6b6ce89353cd98e196bce3c3f9e4cdf31f6",
"date": "2018-03-09" "date": "2018-03-09"
}, },
{ {
"name": "unconvert", "name": "unconvert",
"package": "github.com/mdempsky/unconvert", "package": "github.com/mdempsky/unconvert",
"version": "4a038b3d31f56ff5ba511953b745c80a2317e4ae", "version": "v0.0.0-20250216222326-4a038b3d31f5",
"hash": "4a038b3d31f56ff5ba511953b745c80a2317e4ae",
"date": "2025-02-16" "date": "2025-02-16"
}, },
{ {
"name": "gopkgs", "name": "gopkgs",
"package": "github.com/uudashr/gopkgs/v2/cmd/gopkgs", "package": "github.com/uudashr/gopkgs/v2/cmd/gopkgs",
"version": "4d0f738b8305f9b3a4b8d6471aaa60e9211636a4", "version": "v2.1.2",
"hash": "4d0f738b8305f9b3a4b8d6471aaa60e9211636a4",
"date": "2020-02-14" "date": "2020-02-14"
}, },
{ {
"name": "go-outline", "name": "go-outline",
"package": "github.com/ramya-rao-a/go-outline", "package": "github.com/ramya-rao-a/go-outline",
"version": "9736a4bde949f321d201e5eaa5ae2bcde011bf00", "version": "v0.0.0-20210608161538-9736a4bde949",
"hash": "9736a4bde949f321d201e5eaa5ae2bcde011bf00",
"date": "2021-06-08" "date": "2021-06-08"
}, },
{ {
"name": "go-symbols", "name": "go-symbols",
"package": "github.com/acroca/go-symbols", "package": "github.com/acroca/go-symbols",
"version": "b3af8b100b8a7d0136e0c17820a066d8365f1316", "version": "v0.1.1",
"hash": "b3af8b100b8a7d0136e0c17820a066d8365f1316",
"date": "2019-01-14" "date": "2019-01-14"
} }
] ]