Compare commits
7 Commits
64e871ad4f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 998dc1d37b | |||
| 49ba38602c | |||
| a414a82306 | |||
| 33c099ae4f | |||
| 30b1cebd02 | |||
| 0c31667230 | |||
| cf739a6e93 |
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Binaries
|
||||||
|
/gosetup
|
||||||
|
/update
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Test binaries
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
@@ -6,7 +6,7 @@ Installs common Go development tools at pinned versions.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# current as of 2025-12-18
|
# current as of 2025-12-18
|
||||||
go install sneak.berlin/go/gosetup@7188d87c39f4f468754c69a1e669d607771af22e ; hash -r ; gosetup
|
go install sneak.berlin/go/gosetup@a414a82306fe2095119eeeb3051bb3f23a803e1e ; hash -r ; gosetup
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -41,6 +41,7 @@ go run ./cmd/update -o tools.json
|
|||||||
- **Language Server**: gopls
|
- **Language Server**: gopls
|
||||||
- **Formatters**: gofumpt, goimports, golines
|
- **Formatters**: gofumpt, goimports, golines
|
||||||
- **Linters**: golangci-lint, staticcheck, errcheck, revive
|
- **Linters**: golangci-lint, staticcheck, errcheck, revive
|
||||||
- **vim-go tools**: godef, guru, gorename, gotests, gomodifytags, impl, fillstruct, fillswitch, motion, iferr, keyify, asmfmt, gotags
|
- **vim-go tools**: godef, gotests, gomodifytags, impl, fillstruct, fillswitch, motion, iferr, asmfmt, gotags
|
||||||
- **Debugger**: dlv (delve)
|
- **Debugger**: dlv (delve)
|
||||||
|
- **Documentation**: godoc
|
||||||
- **And more**: gocyclo, ineffassign, misspell, unconvert, gopkgs, go-outline, go-symbols
|
- **And more**: gocyclo, ineffassign, misspell, unconvert, gopkgs, go-outline, go-symbols
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -16,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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,6 +28,11 @@ type ToolsFile struct {
|
|||||||
type ModuleInfo struct {
|
type ModuleInfo struct {
|
||||||
Version string `json:"Version"`
|
Version string `json:"Version"`
|
||||||
Time string `json:"Time"`
|
Time string `json:"Time"`
|
||||||
|
Origin struct {
|
||||||
|
VCS string `json:"VCS"`
|
||||||
|
URL string `json:"URL"`
|
||||||
|
Hash string `json:"Hash"`
|
||||||
|
} `json:"Origin"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -79,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++
|
||||||
}
|
}
|
||||||
@@ -100,7 +111,7 @@ func main() {
|
|||||||
output = append(output, '\n')
|
output = append(output, '\n')
|
||||||
|
|
||||||
absPath, _ := filepath.Abs(*outputPath)
|
absPath, _ := filepath.Abs(*outputPath)
|
||||||
if err := os.WriteFile(*outputPath, output, 0644); err != nil {
|
if err := os.WriteFile(*outputPath, output, 0o644); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "error writing %s: %v\n", *outputPath, err)
|
fmt.Fprintf(os.Stderr, "error writing %s: %v\n", *outputPath, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -114,26 +125,81 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getModulePath extracts the module path from a package path
|
// getModulePath extracts the module path from a package path
|
||||||
// e.g., "golang.org/x/tools/cmd/goimports" -> "golang.org/x/tools"
|
|
||||||
func getModulePath(pkg string) string {
|
func getModulePath(pkg string) string {
|
||||||
// Handle special cases where cmd is in a subpath
|
|
||||||
if strings.Contains(pkg, "/cmd/") {
|
if strings.Contains(pkg, "/cmd/") {
|
||||||
parts := strings.Split(pkg, "/cmd/")
|
parts := strings.Split(pkg, "/cmd/")
|
||||||
return parts[0]
|
return parts[0]
|
||||||
}
|
}
|
||||||
// For packages like "github.com/cweill/gotests/gotests"
|
|
||||||
// we need the parent module
|
|
||||||
if strings.Contains(pkg, "/gojson") && strings.Contains(pkg, "ChimeraCoder") {
|
if strings.Contains(pkg, "/gojson") && strings.Contains(pkg, "ChimeraCoder") {
|
||||||
return "github.com/ChimeraCoder/gojson"
|
return "github.com/ChimeraCoder/gojson"
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(pkg, "/gotests") {
|
if strings.HasSuffix(pkg, "/gotests") {
|
||||||
return strings.TrimSuffix(pkg, "/gotests")
|
return strings.TrimSuffix(pkg, "/gotests")
|
||||||
}
|
}
|
||||||
|
// gopls is a submodule of golang.org/x/tools
|
||||||
|
if strings.HasSuffix(pkg, "/gopls") {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
return pkg
|
return pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getRepoPath extracts the git repository path from a module path
|
||||||
|
func getRepoPath(modPath string) string {
|
||||||
|
// golang.org/x/tools/gopls -> golang.org/x/tools
|
||||||
|
if strings.HasPrefix(modPath, "golang.org/x/") {
|
||||||
|
parts := strings.Split(modPath, "/")
|
||||||
|
if len(parts) >= 3 {
|
||||||
|
return strings.Join(parts[:3], "/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// getGitURL returns the git URL for a module path
|
||||||
|
func getGitURL(modPath string) string {
|
||||||
|
// Get the repo path first
|
||||||
|
repoPath := getRepoPath(modPath)
|
||||||
|
|
||||||
|
// Handle vanity imports
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(repoPath, "golang.org/x/"):
|
||||||
|
name := strings.TrimPrefix(repoPath, "golang.org/x/")
|
||||||
|
return "https://github.com/golang/" + name + ".git"
|
||||||
|
case strings.HasPrefix(repoPath, "honnef.co/go/tools"):
|
||||||
|
return "https://github.com/dominikh/go-tools.git"
|
||||||
|
case strings.HasPrefix(repoPath, "mvdan.cc/"):
|
||||||
|
name := strings.TrimPrefix(repoPath, "mvdan.cc/")
|
||||||
|
return "https://github.com/mvdan/" + name + ".git"
|
||||||
|
default:
|
||||||
|
// Assume github.com/user/repo format
|
||||||
|
parts := strings.Split(repoPath, "/")
|
||||||
|
if len(parts) >= 3 {
|
||||||
|
return "https://" + strings.Join(parts[:3], "/") + ".git"
|
||||||
|
}
|
||||||
|
return "https://" + repoPath + ".git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTagPattern returns the git tag pattern for a module
|
||||||
|
func getTagPattern(pkg, version string) string {
|
||||||
|
// gopls has tags like "gopls/v0.21.0"
|
||||||
|
if strings.Contains(pkg, "/gopls") {
|
||||||
|
return "gopls/" + version
|
||||||
|
}
|
||||||
|
// godoc has tags like "cmd/godoc/v0.1.0-deprecated"
|
||||||
|
if strings.HasSuffix(pkg, "/cmd/godoc") {
|
||||||
|
return "cmd/godoc/" + version
|
||||||
|
}
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
|
// pseudoVersionRe matches pseudo-versions like v0.0.0-20250907133731-34b10582faa4
|
||||||
|
var pseudoVersionRe = regexp.MustCompile(`^v\d+\.\d+\.\d+-\d{14}-([a-f0-9]{12})$`)
|
||||||
|
|
||||||
func fetchLatestVersion(tool Tool) (Tool, error) {
|
func fetchLatestVersion(tool Tool) (Tool, error) {
|
||||||
modPath := getModulePath(tool.Package)
|
modPath := getModulePath(tool.Package)
|
||||||
|
|
||||||
|
// First get the latest version info
|
||||||
cmd := exec.Command("go", "list", "-m", "-json", modPath+"@latest")
|
cmd := exec.Command("go", "list", "-m", "-json", modPath+"@latest")
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -153,17 +219,92 @@ func fetchLatestVersion(tool Tool) (Tool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if it's already a pseudo-version with commit hash
|
||||||
|
if matches := pseudoVersionRe.FindStringSubmatch(info.Version); matches != nil {
|
||||||
|
// Extract the 12-char hash from pseudo-version, we need the full hash
|
||||||
|
shortHash := matches[1]
|
||||||
|
gitURL := getGitURL(modPath)
|
||||||
|
fullHash, err := resolveShortHash(gitURL, shortHash)
|
||||||
|
if err != nil {
|
||||||
|
return Tool{}, fmt.Errorf("resolve hash failed: %w", err)
|
||||||
|
}
|
||||||
|
return Tool{
|
||||||
|
Name: tool.Name,
|
||||||
|
Package: tool.Package,
|
||||||
|
Version: info.Version,
|
||||||
|
Hash: fullHash,
|
||||||
|
Date: date,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's a tagged version, resolve to commit hash
|
||||||
|
gitURL := getGitURL(modPath)
|
||||||
|
tagPattern := getTagPattern(tool.Package, info.Version)
|
||||||
|
|
||||||
|
hash, err := resolveTagToHash(gitURL, tagPattern)
|
||||||
|
if err != nil {
|
||||||
|
return Tool{}, fmt.Errorf("resolve tag failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return Tool{
|
return Tool{
|
||||||
Name: tool.Name,
|
Name: tool.Name,
|
||||||
Package: tool.Package,
|
Package: tool.Package,
|
||||||
Version: info.Version,
|
Version: info.Version,
|
||||||
|
Hash: hash,
|
||||||
Date: date,
|
Date: date,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveTagToHash(gitURL, tag string) (string, error) {
|
||||||
|
cmd := exec.Command("git", "ls-remote", "--tags", gitURL, tag)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("git ls-remote failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.TrimSpace(string(output))
|
||||||
|
if lines == "" {
|
||||||
|
return "", fmt.Errorf("tag %s not found", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: <hash>\t<ref>
|
||||||
|
parts := strings.Fields(lines)
|
||||||
|
if len(parts) < 1 {
|
||||||
|
return "", fmt.Errorf("unexpected git ls-remote output")
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveShortHash(gitURL, shortHash string) (string, error) {
|
||||||
|
// Use git ls-remote with the short hash to find full hash
|
||||||
|
cmd := exec.Command("git", "ls-remote", gitURL)
|
||||||
|
output, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("git ls-remote failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := strings.Split(string(output), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
parts := strings.Fields(line)
|
||||||
|
if len(parts) >= 1 && strings.HasPrefix(parts[0], shortHash) {
|
||||||
|
return parts[0], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("hash %s not found", shortHash)
|
||||||
|
}
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
idx int
|
idx int
|
||||||
tool Tool
|
tool Tool
|
||||||
updated Tool
|
updated Tool
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shortHash(h string) string {
|
||||||
|
if len(h) >= 12 {
|
||||||
|
return h[:12]
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|||||||
36
main.go
36
main.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed tools.json
|
//go:embed tools.json
|
||||||
@@ -17,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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,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
|
||||||
}
|
}
|
||||||
@@ -48,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
|
||||||
}
|
}
|
||||||
@@ -57,6 +59,8 @@ func main() {
|
|||||||
sem := make(chan struct{}, *parallel)
|
sem := make(chan struct{}, *parallel)
|
||||||
results := make(chan result, len(tf.Tools))
|
results := make(chan result, len(tf.Tools))
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
|
|
||||||
for _, t := range tf.Tools {
|
for _, t := range tf.Tools {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(tool Tool) {
|
go func(tool Tool) {
|
||||||
@@ -65,14 +69,15 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg := fmt.Sprintf("%s@%s", tool.Package, tool.Version)
|
toolStart := time.Now()
|
||||||
|
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()
|
||||||
results <- result{tool: tool, err: err, output: string(output)}
|
results <- result{tool: tool, err: err, output: string(output), duration: time.Since(toolStart)}
|
||||||
}(t)
|
}(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,25 +89,34 @@ 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\n", r.tool.Name, r.tool.Version, r.err)
|
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\n", r.tool.Name, r.tool.Version)
|
fmt.Printf("✓ %s@%s [%s] (in %s)\n", r.tool.Name, r.tool.Version, r.tool.Hash[:12], formatDuration(r.duration))
|
||||||
succeeded++
|
succeeded++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\nDone: %d succeeded, %d failed\n", succeeded, failed)
|
totalDuration := time.Since(startTime)
|
||||||
|
fmt.Printf("\nDone: %d succeeded, %d failed in %s\n", succeeded, failed, formatDuration(totalDuration))
|
||||||
if failed > 0 {
|
if failed > 0 {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type result struct {
|
type result struct {
|
||||||
tool Tool
|
tool Tool
|
||||||
err error
|
err error
|
||||||
output string
|
output string
|
||||||
|
duration time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatDuration(d time.Duration) string {
|
||||||
|
if d < time.Second {
|
||||||
|
return fmt.Sprintf("%dms", d.Milliseconds())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.1fs", d.Seconds())
|
||||||
}
|
}
|
||||||
|
|||||||
54
tools.json
54
tools.json
@@ -4,192 +4,210 @@
|
|||||||
"name": "gopls",
|
"name": "gopls",
|
||||||
"package": "golang.org/x/tools/gopls",
|
"package": "golang.org/x/tools/gopls",
|
||||||
"version": "v0.21.0",
|
"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": "v0.9.2",
|
"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": "v0.40.0",
|
"version": "v0.40.0",
|
||||||
|
"hash": "00b22d96a3616723b0ee0341fb34c40b73e19c96",
|
||||||
"date": "2025-12-08"
|
"date": "2025-12-08"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "godoc",
|
||||||
|
"package": "golang.org/x/tools/cmd/godoc",
|
||||||
|
"version": "v0.1.0-deprecated",
|
||||||
|
"hash": "ccfe399eae9bf60bad2b93ac1f9a37d08d3c46df",
|
||||||
|
"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": "v1.64.8",
|
"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": "v0.6.1",
|
"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": "v1.9.0",
|
"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": "v1.13.0",
|
"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": "v1.1.2",
|
"version": "v1.1.2",
|
||||||
|
"hash": "8318a6814d22e99151760ac2fc890f55088a3192",
|
||||||
"date": "2020-03-03"
|
"date": "2020-03-03"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "guru",
|
|
||||||
"package": "golang.org/x/tools/cmd/guru",
|
|
||||||
"version": "v0.40.0",
|
|
||||||
"date": "2025-12-08"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "gorename",
|
|
||||||
"package": "golang.org/x/tools/cmd/gorename",
|
|
||||||
"version": "v0.40.0",
|
|
||||||
"date": "2025-12-08"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "gotests",
|
"name": "gotests",
|
||||||
"package": "github.com/cweill/gotests/gotests",
|
"package": "github.com/cweill/gotests/gotests",
|
||||||
"version": "v1.9.0",
|
"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": "v1.17.0",
|
"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": "v1.5.0",
|
"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": "v0.0.0-20250907133731-34b10582faa4",
|
"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": "v0.0.0-20250907133731-34b10582faa4",
|
"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": "v0.0.0-20250907133731-34b10582faa4",
|
"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": "v1.25.2",
|
"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": "v1.4.1",
|
"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": "v0.0.0-20190228002656-b37376c5da6a",
|
"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": "v0.0.0-20240122035601-9c3e2fbe4bd1",
|
"version": "v0.0.0-20240122035601-9c3e2fbe4bd1",
|
||||||
|
"hash": "9c3e2fbe4bd19a7f0338e42bb483562ed4cf4d50",
|
||||||
"date": "2024-01-22"
|
"date": "2024-01-22"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "keyify",
|
|
||||||
"package": "honnef.co/go/tools/cmd/keyify",
|
|
||||||
"version": "v0.6.1",
|
|
||||||
"date": "2025-03-05"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "asmfmt",
|
"name": "asmfmt",
|
||||||
"package": "github.com/klauspost/asmfmt/cmd/asmfmt",
|
"package": "github.com/klauspost/asmfmt/cmd/asmfmt",
|
||||||
"version": "v1.3.2",
|
"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": "v1.2.0",
|
"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": "v1.1.0",
|
"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": "v0.13.0",
|
"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": "v0.6.0",
|
"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": "v0.2.0",
|
"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": "v0.3.4",
|
"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": "v0.0.0-20250216222326-4a038b3d31f5",
|
"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": "v2.1.2",
|
"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": "v0.0.0-20210608161538-9736a4bde949",
|
"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": "v0.1.1",
|
"version": "v0.1.1",
|
||||||
|
"hash": "b3af8b100b8a7d0136e0c17820a066d8365f1316",
|
||||||
"date": "2019-01-14"
|
"date": "2019-01-14"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user