in cmd/gorelease/gorelease.go [164:261]
func runRelease(ctx context.Context, w io.Writer, dir string, args []string) (success bool, err error) {
// Validate arguments and flags. We'll print our own errors, since we want to
// test without printing to stderr.
fs := flag.NewFlagSet("gorelease", flag.ContinueOnError)
fs.Usage = func() {}
fs.SetOutput(ioutil.Discard)
var baseOpt, releaseVersion string
fs.StringVar(&baseOpt, "base", "", "previous version to compare against")
fs.StringVar(&releaseVersion, "version", "", "proposed version to be released")
if err := fs.Parse(args); err != nil {
return false, &usageError{err: err}
}
if len(fs.Args()) > 0 {
return false, usageErrorf("no arguments allowed")
}
if releaseVersion != "" {
if semver.Build(releaseVersion) != "" {
return false, usageErrorf("release version %q is not a canonical semantic version: build metadata is not supported", releaseVersion)
}
if c := semver.Canonical(releaseVersion); c != releaseVersion {
return false, usageErrorf("release version %q is not a canonical semantic version", releaseVersion)
}
}
var baseModPath, baseVersion string
if at := strings.Index(baseOpt, "@"); at >= 0 {
baseModPath = baseOpt[:at]
baseVersion = baseOpt[at+1:]
} else if dot, slash := strings.Index(baseOpt, "."), strings.Index(baseOpt, "/"); dot >= 0 && slash >= 0 && dot < slash {
baseModPath = baseOpt
} else {
baseVersion = baseOpt
}
if baseModPath == "" {
if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && releaseVersion != "" {
if cmp := semver.Compare(baseOpt, releaseVersion); cmp == 0 {
return false, usageErrorf("-base and -version must be different")
} else if cmp > 0 {
return false, usageErrorf("base version (%q) must be lower than release version (%q)", baseVersion, releaseVersion)
}
}
} else if baseModPath != "" && baseVersion == "none" {
return false, usageErrorf(`base version (%q) cannot have version "none" with explicit module path`, baseOpt)
}
// Find the local module and repository root directories.
modRoot, err := findModuleRoot(dir)
if err != nil {
return false, err
}
repoRoot := findRepoRoot(modRoot)
// Load packages for the version to be released from the local directory.
release, err := loadLocalModule(ctx, modRoot, repoRoot, releaseVersion)
if err != nil {
return false, err
}
// Find the base version if there is one, download it, and load packages from
// the module cache.
var max string
if baseModPath == "" {
if baseVersion != "" && semver.Canonical(baseVersion) == baseVersion && module.Check(release.modPath, baseVersion) != nil {
// Base version was specified, but it's not consistent with the release
// module path, for example, the module path is example.com/m/v2, but
// the user said -base=v1.0.0. Instead of making the user explicitly
// specify the base module path, we'll adjust the major version suffix.
prefix, _, _ := module.SplitPathVersion(release.modPath)
major := semver.Major(baseVersion)
if strings.HasPrefix(prefix, "gopkg.in/") {
baseModPath = prefix + "." + semver.Major(baseVersion)
} else if major >= "v2" {
baseModPath = prefix + "/" + major
} else {
baseModPath = prefix
}
} else {
baseModPath = release.modPath
max = releaseVersion
}
}
base, err := loadDownloadedModule(ctx, baseModPath, baseVersion, max)
if err != nil {
return false, err
}
// Compare packages and check for other issues.
report, err := makeReleaseReport(ctx, base, release)
if err != nil {
return false, err
}
if _, err := fmt.Fprint(w, report.String()); err != nil {
return false, err
}
return report.isSuccessful(), nil
}