cmd/go: implement -reuse for Mercurial repos

When we added -reuse in CL 411398, we only handled Git repos.
This was partly because we were focused on Git traffic,
partly because Git is the dominant module VCS, and
partly because I couldn't see how to retrieve the metadata needed
in other version control systems.

This CL adds -reuse support for Mercurial, the second
most popular VCS for modules, now that I see how to
implement it. Although the Mercurial command line does
not have sufficient information, the Mercurial Python API does,
so we ship and invoke a Mercurial extension written in Python
that can compute a hash of the remote repo without downloading
it entirely, as well as resolve a remote name to a hash or check
the continued existence of a hash. Then we can avoid
downloading the repo at all if it hasn't changed since the last check
or if the specific reference we need still resolves or exists.

Fixes #75119.

Change-Id: Ia47d89b15c1091c44efef9d325270fc400a412c4
Reviewed-on: https://go-review.googlesource.com/c/go/+/718382
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Matloob <matloob@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Russ Cox 2025-08-19 15:27:39 -04:00 committed by Gopher Robot
parent 5241d114f5
commit 426ef30ecf
12 changed files with 433 additions and 248 deletions

64
lib/hg/goreposum.py Normal file
View file

@ -0,0 +1,64 @@
# Copyright 2025 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Mercurial extension to add a 'goreposum' command that
# computes a hash of a remote repo's tag state.
# Tag definitions can come from the .hgtags file stored in
# any head of any branch, and the server protocol does not
# expose the tags directly. However, the protocol does expose
# the hashes of all the branch heads, so we can use a hash of
# all those branch names and heads as a conservative snapshot
# of the entire remote repo state, and use that as the tag sum.
# Any change on the server then invalidates the tag sum,
# even if it didn't have anything to do with tags, but at least
# we will avoid re-cloning a server when there have been no
# changes at all.
#
# Separately, this extension also adds a 'golookup' command that
# returns the hash of a specific reference, like 'default' or a tag.
# And golookup of a hash confirms that it still exists on the server.
# We can use that to revalidate that specific versions still exist and
# have the same meaning they did the last time we checked.
#
# Usage:
#
# hg --config "extensions.goreposum=$GOROOT/lib/hg/goreposum.py" goreposum REPOURL
import base64, hashlib, sys
from mercurial import registrar, ui, hg, node
from mercurial.i18n import _
cmdtable = {}
command = registrar.command(cmdtable)
@command(b'goreposum', [], _('url'), norepo=True)
def goreposum(ui, url):
"""
goreposum computes a checksum of all the named state in the remote repo.
It hashes together all the branch names and hashes
and then all the bookmark names and hashes.
Tags are stored in .hgtags files in any of the branches,
so the branch metadata includes the tags as well.
"""
h = hashlib.sha256()
peer = hg.peer(ui, {}, url)
for name, revs in peer.branchmap().items():
h.update(name)
for r in revs:
h.update(b' ')
h.update(r)
h.update(b'\n')
if (b'bookmarks' in peer.listkeys(b'namespaces')):
for name, rev in peer.listkeys(b'bookmarks').items():
h.update(name)
h.update(b'=')
h.update(rev)
h.update(b'\n')
print('r1:'+base64.standard_b64encode(h.digest()).decode('utf-8'))
@command(b'golookup', [], _('url rev'), norepo=True)
def golookup(ui, url, rev):
"""
golookup looks up a single identifier in the repo,
printing its hash.
"""
print(node.hex(hg.peer(ui, {}, url).lookup(rev)).decode('utf-8'))

View file

