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
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.
o.TagSum = ""
o.TagPrefix = ""
o.RepoSum = ""
// Ref doesn't matter if you have a pseudoversion.
if module.IsPseudoVersion(info.Version) {
o.Ref = ""

View file

@ -116,9 +116,12 @@ type Origin struct {
Ref string `json:",omitempty"`
// 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.
// 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.
// 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
// 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"`
}

View file

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

View file

@ -17,9 +17,11 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/lockedfile"
"cmd/go/internal/str"
"cmd/internal/par"
@ -80,6 +82,10 @@ type vcsRepo struct {
fetchOnce sync.Once
fetchErr error
fetched atomic.Bool
repoSumOnce sync.Once
repoSum string
}
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
}
_, err = Run(ctx, r.dir, cmd.init(r.remote))
if err == nil && cmd.postInit != nil {
err = cmd.postInit(ctx, r)
}
release()
if err != nil {
@ -144,18 +153,25 @@ const vcsWorkDirType = "vcs1."
type vcsCmd struct {
vcs string // vcs name "hg"
init func(remote string) []string // cmd to init repo to track remote
postInit func(context.Context, *vcsRepo) error // func to init repo after .init runs
repoSum func(remote string) []string // cmd to calculate reposum of remote repo
lookupRef func(remote, ref string) []string // cmd to look up ref in remote repo
tags func(remote string) []string // cmd to list local tags
tagsNeedsFetch bool // run fetch before tags
tagRE *lazyregexp.Regexp // regexp to extract tag names from output of tags cmd
branches func(remote string) []string // cmd to list local branches
branchesNeedsFetch bool // run branches before tags
branchRE *lazyregexp.Regexp // regexp to extract branch names from output of tags cmd
badLocalRevRE *lazyregexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first
statLocal func(rev, remote string) []string // cmd to stat local rev
parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal
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
doReadZip func(ctx context.Context, dst io.Writer, workDir, rev, subdir, remote string) error // arbitrary function 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
@ -163,16 +179,36 @@ var re = lazyregexp.New
var vcsCmds = map[string]*vcsCmd{
"hg": {
vcs: "hg",
init: func(remote string) []string {
return []string{"hg", "clone", "-U", "--", remote, "."}
repoSum: func(remote string) []string {
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 {
return []string{"hg", "tags", "-q"}
},
tagsNeedsFetch: true,
tagRE: re(`(?m)^[^\n]+$`),
branches: func(remote string) []string {
return []string{"hg", "branches", "-c", "-q"}
},
branchesNeedsFetch: true,
branchRE: re(`(?m)^[^\n]+$`),
badLocalRevRE: re(`(?m)^(tip)$`),
statLocal: func(rev, remote string) []string {
@ -276,6 +312,10 @@ var vcsCmds = map[string]*vcsCmd{
}
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))
if err != nil {
return
@ -296,6 +336,10 @@ func (r *vcsRepo) loadBranches(ctx context.Context) {
return
}
if r.cmd.branchesNeedsFetch {
r.fetchOnce.Do(func() { r.fetch(ctx) })
}
out, err := Run(ctx, r.dir, r.cmd.branches(r.remote))
if err != nil {
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 {
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)
}
@ -323,13 +444,7 @@ func (r *vcsRepo) Tags(ctx context.Context, prefix string) (*Tags, error) {
r.tagsOnce.Do(func() { r.loadTags(ctx) })
tags := &Tags{
// None of the other VCS provide a reasonable way to compute TagSum
// without downloading the whole repo, so we only include VCS and URL
// in the Origin.
Origin: &Origin{
VCS: r.cmd.vcs,
URL: r.remote,
},
Origin: r.repoSumOrigin(ctx),
List: []Tag{},
}
for tag := range r.tags {
@ -372,7 +487,7 @@ func (r *vcsRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
}
info, err := r.statLocal(ctx, rev)
if err != nil {
return nil, err
return info, err
}
if !revOK {
info.Version = info.Name
@ -389,13 +504,15 @@ func (r *vcsRepo) fetch(ctx context.Context) {
}
_, r.fetchErr = Run(ctx, r.dir, r.cmd.fetch)
release()
r.fetched.Store(true)
}
}
func (r *vcsRepo) statLocal(ctx context.Context, rev string) (*RevInfo, error) {
out, err := Run(ctx, r.dir, r.cmd.statLocal(rev, r.remote))
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))
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.URL = r.remote
info.Origin.Ref = rev
if strings.HasPrefix(info.Name, rev) && len(rev) >= 12 {
info.Origin.Ref = "" // duplicates Hash
}
return info, nil
}
@ -521,6 +642,11 @@ func (d *deleteCloser) Close() error {
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) {
f := strings.Fields(out)
if len(f) < 3 {
@ -545,9 +671,7 @@ func hgParseStat(rev, out string) (*RevInfo, error) {
sort.Strings(tags)
info := &RevInfo{
Origin: &Origin{
Hash: hash,
},
Origin: &Origin{Hash: hash},
Name: hash,
Short: ShortenSHA1(hash),
Time: time.Unix(t, 0).UTC(),
@ -630,9 +754,7 @@ func fossilParseStat(rev, out string) (*RevInfo, error) {
version = hash // extend to full hash
}
info := &RevInfo{
Origin: &Origin{
Hash: hash,
},
Origin: &Origin{Hash: hash},
Name: hash,
Short: ShortenSHA1(hash),
Time: t,

View file

@ -384,6 +384,9 @@ func (r *codeRepo) convert(ctx context.Context, info *codehost.RevInfo, statVers
} else {
origin.TagPrefix = tags.Origin.TagPrefix
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.TagPrefix = m2.TagPrefix
}
if m2.RepoSum != "" {
if m1.RepoSum != "" && m1.RepoSum != m2.RepoSum {
return nil
}
merged.RepoSum = m2.RepoSum
}
if m2.Ref != "" {
if m1.Ref != "" && m1.Ref != m2.Ref {
return nil

View file

@ -199,8 +199,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
defer func() {
if v := recover(); v != nil {
debug.PrintStack()
s.logger.Fatal(v)
if v == http.ErrAbortHandler {
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 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
stderr 'git( .*)* fetch'
cp stdout hellopseudo.json
! stdout '"(Query|TagPrefix|TagSum|Ref)"'
! stdout '"(Query|TagPrefix|TagSum|Ref|RepoSum)"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"VCS": "git"'
stdout '"URL": ".*/git/hello"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
go clean -modcache
# go mod download vcstest/hello should invoke git, print origin info

View file

@ -1,21 +1,19 @@
skip
[short] skip
[!hg] skip
[!exec:hg] skip
env GO111MODULE=on
env GOPROXY=direct
env GOSUMDB=off
# go mod download with the pseudo-version should invoke hg but not have a TagSum or Ref.
go mod download -x -json vcs-test.golang.org/hg/hello.hg@v0.0.0-20170922010558-fc3a09f3dc5c
# 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-20170922011414-e483a7d9f8c9
stderr 'hg( .*)* pull'
cp stdout hellopseudo.json
! stdout '"(Query|TagPrefix|TagSum|Ref)"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
! stdout '"(Query|TagPrefix|TagSum|Ref|RepoSum)"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"RepoSum"'
go clean -modcache
@ -23,64 +21,63 @@ go clean -modcache
go mod download -x -json vcs-test.golang.org/hg/hello.hg@latest
stderr 'hg( .*)* pull'
cp stdout hello.json
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
! stdout '"TagSum"'
stdout '"Ref": "tip"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
# 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,
# 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'
cp stdout hellopseudo2.json
cmpenv hellopseudo.json hellopseudo2.json
# go mod download vcstest/hello@hash needs to check TagSum to find pseudoversion base.
go mod download -x -json vcs-test.golang.org/hg/hello.hg@fc3a09f3dc5c
! stderr 'hg( .*)* pull'
# go mod download hg/hello@hash needs to check RepoSum to find pseudoversion base,
# which does a refreshing hg pull.
go mod download -x -json vcs-test.golang.org/hg/hello.hg@e483a7d9f8c9
stderr 'hg( .*)* pull'
cp stdout hellohash.json
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Query": "fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"Query": "e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
# 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
cp stdout hellov9.json
stdout '"Version": "latest"'
stdout '"Error":.*no matching versions'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout 'RepoSum'
! stdout '"TagSum"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
# 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
cp stdout hellosubv9.json
stdout '"Version": "latest"'
stdout '"Error":.*no matching versions'
stdout '"TagPrefix": "sub/"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout 'RepoSum'
! stdout '"TagPrefix"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
# 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
cp stdout hellononexist.json
stdout '"Version": "nonexist"'
stdout '"Error":.*unknown revision nonexist'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# 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
stdout '"Version": "1234567890123456789012345678901234567890"'
stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# 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
stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
stdout '"Error":.*unknown revision 123456789abc'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
# 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
stderr 'hg( .*)* pull'
cp stdout tagtests.json
@ -110,12 +108,11 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
! stdout '"RepoSum"'
! stdout '"TagSum"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
# 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
cp stdout tagtestsv022.json
stdout '"Version": "v0.2.2"'
@ -124,22 +121,21 @@ stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
! stdout '"TagSum"'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
! stdout '"RepoSum"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
# go mod download vcstest/tagtests@master needs a TagSum again
go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@master
cp stdout tagtestsmaster.json
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
stdout '"Query": "master"'
# go mod download vcstest/tagtests@default needs a RepoSum again
go mod download -x -json vcs-test.golang.org/hg/tagtests.hg@default
cp stdout tagtestsdefault.json
stdout '"Version": "v0.0.0-20190509225625-8d0b18b816df"'
stdout '"Query": "default"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/heads/master"'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
! stdout '"RepoSum"'
! stdout '"TagSum"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
# 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
@ -150,14 +146,14 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/prefixtagtests"'
stdout '"Subdir": "sub"'
stdout '"TagPrefix": "sub/"'
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
stdout '"Ref": "refs/tags/sub/v0.0.10"'
stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"'
! stdout '"RepoSum"'
stdout '"Ref": "sub/v0.0.10"'
! stdout '"TagPrefix"'
! stdout '"TagSum"'
stdout '"RepoSum": "r1:YWOcei109p5Kohsr5xnSYlaQXmpT3iWZHZhRbfMoTkc="'
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 -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
# 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
! stderr 'hg( .*)* pull'
stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "tip"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello pseudoversion result
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'
stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
! stdout '"(Query|TagPrefix|TagSum|Ref)"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
# reuse go mod download vcstest/hello@hash
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'
stdout '"Reuse": true'
stdout '"Query": "fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Query": "e483a7d9f8c9"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
! stdout '"(TagPrefix|Ref)"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello/v9 error result
go clean -modcache
@ -213,10 +209,9 @@ go clean -modcache
stdout '"Reuse": true'
stdout '"Error":.*no matching versions'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello/sub/v9 error result
go clean -modcache
@ -224,11 +219,11 @@ go clean -modcache
! stderr 'hg( .*)* pull'
stdout '"Reuse": true'
stdout '"Error":.*no matching versions'
stdout '"TagPrefix": "sub/"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Ref": "HEAD"'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
! stdout '"TagPrefix"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Ref": "tip"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/hello@nonexist
go clean -modcache
@ -237,7 +232,7 @@ go clean -modcache
stdout '"Reuse": true'
stdout '"Version": "nonexist"'
stdout '"Error":.*unknown revision nonexist'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"'
@ -248,7 +243,7 @@ go clean -modcache
stdout '"Reuse": true'
stdout '"Version": "1234567890123456789012345678901234567890"'
stdout '"Error":.*unknown revision 1234567890123456789012345678901234567890'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"'
@ -259,7 +254,7 @@ go clean -modcache
stdout '"Reuse": true'
stdout '"Version": "v0.0.0-20220101120101-123456789abc"'
stdout '"Error":.*unknown revision 123456789abc'
stdout '"RepoSum": "r1:c0/9JCZ25lxoBiK3[+]3BhACU4giH49flcJmBynJ[+]Jvmc="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
! stdout '"(TagPrefix|TagSum|Ref|Hash)"'
! stdout '"(Dir|Info|GoMod|Zip)"'
@ -273,10 +268,9 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse go mod download vcstest/tagtests@v0.2.2 result
go clean -modcache
@ -289,39 +283,42 @@ stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
! stdout '"TagSum"'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
! 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 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'
stdout '"Reuse": true'
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
stdout '"Query": "master"'
# NOTE: Strictly speaking this should be v0.2.3-... but we never
# 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 '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/heads/master"'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Ref": "default"'
stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
! 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 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'
stdout '"Reuse": true'
stdout '"Version": "v0.2.3-0.20190509225625-c7818c24fa2f"'
stdout '"Query": "master"'
stdout '"Version": "v0.0.0-20190509225625-8d0b18b816df"'
stdout '"Query": "default"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/heads/master"'
stdout '"Hash": "c7818c24fa2f3f714c67d0a6d3e411c85a518d1f"'
! stdout '"(Dir|Info|GoMod|Zip|RepoSum)"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
stdout '"Ref": "default"'
stdout '"Hash": "8d0b18b816df5e9c564761b405b1d7949c24ee6b"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# go mod download vcstest/prefixtagtests result with json
go clean -modcache
@ -332,15 +329,14 @@ stdout '"Query": "latest"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/prefixtagtests"'
stdout '"Subdir": "sub"'
stdout '"TagPrefix": "sub/"'
stdout '"TagSum": "t1:YGSbWkJ8dn9ORAr[+]BlKHFK/2ZhXLb9hVuYfTZ9D8C7g="'
stdout '"Ref": "refs/tags/sub/v0.0.10"'
stdout '"Hash": "2b7c4692e12c109263cab51b416fcc835ddd7eae"'
stdout '"RepoSum": "r1:YWOcei109p5Kohsr5xnSYlaQXmpT3iWZHZhRbfMoTkc="'
stdout '"Ref": "sub/v0.0.10"'
stdout '"Hash": "1cc0dfcc254cb8901799e7f7ae182c04019b7a88"'
! stdout '"(Dir|Info|GoMod|Zip)"'
# reuse the bulk results with all.json
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'
stdout '"Reuse": true'
! stdout '"(Dir|Info|GoMod|Zip)"'
@ -348,7 +344,7 @@ stdout '"Reuse": true'
# reuse attempt with stale hash should reinvoke hg, not report reuse
go clean -modcache
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
stderr 'hg( .*)* pull'
! stdout '"Reuse": true'
@ -357,8 +353,8 @@ stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"(TagPrefix|TagSum|RepoSum)"'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"Dir"'
stdout '"Info"'
stdout '"GoMod"'
@ -388,20 +384,19 @@ stdout '"URL": ".*/hg/tagtests"'
# reuse with stale Dir
go clean -modcache
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
! stdout '"Reuse": true'
stdout '"URL": ".*/hg/tagtests"'
! stdout '"RepoSum"'
# reuse with stale TagSum
# reuse with stale RepoSum
go clean -modcache
cp tagtests.json tagtestsbadtagsum.json
replace 'sMEOGo=' 'sMEoGo=XXX' tagtestsbadtagsum.json
go mod download -reuse=tagtestsbadtagsum.json -x -json vcs-test.golang.org/hg/tagtests.hg@latest
cp tagtests.json tagtestsbadreposum.json
replace '8dnv90' '8dnv90XXX' tagtestsbadreposum.json
go mod download -reuse=tagtestsbadreposum.json -x -json vcs-test.golang.org/hg/tagtests.hg@latest
! stdout '"Reuse": true'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
! stdout '"RepoSum"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
# go list on repo with no tags
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'
cp stdout hellolist.json
! stdout '"Versions"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
# reuse go list on repo with no tags
go clean -modcache
@ -424,24 +417,22 @@ go list -x -reuse=hellolist.json -json -m -retracted -versions vcs-test.golang.o
! stderr 'hg( .*)* pull'
stdout '"Reuse": true'
! stdout '"Versions"'
stdout '"Version": "v0.0.0-20170922010558-fc3a09f3dc5c"'
stdout '"Version": "v0.0.0-20170922011414-e483a7d9f8c9"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/hello"'
stdout '"Query": "latest"'
! stdout '"TagPrefix"'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"Hash": "fc3a09f3dc5cfe0d7a743ea18f1f5226e68b3777"'
! stdout '"RepoSum"'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
stdout '"Hash": "e483a7d9f8c9b4bc57430bdd8f81f0a65e4011c0"'
# reuse with stale list
go clean -modcache
cp hellolist.json hellolistbad.json
replace '47DEQ' 'ZZZ' hellolistbad.json
replace 'blLvkhBri' 'ZZZ' hellolistbad.json
go clean -modcache
go list -x -reuse=hellolistbad.json -json -m -retracted -versions vcs-test.golang.org/hg/hello.hg@latest
stderr 'hg( .*)* pull'
! stdout '"Reuse": true'
stdout '"TagSum": "t1:47DEQpj8HBSa[+]/TImW[+]5JCeuQeRkm5NMpJWZG3hSuFU="'
stdout '"RepoSum": "r1:blLvkhBriVMV[+]6Il4Ub43wlyWXIe1NpobTelF0peaG0="'
# go list on repo with tags
go clean -modcache
@ -454,9 +445,9 @@ stdout '"v0.2.2"'
stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
# reuse go list on repo with tags
go clean -modcache
@ -469,15 +460,15 @@ stdout '"v0.2.2"'
stdout '"Version": "v0.2.2"'
stdout '"VCS": "hg"'
stdout '"URL": ".*/hg/tagtests"'
stdout '"Hash": "59356c8cd18c5fe9a598167d98a6843e52d57952"'
stdout '"TagSum": "t1:Dp7yRKDuE8WjG0429PN9hYWjqhy2te7P9Oki/sMEOGo="'
stdout '"Ref": "refs/tags/v0.2.2"'
stdout '"Ref": "v0.2.2"'
stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
stdout '"RepoSum": "r1:8dnv906Aq1vb9YpNl9pslfva0VfG9enKb6O6NWs0xF0="'
# reuse with stale list
go clean -modcache
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
stderr 'hg( .*)* pull'
! 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'
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
handle hg
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
git add sub
git commit -m 'create module sub'
git branch -m master
echo 'v0.1.0'
echo v0.1.0
cp stdout status
git add status
git commit -a -m 'v0.1.0'
git tag 'v0.1.0'
hg add status
hg commit -u rsc -d $date -m 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
git commit -a -m 'sub/v0.0.9'
git tag 'sub/v0.0.9'
hg add status
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
git commit -a -m 'sub/v0.0.10'
git tag 'sub/v0.0.10'
hg commit -u rsc -d $date -m sub/v0.0.10 status
hg tag -u rsc -d $date sub/v0.0.10
echo 'v0.2.0'
echo v0.2.0
cp stdout status
git commit -a -m 'v0.2.0'
git tag 'v0.2.0'
hg commit -u rsc -d $date -m v0.2.0
hg tag -u rsc -d $date v0.2.0
echo 'after last tag'
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
cmp stdout .git-refs
hg tags
cmp stdout .hg-tags
-- .git-refs --
c3ee5d0dfbb9bf3c4d8bb2bce24cd8d14d2d4238 refs/heads/master
2b7c4692e12c109263cab51b416fcc835ddd7eae refs/tags/sub/v0.0.10
883885166298d79a0561d571a3044ec5db2e7c28 refs/tags/sub/v0.0.9
db89fc573cfb939faf0aa0660671eb4cf8b8b673 refs/tags/v0.1.0
1abe41965749e50828dd41de8d12c6ebc8e4e131 refs/tags/v0.2.0
hg branches
cmp stdout .hg-branches
-- .hg-tags --
tip 9:840814f739c2
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 --
module vcs-test.golang.org/git/prefixtagtests.git/sub
-- 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'
env GIT_AUTHOR_EMAIL='jayconrod@google.com'
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
handle hg
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
git commit -m 'create module tagtests'
git branch -m master
git branch b
hg tags
cmp stdout .hg-tags
git add v0.2.1
git commit -m 'v0.2.1'
git tag 'v0.2.1'
hg branches
cmp stdout .hg-branches
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 --
module vcs-test.golang.org/git/tagtests.git
-- tagtests.go --
@ -42,3 +29,10 @@ package tagtests
v0.2.1
-- 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