mirror of
https://github.com/golang/go
synced 2024-11-17 17:54:48 -07:00
cmd/go: add -retract and -dropretract flags to 'go mod edit'
'go mod edit' can now add and remove 'retract' directives from go.mod files. Also, retractions are now included in the 'go mod edit -json' output. For #24031 Change-Id: Ife7915e259fa508626d6ec5f786b5c860b489599 Reviewed-on: https://go-review.googlesource.com/c/go/+/228381 Run-TryBot: Jay Conrod <jayconrod@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
parent
c769f034d7
commit
0bbd386e8b
@ -1100,9 +1100,14 @@
|
||||
// module path and version pair. If the @v is omitted, a replacement without
|
||||
// a version on the left side is dropped.
|
||||
//
|
||||
// The -retract=version and -dropretract=version flags add and drop a
|
||||
// retraction on the given version. The version may be a single version
|
||||
// like "v1.2.3" or a closed interval like "[v1.1.0-v1.1.9]". Note that
|
||||
// -retract=version is a no-op if that retraction already exists.
|
||||
//
|
||||
// The -require, -droprequire, -exclude, -dropexclude, -replace,
|
||||
// and -dropreplace editing flags may be repeated, and the changes
|
||||
// are applied in the order given.
|
||||
// -dropreplace, -retract, and -dropretract editing flags may be repeated,
|
||||
// and the changes are applied in the order given.
|
||||
//
|
||||
// The -go=version flag sets the expected Go language version.
|
||||
//
|
||||
@ -1136,6 +1141,15 @@
|
||||
// New Module
|
||||
// }
|
||||
//
|
||||
// type Retract struct {
|
||||
// Low string
|
||||
// High string
|
||||
// Rationale string
|
||||
// }
|
||||
//
|
||||
// Retract entries representing a single version (not an interval) will have
|
||||
// the "Low" and "High" fields set to the same value.
|
||||
//
|
||||
// Note that this only describes the go.mod file itself, not other modules
|
||||
// referred to indirectly. For the full set of modules available to a build,
|
||||
// use 'go list -m -json all'.
|
||||
|
@ -68,9 +68,14 @@ The -dropreplace=old[@v] flag drops a replacement of the given
|
||||
module path and version pair. If the @v is omitted, a replacement without
|
||||
a version on the left side is dropped.
|
||||
|
||||
The -retract=version and -dropretract=version flags add and drop a
|
||||
retraction on the given version. The version may be a single version
|
||||
like "v1.2.3" or a closed interval like "[v1.1.0-v1.1.9]". Note that
|
||||
-retract=version is a no-op if that retraction already exists.
|
||||
|
||||
The -require, -droprequire, -exclude, -dropexclude, -replace,
|
||||
and -dropreplace editing flags may be repeated, and the changes
|
||||
are applied in the order given.
|
||||
-dropreplace, -retract, and -dropretract editing flags may be repeated,
|
||||
and the changes are applied in the order given.
|
||||
|
||||
The -go=version flag sets the expected Go language version.
|
||||
|
||||
@ -104,6 +109,15 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
|
||||
New Module
|
||||
}
|
||||
|
||||
type Retract struct {
|
||||
Low string
|
||||
High string
|
||||
Rationale string
|
||||
}
|
||||
|
||||
Retract entries representing a single version (not an interval) will have
|
||||
the "Low" and "High" fields set to the same value.
|
||||
|
||||
Note that this only describes the go.mod file itself, not other modules
|
||||
referred to indirectly. For the full set of modules available to a build,
|
||||
use 'go list -m -json all'.
|
||||
@ -137,6 +151,8 @@ func init() {
|
||||
cmdEdit.Flag.Var(flagFunc(flagDropReplace), "dropreplace", "")
|
||||
cmdEdit.Flag.Var(flagFunc(flagReplace), "replace", "")
|
||||
cmdEdit.Flag.Var(flagFunc(flagDropExclude), "dropexclude", "")
|
||||
cmdEdit.Flag.Var(flagFunc(flagRetract), "retract", "")
|
||||
cmdEdit.Flag.Var(flagFunc(flagDropRetract), "dropretract", "")
|
||||
|
||||
work.AddModCommonFlags(cmdEdit)
|
||||
base.AddBuildFlagsNX(&cmdEdit.Flag)
|
||||
@ -252,12 +268,7 @@ func parsePathVersion(flag, arg string) (path, version string) {
|
||||
base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err)
|
||||
}
|
||||
|
||||
// We don't call modfile.CheckPathVersion, because that insists
|
||||
// on versions being in semver form, but here we want to allow
|
||||
// versions like "master" or "1234abcdef", which the go command will resolve
|
||||
// the next time it runs (or during -fix).
|
||||
// Even so, we need to make sure the version is a valid token.
|
||||
if modfile.MustQuote(version) {
|
||||
if !allowedVersionArg(version) {
|
||||
base.Fatalf("go mod: -%s=%s: invalid version %q", flag, arg, version)
|
||||
}
|
||||
|
||||
@ -289,12 +300,48 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version
|
||||
return path, version, fmt.Errorf("invalid %s path: %v", adj, err)
|
||||
}
|
||||
}
|
||||
if path != arg && modfile.MustQuote(version) {
|
||||
if path != arg && !allowedVersionArg(version) {
|
||||
return path, version, fmt.Errorf("invalid %s version: %q", adj, version)
|
||||
}
|
||||
return path, version, nil
|
||||
}
|
||||
|
||||
// parseVersionInterval parses a single version like "v1.2.3" or a closed
|
||||
// interval like "[v1.2.3,v1.4.5]". Note that a single version has the same
|
||||
// representation as an interval with equal upper and lower bounds: both
|
||||
// Low and High are set.
|
||||
func parseVersionInterval(arg string) (modfile.VersionInterval, error) {
|
||||
if !strings.HasPrefix(arg, "[") {
|
||||
if !allowedVersionArg(arg) {
|
||||
return modfile.VersionInterval{}, fmt.Errorf("invalid version: %q", arg)
|
||||
}
|
||||
return modfile.VersionInterval{Low: arg, High: arg}, nil
|
||||
}
|
||||
if !strings.HasSuffix(arg, "]") {
|
||||
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
|
||||
}
|
||||
s := arg[1 : len(arg)-1]
|
||||
i := strings.Index(s, ",")
|
||||
if i < 0 {
|
||||
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
|
||||
}
|
||||
low := strings.TrimSpace(s[:i])
|
||||
high := strings.TrimSpace(s[i+1:])
|
||||
if !allowedVersionArg(low) || !allowedVersionArg(high) {
|
||||
return modfile.VersionInterval{}, fmt.Errorf("invalid version interval: %q", arg)
|
||||
}
|
||||
return modfile.VersionInterval{Low: low, High: high}, nil
|
||||
}
|
||||
|
||||
// allowedVersionArg returns whether a token may be used as a version in go.mod.
|
||||
// We don't call modfile.CheckPathVersion, because that insists on versions
|
||||
// being in semver form, but here we want to allow versions like "master" or
|
||||
// "1234abcdef", which the go command will resolve the next time it runs (or
|
||||
// during -fix). Even so, we need to make sure the version is a valid token.
|
||||
func allowedVersionArg(arg string) bool {
|
||||
return !modfile.MustQuote(arg)
|
||||
}
|
||||
|
||||
// flagRequire implements the -require flag.
|
||||
func flagRequire(arg string) {
|
||||
path, version := parsePathVersion("require", arg)
|
||||
@ -377,6 +424,32 @@ func flagDropReplace(arg string) {
|
||||
})
|
||||
}
|
||||
|
||||
// flagRetract implements the -retract flag.
|
||||
func flagRetract(arg string) {
|
||||
vi, err := parseVersionInterval(arg)
|
||||
if err != nil {
|
||||
base.Fatalf("go mod: -retract=%s: %v", arg, err)
|
||||
}
|
||||
edits = append(edits, func(f *modfile.File) {
|
||||
if err := f.AddRetract(vi, ""); err != nil {
|
||||
base.Fatalf("go mod: -retract=%s: %v", arg, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// flagDropRetract implements the -dropretract flag.
|
||||
func flagDropRetract(arg string) {
|
||||
vi, err := parseVersionInterval(arg)
|
||||
if err != nil {
|
||||
base.Fatalf("go mod: -dropretract=%s: %v", arg, err)
|
||||
}
|
||||
edits = append(edits, func(f *modfile.File) {
|
||||
if err := f.DropRetract(vi); err != nil {
|
||||
base.Fatalf("go mod: -dropretract=%s: %v", arg, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// fileJSON is the -json output data structure.
|
||||
type fileJSON struct {
|
||||
Module module.Version
|
||||
@ -384,6 +457,7 @@ type fileJSON struct {
|
||||
Require []requireJSON
|
||||
Exclude []module.Version
|
||||
Replace []replaceJSON
|
||||
Retract []retractJSON
|
||||
}
|
||||
|
||||
type requireJSON struct {
|
||||
@ -397,6 +471,12 @@ type replaceJSON struct {
|
||||
New module.Version
|
||||
}
|
||||
|
||||
type retractJSON struct {
|
||||
Low string `json:",omitempty"`
|
||||
High string `json:",omitempty"`
|
||||
Rationale string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// editPrintJSON prints the -json output.
|
||||
func editPrintJSON(modFile *modfile.File) {
|
||||
var f fileJSON
|
||||
@ -415,6 +495,9 @@ func editPrintJSON(modFile *modfile.File) {
|
||||
for _, r := range modFile.Replace {
|
||||
f.Replace = append(f.Replace, replaceJSON{r.Old, r.New})
|
||||
}
|
||||
for _, r := range modFile.Retract {
|
||||
f.Retract = append(f.Retract, retractJSON{r.Low, r.High, r.Rationale})
|
||||
}
|
||||
data, err := json.MarshalIndent(&f, "", "\t")
|
||||
if err != nil {
|
||||
base.Fatalf("go: internal error: %v", err)
|
||||
|
114
src/cmd/go/testdata/script/mod_edit.txt
vendored
114
src/cmd/go/testdata/script/mod_edit.txt
vendored
@ -16,15 +16,19 @@ cmpenv go.mod $WORK/go.mod.init
|
||||
cmpenv go.mod $WORK/go.mod.init
|
||||
|
||||
# go mod edits
|
||||
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z'
|
||||
go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' -retract=v1.6.0 -retract=[v1.1.0,v1.2.0] -retract=[v1.3.0,v1.4.0] -retract=v1.0.0
|
||||
cmpenv go.mod $WORK/go.mod.edit1
|
||||
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0
|
||||
go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 -dropretract=v1.0.0 -dropretract=[v1.1.0,v1.2.0]
|
||||
cmpenv go.mod $WORK/go.mod.edit2
|
||||
|
||||
# go mod edit -json
|
||||
go mod edit -json
|
||||
cmpenv stdout $WORK/go.mod.json
|
||||
|
||||
# go mod edit -json (retractions with rationales)
|
||||
go mod edit -json $WORK/go.mod.retractrationale
|
||||
cmp stdout $WORK/go.mod.retractrationale.json
|
||||
|
||||
# go mod edit -json (empty mod file)
|
||||
go mod edit -json $WORK/go.mod.empty
|
||||
cmp stdout $WORK/go.mod.empty.json
|
||||
@ -40,11 +44,11 @@ cmpenv go.mod $WORK/go.mod.edit5
|
||||
# go mod edit -fmt
|
||||
cp $WORK/go.mod.badfmt go.mod
|
||||
go mod edit -fmt -print # -print should avoid writing file
|
||||
cmpenv stdout $WORK/go.mod.edit6
|
||||
cmpenv stdout $WORK/go.mod.goodfmt
|
||||
cmp go.mod $WORK/go.mod.badfmt
|
||||
go mod edit -fmt # without -print, should write file (and nothing to stdout)
|
||||
! stdout .
|
||||
cmpenv go.mod $WORK/go.mod.edit6
|
||||
cmpenv go.mod $WORK/go.mod.goodfmt
|
||||
|
||||
# go mod edit -module
|
||||
cd $WORK/m
|
||||
@ -84,6 +88,13 @@ replace (
|
||||
x.1 v1.3.0 => y.1 v1.4.0
|
||||
x.1 v1.4.0 => ../z
|
||||
)
|
||||
|
||||
retract (
|
||||
v1.6.0
|
||||
[v1.3.0, v1.4.0]
|
||||
[v1.1.0, v1.2.0]
|
||||
v1.0.0
|
||||
)
|
||||
-- $WORK/go.mod.edit2 --
|
||||
module x.x/y/z
|
||||
|
||||
@ -93,6 +104,11 @@ exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 v1.4.0 => ../z
|
||||
|
||||
retract (
|
||||
v1.6.0
|
||||
[v1.3.0, v1.4.0]
|
||||
)
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/go.mod.json --
|
||||
{
|
||||
@ -122,6 +138,16 @@ require x.3 v1.99.0
|
||||
"Path": "../z"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Retract": [
|
||||
{
|
||||
"Low": "v1.6.0",
|
||||
"High": "v1.6.0"
|
||||
},
|
||||
{
|
||||
"Low": "v1.3.0",
|
||||
"High": "v1.4.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
-- $WORK/go.mod.edit3 --
|
||||
@ -136,6 +162,11 @@ replace (
|
||||
x.1 v1.4.0 => y.1/v2 v2.3.5
|
||||
)
|
||||
|
||||
retract (
|
||||
v1.6.0
|
||||
[v1.3.0, v1.4.0]
|
||||
)
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/go.mod.edit4 --
|
||||
module x.x/y/z
|
||||
@ -146,6 +177,11 @@ exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 => y.1/v2 v2.3.6
|
||||
|
||||
retract (
|
||||
v1.6.0
|
||||
[v1.3.0, v1.4.0]
|
||||
)
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/go.mod.edit5 --
|
||||
module x.x/y/z
|
||||
@ -154,15 +190,10 @@ go $goversion
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/go.mod.edit6 --
|
||||
module x.x/y/z
|
||||
|
||||
go 1.10
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 => y.1/v2 v2.3.6
|
||||
retract (
|
||||
v1.6.0
|
||||
[v1.3.0, v1.4.0]
|
||||
)
|
||||
|
||||
require x.3 v1.99.0
|
||||
-- $WORK/local/go.mod.edit --
|
||||
@ -183,10 +214,64 @@ exclude x.1 v1.2.0
|
||||
replace x.1 => y.1/v2 v2.3.6
|
||||
|
||||
require x.3 v1.99.0
|
||||
|
||||
retract [ "v1.8.1" , "v1.8.2" ]
|
||||
-- $WORK/go.mod.goodfmt --
|
||||
module x.x/y/z
|
||||
|
||||
go 1.10
|
||||
|
||||
exclude x.1 v1.2.0
|
||||
|
||||
replace x.1 => y.1/v2 v2.3.6
|
||||
|
||||
require x.3 v1.99.0
|
||||
|
||||
retract [v1.8.1, v1.8.2]
|
||||
-- $WORK/m/go.mod.edit --
|
||||
module x.x/y/z
|
||||
|
||||
go $goversion
|
||||
-- $WORK/go.mod.retractrationale --
|
||||
module x.x/y/z
|
||||
|
||||
go 1.15
|
||||
|
||||
// a
|
||||
retract v1.0.0
|
||||
|
||||
// b
|
||||
retract (
|
||||
v1.0.1
|
||||
v1.0.2 // c
|
||||
)
|
||||
-- $WORK/go.mod.retractrationale.json --
|
||||
{
|
||||
"Module": {
|
||||
"Path": "x.x/y/z"
|
||||
},
|
||||
"Go": "1.15",
|
||||
"Require": null,
|
||||
"Exclude": null,
|
||||
"Replace": null,
|
||||
"Retract": [
|
||||
{
|
||||
"Low": "v1.0.0",
|
||||
"High": "v1.0.0",
|
||||
"Rationale": "a"
|
||||
},
|
||||
{
|
||||
"Low": "v1.0.1",
|
||||
"High": "v1.0.1",
|
||||
"Rationale": "b"
|
||||
},
|
||||
{
|
||||
"Low": "v1.0.2",
|
||||
"High": "v1.0.2",
|
||||
"Rationale": "c"
|
||||
}
|
||||
]
|
||||
}
|
||||
-- $WORK/go.mod.empty --
|
||||
-- $WORK/go.mod.empty.json --
|
||||
{
|
||||
@ -195,5 +280,6 @@ go $goversion
|
||||
},
|
||||
"Require": null,
|
||||
"Exclude": null,
|
||||
"Replace": null
|
||||
"Replace": null,
|
||||
"Retract": null
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user