mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-18 12:36:32 +09:00
tools/bump: upgrade modules behind tool directives
x/tools is indirect, so never moved; v0.49.0 cannot read Go 1.27.2 export data and viewer emits invalid types, failing go generate.
This commit is contained in:
1 parent
bf63feb320
commit
fd09dd86f2
2 files changed
+65
-2
No files matched your search
+24
-2
@@ -166,7 +166,9 @@ func sqliteAtom(ctx context.Context, r *repo) (string, error) {
|
||||
}
|
||||
|
||||
// directRequirements is every direct requirement not already owned by a
|
||||
// lockstep atom.
|
||||
// lockstep atom, plus the modules behind go.mod's tool lines. Those are marked
|
||||
// indirect when nothing imports them, yet go generate runs them, and a stale
|
||||
// golang.org/x/tools cannot read the export data a newer Go writes.
|
||||
func directRequirements(r *repo) ([]string, error) {
|
||||
f, err := parseGoMod(r)
|
||||
if err != nil {
|
||||
@@ -181,10 +183,15 @@ func directRequirements(r *repo) ([]string, error) {
|
||||
modLibc: true,
|
||||
}
|
||||
|
||||
tools := map[string]bool{}
|
||||
for _, t := range f.Tool {
|
||||
tools[toolModule(f, t.Path)] = true
|
||||
}
|
||||
|
||||
var paths []string
|
||||
|
||||
for _, req := range f.Require {
|
||||
if req.Indirect || owned[req.Mod.Path] {
|
||||
if owned[req.Mod.Path] || (req.Indirect && !tools[req.Mod.Path]) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -194,6 +201,21 @@ func directRequirements(r *repo) ([]string, error) {
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
// toolModule finds the required module providing pkg. The longest match wins,
|
||||
// since a nested module shadows its parent's tree.
|
||||
func toolModule(f *modfile.File, pkg string) string {
|
||||
var best string
|
||||
|
||||
for _, req := range f.Require {
|
||||
p := req.Mod.Path
|
||||
if (pkg == p || strings.HasPrefix(pkg, p+"/")) && len(p) > len(best) {
|
||||
best = p
|
||||
}
|
||||
}
|
||||
|
||||
return best
|
||||
}
|
||||
|
||||
// moduleAtom upgrades one direct requirement. One atom per module costs nothing
|
||||
// on a good day, because the bisect tries every atom together first and only
|
||||
// splits when that fails. It is what stops a single dependency deprecating an
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
@@ -117,3 +120,41 @@ func TestRepoLockstepNotesAttached(t *testing.T) {
|
||||
t.Error("go.mod: tool block is missing")
|
||||
}
|
||||
}
|
||||
|
||||
// A tool's module is indirect in go.mod, but it still has to move: go generate
|
||||
// runs it against whatever Go the flake ships.
|
||||
func TestDirectRequirementsIncludesTools(t *testing.T) {
|
||||
const content = `module example.com/x
|
||||
|
||||
go 1.27.0
|
||||
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.4.0
|
||||
golang.org/x/net v0.58.0 // indirect
|
||||
golang.org/x/tools v0.49.0 // indirect
|
||||
tailscale.com v1.100.0
|
||||
)
|
||||
|
||||
tool (
|
||||
golang.org/x/tools/cmd/stringer
|
||||
tailscale.com/cmd/viewer
|
||||
)
|
||||
`
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte(content), 0o600)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := directRequirements(&repo{Root: dir})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := []string{"github.com/go-chi/chi/v5", "golang.org/x/tools"}
|
||||
if !slices.Equal(got, want) {
|
||||
t.Errorf("directRequirements = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user