@ -622,10 +622,11 @@ func writeDiskStat(ctx context.Context, file string, info *RevInfo) error {
o := *info.Origin o := *info.Origin
info.Origin = &o info.Origin = &o
// Tags never matter if you are starting with a semver version, // Tags and RepoSum never matter if you are starting with a semver version,
// as we would be when finding this cache entry. // as we would be when finding this cache entry.
o.TagSum = "" o.TagSum = ""
o.TagPrefix = "" o.TagPrefix = ""
o.RepoSum = ""
// Ref doesn't matter if you have a pseudoversion. // Ref doesn't matter if you have a pseudoversion.
if module.IsPseudoVersion(info.Version) { if module.IsPseudoVersion(info.Version) {
o.Ref = "" o.Ref = ""

View file

@ -116,9 +116,12 @@ type Origin struct {
Ref string `json:",omitempty"` Ref string `json:",omitempty"`
// If RepoSum is non-empty, then the resolution of this module version // If RepoSum is non-empty, then the resolution of this module version
// failed due to the repo being available but the version not being present. // depends on the entire state of the repo, which RepoSum summarizes.
// This depends on the entire state of the repo, which RepoSum summarizes. // For Git, this is a hash of all the refs and their hashes, and the RepoSum
// For Git, this is a hash of all the refs and their hashes. // is only needed for module versions that don't exist.
// For Mercurial, this is a hash of all the branches and their heads' hashes,
// since the set of available tags is dervied from .hgtags files in those branches,
// and the RepoSum is used for all module versions, available and not,
RepoSum string `json:",omitempty"` RepoSum string `json:",omitempty"`
} }

View file

@ -383,6 +383,7 @@ func TestLatest(t *testing.T) {
Origin: &Origin{ Origin: &Origin{
VCS: "hg", VCS: "hg",
URL: hgrepo1, URL: hgrepo1,
Ref: "tip",
Hash: "745aacc8b24decc44ac2b13870f5472b479f4d72", Hash: "745aacc8b24decc44ac2b13870f5472b479f4d72",
}, },
Name: "745aacc8b24decc44ac2b13870f5472b479f4d72", Name: "745aacc8b24decc44ac2b13870f5472b479f4d72",

View file

@ -17,9 +17,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"cmd/go/internal/base" "cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/lockedfile" "cmd/go/internal/lockedfile"
"cmd/go/internal/str" "cmd/go/internal/str"
"cmd/internal/par" "cmd/internal/par"
@ -80,6 +82,10 @@ type vcsRepo struct {
fetchOnce sync.Once fetchOnce sync.Once
fetchErr error fetchErr error
fetched atomic.Bool
repoSumOnce sync.Once
repoSum string
} }
func newVCSRepo(ctx context.Context, vcs, remote string, local bool) (Repo, error) { func newVCSRepo(ctx context.Context, vcs, remote string, local bool) (Repo, error) {
@ -129,6 +135,9 @@ func newVCSRepo(ctx context.Context, vcs, remote string, local bool) (Repo, erro
return nil, err return nil, err
} }
_, err = Run(ctx, r.dir, cmd.init(r.remote)) _, err = Run(ctx, r.dir, cmd.init(r.remote))
if err == nil && cmd.postInit != nil {
err = cmd.postInit(ctx, r)
}
release() release()
if err != nil { if err != nil {
@ -142,20 +151,27 @@ func newVCSRepo(ctx context.Context, vcs, remote string, local bool) (Repo, erro
const vcsWorkDirType = "vcs1." const vcsWorkDirType = "vcs1."
type vcsCmd struct { type vcsCmd struct {
vcs string // vcs name "hg" vcs string // vcs name "hg"
init func(remote string) []string // cmd to init repo to track remote init func(remote string) []string // cmd to init repo to track remote
tags func(remote string) []string // cmd to list local tags postInit func(context.Context, *vcsRepo) error // func to init repo after .init runs
tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd repoSum func(remote string) []string // cmd to calculate reposum of remote repo
branches func(remote string) []string // cmd to list local branches lookupRef func(remote, ref string) []string // cmd to look up ref in remote repo
branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd tags func(remote string) []string // cmd to list local tags
badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first tagsNeedsFetch bool // run fetch before tags
statLocal func(rev, remote string) []string // cmd to stat local rev tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal branches func(remote string) []string // cmd to list local branches
fetch []string // cmd to fetch everything from remote branchesNeedsFetch bool // run branches before tags
latest string // name of latest commit on remote (tip, HEAD, etc) branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd
readFile func(rev, file, remote string) []string // cmd to read rev's file badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first
readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file statLocal func(rev, remote string) []string // cmd to stat local rev
doReadZip func(ctx context.Context, dst io.Writer, workDir, rev, subdir, remote string) error // arbitrary function to read rev's subdir as zip file parseStat func(rev, out string) (*RevInfo, error) // func to parse output of statLocal
fetch []string // cmd to fetch everything from remote
latest string // name of latest commit on remote (tip, HEAD, etc)
readFile func(rev, file, remote string) []string // cmd to read rev's file
readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file
// arbitrary function to read rev's subdir as zip file
doReadZip func(ctx context.Context, dst io.Writer, workDir, rev, subdir, remote string) error
} }
var re = lazyregexp.New var re = lazyregexp.New
@ -163,18 +179,38 @@ var re = lazyregexp.New
var vcsCmds = map[string]*vcsCmd{ var vcsCmds = map[string]*vcsCmd{
"hg": { "hg": {
vcs: "hg", vcs: "hg",
init: func(remote string) []string { repoSum: func(remote string) []string {
return []string{"hg", "clone", "-U", "--", remote, "."} return []string{
"hg",
"--config=extensions.goreposum=" + filepath.Join(cfg.GOROOT, "lib/hg/goreposum.py"),
"goreposum",
remote,
}
}, },
lookupRef: func(remote, ref string) []string {
return []string{
"hg",
"--config=extensions.goreposum=" + filepath.Join(cfg.GOROOT, "lib/hg/goreposum.py"),
"golookup",
remote,
ref,
}
},
init: func(remote string) []string {
return []string{"hg", "init", "."}
},
postInit: hgAddRemote,
tags: func(remote string) []string { tags: func(remote string) []string {
return []string{"hg", "tags", "-q"} return []string{"hg", "tags", "-q"}
}, },
tagRE: re(`(?m)^[^\n]+$`), tagsNeedsFetch: true,
tagRE: re(`(?m)^[^\n]+$`),
branches: func(remote string) []string { branches: func(remote string) []string {
return []string{"hg", "branches", "-c", "-q"} return []string{"hg", "branches", "-c", "-q"}
}, },
branchRE: re(`(?m)^[^\n]+$`), branchesNeedsFetch: true,
badLocalRevRE: re(`(?m)^(tip)$`), branchRE: re(`(?m)^[^\n]+$`),
badLocalRevRE: re(`(?m)^(tip)$`),
statLocal: func(rev, remote string) []string { statLocal: func(rev, remote string) []string {
return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"} return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"}
}, },
@ -276,6 +312,10 @@ var vcsCmds = map[string]*vcsCmd{
} }
func (r *vcsRepo) loadTags(ctx context.Context) { func (r *vcsRepo) loadTags(ctx context.Context) {
if r.cmd.tagsNeedsFetch {
r.fetchOnce.Do(func() { r.fetch(ctx) })
}
out, err := Run(ctx, r.dir, r.cmd.tags(r.remote)) out, err := Run(ctx, r.dir, r.cmd.tags(r.remote))
if err != nil { if err != nil {
return return
@ -296,6 +336,10 @@ func (r *vcsRepo) loadBranches(ctx context.Context) {
return return
} }
if r.cmd.branchesNeedsFetch {
r.fetchOnce.Do(func() { r.fetch(ctx) })
}
out, err := Run(ctx, r.dir, r.cmd.branches(r.remote)) out, err := Run(ctx, r.dir, r.cmd.branches(r.remote))
if err != nil { if err != nil {
return return
@ -310,7 +354,84 @@ func (r *vcsRepo) loadBranches(ctx context.Context) {
} }
} }
func (r *vcsRepo) loadRepoSum(ctx context.Context) {
if r.cmd.repoSum == nil {
return
}
where := r.remote
if r.fetched.Load() {
where = "." // use local repo
}
out, err := Run(ctx, r.dir, r.cmd.repoSum(where))
if err != nil {
return
}
r.repoSum = strings.TrimSpace(string(out))
}
func (r *vcsRepo) lookupRef(ctx context.Context, ref string) (string, error) {
if r.cmd.lookupRef == nil {
return "", fmt.Errorf("no lookupRef")
}
out, err := Run(ctx, r.dir, r.cmd.lookupRef(r.remote, ref))
if err != nil {
return "", err
}
return strings.TrimSpace(string(out)), nil
}
// repoSumOrigin returns an Origin containing a RepoSum.
func (r *vcsRepo) repoSumOrigin(ctx context.Context) *Origin {
origin := &Origin{
VCS: r.cmd.vcs,
URL: r.remote,
RepoSum: r.repoSum,
}
r.repoSumOnce.Do(func() { r.loadRepoSum(ctx) })
origin.RepoSum = r.repoSum
return origin
}
func (r *vcsRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error { func (r *vcsRepo) CheckReuse(ctx context.Context, old *Origin, subdir string) error {
if old == nil {
return fmt.Errorf("missing origin")
}
if old.VCS != r.cmd.vcs || old.URL != r.remote {
return fmt.Errorf("origin moved from %v %q to %v %q", old.VCS, old.URL, r.cmd.vcs, r.remote)
}
if old.Subdir != subdir {
return fmt.Errorf("origin moved from %v %q %q to %v %q %q", old.VCS, old.URL, old.Subdir, r.cmd.vcs, r.remote, subdir)
}
if old.Ref == "" && old.RepoSum == "" && old.Hash != "" {
// Hash has to remain in repo.
hash, err := r.lookupRef(ctx, old.Hash)
if err == nil && hash == old.Hash {
return nil
}
if err != nil {
return fmt.Errorf("looking up hash: %v", err)
}
return fmt.Errorf("hash changed") // weird but maybe they made a tag
}
if old.Ref != "" && old.RepoSum == "" {
hash, err := r.lookupRef(ctx, old.Ref)
if err == nil && hash != "" && hash == old.Hash {
return nil
}
}
r.repoSumOnce.Do(func() { r.loadRepoSum(ctx) })
if r.repoSum != "" {
if old.RepoSum == "" {
return fmt.Errorf("non-specific origin")
}
if old.RepoSum != r.repoSum {
return fmt.Errorf("repo changed")
}
return nil
}
return fmt.Errorf("vcs %s: CheckReuse: %w", r.cmd.vcs, errors.ErrUnsupported) return fmt.Errorf("vcs %s: CheckReuse: %w", r.cmd.vcs, errors.ErrUnsupported)
} }
@ -323,14 +444,8 @@ func (r *vcsRepo) Tags(ctx context.Context, prefix string) (*Tags, error) {
r.tagsOnce.Do(func() { r.loadTags(ctx) }) r.tagsOnce.Do(func() { r.loadTags(ctx) })
tags := &Tags{ tags := &Tags{
// None of the other VCS provide a reasonable way to compute TagSum Origin: r.repoSumOrigin(ctx),
// without downloading the whole repo, so we only include VCS and URL List: []Tag{},
// in the Origin.
Origin: &Origin{
VCS: r.cmd.vcs,
URL: r.remote,
},
List: []Tag{},
} }
for tag := range r.tags { for tag := range r.tags {
if strings.HasPrefix(tag, prefix) { if strings.HasPrefix(tag, prefix) {
@ -372,7 +487,7 @@ func (r *vcsRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
} }
info, err := r.statLocal(ctx, rev) info, err := r.statLocal(ctx, rev)
if err != nil { if err != nil {
return nil, err return info, err
} }
if !revOK { if !revOK {
info.Version = info.Name info.Version = info.Name
@ -389,13 +504,15 @@ func (r *vcsRepo) fetch(ctx context.Context) {
} }
_, r.fetchErr = Run(ctx, r.dir, r.cmd.fetch) _, r.fetchErr = Run(ctx, r.dir, r.cmd.fetch)
release() release()
r.fetched.Store(true)
} }
} }
func (r *vcsRepo) statLocal(ctx context.Context, rev string) (*RevInfo, error) { func (r *vcsRepo) statLocal(ctx context.Context, rev string) (*RevInfo, error) {
out, err := Run(ctx, r.dir, r.cmd.statLocal(rev, r.remote)) out, err := Run(ctx, r.dir, r.cmd.statLocal(rev, r.remote))
if err != nil { if err != nil {
return nil, &UnknownRevisionError{Rev: rev} info := &RevInfo{Origin: r.repoSumOrigin(ctx)}
return info, &UnknownRevisionError{Rev: rev}
} }
info, err := r.cmd.parseStat(rev, string(out)) info, err := r.cmd.parseStat(rev, string(out))
if err != nil { if err != nil {
@ -406,6 +523,10 @@ func (r *vcsRepo) statLocal(ctx context.Context, rev string) (*RevInfo, error) {
} }
info.Origin.VCS = r.cmd.vcs info.Origin.VCS = r.cmd.vcs
info.Origin.URL = r.remote info.Origin.URL = r.remote
info.Origin.Ref = rev
if strings.HasPrefix(info.Name, rev) && len(rev) >= 12 {
info.Origin.Ref = "" // duplicates Hash
}
return info, nil return info, nil
} }
@ -521,6 +642,11 @@ func (d *deleteCloser) Close() error {
return d.File.Close() return d.File.Close()
} }
func hgAddRemote(ctx context.Context, r *vcsRepo) error {
// Write .hg/hgrc with remote URL in it.
return os.WriteFile(filepath.Join(r.dir, ".hg/hgrc"), []byte(fmt.Sprintf("[paths]\ndefault = %s\n", r.remote)), 0666)
}
func hgParseStat(rev, out string) (*RevInfo, error) { func hgParseStat(rev, out string) (*RevInfo, error) {
f := strings.Fields(out) f := strings.Fields(out)
if len(f) < 3 { if len(f) < 3 {
@ -545,9 +671,7 @@ func hgParseStat(rev, out string) (*RevInfo, error) {
sort.Strings(tags) sort.Strings(tags)
info := &RevInfo{ info := &RevInfo{
Origin: &Origin{ Origin: &Origin{Hash: hash},
Hash: hash,
},
Name: hash, Name: hash,
Short: ShortenSHA1(hash), Short: ShortenSHA1(hash),
Time: time.Unix(t, 0).UTC(), Time: time.Unix(t, 0).UTC(),
@ -630,9 +754,7 @@ func fossilParseStat(rev, out string) (*RevInfo, error) {
version = hash // extend to full hash version = hash // extend to full hash
} }
info := &RevInfo{ info := &RevInfo{
Origin: &Origin{ Origin: &Origin{Hash: hash},
Hash: hash,
},
Name: hash, Name: hash,
Short: ShortenSHA1(hash), Short: ShortenSHA1(hash),
Time: t, Time: t,

View file

@ -384,6 +384,9 @@ func (r *codeRepo) convert(ctx context.Context, info *codehost.RevInfo, statVers
} else { } else {
origin.TagPrefix = tags.Origin.TagPrefix origin.TagPrefix = tags.Origin.TagPrefix
origin.TagSum = tags.Origin.TagSum origin.TagSum = tags.Origin.TagSum
if tags.Origin.RepoSum != "" {
origin.RepoSum = tags.Origin.RepoSum
}
} }
} }
}() }()

View file

@ -189,6 +189,12 @@ func mergeOrigin(m1, m2 *codehost.Origin) *codehost.Origin {
merged.TagSum = m2.TagSum merged.TagSum = m2.TagSum
merged.TagPrefix = m2.TagPrefix merged.TagPrefix = m2.TagPrefix
} }
if m2.RepoSum != "" {
if m1.RepoSum != "" && m1.RepoSum != m2.RepoSum {
return nil
}
merged.RepoSum = m2.RepoSum
}
if m2.Ref != "" { if m2.Ref != "" {
if m1.Ref != "" && m1.Ref != m2.Ref { if m1.Ref != "" && m1.Ref != m2.Ref {
return nil return nil

View file

@ -199,8 +199,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
defer func() { defer func() {
if v := recover(); v != nil { if v := recover(); v != nil {
debug.PrintStack() if v == http.ErrAbortHandler {
s.logger.Fatal(v) panic(v)
}
s.logger.Fatalf("panic serving %s: %v\n%s", req.URL, v, debug.Stack())
} }
}() }()

View file

@ -5,16 +5,15 @@ env GO111MODULE=on
env GOPROXY=direct env GOPROXY=direct
env GOSUMDB=off env GOSUMDB=off
# go mod download with the pseudo-version should invoke git but not have a TagSum or Ref. # go mod download with the pseudo-version should invoke git but not have a TagSum or Ref or RepoSum.
go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c go mod download -x -json vcs-test.golang.org/git/hello.git@v0.0.0-20170922010558-fc3a09f3dc5c
stderr 'git( .*)* fetch' stderr 'git( .*)* fetch'
cp stdout hellopseudo.json cp stdout hellopseudo.json
! stdout '"(Query|TagPrefix|TagSum|Ref)"' ! stdout '"(Query|TagPrefix|TagSum|Ref|RepoSum)"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"VCS": "git"' stdout '"VCS": "git"'
stdout '"URL": ".*/git/hello"' stdout '"URL": ".*/git/hello"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
go clean -modcache go clean -modcache
# go mod download vcstest/hello should invoke git, print origin info # go mod download vcstest/hello should invoke git, print origin info

View file

@ -1,21 +1,19 @@
skip
[short] skip [short] skip
[!hg] skip [!exec:hg] skip
env GO111MODULE=on env GO111MODULE=on
env GOPROXY=direct env GOPROXY=direct
env GOSUMDB=off env GOSUMDB=off
# go mod download with the pseudo-version should invoke hg but not have a TagSum or Ref. # go mod download with the pseudo-version should invoke hg but not have a TagSum or Ref or RepoSum.
go mod download -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922010558-fc3a09f3dc5c go mod download -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922011414-e483a7d9f8c9
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
cp stdout hellopseudo.json cp stdout hellopseudo.json
! stdout '"(Query|TagPrefix|TagSum|Ref)"' ! stdout '"(Query|TagPrefix|TagSum|Ref|RepoSum)"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"RepoSum"' ! stdout '"RepoSum"'
go clean -modcache go clean -modcache
@ -23,64 +21,63 @@ go clean -modcache
go mod download -x -json vcs-test.golang.org/hg/hello.hg@latest go mod download -x -json vcs-test.golang.org/hg/hello.hg@latest
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
cp stdout hello.json cp stdout hello.json
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"' stdout '"Query": "latest"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' ! stdout '"TagSum"'
stdout '"Ref": "HEAD"' stdout '"Ref": "tip"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"RepoSum"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
# pseudo-version again should not invoke hg pull (it has the version from the @latest query) # pseudo-version again should not invoke hg pull (it has the version from the @latest query)
# but still be careful not to include a TagSum or a Ref, especially not Ref set to HEAD, # but still be careful not to include a TagSum or a Ref, especially not Ref set to HEAD,
# which is easy to do when reusing the cached version from the @latest query. # which is easy to do when reusing the cached version from the @latest query.
go mod download -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922010558-fc3a09f3dc5c go mod download -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922011414-e483a7d9f8c9
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
cp stdout hellopseudo2.json cp stdout hellopseudo2.json
cmpenv hellopseudo.json hellopseudo2.json cmpenv hellopseudo.json hellopseudo2.json
# go mod download vcstest/hello@hash needs to check TagSum to find pseudoversion base. # go mod download hg/hello@hash needs to check RepoSum to find pseudoversion base,
go mod download -x -json vcs-test.golang.org/hg/hello.hg@fc3a09f3dc5c # which does a refreshing hg pull.
! stderr 'hg( .*)* pull' go mod download -x -json vcs-test.golang.org/hg/hello.hg@e483a7d9f8c9
stderr 'hg( .*)* pull'
cp stdout hellohash.json cp stdout hellohash.json
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"Query": "fc3a09f3dc5c"' stdout '"Query": "e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"RepoSum"'
# go mod download vcstest/hello/v9 should fail, still print origin info # go mod download vcstest/hello/v9 should fail, still print origin info
# hg uses RepoSum instead of TagSum to describe failure condition.
! go mod download -x -json vcs-test.golang.org/hg/hello.hg/v9@latest ! go mod download -x -json vcs-test.golang.org/hg/hello.hg/v9@latest
cp stdout hellov9.json cp stdout hellov9.json
stdout '"Version": "latest"' stdout '"Version": "latest"'
stdout '"Error":.*no matching versions' stdout '"Error":.*no matching versions'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' ! stdout '"TagSum"'
stdout '"Ref": "HEAD"' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout 'RepoSum'
# go mod download vcstest/hello/sub/v9 should also fail, print origin info with TagPrefix # go mod download vcstest/hello/sub/v9 should also fail, print origin info
# hg uses RepoSum instead of TagSum to describe failure condition.
! go mod download -x -json vcs-test.golang.org/hg/hello.hg/sub/v9@latest ! go mod download -x -json vcs-test.golang.org/hg/hello.hg/sub/v9@latest
cp stdout hellosubv9.json cp stdout hellosubv9.json
stdout '"Version": "latest"' stdout '"Version": "latest"'
stdout '"Error":.*no matching versions' stdout '"Error":.*no matching versions'
stdout '"TagPrefix": "sub/"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "HEAD"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout 'RepoSum'
# go mod download vcstest/hello@nonexist should fail, still print origin info # go mod download vcstest/hello@nonexist should fail, still print origin info
! go mod download -x -json vcs-test.golang.org/hg/hello.hg@nonexist ! go mod download -x -json vcs-test.golang.org/hg/hello.hg@nonexist
cp stdout hellononexist.json cp stdout hellononexist.json
stdout '"Version": "nonexist"' stdout '"Version": "nonexist"'
stdout '"Error":.*unknown revision nonexist' stdout '"Error":.*unknown revision nonexist'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# go mod download vcstest/hello@1234567890123456789012345678901234567890 should fail, still print origin info # go mod download vcstest/hello@1234567890123456789012345678901234567890 should fail, still print origin info
@ -89,7 +86,7 @@ stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
cp stdout hellononhash.json cp stdout hellononhash.json
stdout '"Version": "1234567890123456789012345678901234567890"' stdout '"Version": "1234567890123456789012345678901234567890"'
stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890' stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# go mod download vcstest/hello@v0.0.0-20220101120101-123456789abc should fail, still print origin info # go mod download vcstest/hello@v0.0.0-20220101120101-123456789abc should fail, still print origin info
@ -98,10 +95,11 @@ stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
cp stdout hellononpseudo.json cp stdout hellononpseudo.json
stdout '"Version": "v0.0.0-20220101120101-123456789abc"' stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
stdout '"Error":.*unknown revision 123456789abc' stdout '"Error":.*unknown revision 123456789abc'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# go mod download vcstest/tagtests should invoke hg, print origin info # go mod download vcstest/tagtests should invoke hg, print origin info
# Need RepoSum to lock in tagged "latest".
go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@latest go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@latest
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
cp stdout tagtests.json cp stdout tagtests.json
@ -110,12 +108,11 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' ! stdout '"TagSum"'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
! stdout '"RepoSum"'
# go mod download vcstest/tagtests@v0.2.2 should print origin info, no TagSum needed # go mod download vcstest/tagtests@v0.2.2 should print origin info, no TagSum or RepoSum needed.
go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2 go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2
cp stdout tagtestsv022.json cp stdout tagtestsv022.json
stdout '"Version": "v0.2.2"' stdout '"Version": "v0.2.2"'
@ -124,22 +121,21 @@ stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
! stdout '"TagSum"' ! stdout '"TagSum"'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
! stdout '"RepoSum"' ! stdout '"RepoSum"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
# go mod download vcstest/tagtests@master needs a TagSum again # go mod download vcstest/tagtests@default needs a RepoSum again
go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@master go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@default
cp stdout tagtestsmaster.json cp stdout tagtestsdefault.json
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"' stdout '"Version": "v0.0.0-20190509225625-8d0b18b816df"'
stdout '"Query": "master"' stdout '"Query": "default"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' ! stdout '"TagSum"'
stdout '"Ref": "refs/heads/master"' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"' stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
! stdout '"RepoSum"'
# go mod download vcstest/prefixtagtests should invoke hg, print origin info # go mod download vcstest/prefixtagtests should invoke hg, print origin info
go mod download -x -json vcs-test.golang.org/hg/prefixtagtests.hg/sub@latest go mod download -x -json vcs-test.golang.org/hg/prefixtagtests.hg/sub@latest
@ -150,14 +146,14 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/prefixtagtests"' stdout '"URL": ".*/hg/prefixtagtests"'
stdout '"Subdir": "sub"' stdout '"Subdir": "sub"'
stdout '"TagPrefix": "sub/"' stdout '"Ref": "sub/v0.0.10"'
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="' ! stdout '"TagPrefix"'
stdout '"Ref": "refs/tags/sub/v0.0.10"' ! stdout '"TagSum"'
stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"' stdout '"RepoSum": "r1:YWOcei109p5Kohsr5xnSYlaQXmpT3iWZHZhRbfMoTkc="'
! stdout '"RepoSum"' stdout '"Hash": "1cc0dfcc254cb8901799e7f7ae182c04019b7a88"'
# go mod download of a bunch of these should fail (some are invalid) but write good JSON for later # go mod download of a bunch of these should fail (some are invalid) but write good JSON for later
! go mod download -json vcs-test.golang.org/hg/hello.hg@latest vcs-test.golang.org/hg/hello.hg/v9@latest vcs-test.golang.org/hg/hello.hg/sub/v9@latest vcs-test.golang.org/hg/tagtests.hg@latest vcs-test.golang.org/hg/tagtests.hg@v0.2.2 vcs-test.golang.org/hg/tagtests.hg@master ! go mod download -json vcs-test.golang.org/hg/hello.hg@latest vcs-test.golang.org/hg/hello.hg/v9@latest vcs-test.golang.org/hg/hello.hg/sub/v9@latest vcs-test.golang.org/hg/tagtests.hg@latest vcs-test.golang.org/hg/tagtests.hg@v0.2.2 vcs-test.golang.org/hg/tagtests.hg@default
cp stdout all.json cp stdout all.json
# clean the module cache, make sure that makes go mod download re-run hg pull, clean again # clean the module cache, make sure that makes go mod download re-run hg pull, clean again
@ -171,40 +167,40 @@ go clean -modcache
go mod download -reuse=hello.json -x -json vcs-test.golang.org/hg/hello.hg@latest go mod download -reuse=hello.json -x -json vcs-test.golang.org/hg/hello.hg@latest
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "HEAD"' stdout '"Ref": "tip"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello pseudoversion result # reuse go mod download vcstest/hello pseudoversion result
go clean -modcache go clean -modcache
go mod download -reuse=hellopseudo.json -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922010558-fc3a09f3dc5c go mod download -reuse=hellopseudo.json -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922011414-e483a7d9f8c9
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
! stdout '"(Query|TagPrefix|TagSum|Ref)"' ! stdout '"(Query|TagPrefix|TagSum|Ref)"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
# reuse go mod download vcstest/hello@hash # reuse go mod download vcstest/hello@hash
go clean -modcache go clean -modcache
go mod download -reuse=hellohash.json -x -json vcs-test.golang.org/hg/hello.hg@fc3a09f3dc5c go mod download -reuse=hellohash.json -x -json vcs-test.golang.org/hg/hello.hg@e483a7d9f8c9
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Query": "fc3a09f3dc5c"' stdout '"Query": "e483a7d9f8c9"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
! stdout '"(TagPrefix|Ref)"' ! stdout '"(TagPrefix|Ref)"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello/v9 error result # reuse go mod download vcstest/hello/v9 error result
go clean -modcache go clean -modcache
@ -213,10 +209,9 @@ go clean -modcache
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Error":.*no matching versions' stdout '"Error":.*no matching versions'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "HEAD"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' ! stdout '"(Dir|Info|GoMod|Zip)"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
# reuse go mod download vcstest/hello/sub/v9 error result # reuse go mod download vcstest/hello/sub/v9 error result
go clean -modcache go clean -modcache
@ -224,11 +219,11 @@ go clean -modcache
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Error":.*no matching versions' stdout '"Error":.*no matching versions'
stdout '"TagPrefix": "sub/"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "HEAD"' stdout '"Ref": "tip"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello@nonexist # reuse go mod download vcstest/hello@nonexist
go clean -modcache go clean -modcache
@ -237,7 +232,7 @@ go clean -modcache
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "nonexist"' stdout '"Version": "nonexist"'
stdout '"Error":.*unknown revision nonexist' stdout '"Error":.*unknown revision nonexist'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
@ -248,7 +243,7 @@ go clean -modcache
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "1234567890123456789012345678901234567890"' stdout '"Version": "1234567890123456789012345678901234567890"'
stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890' stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
@ -259,7 +254,7 @@ go clean -modcache
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20220101120101-123456789abc"' stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
stdout '"Error":.*unknown revision 123456789abc' stdout '"Error":.*unknown revision 123456789abc'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"' ! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
@ -273,10 +268,9 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' ! stdout '"(Dir|Info|GoMod|Zip)"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
# reuse go mod download vcstest/tagtests@v0.2.2 result # reuse go mod download vcstest/tagtests@v0.2.2 result
go clean -modcache go clean -modcache
@ -289,39 +283,42 @@ stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
! stdout '"TagSum"' ! stdout '"TagSum"'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"Ref": "v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
# reuse go mod download vcstest/tagtests@master result # reuse go mod download vcstest/tagtests@default result
go clean -modcache go clean -modcache
go mod download -reuse=tagtestsmaster.json -x -json vcs-test.golang.org/hg/tagtests.hg@master go mod download -reuse=tagtestsdefault.json -x -json vcs-test.golang.org/hg/tagtests.hg@default
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"' # NOTE: Strictly speaking this should be v0.2.3-... but we never
stdout '"Query": "master"' # implemented Mercurial support for finding ancestor tags to
# create pseudo-versions.
stdout '"Version": "v0.0.0-20190509225625-8d0b18b816df"'
stdout '"Query": "default"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Ref": "refs/heads/master"' stdout '"Ref": "default"'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"' stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/tagtests@master result again with all.json # reuse go mod download vcstest/tagtests@default result again with all.json
go clean -modcache go clean -modcache
go mod download -reuse=all.json -x -json vcs-test.golang.org/hg/tagtests.hg@master go mod download -reuse=all.json -x -json vcs-test.golang.org/hg/tagtests.hg@default
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"' stdout '"Version": "v0.0.0-20190509225625-8d0b18b816df"'
stdout '"Query": "master"' stdout '"Query": "default"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"' ! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Ref": "refs/heads/master"' stdout '"Ref": "default"'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"' stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# go mod download vcstest/prefixtagtests result with json # go mod download vcstest/prefixtagtests result with json
go clean -modcache go clean -modcache
@ -332,15 +329,14 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/prefixtagtests"' stdout '"URL": ".*/hg/prefixtagtests"'
stdout '"Subdir": "sub"' stdout '"Subdir": "sub"'
stdout '"TagPrefix": "sub/"' stdout '"RepoSum": "r1:YWOcei109p5Kohsr5xnSYlaQXmpT3iWZHZhRbfMoTkc="'
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="' stdout '"Ref": "sub/v0.0.10"'
stdout '"Ref": "refs/tags/sub/v0.0.10"' stdout '"Hash": "1cc0dfcc254cb8901799e7f7ae182c04019b7a88"'
stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"'
! stdout '"(Dir|Info|GoMod|Zip)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse the bulk results with all.json # reuse the bulk results with all.json
go clean -modcache go clean -modcache
! go mod download -reuse=all.json -json vcs-test.golang.org/hg/hello.hg@latest vcs-test.golang.org/hg/hello.hg/v9@latest vcs-test.golang.org/hg/hello.hg/sub/v9@latest vcs-test.golang.org/hg/tagtests.hg@latest vcs-test.golang.org/hg/tagtests.hg@v0.2.2 vcs-test.golang.org/hg/tagtests.hg@master ! go mod download -reuse=all.json -json vcs-test.golang.org/hg/hello.hg@latest vcs-test.golang.org/hg/hello.hg/v9@latest vcs-test.golang.org/hg/hello.hg/sub/v9@latest vcs-test.golang.org/hg/tagtests.hg@latest vcs-test.golang.org/hg/tagtests.hg@v0.2.2 vcs-test.golang.org/hg/tagtests.hg@default
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
! stdout '"(Dir|Info|GoMod|Zip)"' ! stdout '"(Dir|Info|GoMod|Zip)"'
@ -348,7 +344,7 @@ stdout '"Reuse": true'
# reuse attempt with stale hash should reinvoke hg, not report reuse # reuse attempt with stale hash should reinvoke hg, not report reuse
go clean -modcache go clean -modcache
cp tagtestsv022.json tagtestsv022badhash.json cp tagtestsv022.json tagtestsv022badhash.json
replace '57952' '56952XXX' tagtestsv022badhash.json replace '1e5315' '1e5315XXX' tagtestsv022badhash.json
go mod download -reuse=tagtestsv022badhash.json -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2 go mod download -reuse=tagtestsv022badhash.json -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
! stdout '"Reuse": true' ! stdout '"Reuse": true'
@ -357,8 +353,8 @@ stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"(TagPrefix|TagSum|RepoSum)"' ! stdout '"(TagPrefix|TagSum|RepoSum)"'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"Ref": "v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"Dir"' stdout '"Dir"'
stdout '"Info"' stdout '"Info"'
stdout '"GoMod"' stdout '"GoMod"'
@ -388,20 +384,19 @@ stdout '"URL": ".*/hg/tagtests"'
# reuse with stale Dir # reuse with stale Dir
go clean -modcache go clean -modcache
cp tagtestsv022.json tagtestsv022baddir.json cp tagtestsv022.json tagtestsv022baddir.json
replace '\t\t\"Ref\":' '\t\t\"Subdir\": \"subdir\",\n\t\t\"Ref\":' tagtestsv022baddir.json replace '\"VCS\":' '\"Subdir\":\"subdir\", \"VCS\":' tagtestsv022baddir.json
go mod download -reuse=tagtestsv022baddir.json -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2 go mod download -reuse=tagtestsv022baddir.json -x -json vcs-test.golang.org/hg/tagtests.hg@v0.2.2
! stdout '"Reuse": true' ! stdout '"Reuse": true'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
! stdout '"RepoSum"' ! stdout '"RepoSum"'
# reuse with stale TagSum # reuse with stale RepoSum
go clean -modcache go clean -modcache
cp tagtests.json tagtestsbadtagsum.json cp tagtests.json tagtestsbadreposum.json
replace 'sMEOGo=' 'sMEoGo=XXX' tagtestsbadtagsum.json replace '8dnv90' '8dnv90XXX' tagtestsbadreposum.json
go mod download -reuse=tagtestsbadtagsum.json -x -json vcs-test.golang.org/hg/tagtests.hg@latest go mod download -reuse=tagtestsbadreposum.json -x -json vcs-test.golang.org/hg/tagtests.hg@latest
! stdout '"Reuse": true' ! stdout '"Reuse": true'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
! stdout '"RepoSum"'
# go list on repo with no tags # go list on repo with no tags
go clean -modcache go clean -modcache
@ -409,14 +404,12 @@ go list -x -json -m -retracted -versions vcs-test.golang.org/hg/hello.hg@latest
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
cp stdout hellolist.json cp stdout hellolist.json
! stdout '"Versions"' ! stdout '"Versions"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"' stdout '"Query": "latest"'
! stdout '"TagPrefix"' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
# reuse go list on repo with no tags # reuse go list on repo with no tags
go clean -modcache go clean -modcache
@ -424,24 +417,22 @@ go list -x -reuse=hellolist.json -json -m -retracted -versions vcs-test.golang.o
! stderr 'hg( .*)* pull' ! stderr 'hg( .*)* pull'
stdout '"Reuse": true' stdout '"Reuse": true'
! stdout '"Versions"' ! stdout '"Versions"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"' stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"' stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"' stdout '"Query": "latest"'
! stdout '"TagPrefix"' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
# reuse with stale list # reuse with stale list
go clean -modcache go clean -modcache
cp hellolist.json hellolistbad.json cp hellolist.json hellolistbad.json
replace '47DEQ' 'ZZZ' hellolistbad.json replace 'blLvkhBri' 'ZZZ' hellolistbad.json
go clean -modcache go clean -modcache
go list -x -reuse=hellolistbad.json -json -m -retracted -versions vcs-test.golang.org/hg/hello.hg@latest go list -x -reuse=hellolistbad.json -json -m -retracted -versions vcs-test.golang.org/hg/hello.hg@latest
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
! stdout '"Reuse": true' ! stdout '"Reuse": true'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="' stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
# go list on repo with tags # go list on repo with tags
go clean -modcache go clean -modcache
@ -454,9 +445,9 @@ stdout '"v0.2.2"'
stdout '"Version": "v0.2.2"' stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' stdout '"Ref": "v0.2.2"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
# reuse go list on repo with tags # reuse go list on repo with tags
go clean -modcache go clean -modcache
@ -469,15 +460,15 @@ stdout '"v0.2.2"'
stdout '"Version": "v0.2.2"' stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"' stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"' stdout '"URL": ".*/hg/tagtests"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"' stdout '"Ref": "v0.2.2"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"Ref": "refs/tags/v0.2.2"' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
# reuse with stale list # reuse with stale list
go clean -modcache go clean -modcache
cp taglist.json taglistbad.json cp taglist.json taglistbad.json
replace 'Dp7yRKDu' 'ZZZ' taglistbad.json replace '8dnv906' 'ZZZ' taglistbad.json
go list -reuse=taglistbad.json -x -json -m -retracted -versions vcs-test.golang.org/hg/tagtests.hg@latest go list -reuse=taglistbad.json -x -json -m -retracted -versions vcs-test.golang.org/hg/tagtests.hg@latest
stderr 'hg( .*)* pull' stderr 'hg( .*)* pull'
! stdout '"Reuse": true' ! stdout '"Reuse": true'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="' stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'

View file

@ -1,52 +1,51 @@
handle git env date=2019-05-09T18:35:00-04:00
env GIT_AUTHOR_NAME='Jay Conrod' handle hg
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
at 2019-05-09T18:35:00-04:00 hg init
hg add sub
hg commit -u rsc -d $date -m 'create module sub'
git init echo v0.1.0
git add sub
git commit -m 'create module sub'
git branch -m master
echo 'v0.1.0'
cp stdout status cp stdout status
git add status hg add status
git commit -a -m 'v0.1.0' hg commit -u rsc -d $date -m v0.1.0
git tag 'v0.1.0' hg tag -u rsc -d $date v0.1.0
echo 'sub/v0.0.9' echo sub/v0.0.9
cp stdout status cp stdout status
git commit -a -m 'sub/v0.0.9' hg add status
git tag 'sub/v0.0.9' hg commit -u rsc -d $date -m sub/v0.0.9
hg tag -u rsc -d $date sub/v0.0.9
echo 'sub/v0.0.10' echo sub/v0.0.10
cp stdout status cp stdout status
git commit -a -m 'sub/v0.0.10' hg commit -u rsc -d $date -m sub/v0.0.10 status
git tag 'sub/v0.0.10' hg tag -u rsc -d $date sub/v0.0.10
echo 'v0.2.0' echo v0.2.0
cp stdout status cp stdout status
git commit -a -m 'v0.2.0' hg commit -u rsc -d $date -m v0.2.0
git tag 'v0.2.0' hg tag -u rsc -d $date v0.2.0
echo 'after last tag' echo 'after last tag'
cp stdout status cp stdout status
git commit -a -m 'after last tag' hg commit -u rsc -d $date -m 'after last tag'
git show-ref --tags --heads hg tags
cmp stdout .git-refs cmp stdout .hg-tags
-- .git-refs -- hg branches
c3ee5d0dfbb9bf3c4d8bb2bce24cd8d14d2d4238 refs/heads/master cmp stdout .hg-branches
2b7c4692e12c109263cab51b416fcc835ddd7eae refs/tags/sub/v0.0.10
883885166298d79a0561d571a3044ec5db2e7c28 refs/tags/sub/v0.0.9 -- .hg-tags --
db89fc573cfb939faf0aa0660671eb4cf8b8b673 refs/tags/v0.1.0 tip 9:840814f739c2
1abe41965749e50828dd41de8d12c6ebc8e4e131 refs/tags/v0.2.0 v0.2.0 7:84e452ea2b0a
sub/v0.0.10 5:1cc0dfcc254c
sub/v0.0.9 3:c5f5e3168705
v0.1.0 1:d6ba12969a9b
-- .hg-branches --
default 9:840814f739c2
-- sub/go.mod -- -- sub/go.mod --
module vcs-test.golang.org/git/prefixtagtests.git/sub module vcs-test.golang.org/git/prefixtagtests.git/sub
-- sub/sub.go -- -- sub/sub.go --

View file

@ -1,39 +1,26 @@
handle git env date=2019-05-09T18:56:25-04:00
env GIT_AUTHOR_NAME='Jay Conrod' handle hg
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
at 2019-05-09T18:56:25-04:00 hg init
hg add go.mod tagtests.go
hg commit --user 'rsc' --date $date -m 'create module tagtests'
hg branch b
hg add v0.2.1
hg commit --user 'rsc' --date $date -m 'v0.2.1'
hg tag --user 'rsc' --date $date v0.2.1
git init hg update default
hg add v0.2.2
hg commit --user 'rsc' --date $date -m 'v0.2.2'
hg tag --user 'rsc' --date $date v0.2.2
git add go.mod tagtests.go hg tags
git commit -m 'create module tagtests' cmp stdout .hg-tags
git branch -m master
git branch b
git add v0.2.1 hg branches
git commit -m 'v0.2.1' cmp stdout .hg-branches
git tag 'v0.2.1'
git checkout b
git add 'v0.2.2'
git commit -m 'v0.2.2'
git tag 'v0.2.2'
git checkout master
git merge b -m 'merge'
git show-ref --tags --heads
cmp stdout .git-refs
-- .git-refs --
59356c8cd18c5fe9a598167d98a6843e52d57952 refs/heads/b
c7818c24fa2f3f714c67d0a6d3e411c85a518d1f refs/heads/master
101c49f5af1b2466332158058cf5f03c8cca6429 refs/tags/v0.2.1
59356c8cd18c5fe9a598167d98a6843e52d57952 refs/tags/v0.2.2
-- go.mod -- -- go.mod --
module vcs-test.golang.org/git/tagtests.git module vcs-test.golang.org/git/tagtests.git
-- tagtests.go -- -- tagtests.go --
@ -42,3 +29,10 @@ package tagtests
v0.2.1 v0.2.1
-- v0.2.2 -- -- v0.2.2 --
v0.2.2 v0.2.2
-- .hg-tags --
tip 4:8d0b18b816df
v0.2.2 3:1e531550e864
v0.2.1 1:010a2d1a2ea7
-- .hg-branches --
default 4:8d0b18b816df
b 2:ceae444ffda5