]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: implement -reuse for Mercurial repos
authorRuss Cox <rsc@golang.org>
Tue, 19 Aug 2025 19:27:39 +0000 (15:27 -0400)
committerGopher Robot <gobot@golang.org>
Tue, 11 Nov 2025 15:21:02 +0000 (07:21 -0800)
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>

12 files changed:
lib/hg/goreposum.py [new file with mode: 0644]
src/cmd/go/internal/modfetch/cache.go
src/cmd/go/internal/modfetch/codehost/codehost.go
src/cmd/go/internal/modfetch/codehost/git_test.go
src/cmd/go/internal/modfetch/codehost/vcs.go
src/cmd/go/internal/modfetch/coderepo.go
src/cmd/go/internal/modload/build.go
src/cmd/go/internal/vcweb/vcweb.go
src/cmd/go/testdata/script/reuse_git.txt
src/cmd/go/testdata/script/reuse_hg.txt
src/cmd/go/testdata/vcstest/hg/prefixtagtests.txt
src/cmd/go/testdata/vcstest/hg/tagtests.txt

diff --git a/lib/hg/goreposum.py b/lib/hg/goreposum.py
new file mode 100644 (file)
index 0000000..1a7d7a4
--- /dev/null
@@ -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'))
index 9c34581a910a4ab7bfda024b4d5b649125b8e26f..30020d24a711b5c6e3813dfdf4ddbc7a83887333 100644 (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 = ""
index edb87e4089144b1f8adbfb3393fd35a678b933e0..08b1216d6bfa29403e041158594ecc9967b474a3 100644 (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"`
 }
 
index 68b0d161a095997c46fcd396afc159b3230819c1..e032a14e124e9a2c9df7af6c4a6d53dc3880f3ab 100644 (file)
@@ -383,6 +383,7 @@ func TestLatest(t *testing.T) {
                                Origin: &Origin{
                                        VCS:  "hg",
                                        URL:  hgrepo1,
+                                       Ref:  "tip",
                                        Hash: "745aacc8b24decc44ac2b13870f5472b479f4d72",
                                },
                                Name:    "745aacc8b24decc44ac2b13870f5472b479f4d72",
index d80397502b422d0ec138bc23de45c0d29203e09f..a73f882ccc63128f9608dde35eb0a5225818a29e 100644 (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 {
@@ -142,20 +151,27 @@ func newVCSRepo(ctx context.Context, vcs, remote string, local bool) (Repo, erro
 const vcsWorkDirType = "vcs1."
 
 type vcsCmd struct {
-       vcs           string                                                                              // vcs name "hg"
-       init          func(remote string) []string                                                        // cmd to init repo to track remote
-       tags          func(remote string) []string                                                        // cmd to list local tags
-       tagRE         *lazyregexp.Regexp                                                                  // regexp to extract tag names from output of tags cmd
-       branches      func(remote string) []string                                                        // cmd to list local branches
-       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
-       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
+       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)           // 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
@@ -163,18 +179,38 @@ var re = lazyregexp.New
 var vcsCmds = map[string]*vcsCmd{
        "hg": {
                vcs: "hg",
+               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", "clone", "-U", "--", remote, "."}
+                       return []string{"hg", "init", "."}
                },
+               postInit: hgAddRemote,
                tags: func(remote string) []string {
                        return []string{"hg", "tags", "-q"}
                },
-               tagRE: re(`(?m)^[^\n]+$`),
+               tagsNeedsFetch: true,
+               tagRE:          re(`(?m)^[^\n]+$`),
                branches: func(remote string) []string {
                        return []string{"hg", "branches", "-c", "-q"}
                },
-               branchRE:      re(`(?m)^[^\n]+$`),
-               badLocalRevRE: re(`(?m)^(tip)$`),
+               branchesNeedsFetch: true,
+               branchRE:           re(`(?m)^[^\n]+$`),
+               badLocalRevRE:      re(`(?m)^(tip)$`),
                statLocal: func(rev, remote string) []string {
                        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) {
+       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,14 +444,8 @@ 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,
-               },
-               List: []Tag{},
+               Origin: r.repoSumOrigin(ctx),
+               List:   []Tag{},
        }
        for tag := range r.tags {
                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)
        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,
index 3df469d28525fa3ca2b5c229eb8363fb3f05bba6..7cec96a307012d8a52fa2f3660fc97bc442020e9 100644 (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
+                               }
                        }
                }
        }()
index f6ba8d43b779f59396b511ac86eb2b56babf868a..4f334a47203fdd1a79917dec421166329cd41d29 100644 (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
index 4b4e127bb042e086d34e9bd81a712aa7ca7d2003..98d39a3b1f28a66014037fd92aad13cdaf476bbc 100644 (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())
                }
        }()
 
index 3ec6421cfaeeaf20e409620fc76c9724f1b972b7..faf2124db56620368047e6e1c45fff7e29c67fe6 100644 (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
index ebc7643733d9eb2d3fb7550125cf44aba58e7436..b9df7ae7f260df2ce90ab295af174e65e95e1bd4 100644 (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"'
-
-# 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"'
+stdout '"Ref": "v0.2.2"'
+stdout '"Hash": "1e531550e864b16f25013cfbbf2d8e7cf07a0374"'
+
+# 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="'
index 6c89c857f49ef86304f4ea4257feff92d799c589..c61c9bacae93d071252d403abd376980ba188718 100644 (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'
-
-git show-ref --tags --heads
-cmp stdout .git-refs
-
--- .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 commit -u rsc -d $date -m 'after last tag'
+
+hg tags
+cmp stdout .hg-tags
+
+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 --
index 92e79cda877f87fb1d0b88d9fd989fa6b057ff6a..38b3e97ef9b3598dcc2b7eb4dd9e94dc0c133da8 100644 (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