--- a/hgext/extdiff.py Fri May 15 00:53:37 2020 +0200
+++ b/hgext/extdiff.py Tue May 26 08:07:24 2020 -0700
@@ -360,14 +360,12 @@
- just invoke the diff for a single file in the working dir
'''
+ cmdutil.check_at_most_one_arg(opts, b'rev', b'change')
revs = opts.get(b'rev')
change = opts.get(b'change')
do3way = b'$parent2' in cmdline
- if revs and change:
- msg = _(b'cannot specify --rev and --change at the same time')
- raise error.Abort(msg)
- elif change:
+ if change:
ctx2 = scmutil.revsingle(repo, change, None)
ctx1a, ctx1b = ctx2.p1(), ctx2.p2()
else:
--- a/hgext/git/gitlog.py Fri May 15 00:53:37 2020 +0200
+++ b/hgext/git/gitlog.py Tue May 26 08:07:24 2020 -0700
@@ -247,6 +247,60 @@
def descendants(self, revs):
return dagop.descendantrevs(revs, self.revs, self.parentrevs)
+ def incrementalmissingrevs(self, common=None):
+ """Return an object that can be used to incrementally compute the
+ revision numbers of the ancestors of arbitrary sets that are not
+ ancestors of common. This is an ancestor.incrementalmissingancestors
+ object.
+
+ 'common' is a list of revision numbers. If common is not supplied, uses
+ nullrev.
+ """
+ if common is None:
+ common = [nodemod.nullrev]
+
+ return ancestor.incrementalmissingancestors(self.parentrevs, common)
+
+ def findmissing(self, common=None, heads=None):
+ """Return the ancestors of heads that are not ancestors of common.
+
+ More specifically, return a list of nodes N such that every N
+ satisfies the following constraints:
+
+ 1. N is an ancestor of some node in 'heads'
+ 2. N is not an ancestor of any node in 'common'
+
+ The list is sorted by revision number, meaning it is
+ topologically sorted.
+
+ 'heads' and 'common' are both lists of node IDs. If heads is
+ not supplied, uses all of the revlog's heads. If common is not
+ supplied, uses nullid."""
+ if common is None:
+ common = [nodemod.nullid]
+ if heads is None:
+ heads = self.heads()
+
+ common = [self.rev(n) for n in common]
+ heads = [self.rev(n) for n in heads]
+
+ inc = self.incrementalmissingrevs(common=common)
+ return [self.node(r) for r in inc.missingancestors(heads)]
+
+ def children(self, node):
+ """find the children of a given node"""
+ c = []
+ p = self.rev(node)
+ for r in self.revs(start=p + 1):
+ prevs = [pr for pr in self.parentrevs(r) if pr != nodemod.nullrev]
+ if prevs:
+ for pr in prevs:
+ if pr == p:
+ c.append(self.node(r))
+ elif p == nodemod.nullrev:
+ c.append(self.node(r))
+ return c
+
def reachableroots(self, minroot, heads, roots, includepath=False):
return dagop._reachablerootspure(
self.parentrevs, minroot, roots, heads, includepath
@@ -270,7 +324,10 @@
def parentrevs(self, rev):
n = self.node(rev)
hn = gitutil.togitnode(n)
- c = self.gitrepo[hn]
+ if hn != gitutil.nullgit:
+ c = self.gitrepo[hn]
+ else:
+ return nodemod.nullrev, nodemod.nullrev
p1 = p2 = nodemod.nullrev
if c.parents:
p1 = self.rev(c.parents[0].id.raw)
--- a/hgext/git/manifest.py Fri May 15 00:53:37 2020 +0200
+++ b/hgext/git/manifest.py Tue May 26 08:07:24 2020 -0700
@@ -205,7 +205,7 @@
return memgittreemanifestctx(self._repo, self._tree)
def find(self, path):
- self.read()[path]
+ return self.read()[path]
@interfaceutil.implementer(repository.imanifestrevisionwritable)
--- a/hgext/mq.py Fri May 15 00:53:37 2020 +0200
+++ b/hgext/mq.py Tue May 26 08:07:24 2020 -0700
@@ -836,7 +836,15 @@
stat = opts.get(b'stat')
m = scmutil.match(repo[node1], files, opts)
logcmdutil.diffordiffstat(
- self.ui, repo, diffopts, node1, node2, m, changes, stat, fp
+ self.ui,
+ repo,
+ diffopts,
+ repo[node1],
+ repo[node2],
+ m,
+ changes,
+ stat,
+ fp,
)
def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
--- a/hgext/phabricator.py Fri May 15 00:53:37 2020 +0200
+++ b/hgext/phabricator.py Tue May 26 08:07:24 2020 -0700
@@ -238,8 +238,8 @@
def decorate(fn):
def inner(*args, **kwargs):
- cassette = pycompat.fsdecode(kwargs.pop('test_vcr', None))
- if cassette:
+ if kwargs.get('test_vcr'):
+ cassette = pycompat.fsdecode(kwargs.pop('test_vcr'))
import hgdemandimport
with hgdemandimport.deactivated():
--- a/mercurial/changelog.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/changelog.py Tue May 26 08:07:24 2020 -0700
@@ -385,9 +385,7 @@
datafile=datafile,
checkambig=True,
mmaplargeindex=True,
- persistentnodemap=opener.options.get(
- b'exp-persistent-nodemap', False
- ),
+ persistentnodemap=opener.options.get(b'persistent-nodemap', False),
)
if self._initempty and (self.version & 0xFFFF == revlog.REVLOGV1):
--- a/mercurial/commands.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/commands.py Tue May 26 08:07:24 2020 -0700
@@ -2350,7 +2350,7 @@
Returns 0 on success, 1 if errors are encountered.
"""
opts = pycompat.byteskwargs(opts)
- with repo.wlock(False):
+ with repo.wlock():
return cmdutil.copy(ui, repo, pats, opts)
@@ -2475,26 +2475,27 @@
Returns 0 on success.
"""
+ cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
opts = pycompat.byteskwargs(opts)
revs = opts.get(b'rev')
change = opts.get(b'change')
stat = opts.get(b'stat')
reverse = opts.get(b'reverse')
- if revs and change:
- msg = _(b'cannot specify --rev and --change at the same time')
- raise error.Abort(msg)
- elif change:
+ if change:
repo = scmutil.unhidehashlikerevs(repo, [change], b'nowarn')
ctx2 = scmutil.revsingle(repo, change, None)
ctx1 = ctx2.p1()
else:
repo = scmutil.unhidehashlikerevs(repo, revs, b'nowarn')
ctx1, ctx2 = scmutil.revpair(repo, revs)
- node1, node2 = ctx1.node(), ctx2.node()
if reverse:
- node1, node2 = node2, node1
+ ctxleft = ctx2
+ ctxright = ctx1
+ else:
+ ctxleft = ctx1
+ ctxright = ctx2
diffopts = patch.diffallopts(ui, opts)
m = scmutil.match(ctx2, pats, opts)
@@ -2504,8 +2505,8 @@
ui,
repo,
diffopts,
- node1,
- node2,
+ ctxleft,
+ ctxright,
m,
stat=stat,
listsubrepos=opts.get(b'subrepos'),
@@ -3427,8 +3428,11 @@
m = regexp.search(self.line, p)
if not m:
break
- yield m.span()
- p = m.end()
+ if m.end() == p:
+ p += 1
+ else:
+ yield m.span()
+ p = m.end()
matches = {}
copies = {}
@@ -3574,31 +3578,41 @@
getrenamed = scmutil.getrenamedfn(repo)
- def get_file_content(filename, filelog, filenode, context, revision):
- try:
- content = filelog.read(filenode)
- except error.WdirUnsupported:
- content = context[filename].data()
- except error.CensoredNodeError:
- content = None
- ui.warn(
- _(b'cannot search in censored file: %(filename)s:%(revnum)s\n')
- % {b'filename': filename, b'revnum': pycompat.bytestr(revision)}
- )
- return content
+ def readfile(ctx, fn):
+ rev = ctx.rev()
+ if rev is None:
+ fctx = ctx[fn]
+ try:
+ return fctx.data()
+ except IOError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ else:
+ flog = getfile(fn)
+ fnode = ctx.filenode(fn)
+ try:
+ return flog.read(fnode)
+ except error.CensoredNodeError:
+ ui.warn(
+ _(
+ b'cannot search in censored file: %(filename)s:%(revnum)s\n'
+ )
+ % {b'filename': fn, b'revnum': pycompat.bytestr(rev),}
+ )
def prep(ctx, fns):
rev = ctx.rev()
pctx = ctx.p1()
- parent = pctx.rev()
matches.setdefault(rev, {})
- matches.setdefault(parent, {})
+ if diff:
+ parent = pctx.rev()
+ matches.setdefault(parent, {})
files = revfiles.setdefault(rev, [])
for fn in fns:
- flog = getfile(fn)
- try:
- fnode = ctx.filenode(fn)
- except error.LookupError:
+ # fn might not exist in the revision (could be a file removed by the
+ # revision). We could check `fn not in ctx` even when rev is None,
+ # but it's less racy to protect againt that in readfile.
+ if rev is not None and fn not in ctx:
continue
copy = None
@@ -3613,17 +3627,12 @@
files.append(fn)
if fn not in matches[rev]:
- content = get_file_content(fn, flog, fnode, ctx, rev)
- grepbody(fn, rev, content)
-
- pfn = copy or fn
- if pfn not in matches[parent]:
- try:
- pfnode = pctx.filenode(pfn)
- pcontent = get_file_content(pfn, flog, pfnode, pctx, parent)
- grepbody(pfn, parent, pcontent)
- except error.LookupError:
- pass
+ grepbody(fn, rev, readfile(ctx, fn))
+
+ if diff:
+ pfn = copy or fn
+ if pfn not in matches[parent] and pfn in pctx:
+ grepbody(pfn, parent, readfile(pctx, pfn))
ui.pager(b'grep')
fm = ui.formatter(b'grep', opts)
@@ -5807,7 +5816,7 @@
Returns 0 on success, 1 if errors are encountered.
"""
opts = pycompat.byteskwargs(opts)
- with repo.wlock(False):
+ with repo.wlock():
return cmdutil.copy(ui, repo, pats, opts, rename=True)
@@ -6786,6 +6795,7 @@
"""
+ cmdutil.check_at_most_one_arg(opts, 'rev', 'change')
opts = pycompat.byteskwargs(opts)
revs = opts.get(b'rev')
change = opts.get(b'change')
@@ -6796,10 +6806,7 @@
else:
terse = ui.config(b'commands', b'status.terse')
- if revs and change:
- msg = _(b'cannot specify --rev and --change at the same time')
- raise error.Abort(msg)
- elif revs and terse:
+ if revs and terse:
msg = _(b'cannot use --terse with --rev')
raise error.Abort(msg)
elif change:
--- a/mercurial/configitems.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/configitems.py Tue May 26 08:07:24 2020 -0700
@@ -405,18 +405,6 @@
coreconfigitem(
b'devel', b'legacy.exchange', default=list,
)
-# TODO before getting `persistent-nodemap` out of experimental
-#
-# * decide for a "status" of the persistent nodemap and associated location
-# - part of the store next the revlog itself (new requirements)
-# - part of the cache directory
-# - part of an `index` directory
-# (https://www.mercurial-scm.org/wiki/ComputedIndexPlan)
-# * do we want to use this for more than just changelog? if so we need:
-# - simpler "pending" logic for them
-# - double check the memory story (we dont want to keep all revlog in memory)
-# - think about the naming scheme if we are in "cache"
-# * increment the version format to "1" and freeze it.
coreconfigitem(
b'devel', b'persistent-nodemap', default=False,
)
@@ -675,12 +663,6 @@
b'experimental', b'rust.index', default=False,
)
coreconfigitem(
- b'experimental', b'exp-persistent-nodemap', default=False,
-)
-coreconfigitem(
- b'experimental', b'exp-persistent-nodemap.mmap', default=True,
-)
-coreconfigitem(
b'experimental', b'server.filesdata.recommended-batch-size', default=50000,
)
coreconfigitem(
@@ -783,6 +765,12 @@
coreconfigitem(
b'format', b'usestore', default=True,
)
+# Right now, the only efficient implement of the nodemap logic is in Rust, so
+# the persistent nodemap feature needs to stay experimental as long as the Rust
+# extensions are an experimental feature.
+coreconfigitem(
+ b'format', b'use-persistent-nodemap', default=False, experimental=True
+)
coreconfigitem(
b'format',
b'exp-use-copies-side-data-changeset',
@@ -1088,6 +1076,14 @@
default=True,
alias=[(b'format', b'aggressivemergedeltas')],
)
+# experimental as long as rust is experimental (or a C version is implemented)
+coreconfigitem(
+ b'storage', b'revlog.nodemap.mmap', default=True, experimental=True
+)
+# experimental as long as format.use-persistent-nodemap is.
+coreconfigitem(
+ b'storage', b'revlog.nodemap.mode', default=b'compat', experimental=True
+)
coreconfigitem(
b'storage', b'revlog.reuse-external-delta', default=True,
)
--- a/mercurial/copies.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/copies.py Tue May 26 08:07:24 2020 -0700
@@ -183,10 +183,27 @@
* p1copies: mapping of copies from p1
* p2copies: mapping of copies from p2
* removed: a list of removed files
+ * ismerged: a callback to know if file was merged in that revision
"""
cl = repo.changelog
parents = cl.parentrevs
+ def get_ismerged(rev):
+ ctx = repo[rev]
+
+ def ismerged(path):
+ if path not in ctx.files():
+ return False
+ fctx = ctx[path]
+ parents = fctx._filelog.parents(fctx._filenode)
+ nb_parents = 0
+ for n in parents:
+ if n != node.nullid:
+ nb_parents += 1
+ return nb_parents >= 2
+
+ return ismerged
+
if repo.filecopiesmode == b'changeset-sidedata':
changelogrevision = cl.changelogrevision
flags = cl.flags
@@ -218,6 +235,7 @@
def revinfo(rev):
p1, p2 = parents(rev)
+ value = None
if flags(rev) & REVIDX_SIDEDATA:
e = merge_caches.pop(rev, None)
if e is not None:
@@ -228,12 +246,22 @@
removed = c.filesremoved
if p1 != node.nullrev and p2 != node.nullrev:
# XXX some case we over cache, IGNORE
- merge_caches[rev] = (p1, p2, p1copies, p2copies, removed)
+ value = merge_caches[rev] = (
+ p1,
+ p2,
+ p1copies,
+ p2copies,
+ removed,
+ get_ismerged(rev),
+ )
else:
p1copies = {}
p2copies = {}
removed = []
- return p1, p2, p1copies, p2copies, removed
+
+ if value is None:
+ value = (p1, p2, p1copies, p2copies, removed, get_ismerged(rev))
+ return value
else:
@@ -242,7 +270,7 @@
ctx = repo[rev]
p1copies, p2copies = ctx._copies
removed = ctx.filesremoved()
- return p1, p2, p1copies, p2copies, removed
+ return p1, p2, p1copies, p2copies, removed, get_ismerged(rev)
return revinfo
@@ -256,6 +284,7 @@
revinfo = _revinfogetter(repo)
cl = repo.changelog
+ isancestor = cl.isancestorrev # XXX we should had chaching to this.
missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()])
mrset = set(missingrevs)
roots = set()
@@ -283,10 +312,14 @@
iterrevs.update(roots)
iterrevs.remove(b.rev())
revs = sorted(iterrevs)
- return _combinechangesetcopies(revs, children, b.rev(), revinfo, match)
+ return _combinechangesetcopies(
+ revs, children, b.rev(), revinfo, match, isancestor
+ )
-def _combinechangesetcopies(revs, children, targetrev, revinfo, match):
+def _combinechangesetcopies(
+ revs, children, targetrev, revinfo, match, isancestor
+):
"""combine the copies information for each item of iterrevs
revs: sorted iterable of revision to visit
@@ -305,7 +338,7 @@
# this is a root
copies = {}
for i, c in enumerate(children[r]):
- p1, p2, p1copies, p2copies, removed = revinfo(c)
+ p1, p2, p1copies, p2copies, removed, ismerged = revinfo(c)
if r == p1:
parent = 1
childcopies = p1copies
@@ -319,9 +352,12 @@
}
newcopies = copies
if childcopies:
- newcopies = _chain(newcopies, childcopies)
- # _chain makes a copies, we can avoid doing so in some
- # simple/linear cases.
+ newcopies = copies.copy()
+ for dest, source in pycompat.iteritems(childcopies):
+ prev = copies.get(source)
+ if prev is not None and prev[1] is not None:
+ source = prev[1]
+ newcopies[dest] = (c, source)
assert newcopies is not copies
for f in removed:
if f in newcopies:
@@ -330,7 +366,7 @@
# branches. when there are no other branches, this
# could be avoided.
newcopies = copies.copy()
- del newcopies[f]
+ newcopies[f] = (c, None)
othercopies = all_copies.get(c)
if othercopies is None:
all_copies[c] = newcopies
@@ -338,21 +374,55 @@
# we are the second parent to work on c, we need to merge our
# work with the other.
#
- # Unlike when copies are stored in the filelog, we consider
- # it a copy even if the destination already existed on the
- # other branch. It's simply too expensive to check if the
- # file existed in the manifest.
- #
# In case of conflict, parent 1 take precedence over parent 2.
# This is an arbitrary choice made anew when implementing
# changeset based copies. It was made without regards with
# potential filelog related behavior.
if parent == 1:
- othercopies.update(newcopies)
+ _merge_copies_dict(
+ othercopies, newcopies, isancestor, ismerged
+ )
else:
- newcopies.update(othercopies)
+ _merge_copies_dict(
+ newcopies, othercopies, isancestor, ismerged
+ )
all_copies[c] = newcopies
- return all_copies[targetrev]
+
+ final_copies = {}
+ for dest, (tt, source) in all_copies[targetrev].items():
+ if source is not None:
+ final_copies[dest] = source
+ return final_copies
+
+
+def _merge_copies_dict(minor, major, isancestor, ismerged):
+ """merge two copies-mapping together, minor and major
+
+ In case of conflict, value from "major" will be picked.
+
+ - `isancestors(low_rev, high_rev)`: callable return True if `low_rev` is an
+ ancestors of `high_rev`,
+
+ - `ismerged(path)`: callable return True if `path` have been merged in the
+ current revision,
+ """
+ for dest, value in major.items():
+ other = minor.get(dest)
+ if other is None:
+ minor[dest] = value
+ else:
+ new_tt = value[0]
+ other_tt = other[0]
+ if value[1] == other[1]:
+ continue
+ # content from "major" wins, unless it is older
+ # than the branch point or there is a merge
+ if (
+ new_tt == other_tt
+ or not isancestor(new_tt, other_tt)
+ or ismerged(dest)
+ ):
+ minor[dest] = value
def _forwardcopies(a, b, base=None, match=None):
--- a/mercurial/dirstate.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/dirstate.py Tue May 26 08:07:24 2020 -0700
@@ -187,7 +187,7 @@
@propertycache
def _checkexec(self):
- return util.checkexec(self._root)
+ return bool(util.checkexec(self._root))
@propertycache
def _checkcase(self):
@@ -1114,6 +1114,7 @@
unknown,
warnings,
bad,
+ traversed,
) = rustmod.status(
self._map._rustmap,
matcher,
@@ -1124,7 +1125,13 @@
bool(list_clean),
bool(list_ignored),
bool(list_unknown),
+ bool(matcher.traversedir),
)
+
+ if matcher.traversedir:
+ for dir in traversed:
+ matcher.traversedir(dir)
+
if self._ui.warn:
for item in warnings:
if isinstance(item, tuple):
@@ -1200,10 +1207,8 @@
use_rust = False
elif sparse.enabled:
use_rust = False
- elif match.traversedir is not None:
- use_rust = False
elif not isinstance(match, allowed_matchers):
- # Matchers have yet to be implemented
+ # Some matchers have yet to be implemented
use_rust = False
if use_rust:
--- a/mercurial/helptext/internals/requirements.txt Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/helptext/internals/requirements.txt Tue May 26 08:07:24 2020 -0700
@@ -142,3 +142,16 @@
August 2019). The requirement will only be present on repositories
that have opted in to this format (by having
``format.bookmarks-in-store=true`` set when they were created).
+
+persistent-nodemap
+==================
+
+The `nodemap` index (mapping nodeid to local revision number) is persisted on
+disk. This provides speed benefit (if the associated native code is used). The
+persistent nodemap is only used for two revlogs: the changelog and the
+manifestlog.
+
+Support for this requirement was added in Mercurial 5.5 (released August 2020).
+Note that as of 5.5, only installations compiled with the Rust extension will
+benefit from a speedup. The other installations will do the necessary work to
+keep the index up to date, but will suffer a slowdown.
--- a/mercurial/hook.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/hook.py Tue May 26 08:07:24 2020 -0700
@@ -158,6 +158,10 @@
env[b'HG_HOOKNAME'] = name
for k, v in pycompat.iteritems(args):
+ # transaction changes can accumulate MBs of data, so skip it
+ # for external hooks
+ if k == b'changes':
+ continue
if callable(v):
v = v()
if isinstance(v, (dict, list)):
--- a/mercurial/interfaces/repository.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/interfaces/repository.py Tue May 26 08:07:24 2020 -0700
@@ -1395,6 +1395,9 @@
Raises ``error.LookupError`` if the node is not known.
"""
+ def update_caches(transaction):
+ """update whatever cache are relevant for the used storage."""
+
class ilocalrepositoryfilestorage(interfaceutil.Interface):
"""Local repository sub-interface providing access to tracked file storage.
--- a/mercurial/localrepo.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/localrepo.py Tue May 26 08:07:24 2020 -0700
@@ -445,6 +445,9 @@
# copies related information in changeset's sidedata.
COPIESSDC_REQUIREMENT = b'exp-copies-sidedata-changeset'
+# The repository use persistent nodemap for the changelog and the manifest.
+NODEMAP_REQUIREMENT = b'persistent-nodemap'
+
# Functions receiving (ui, features) that extensions can register to impact
# the ability to load repositories with custom requirements. Only
# functions defined in loaded extensions are called.
@@ -933,10 +936,12 @@
if ui.configbool(b'experimental', b'rust.index'):
options[b'rust.index'] = True
- if ui.configbool(b'experimental', b'exp-persistent-nodemap'):
- options[b'exp-persistent-nodemap'] = True
- if ui.configbool(b'experimental', b'exp-persistent-nodemap.mmap'):
- options[b'exp-persistent-nodemap.mmap'] = True
+ if NODEMAP_REQUIREMENT in requirements:
+ options[b'persistent-nodemap'] = True
+ if ui.configbool(b'storage', b'revlog.nodemap.mmap'):
+ options[b'persistent-nodemap.mmap'] = True
+ epnm = ui.config(b'storage', b'revlog.nodemap.mode')
+ options[b'persistent-nodemap.mode'] = epnm
if ui.configbool(b'devel', b'persistent-nodemap'):
options[b'devel-force-nodemap'] = True
@@ -1021,6 +1026,7 @@
REVLOGV2_REQUIREMENT,
SIDEDATA_REQUIREMENT,
SPARSEREVLOG_REQUIREMENT,
+ NODEMAP_REQUIREMENT,
bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
}
_basesupported = supportedformats | {
@@ -2239,6 +2245,7 @@
tr.hookargs[b'txnid'] = txnid
tr.hookargs[b'txnname'] = desc
+ tr.hookargs[b'changes'] = tr.changes
# note: writing the fncache only during finalize mean that the file is
# outdated when running hooks. As fncache is used for streaming clone,
# this is not expected to break anything that happen during the hooks.
@@ -2511,6 +2518,7 @@
unfi = self.unfiltered()
self.changelog.update_caches(transaction=tr)
+ self.manifestlog.update_caches(transaction=tr)
rbc = unfi.revbranchcache()
for r in unfi.changelog:
@@ -3018,6 +3026,12 @@
self.ui.write(
_(b'note: commit message saved in %s\n') % msgfn
)
+ self.ui.write(
+ _(
+ b"note: use 'hg commit --logfile "
+ b".hg/last-message.txt --edit' to reuse it\n"
+ )
+ )
raise
def commithook(unused_success):
@@ -3653,6 +3667,9 @@
if ui.configbool(b'format', b'bookmarks-in-store'):
requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
+ if ui.configbool(b'format', b'use-persistent-nodemap'):
+ requirements.add(NODEMAP_REQUIREMENT)
+
return requirements
--- a/mercurial/logcmdutil.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/logcmdutil.py Tue May 26 08:07:24 2020 -0700
@@ -72,8 +72,8 @@
ui,
repo,
diffopts,
- node1,
- node2,
+ ctx1,
+ ctx2,
match,
changes=None,
stat=False,
@@ -85,8 +85,6 @@
hunksfilterfn=None,
):
'''show diff or diffstat.'''
- ctx1 = repo[node1]
- ctx2 = repo[node2]
if root:
relroot = pathutil.canonpath(repo.root, repo.getcwd(), root)
else:
@@ -173,6 +171,7 @@
for chunk, label in chunks:
ui.write(chunk, label=label)
+ node2 = ctx2.node()
for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
tempnode2 = node2
try:
@@ -208,15 +207,12 @@
return None
def showdiff(self, ui, ctx, diffopts, graphwidth=0, stat=False):
- repo = ctx.repo()
- node = ctx.node()
- prev = ctx.p1().node()
diffordiffstat(
ui,
- repo,
+ ctx.repo(),
diffopts,
- prev,
- node,
+ ctx.p1(),
+ ctx,
match=self._makefilematcher(ctx),
stat=stat,
graphwidth=graphwidth,
--- a/mercurial/manifest.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/manifest.py Tue May 26 08:07:24 2020 -0700
@@ -1599,6 +1599,7 @@
checkambig=not bool(tree),
mmaplargeindex=True,
upperboundcomp=MAXCOMPRESSION,
+ persistentnodemap=opener.options.get(b'persistent-nodemap', False),
)
self.index = self._revlog.index
@@ -1959,6 +1960,9 @@
def rev(self, node):
return self._rootstore.rev(node)
+ def update_caches(self, transaction):
+ return self._rootstore._revlog.update_caches(transaction=transaction)
+
@interfaceutil.implementer(repository.imanifestrevisionwritable)
class memmanifestctx(object):
--- a/mercurial/revlogutils/nodemap.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/revlogutils/nodemap.py Tue May 26 08:07:24 2020 -0700
@@ -13,6 +13,8 @@
import re
import struct
+from ..i18n import _
+
from .. import (
error,
node as nodemod,
@@ -48,7 +50,7 @@
docket.data_unused = data_unused
filename = _rawdata_filepath(revlog, docket)
- use_mmap = revlog.opener.options.get(b"exp-persistent-nodemap.mmap")
+ use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
try:
with revlog.opener(filename) as fd:
if use_mmap:
@@ -105,6 +107,9 @@
def addabort(self, *args, **kwargs):
pass
+ def _report(self, *args):
+ pass
+
def update_persistent_nodemap(revlog):
"""update the persistent nodemap right now
@@ -137,7 +142,14 @@
can_incremental = util.safehasattr(revlog.index, "nodemap_data_incremental")
ondisk_docket = revlog._nodemap_docket
feed_data = util.safehasattr(revlog.index, "update_nodemap_data")
- use_mmap = revlog.opener.options.get(b"exp-persistent-nodemap.mmap")
+ use_mmap = revlog.opener.options.get(b"persistent-nodemap.mmap")
+ mode = revlog.opener.options.get(b"persistent-nodemap.mode")
+ if not can_incremental:
+ msg = _(b"persistent nodemap in strict mode without efficient method")
+ if mode == b'warn':
+ tr._report(b"%s\n" % msg)
+ elif mode == b'strict':
+ raise error.Abort(msg)
data = None
# first attemp an incremental update of the data
@@ -255,8 +267,7 @@
# data. Its content is currently very light, but it will expand as the on disk
# nodemap gains the necessary features to be used in production.
-# version 0 is experimental, no BC garantee, do no use outside of tests.
-ONDISK_VERSION = 0
+ONDISK_VERSION = 1
S_VERSION = struct.Struct(">B")
S_HEADER = struct.Struct(">BQQQQ")
--- a/mercurial/scmutil.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/scmutil.py Tue May 26 08:07:24 2020 -0700
@@ -456,9 +456,7 @@
def resolvehexnodeidprefix(repo, prefix):
- if prefix.startswith(b'x') and repo.ui.configbool(
- b'experimental', b'revisions.prefixhexnode'
- ):
+ if prefix.startswith(b'x'):
prefix = prefix[1:]
try:
# Uses unfiltered repo because it's faster when prefix is ambiguous/
--- a/mercurial/subrepo.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/subrepo.py Tue May 26 08:07:24 2020 -0700
@@ -617,8 +617,8 @@
ui,
self._repo,
diffopts,
- node1,
- node2,
+ self._repo[node1],
+ self._repo[node2],
match,
prefix=prefix,
listsubrepos=True,
--- a/mercurial/upgrade.py Fri May 15 00:53:37 2020 +0200
+++ b/mercurial/upgrade.py Tue May 26 08:07:24 2020 -0700
@@ -78,6 +78,7 @@
localrepo.SPARSEREVLOG_REQUIREMENT,
localrepo.SIDEDATA_REQUIREMENT,
localrepo.COPIESSDC_REQUIREMENT,
+ localrepo.NODEMAP_REQUIREMENT,
}
for name in compression.compengines:
engine = compression.compengines[name]
@@ -105,6 +106,7 @@
localrepo.SPARSEREVLOG_REQUIREMENT,
localrepo.SIDEDATA_REQUIREMENT,
localrepo.COPIESSDC_REQUIREMENT,
+ localrepo.NODEMAP_REQUIREMENT,
}
for name in compression.compengines:
engine = compression.compengines[name]
@@ -132,6 +134,7 @@
localrepo.SPARSEREVLOG_REQUIREMENT,
localrepo.SIDEDATA_REQUIREMENT,
localrepo.COPIESSDC_REQUIREMENT,
+ localrepo.NODEMAP_REQUIREMENT,
}
for name in compression.compengines:
engine = compression.compengines[name]
@@ -374,6 +377,21 @@
@registerformatvariant
+class persistentnodemap(requirementformatvariant):
+ name = b'persistent-nodemap'
+
+ _requirement = localrepo.NODEMAP_REQUIREMENT
+
+ default = False
+
+ description = _(
+ b'persist the node -> rev mapping on disk to speedup lookup'
+ )
+
+ upgrademessage = _(b'Speedup revision lookup by node id.')
+
+
+@registerformatvariant
class copiessdc(requirementformatvariant):
name = b'copies-sdc'
@@ -807,14 +825,14 @@
if not revcount:
return
- ui.write(
+ ui.status(
_(
b'migrating %d total revisions (%d in filelogs, %d in manifests, '
b'%d in changelog)\n'
)
% (revcount, frevcount, mrevcount, crevcount)
)
- ui.write(
+ ui.status(
_(b'migrating %s in store; %s tracked data\n')
% ((util.bytecount(srcsize), util.bytecount(srcrawsize)))
)
@@ -837,7 +855,7 @@
oldrl = _revlogfrompath(srcrepo, unencoded)
if isinstance(oldrl, changelog.changelog) and b'c' not in seen:
- ui.write(
+ ui.status(
_(
b'finished migrating %d manifest revisions across %d '
b'manifests; change in size: %s\n'
@@ -845,7 +863,7 @@
% (mrevcount, mcount, util.bytecount(mdstsize - msrcsize))
)
- ui.write(
+ ui.status(
_(
b'migrating changelog containing %d revisions '
b'(%s in store; %s tracked data)\n'
@@ -861,7 +879,7 @@
_(b'changelog revisions'), total=crevcount
)
elif isinstance(oldrl, manifest.manifestrevlog) and b'm' not in seen:
- ui.write(
+ ui.status(
_(
b'finished migrating %d filelog revisions across %d '
b'filelogs; change in size: %s\n'
@@ -869,7 +887,7 @@
% (frevcount, fcount, util.bytecount(fdstsize - fsrcsize))
)
- ui.write(
+ ui.status(
_(
b'migrating %d manifests containing %d revisions '
b'(%s in store; %s tracked data)\n'
@@ -888,7 +906,7 @@
_(b'manifest revisions'), total=mrevcount
)
elif b'f' not in seen:
- ui.write(
+ ui.status(
_(
b'migrating %d filelogs containing %d revisions '
b'(%s in store; %s tracked data)\n'
@@ -941,7 +959,7 @@
progress.complete()
- ui.write(
+ ui.status(
_(
b'finished migrating %d changelog revisions; change in size: '
b'%s\n'
@@ -949,7 +967,7 @@
% (crevcount, util.bytecount(cdstsize - csrcsize))
)
- ui.write(
+ ui.status(
_(
b'finished migrating %d total revisions; total change in store '
b'size: %s\n'
@@ -975,7 +993,7 @@
Function should return ``True`` if the file is to be copied.
"""
# Skip revlogs.
- if path.endswith((b'.i', b'.d')):
+ if path.endswith((b'.i', b'.d', b'.n', b'.nd')):
return False
# Skip transaction related files.
if path.startswith(b'undo'):
@@ -1013,7 +1031,7 @@
assert srcrepo.currentwlock()
assert dstrepo.currentwlock()
- ui.write(
+ ui.status(
_(
b'(it is safe to interrupt this process any time before '
b'data migration completes)\n'
@@ -1048,14 +1066,14 @@
if not _filterstorefile(srcrepo, dstrepo, requirements, p, kind, st):
continue
- srcrepo.ui.write(_(b'copying %s\n') % p)
+ srcrepo.ui.status(_(b'copying %s\n') % p)
src = srcrepo.store.rawvfs.join(p)
dst = dstrepo.store.rawvfs.join(p)
util.copyfile(src, dst, copystat=True)
_finishdatamigration(ui, srcrepo, dstrepo, requirements)
- ui.write(_(b'data fully migrated to temporary repository\n'))
+ ui.status(_(b'data fully migrated to temporary repository\n'))
backuppath = pycompat.mkdtemp(prefix=b'upgradebackup.', dir=srcrepo.path)
backupvfs = vfsmod.vfs(backuppath)
@@ -1067,7 +1085,7 @@
# as a mechanism to lock out new clients during the data swap. This is
# better than allowing a client to continue while the repository is in
# an inconsistent state.
- ui.write(
+ ui.status(
_(
b'marking source repository as being upgraded; clients will be '
b'unable to read from repository\n'
@@ -1077,18 +1095,18 @@
srcrepo.vfs, srcrepo.requirements | {b'upgradeinprogress'}
)
- ui.write(_(b'starting in-place swap of repository data\n'))
- ui.write(_(b'replaced files will be backed up at %s\n') % backuppath)
+ ui.status(_(b'starting in-place swap of repository data\n'))
+ ui.status(_(b'replaced files will be backed up at %s\n') % backuppath)
# Now swap in the new store directory. Doing it as a rename should make
# the operation nearly instantaneous and atomic (at least in well-behaved
# environments).
- ui.write(_(b'replacing store...\n'))
+ ui.status(_(b'replacing store...\n'))
tstart = util.timer()
util.rename(srcrepo.spath, backupvfs.join(b'store'))
util.rename(dstrepo.spath, srcrepo.spath)
elapsed = util.timer() - tstart
- ui.write(
+ ui.status(
_(
b'store replacement complete; repository was inconsistent for '
b'%0.1fs\n'
@@ -1098,7 +1116,7 @@
# We first write the requirements file. Any new requirements will lock
# out legacy clients.
- ui.write(
+ ui.status(
_(
b'finalizing requirements file and making repository readable '
b'again\n'
@@ -1274,9 +1292,20 @@
ui.write((b'\n'))
ui.write(b'\n')
+ def printoptimisations():
+ optimisations = [a for a in actions if a.type == optimisation]
+ optimisations.sort(key=lambda a: a.name)
+ if optimisations:
+ ui.write(_(b'optimisations: '))
+ write_labeled(
+ [a.name for a in optimisations],
+ "upgrade-repo.optimisation.performed",
+ )
+ ui.write(b'\n\n')
+
def printupgradeactions():
for a in actions:
- ui.write(b'%s\n %s\n\n' % (a.name, a.upgrademessage))
+ ui.status(b'%s\n %s\n\n' % (a.name, a.upgrademessage))
if not run:
fromconfig = []
@@ -1291,35 +1320,35 @@
if fromconfig or onlydefault:
if fromconfig:
- ui.write(
+ ui.status(
_(
b'repository lacks features recommended by '
b'current config options:\n\n'
)
)
for i in fromconfig:
- ui.write(b'%s\n %s\n\n' % (i.name, i.description))
+ ui.status(b'%s\n %s\n\n' % (i.name, i.description))
if onlydefault:
- ui.write(
+ ui.status(
_(
b'repository lacks features used by the default '
b'config options:\n\n'
)
)
for i in onlydefault:
- ui.write(b'%s\n %s\n\n' % (i.name, i.description))
+ ui.status(b'%s\n %s\n\n' % (i.name, i.description))
- ui.write(b'\n')
+ ui.status(b'\n')
else:
- ui.write(
+ ui.status(
_(
b'(no feature deficiencies found in existing '
b'repository)\n'
)
)
- ui.write(
+ ui.status(
_(
b'performing an upgrade with "--run" will make the following '
b'changes:\n\n'
@@ -1327,31 +1356,33 @@
)
printrequirements()
+ printoptimisations()
printupgradeactions()
unusedoptimize = [i for i in alloptimizations if i not in actions]
if unusedoptimize:
- ui.write(
+ ui.status(
_(
b'additional optimizations are available by specifying '
b'"--optimize <name>":\n\n'
)
)
for i in unusedoptimize:
- ui.write(_(b'%s\n %s\n\n') % (i.name, i.description))
+ ui.status(_(b'%s\n %s\n\n') % (i.name, i.description))
return
# Else we're in the run=true case.
ui.write(_(b'upgrade will perform the following actions:\n\n'))
printrequirements()
+ printoptimisations()
printupgradeactions()
upgradeactions = [a.name for a in actions]
- ui.write(_(b'beginning upgrade...\n'))
+ ui.status(_(b'beginning upgrade...\n'))
with repo.wlock(), repo.lock():
- ui.write(_(b'repository locked and read-only\n'))
+ ui.status(_(b'repository locked and read-only\n'))
# Our strategy for upgrading the repository is to create a new,
# temporary repository, write data to it, then do a swap of the
# data. There are less heavyweight ways to do this, but it is easier
@@ -1360,7 +1391,7 @@
tmppath = pycompat.mkdtemp(prefix=b'upgrade.', dir=repo.path)
backuppath = None
try:
- ui.write(
+ ui.status(
_(
b'creating temporary repository to stage migrated '
b'data: %s\n'
@@ -1377,15 +1408,17 @@
ui, repo, dstrepo, newreqs, upgradeactions, revlogs=revlogs
)
if not (backup or backuppath is None):
- ui.write(_(b'removing old repository content%s\n') % backuppath)
+ ui.status(
+ _(b'removing old repository content%s\n') % backuppath
+ )
repo.vfs.rmtree(backuppath, forcibly=True)
backuppath = None
finally:
- ui.write(_(b'removing temporary repository %s\n') % tmppath)
+ ui.status(_(b'removing temporary repository %s\n') % tmppath)
repo.vfs.rmtree(tmppath, forcibly=True)
- if backuppath:
+ if backuppath and not ui.quiet:
ui.warn(
_(b'copy of old repository backed up at %s\n') % backuppath
)
--- a/rust/chg/Cargo.lock Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/Cargo.lock Tue May 26 08:07:24 2020 -0700
@@ -6,9 +6,14 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "autocfg"
-version = "1.0.0"
+name = "async-trait"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
[[package]]
name = "bitflags"
@@ -16,20 +21,11 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "byteorder"
-version = "1.3.4"
+name = "bytes"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "bytes"
-version = "0.4.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "cc"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -43,91 +39,17 @@
name = "chg"
version = "0.1.0"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-hglib 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-process 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cloudabi"
-version = "0.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-deque"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-epoch"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-hglib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "crossbeam-queue"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-queue"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.6.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "fnv"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -143,15 +65,84 @@
[[package]]
name = "futures"
-version = "0.1.29"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "hermit-abi"
-version = "0.1.10"
+name = "futures-executor"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-task"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures-util"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -159,7 +150,7 @@
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -178,18 +169,10 @@
[[package]]
name = "libc"
-version = "0.2.68"
+version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "lock_api"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -198,19 +181,11 @@
]
[[package]]
-name = "maybe-uninit"
-version = "2.0.0"
+name = "memchr"
+version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "memoffset"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "mio"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -220,7 +195,7 @@
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -245,7 +220,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -265,7 +240,7 @@
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -275,41 +250,44 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "num_cpus"
-version = "1.12.0"
+name = "pin-project-lite"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0-alpha.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro-hack"
+version = "0.5.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro-nested"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "parking_lot"
-version = "0.9.0"
+name = "quote"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -318,38 +296,12 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
name = "signal-hook-registry"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -358,240 +310,85 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
-name = "smallvec"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
name = "socket2"
-version = "0.3.11"
+version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio"
-version = "0.1.22"
+name = "syn"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-codec"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-current-thread"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-executor"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-fs"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-hglib"
-version = "0.2.0"
+name = "tokio"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-process 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-io"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-process"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-reactor"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-signal"
-version = "0.2.9"
+name = "tokio-hglib"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-sync"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-tcp"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-threadpool"
-version = "0.1.18"
+name = "tokio-macros"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tokio-timer"
-version = "0.2.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-udp"
-version = "0.1.6"
+name = "tokio-util"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "tokio-uds"
-version = "0.2.6"
+name = "unicode-xid"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
-]
[[package]]
name = "winapi"
@@ -633,66 +430,50 @@
[metadata]
"checksum arc-swap 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d663a8e9a99154b5fb793032533f6328da35e23aac63d5c152279aa8ba356825"
-"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
+"checksum async-trait 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "da71fef07bc806586090247e971229289f64c210a278ee5ae419314eb386b31d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
+"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
-"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
-"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
-"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
-"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
-"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
-"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
-"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
-"checksum hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
+"checksum futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c329ae8753502fb44ae4fc2b622fa2a94652c41e795143765ba0927f92ab780"
+"checksum futures-channel 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
+"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
+"checksum futures-executor 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f674f3e1bcb15b37284a90cedf55afdba482ab061c407a9c0ebbd0f3109741ba"
+"checksum futures-io 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
+"checksum futures-macro 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5081aa3de1f7542a794a397cde100ed903b0630152d0973479018fd85423a7"
+"checksum futures-sink 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
+"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
+"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
-"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b"
+"checksum libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
-"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
-"checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
+"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
-"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
-"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
-"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
+"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
+"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
+"checksum proc-macro-hack 0.5.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63"
+"checksum proc-macro-nested 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694"
+"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
+"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
-"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
-"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
-"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
-"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"
-"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
-"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
-"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
-"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
-"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
-"checksum tokio-hglib 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a138c3cb866c8a95ceddae44634bb159eefeebcdba45aec2158f8ad6c201e6d"
-"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
-"checksum tokio-process 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "382d90f43fa31caebe5d3bc6cfd854963394fff3b8cb59d5146607aaae7e7e43"
-"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
-"checksum tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12"
-"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
-"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
-"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
-"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
-"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
-"checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798"
+"checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
+"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
+"checksum tokio 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "34ef16d072d2b6dc8b4a56c70f5c5ced1a37752116f8e7c1e80c659aa7cb6713"
+"checksum tokio-hglib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d7e2b5d44911ebf67a1044423604f5f69206c5cbbd7e911b4966e6831514bca"
+"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
+"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
--- a/rust/chg/Cargo.toml Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/Cargo.toml Tue May 26 08:07:24 2020 -0700
@@ -7,14 +7,16 @@
edition = "2018"
[dependencies]
-bytes = "0.4"
-futures = "0.1"
+async-trait = "0.1"
+bytes = "0.5"
+futures = "0.3"
libc = "0.2"
log = { version = "0.4", features = ["std"] }
-tokio = "0.1"
-tokio-hglib = "0.2"
-tokio-process = "0.2.3"
-tokio-timer = "0.2"
+tokio-hglib = "0.3"
+
+[dependencies.tokio]
+version = "0.2"
+features = ["rt-core", "io-util", "time", "process", "macros"]
[build-dependencies]
cc = "1.0"
--- a/rust/chg/src/attachio.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/attachio.rs Tue May 26 08:07:24 2020 -0700
@@ -5,17 +5,15 @@
//! Functions to send client-side fds over the command server channel.
-use futures::{try_ready, Async, Future, Poll};
use std::io;
use std::os::unix::io::AsRawFd;
use tokio_hglib::codec::ChannelMessage;
-use tokio_hglib::protocol::MessageLoop;
-use tokio_hglib::{Client, Connection};
+use tokio_hglib::{Connection, Protocol};
use crate::message;
use crate::procutil;
-/// Future to send client-side fds over the command server channel.
+/// Sends client-side fds over the command server channel.
///
/// This works as follows:
/// 1. Client sends "attachio" request.
@@ -23,92 +21,48 @@
/// 3. Client sends fds with 1-byte dummy payload in response.
/// 4. Server returns the number of the fds received.
///
-/// If the stderr is omitted, it will be redirected to the stdout. This
-/// allows us to attach the pager stdin to both stdout and stderr, and
-/// dispose of the client-side handle once attached.
-#[must_use = "futures do nothing unless polled"]
-pub struct AttachIo<C, I, O, E>
-where
- C: Connection,
-{
- msg_loop: MessageLoop<C>,
- stdin: I,
- stdout: O,
- stderr: Option<E>,
-}
-
-impl<C, I, O, E> AttachIo<C, I, O, E>
-where
- C: Connection + AsRawFd,
- I: AsRawFd,
- O: AsRawFd,
- E: AsRawFd,
-{
- pub fn with_client(
- client: Client<C>,
- stdin: I,
- stdout: O,
- stderr: Option<E>,
- ) -> AttachIo<C, I, O, E> {
- let msg_loop = MessageLoop::start(client, b"attachio");
- AttachIo {
- msg_loop,
- stdin,
- stdout,
- stderr,
- }
- }
-}
-
-impl<C, I, O, E> Future for AttachIo<C, I, O, E>
-where
- C: Connection + AsRawFd,
- I: AsRawFd,
- O: AsRawFd,
- E: AsRawFd,
-{
- type Item = Client<C>;
- type Error = io::Error;
-
- fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
- loop {
- let (client, msg) = try_ready!(self.msg_loop.poll());
- match msg {
- ChannelMessage::Data(b'r', data) => {
- let fd_cnt = message::parse_result_code(data)?;
- if fd_cnt == 3 {
- return Ok(Async::Ready(client));
- } else {
- return Err(io::Error::new(
- io::ErrorKind::InvalidData,
- "unexpected attachio result",
- ));
- }
- }
- ChannelMessage::Data(..) => {
- // just ignore data sent to uninteresting (optional) channel
- self.msg_loop = MessageLoop::resume(client);
- }
- ChannelMessage::InputRequest(1) => {
- // this may fail with EWOULDBLOCK in theory, but the
- // payload is quite small, and the send buffer should
- // be empty so the operation will complete immediately
- let sock_fd = client.as_raw_fd();
- let ifd = self.stdin.as_raw_fd();
- let ofd = self.stdout.as_raw_fd();
- let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
- procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
- self.msg_loop = MessageLoop::resume(client);
- }
- ChannelMessage::InputRequest(..)
- | ChannelMessage::LineRequest(..)
- | ChannelMessage::SystemRequest(..) => {
+/// The client-side fds may be dropped once duplicated to the server.
+pub async fn attach_io(
+ proto: &mut Protocol<impl Connection + AsRawFd>,
+ stdin: &impl AsRawFd,
+ stdout: &impl AsRawFd,
+ stderr: &impl AsRawFd,
+) -> io::Result<()> {
+ proto.send_command("attachio").await?;
+ loop {
+ match proto.fetch_response().await? {
+ ChannelMessage::Data(b'r', data) => {
+ let fd_cnt = message::parse_result_code(data)?;
+ if fd_cnt == 3 {
+ return Ok(());
+ } else {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
- "unsupported request while attaching io",
+ "unexpected attachio result",
));
}
}
+ ChannelMessage::Data(..) => {
+ // just ignore data sent to uninteresting (optional) channel
+ }
+ ChannelMessage::InputRequest(1) => {
+ // this may fail with EWOULDBLOCK in theory, but the
+ // payload is quite small, and the send buffer should
+ // be empty so the operation will complete immediately
+ let sock_fd = proto.as_raw_fd();
+ let ifd = stdin.as_raw_fd();
+ let ofd = stdout.as_raw_fd();
+ let efd = stderr.as_raw_fd();
+ procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
+ }
+ ChannelMessage::InputRequest(..)
+ | ChannelMessage::LineRequest(..)
+ | ChannelMessage::SystemRequest(..) => {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidData,
+ "unsupported request while attaching io",
+ ));
+ }
}
}
}
--- a/rust/chg/src/clientext.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/clientext.rs Tue May 26 08:07:24 2020 -0700
@@ -5,55 +5,99 @@
//! cHg extensions to command server client.
-use bytes::{BufMut, Bytes, BytesMut};
+use bytes::{BufMut, BytesMut};
use std::ffi::OsStr;
use std::io;
use std::mem;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::AsRawFd;
use std::path::Path;
-use tokio_hglib::protocol::{OneShotQuery, OneShotRequest};
-use tokio_hglib::{Client, Connection};
+use tokio_hglib::UnixClient;
-use crate::attachio::AttachIo;
-use crate::message::{self, Instruction};
-use crate::runcommand::ChgRunCommand;
+use crate::attachio;
+use crate::message::{self, Instruction, ServerSpec};
+use crate::runcommand;
use crate::uihandler::SystemHandler;
-pub trait ChgClientExt<C>
-where
- C: Connection + AsRawFd,
-{
+/// Command-server client that also supports cHg extensions.
+pub struct ChgClient {
+ client: UnixClient,
+}
+
+impl ChgClient {
+ /// Connects to a command server listening at the specified socket path.
+ pub async fn connect(path: impl AsRef<Path>) -> io::Result<Self> {
+ let client = UnixClient::connect(path).await?;
+ Ok(ChgClient { client })
+ }
+
+ /// Server capabilities, encoding, etc.
+ pub fn server_spec(&self) -> &ServerSpec {
+ self.client.server_spec()
+ }
+
/// Attaches the client file descriptors to the server.
- fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
- where
- I: AsRawFd,
- O: AsRawFd,
- E: AsRawFd;
+ pub async fn attach_io(
+ &mut self,
+ stdin: &impl AsRawFd,
+ stdout: &impl AsRawFd,
+ stderr: &impl AsRawFd,
+ ) -> io::Result<()> {
+ attachio::attach_io(self.client.borrow_protocol_mut(), stdin, stdout, stderr).await
+ }
/// Changes the working directory of the server.
- fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C>;
+ pub async fn set_current_dir(&mut self, dir: impl AsRef<Path>) -> io::Result<()> {
+ let dir_bytes = dir.as_ref().as_os_str().as_bytes().to_owned();
+ self.client
+ .borrow_protocol_mut()
+ .send_command_with_args("chdir", dir_bytes)
+ .await
+ }
/// Updates the environment variables of the server.
- fn set_env_vars_os(
- self,
+ pub async fn set_env_vars_os(
+ &mut self,
vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>,
- ) -> OneShotRequest<C>;
+ ) -> io::Result<()> {
+ self.client
+ .borrow_protocol_mut()
+ .send_command_with_args("setenv", message::pack_env_vars_os(vars))
+ .await
+ }
/// Changes the process title of the server.
- fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C>;
+ pub async fn set_process_name(&mut self, name: impl AsRef<OsStr>) -> io::Result<()> {
+ let name_bytes = name.as_ref().as_bytes().to_owned();
+ self.client
+ .borrow_protocol_mut()
+ .send_command_with_args("setprocname", name_bytes)
+ .await
+ }
/// Changes the umask of the server process.
- fn set_umask(self, mask: u32) -> OneShotRequest<C>;
+ pub async fn set_umask(&mut self, mask: u32) -> io::Result<()> {
+ let mut mask_bytes = BytesMut::with_capacity(mem::size_of_val(&mask));
+ mask_bytes.put_u32(mask);
+ self.client
+ .borrow_protocol_mut()
+ .send_command_with_args("setumask2", mask_bytes)
+ .await
+ }
/// Runs the specified Mercurial command with cHg extension.
- fn run_command_chg<H>(
- self,
- handler: H,
+ pub async fn run_command_chg(
+ &mut self,
+ handler: &mut impl SystemHandler,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
- ) -> ChgRunCommand<C, H>
- where
- H: SystemHandler;
+ ) -> io::Result<i32> {
+ runcommand::run_command(
+ self.client.borrow_protocol_mut(),
+ handler,
+ message::pack_args_os(args),
+ )
+ .await
+ }
/// Validates if the server can run Mercurial commands with the expected
/// configuration.
@@ -63,66 +107,15 @@
///
/// Client-side environment must be sent prior to this request, by
/// `set_current_dir()` and `set_env_vars_os()`.
- fn validate(
- self,
+ pub async fn validate(
+ &mut self,
args: impl IntoIterator<Item = impl AsRef<OsStr>>,
- ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>>;
-}
-
-impl<C> ChgClientExt<C> for Client<C>
-where
- C: Connection + AsRawFd,
-{
- fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
- where
- I: AsRawFd,
- O: AsRawFd,
- E: AsRawFd,
- {
- AttachIo::with_client(self, stdin, stdout, Some(stderr))
- }
-
- fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C> {
- OneShotRequest::start_with_args(self, b"chdir", dir.as_ref().as_os_str().as_bytes())
- }
-
- fn set_env_vars_os(
- self,
- vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>,
- ) -> OneShotRequest<C> {
- OneShotRequest::start_with_args(self, b"setenv", message::pack_env_vars_os(vars))
- }
-
- fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C> {
- OneShotRequest::start_with_args(self, b"setprocname", name.as_ref().as_bytes())
- }
-
- fn set_umask(self, mask: u32) -> OneShotRequest<C> {
- let mut args = BytesMut::with_capacity(mem::size_of_val(&mask));
- args.put_u32_be(mask);
- OneShotRequest::start_with_args(self, b"setumask2", args)
- }
-
- fn run_command_chg<H>(
- self,
- handler: H,
- args: impl IntoIterator<Item = impl AsRef<OsStr>>,
- ) -> ChgRunCommand<C, H>
- where
- H: SystemHandler,
- {
- ChgRunCommand::with_client(self, handler, message::pack_args_os(args))
- }
-
- fn validate(
- self,
- args: impl IntoIterator<Item = impl AsRef<OsStr>>,
- ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>> {
- OneShotQuery::start_with_args(
- self,
- b"validate",
- message::pack_args_os(args),
- message::parse_instructions,
- )
+ ) -> io::Result<Vec<Instruction>> {
+ let data = self
+ .client
+ .borrow_protocol_mut()
+ .query_with_args("validate", message::pack_args_os(args))
+ .await?;
+ message::parse_instructions(data)
}
}
--- a/rust/chg/src/lib.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/lib.rs Tue May 26 08:07:24 2020 -0700
@@ -11,5 +11,5 @@
mod runcommand;
mod uihandler;
-pub use clientext::ChgClientExt;
+pub use clientext::ChgClient;
pub use uihandler::{ChgUiHandler, SystemHandler};
--- a/rust/chg/src/locator.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/locator.rs Tue May 26 08:07:24 2020 -0700
@@ -5,7 +5,6 @@
//! Utility for locating command-server process.
-use futures::future::{self, Either, Loop};
use log::debug;
use std::env;
use std::ffi::{OsStr, OsString};
@@ -14,14 +13,11 @@
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::os::unix::fs::{DirBuilderExt, MetadataExt};
use std::path::{Path, PathBuf};
-use std::process::{self, Command};
-use std::time::Duration;
-use tokio::prelude::*;
-use tokio_hglib::UnixClient;
-use tokio_process::{Child, CommandExt};
-use tokio_timer;
+use std::process::{self, Child, Command};
+use std::time::{Duration, Instant};
+use tokio::time;
-use crate::clientext::ChgClientExt;
+use crate::clientext::ChgClient;
use crate::message::{Instruction, ServerSpec};
use crate::procutil;
@@ -82,43 +78,33 @@
/// Connects to the server.
///
/// The server process will be spawned if not running.
- pub fn connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> {
- future::loop_fn((self, 0), |(loc, cnt)| {
- if cnt < 10 {
- let fut = loc
- .try_connect()
- .and_then(|(loc, client)| {
- client
- .validate(&loc.hg_early_args)
- .map(|(client, instructions)| (loc, client, instructions))
- })
- .and_then(move |(loc, client, instructions)| {
- loc.run_instructions(client, instructions, cnt)
- });
- Either::A(fut)
- } else {
- let msg = format!(
- concat!(
- "too many redirections.\n",
- "Please make sure {:?} is not a wrapper which ",
- "changes sensitive environment variables ",
- "before executing hg. If you have to use a ",
- "wrapper, wrap chg instead of hg.",
- ),
- loc.hg_command
- );
- Either::B(future::err(io::Error::new(io::ErrorKind::Other, msg)))
+ pub async fn connect(&mut self) -> io::Result<ChgClient> {
+ for _cnt in 0..10 {
+ let mut client = self.try_connect().await?;
+ let instructions = client.validate(&self.hg_early_args).await?;
+ let reconnect = self.run_instructions(&instructions)?;
+ if !reconnect {
+ return Ok(client);
}
- })
+ }
+
+ let msg = format!(
+ concat!(
+ "too many redirections.\n",
+ "Please make sure {:?} is not a wrapper which ",
+ "changes sensitive environment variables ",
+ "before executing hg. If you have to use a ",
+ "wrapper, wrap chg instead of hg.",
+ ),
+ self.hg_command
+ );
+ Err(io::Error::new(io::ErrorKind::Other, msg))
}
/// Runs instructions received from the server.
- fn run_instructions(
- mut self,
- client: UnixClient,
- instructions: Vec<Instruction>,
- cnt: usize,
- ) -> io::Result<Loop<(Self, UnixClient), (Self, usize)>> {
+ ///
+ /// Returns true if the client should try connecting to the other server.
+ fn run_instructions(&mut self, instructions: &[Instruction]) -> io::Result<bool> {
let mut reconnect = false;
for inst in instructions {
debug!("instruction: {:?}", inst);
@@ -126,7 +112,7 @@
Instruction::Exit(_) => {
// Just returns the current connection to run the
// unparsable command and report the error
- return Ok(Loop::Break((self, client)));
+ return Ok(false);
}
Instruction::Reconnect => {
reconnect = true;
@@ -139,7 +125,7 @@
);
return Err(io::Error::new(io::ErrorKind::InvalidData, msg));
}
- self.redirect_sock_path = Some(path);
+ self.redirect_sock_path = Some(path.to_owned());
reconnect = true;
}
Instruction::Unlink(path) => {
@@ -155,64 +141,44 @@
}
}
- if reconnect {
- Ok(Loop::Continue((self, cnt + 1)))
- } else {
- Ok(Loop::Break((self, client)))
- }
+ Ok(reconnect)
}
/// Tries to connect to the existing server, or spawns new if not running.
- fn try_connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> {
+ async fn try_connect(&mut self) -> io::Result<ChgClient> {
let sock_path = self
.redirect_sock_path
.as_ref()
.unwrap_or(&self.base_sock_path)
.clone();
debug!("try connect to {}", sock_path.display());
- UnixClient::connect(sock_path)
- .then(|res| {
- match res {
- Ok(client) => Either::A(future::ok((self, client))),
- Err(_) => {
- // Prevent us from being re-connected to the outdated
- // master server: We were told by the server to redirect
- // to redirect_sock_path, which didn't work. We do not
- // want to connect to the same master server again
- // because it would probably tell us the same thing.
- if self.redirect_sock_path.is_some() {
- fs::remove_file(&self.base_sock_path).unwrap_or(());
- // may race
- }
- Either::B(self.spawn_connect())
- }
+ let mut client = match ChgClient::connect(sock_path).await {
+ Ok(client) => client,
+ Err(_) => {
+ // Prevent us from being re-connected to the outdated
+ // master server: We were told by the server to redirect
+ // to redirect_sock_path, which didn't work. We do not
+ // want to connect to the same master server again
+ // because it would probably tell us the same thing.
+ if self.redirect_sock_path.is_some() {
+ fs::remove_file(&self.base_sock_path).unwrap_or(());
+ // may race
}
- })
- .and_then(|(loc, client)| {
- check_server_capabilities(client.server_spec())?;
- Ok((loc, client))
- })
- .and_then(|(loc, client)| {
- // It's purely optional, and the server might not support this command.
- if client.server_spec().capabilities.contains("setprocname") {
- let fut = client
- .set_process_name(format!("chg[worker/{}]", loc.process_id))
- .map(|client| (loc, client));
- Either::A(fut)
- } else {
- Either::B(future::ok((loc, client)))
- }
- })
- .and_then(|(loc, client)| {
- client
- .set_current_dir(&loc.current_dir)
- .map(|client| (loc, client))
- })
- .and_then(|(loc, client)| {
- client
- .set_env_vars_os(loc.env_vars.iter().cloned())
- .map(|client| (loc, client))
- })
+ self.spawn_connect().await?
+ }
+ };
+ check_server_capabilities(client.server_spec())?;
+ // It's purely optional, and the server might not support this command.
+ if client.server_spec().capabilities.contains("setprocname") {
+ client
+ .set_process_name(format!("chg[worker/{}]", self.process_id))
+ .await?;
+ }
+ client.set_current_dir(&self.current_dir).await?;
+ client
+ .set_env_vars_os(self.env_vars.iter().cloned())
+ .await?;
+ Ok(client)
}
/// Spawns new server process and connects to it.
@@ -220,10 +186,10 @@
/// The server will be spawned at the current working directory, then
/// chdir to "/", so that the server will load configs from the target
/// repository.
- fn spawn_connect(self) -> impl Future<Item = (Self, UnixClient), Error = io::Error> {
+ async fn spawn_connect(&mut self) -> io::Result<ChgClient> {
let sock_path = self.temp_sock_path();
debug!("start cmdserver at {}", sock_path.display());
- Command::new(&self.hg_command)
+ let server = Command::new(&self.hg_command)
.arg("serve")
.arg("--cmdserver")
.arg("chgunix")
@@ -236,68 +202,49 @@
.env_clear()
.envs(self.env_vars.iter().cloned())
.env("CHGINTERNALMARK", "")
- .spawn_async()
- .into_future()
- .and_then(|server| self.connect_spawned(server, sock_path))
- .and_then(|(loc, client, sock_path)| {
- debug!(
- "rename {} to {}",
- sock_path.display(),
- loc.base_sock_path.display()
- );
- fs::rename(&sock_path, &loc.base_sock_path)?;
- Ok((loc, client))
- })
+ .spawn()?;
+ let client = self.connect_spawned(server, &sock_path).await?;
+ debug!(
+ "rename {} to {}",
+ sock_path.display(),
+ self.base_sock_path.display()
+ );
+ fs::rename(&sock_path, &self.base_sock_path)?;
+ Ok(client)
}
/// Tries to connect to the just spawned server repeatedly until timeout
/// exceeded.
- fn connect_spawned(
- self,
- server: Child,
- sock_path: PathBuf,
- ) -> impl Future<Item = (Self, UnixClient, PathBuf), Error = io::Error> {
+ async fn connect_spawned(
+ &mut self,
+ mut server: Child,
+ sock_path: &Path,
+ ) -> io::Result<ChgClient> {
debug!("try connect to {} repeatedly", sock_path.display());
- let connect = future::loop_fn(sock_path, |sock_path| {
- UnixClient::connect(sock_path.clone()).then(|res| {
- match res {
- Ok(client) => Either::A(future::ok(Loop::Break((client, sock_path)))),
- Err(_) => {
- // try again with slight delay
- let fut = tokio_timer::sleep(Duration::from_millis(10))
- .map(|()| Loop::Continue(sock_path))
- .map_err(|err| io::Error::new(io::ErrorKind::Other, err));
- Either::B(fut)
- }
- }
- })
- });
-
// waits for either connection established or server failed to start
- connect
- .select2(server)
- .map_err(|res| res.split().0)
- .timeout(self.timeout)
- .map_err(|err| {
- err.into_inner().unwrap_or_else(|| {
- io::Error::new(
- io::ErrorKind::TimedOut,
- "timed out while connecting to server",
- )
- })
- })
- .and_then(|res| {
- match res {
- Either::A(((client, sock_path), server)) => {
- server.forget(); // continue to run in background
- Ok((self, client, sock_path))
- }
- Either::B((st, _)) => Err(io::Error::new(
- io::ErrorKind::Other,
- format!("server exited too early: {}", st),
- )),
- }
- })
+ let start_time = Instant::now();
+ while start_time.elapsed() < self.timeout {
+ if let Ok(client) = ChgClient::connect(&sock_path).await {
+ // server handle is dropped here, but the detached process
+ // will continue running in background
+ return Ok(client);
+ }
+
+ if let Some(st) = server.try_wait()? {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ format!("server exited too early: {}", st),
+ ));
+ }
+
+ // try again with slight delay
+ time::delay_for(Duration::from_millis(10)).await;
+ }
+
+ Err(io::Error::new(
+ io::ErrorKind::TimedOut,
+ "timed out while connecting to server",
+ ))
}
}
--- a/rust/chg/src/main.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/main.rs Tue May 26 08:07:24 2020 -0700
@@ -5,13 +5,12 @@
use chg::locator::{self, Locator};
use chg::procutil;
-use chg::{ChgClientExt, ChgUiHandler};
-use futures::sync::oneshot;
+use chg::ChgUiHandler;
use std::env;
use std::io;
+use std::io::Write;
use std::process;
use std::time::Instant;
-use tokio::prelude::*;
struct DebugLogger {
start: Instant,
@@ -67,31 +66,23 @@
process::exit(code);
}
-fn run(umask: u32) -> io::Result<i32> {
+#[tokio::main]
+async fn run(umask: u32) -> io::Result<i32> {
let mut loc = Locator::prepare_from_env()?;
loc.set_early_args(locator::collect_early_args(env::args_os().skip(1)));
- let handler = ChgUiHandler::new();
- let (result_tx, result_rx) = oneshot::channel();
- let fut = loc
- .connect()
- .and_then(|(_, client)| client.attach_io(io::stdin(), io::stdout(), io::stderr()))
- .and_then(move |client| client.set_umask(umask))
- .and_then(|client| {
- let pid = client.server_spec().process_id.unwrap();
- let pgid = client.server_spec().process_group_id;
- procutil::setup_signal_handler_once(pid, pgid)?;
- Ok(client)
- })
- .and_then(|client| client.run_command_chg(handler, env::args_os().skip(1)))
- .map(|(_client, _handler, code)| {
- procutil::restore_signal_handler_once()?;
- Ok(code)
- })
- .or_else(|err| Ok(Err(err))) // pass back error to caller
- .map(|res| result_tx.send(res).unwrap());
- tokio::run(fut);
- result_rx.wait().unwrap_or(Err(io::Error::new(
- io::ErrorKind::Other,
- "no exit code set",
- )))
+ let mut handler = ChgUiHandler::new();
+ let mut client = loc.connect().await?;
+ client
+ .attach_io(&io::stdin(), &io::stdout(), &io::stderr())
+ .await?;
+ client.set_umask(umask).await?;
+ let pid = client.server_spec().process_id.unwrap();
+ let pgid = client.server_spec().process_group_id;
+ procutil::setup_signal_handler_once(pid, pgid)?;
+ let code = client
+ .run_command_chg(&mut handler, env::args_os().skip(1))
+ .await?;
+ procutil::restore_signal_handler_once()?;
+ handler.wait_pager().await?;
+ Ok(code)
}
--- a/rust/chg/src/runcommand.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/runcommand.rs Tue May 26 08:07:24 2020 -0700
@@ -6,164 +6,56 @@
//! Functions to run Mercurial command in cHg-aware command server.
use bytes::Bytes;
-use futures::future::IntoFuture;
-use futures::{Async, Future, Poll};
use std::io;
-use std::mem;
use std::os::unix::io::AsRawFd;
use tokio_hglib::codec::ChannelMessage;
-use tokio_hglib::protocol::MessageLoop;
-use tokio_hglib::{Client, Connection};
+use tokio_hglib::{Connection, Protocol};
-use crate::attachio::AttachIo;
+use crate::attachio;
use crate::message::{self, CommandType};
use crate::uihandler::SystemHandler;
-enum AsyncS<R, S> {
- Ready(R),
- NotReady(S),
- PollAgain(S),
-}
-
-enum CommandState<C, H>
-where
- C: Connection,
- H: SystemHandler,
-{
- Running(MessageLoop<C>, H),
- SpawningPager(Client<C>, <H::SpawnPagerResult as IntoFuture>::Future),
- AttachingPager(AttachIo<C, io::Stdin, H::PagerStdin, H::PagerStdin>, H),
- WaitingSystem(Client<C>, <H::RunSystemResult as IntoFuture>::Future),
- Finished,
-}
-
-type CommandPoll<C, H> = io::Result<AsyncS<(Client<C>, H, i32), CommandState<C, H>>>;
-
-/// Future resolves to `(exit_code, client)`.
-#[must_use = "futures do nothing unless polled"]
-pub struct ChgRunCommand<C, H>
-where
- C: Connection,
- H: SystemHandler,
-{
- state: CommandState<C, H>,
-}
-
-impl<C, H> ChgRunCommand<C, H>
-where
- C: Connection + AsRawFd,
- H: SystemHandler,
-{
- pub fn with_client(client: Client<C>, handler: H, packed_args: Bytes) -> ChgRunCommand<C, H> {
- let msg_loop = MessageLoop::start_with_args(client, b"runcommand", packed_args);
- ChgRunCommand {
- state: CommandState::Running(msg_loop, handler),
- }
- }
-}
-
-impl<C, H> Future for ChgRunCommand<C, H>
-where
- C: Connection + AsRawFd,
- H: SystemHandler,
-{
- type Item = (Client<C>, H, i32);
- type Error = io::Error;
-
- fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
- loop {
- let state = mem::replace(&mut self.state, CommandState::Finished);
- match state.poll()? {
- AsyncS::Ready((client, handler, code)) => {
- return Ok(Async::Ready((client, handler, code)));
- }
- AsyncS::NotReady(newstate) => {
- self.state = newstate;
- return Ok(Async::NotReady);
- }
- AsyncS::PollAgain(newstate) => {
- self.state = newstate;
- }
- }
- }
- }
-}
-
-impl<C, H> CommandState<C, H>
-where
- C: Connection + AsRawFd,
- H: SystemHandler,
-{
- fn poll(self) -> CommandPoll<C, H> {
- match self {
- CommandState::Running(mut msg_loop, handler) => {
- if let Async::Ready((client, msg)) = msg_loop.poll()? {
- process_message(client, handler, msg)
- } else {
- Ok(AsyncS::NotReady(CommandState::Running(msg_loop, handler)))
- }
- }
- CommandState::SpawningPager(client, mut fut) => {
- if let Async::Ready((handler, pin)) = fut.poll()? {
- let fut = AttachIo::with_client(client, io::stdin(), pin, None);
- Ok(AsyncS::PollAgain(CommandState::AttachingPager(
- fut, handler,
- )))
- } else {
- Ok(AsyncS::NotReady(CommandState::SpawningPager(client, fut)))
- }
- }
- CommandState::AttachingPager(mut fut, handler) => {
- if let Async::Ready(client) = fut.poll()? {
- let msg_loop = MessageLoop::start(client, b""); // terminator
- Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
- } else {
- Ok(AsyncS::NotReady(CommandState::AttachingPager(fut, handler)))
- }
- }
- CommandState::WaitingSystem(client, mut fut) => {
- if let Async::Ready((handler, code)) = fut.poll()? {
- let data = message::pack_result_code(code);
- let msg_loop = MessageLoop::resume_with_data(client, data);
- Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
- } else {
- Ok(AsyncS::NotReady(CommandState::WaitingSystem(client, fut)))
- }
- }
- CommandState::Finished => panic!("poll ChgRunCommand after it's done"),
- }
- }
-}
-
-fn process_message<C, H>(client: Client<C>, handler: H, msg: ChannelMessage) -> CommandPoll<C, H>
-where
- C: Connection,
- H: SystemHandler,
-{
- {
- match msg {
+/// Runs the given Mercurial command in cHg-aware command server, and
+/// fetches the result code.
+///
+/// This is a subset of tokio-hglib's `run_command()` with the additional
+/// SystemRequest support.
+pub async fn run_command(
+ proto: &mut Protocol<impl Connection + AsRawFd>,
+ handler: &mut impl SystemHandler,
+ packed_args: impl Into<Bytes>,
+) -> io::Result<i32> {
+ proto
+ .send_command_with_args("runcommand", packed_args)
+ .await?;
+ loop {
+ match proto.fetch_response().await? {
ChannelMessage::Data(b'r', data) => {
- let code = message::parse_result_code(data)?;
- Ok(AsyncS::Ready((client, handler, code)))
+ return message::parse_result_code(data);
}
ChannelMessage::Data(..) => {
// just ignores data sent to optional channel
- let msg_loop = MessageLoop::resume(client);
- Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
}
- ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) => Err(
- io::Error::new(io::ErrorKind::InvalidData, "unsupported request"),
- ),
+ ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) => {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidData,
+ "unsupported request",
+ ));
+ }
ChannelMessage::SystemRequest(data) => {
let (cmd_type, cmd_spec) = message::parse_command_spec(data)?;
match cmd_type {
CommandType::Pager => {
- let fut = handler.spawn_pager(cmd_spec).into_future();
- Ok(AsyncS::PollAgain(CommandState::SpawningPager(client, fut)))
+ // server spins new command loop while pager request is
+ // in progress, which can be terminated by "" command.
+ let pin = handler.spawn_pager(&cmd_spec).await?;
+ attachio::attach_io(proto, &io::stdin(), &pin, &pin).await?;
+ proto.send_command("").await?; // terminator
}
CommandType::System => {
- let fut = handler.run_system(cmd_spec).into_future();
- Ok(AsyncS::PollAgain(CommandState::WaitingSystem(client, fut)))
+ let code = handler.run_system(&cmd_spec).await?;
+ let data = message::pack_result_code(code);
+ proto.send_data(data).await?;
}
}
}
--- a/rust/chg/src/uihandler.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/chg/src/uihandler.rs Tue May 26 08:07:24 2020 -0700
@@ -3,76 +3,75 @@
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
-use futures::future::IntoFuture;
-use futures::Future;
+use async_trait::async_trait;
use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::process::ExitStatusExt;
-use std::process::{Command, Stdio};
+use std::process::Stdio;
use tokio;
-use tokio_process::{ChildStdin, CommandExt};
+use tokio::process::{Child, ChildStdin, Command};
use crate::message::CommandSpec;
use crate::procutil;
/// Callback to process shell command requests received from server.
-pub trait SystemHandler: Sized {
+#[async_trait]
+pub trait SystemHandler {
type PagerStdin: AsRawFd;
- type SpawnPagerResult: IntoFuture<Item = (Self, Self::PagerStdin), Error = io::Error>;
- type RunSystemResult: IntoFuture<Item = (Self, i32), Error = io::Error>;
/// Handles pager command request.
///
/// Returns the pipe to be attached to the server if the pager is spawned.
- fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult;
+ async fn spawn_pager(&mut self, spec: &CommandSpec) -> io::Result<Self::PagerStdin>;
/// Handles system command request.
///
/// Returns command exit code (positive) or signal number (negative).
- fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult;
+ async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32>;
}
/// Default cHg implementation to process requests received from server.
-pub struct ChgUiHandler {}
+pub struct ChgUiHandler {
+ pager: Option<Child>,
+}
impl ChgUiHandler {
pub fn new() -> ChgUiHandler {
- ChgUiHandler {}
+ ChgUiHandler { pager: None }
+ }
+
+ /// Waits until the pager process exits.
+ pub async fn wait_pager(&mut self) -> io::Result<()> {
+ if let Some(p) = self.pager.take() {
+ p.await?;
+ }
+ Ok(())
}
}
+#[async_trait]
impl SystemHandler for ChgUiHandler {
type PagerStdin = ChildStdin;
- type SpawnPagerResult = io::Result<(Self, Self::PagerStdin)>;
- type RunSystemResult = Box<dyn Future<Item = (Self, i32), Error = io::Error> + Send>;
- fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult {
- let mut pager = new_shell_command(&spec)
- .stdin(Stdio::piped())
- .spawn_async()?;
- let pin = pager.stdin().take().unwrap();
+ async fn spawn_pager(&mut self, spec: &CommandSpec) -> io::Result<Self::PagerStdin> {
+ let mut pager = new_shell_command(&spec).stdin(Stdio::piped()).spawn()?;
+ let pin = pager.stdin.take().unwrap();
procutil::set_blocking_fd(pin.as_raw_fd())?;
// TODO: if pager exits, notify the server with SIGPIPE immediately.
// otherwise the server won't get SIGPIPE if it does not write
// anything. (issue5278)
// kill(peerpid, SIGPIPE);
- tokio::spawn(pager.map(|_| ()).map_err(|_| ())); // just ignore errors
- Ok((self, pin))
+ self.pager = Some(pager);
+ Ok(pin)
}
- fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult {
- let fut = new_shell_command(&spec)
- .spawn_async()
- .into_future()
- .flatten()
- .map(|status| {
- let code = status
- .code()
- .or_else(|| status.signal().map(|n| -n))
- .expect("either exit code or signal should be set");
- (self, code)
- });
- Box::new(fut)
+ async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> {
+ let status = new_shell_command(&spec).spawn()?.await?;
+ let code = status
+ .code()
+ .or_else(|| status.signal().map(|n| -n))
+ .expect("either exit code or signal should be set");
+ Ok(code)
}
}
--- a/rust/hg-core/src/dirstate/status.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/hg-core/src/dirstate/status.rs Tue May 26 08:07:24 2020 -0700
@@ -221,6 +221,7 @@
dmap: &'a DirstateMap,
root_dir: impl AsRef<Path> + Sync + Send + 'a,
options: StatusOptions,
+ traversed_sender: crossbeam::Sender<HgPathBuf>,
) -> impl ParallelIterator<Item = IoResult<(&'a HgPath, Dispatch)>> {
files
.unwrap_or(&DEFAULT_WORK)
@@ -255,6 +256,13 @@
Some(Ok((normalized, Dispatch::Unknown)))
} else {
if file_type.is_dir() {
+ if options.collect_traversed_dirs {
+ // The receiver always outlives the sender,
+ // so unwrap.
+ traversed_sender
+ .send(normalized.to_owned())
+ .unwrap()
+ }
Some(Ok((
normalized,
Dispatch::Directory {
@@ -302,6 +310,9 @@
pub list_clean: bool,
pub list_unknown: bool,
pub list_ignored: bool,
+ /// Whether to collect traversed dirs for applying a callback later.
+ /// Used by `hg purge` for example.
+ pub collect_traversed_dirs: bool,
}
/// Dispatch a single entry (file, folder, symlink...) found during `traverse`.
@@ -319,6 +330,7 @@
options: StatusOptions,
filename: HgPathBuf,
dir_entry: DirEntry,
+ traversed_sender: crossbeam::Sender<HgPathBuf>,
) -> IoResult<()> {
let file_type = dir_entry.file_type()?;
let entry_option = dmap.get(&filename);
@@ -341,6 +353,7 @@
options,
entry_option,
filename,
+ traversed_sender,
);
} else if file_type.is_file() || file_type.is_symlink() {
if let Some(entry) = entry_option {
@@ -371,9 +384,11 @@
.unwrap();
}
} else {
- files_sender
- .send(Ok((filename.to_owned(), Dispatch::Unknown)))
- .unwrap();
+ if options.list_unknown {
+ files_sender
+ .send(Ok((filename.to_owned(), Dispatch::Unknown)))
+ .unwrap();
+ }
}
} else if ignore_fn(&filename) && options.list_ignored {
files_sender
@@ -405,6 +420,7 @@
options: StatusOptions,
entry_option: Option<&'a DirstateEntry>,
directory: HgPathBuf,
+ traversed_sender: crossbeam::Sender<HgPathBuf>,
) {
scope.spawn(move |_| {
// Nested `if` until `rust-lang/rust#53668` is stable
@@ -431,6 +447,7 @@
ignore_fn,
dir_ignore_fn,
options,
+ traversed_sender,
)
.unwrap_or_else(|e| files_sender.send(Err(e)).unwrap())
}
@@ -449,9 +466,15 @@
ignore_fn: &IgnoreFnType,
dir_ignore_fn: &IgnoreFnType,
options: StatusOptions,
+ traversed_sender: crossbeam::Sender<HgPathBuf>,
) -> IoResult<()> {
let directory = directory.as_ref();
+ if options.collect_traversed_dirs {
+ // The receiver always outlives the sender, so unwrap.
+ traversed_sender.send(directory.to_owned()).unwrap()
+ }
+
let visit_entries = match matcher.visit_children_set(directory) {
VisitChildrenSet::Empty => return Ok(()),
VisitChildrenSet::This | VisitChildrenSet::Recursive => None,
@@ -508,6 +531,7 @@
options,
filename,
dir_entry,
+ traversed_sender.clone(),
)?;
}
}
@@ -531,6 +555,7 @@
dir_ignore_fn: &IgnoreFnType,
options: StatusOptions,
results: &mut Vec<(Cow<'a, HgPath>, Dispatch)>,
+ traversed_sender: crossbeam::Sender<HgPathBuf>,
) -> IoResult<()> {
let root_dir = root_dir.as_ref();
@@ -548,6 +573,7 @@
&ignore_fn,
&dir_ignore_fn,
options,
+ traversed_sender,
)?;
// Disconnect the channel so the receiver stops waiting
@@ -638,11 +664,14 @@
pub ignored: Vec<Cow<'a, HgPath>>,
pub unknown: Vec<Cow<'a, HgPath>>,
pub bad: Vec<(Cow<'a, HgPath>, BadMatch)>,
+ /// Only filled if `collect_traversed_dirs` is `true`
+ pub traversed: Vec<HgPathBuf>,
}
#[timed]
fn build_response<'a>(
results: impl IntoIterator<Item = (Cow<'a, HgPath>, Dispatch)>,
+ traversed: Vec<HgPathBuf>,
) -> (Vec<Cow<'a, HgPath>>, DirstateStatus<'a>) {
let mut lookup = vec![];
let mut modified = vec![];
@@ -681,6 +710,7 @@
ignored,
unknown,
bad,
+ traversed,
},
)
}
@@ -817,7 +847,7 @@
Vec<PatternFileWarning>,
)> {
// Needs to outlive `dir_ignore_fn` since it's captured.
- let mut ignore_fn: IgnoreFnType;
+ let ignore_fn: IgnoreFnType;
// Only involve real ignore mechanism if we're listing unknowns or ignored.
let (dir_ignore_fn, warnings): (IgnoreFnType, _) = if options.list_ignored
@@ -847,8 +877,17 @@
let files = matcher.file_set();
+ // `crossbeam::Sender` is `Send`, while `mpsc::Sender` is not.
+ let (traversed_sender, traversed_recv) = crossbeam::channel::unbounded();
+
// Step 1: check the files explicitly mentioned by the user
- let explicit = walk_explicit(files, &dmap, root_dir, options);
+ let explicit = walk_explicit(
+ files,
+ &dmap,
+ root_dir,
+ options,
+ traversed_sender.clone(),
+ );
// Collect results into a `Vec` because we do very few lookups in most
// cases.
@@ -886,6 +925,7 @@
&dir_ignore_fn,
options,
&mut results,
+ traversed_sender.clone(),
)?;
}
}
@@ -909,5 +949,9 @@
}
}
- Ok((build_response(results), warnings))
+ // Close the channel
+ drop(traversed_sender);
+ let traversed_dirs = traversed_recv.into_iter().collect();
+
+ Ok((build_response(results, traversed_dirs), warnings))
}
--- a/rust/hg-core/src/filepatterns.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/hg-core/src/filepatterns.rs Tue May 26 08:07:24 2020 -0700
@@ -176,14 +176,15 @@
return vec![];
}
match syntax {
- // The `regex` crate adds `.*` to the start and end of expressions
- // if there are no anchors, so add them.
- PatternSyntax::Regexp => [b"^", &pattern[..], b"$"].concat(),
+ PatternSyntax::Regexp => pattern.to_owned(),
PatternSyntax::RelRegexp => {
// The `regex` crate accepts `**` while `re2` and Python's `re`
// do not. Checking for `*` correctly triggers the same error all
// engines.
- if pattern[0] == b'^' || pattern[0] == b'*' {
+ if pattern[0] == b'^'
+ || pattern[0] == b'*'
+ || pattern.starts_with(b".*")
+ {
return pattern.to_owned();
}
[&b".*"[..], pattern].concat()
@@ -196,15 +197,14 @@
}
PatternSyntax::RootFiles => {
let mut res = if pattern == b"." {
- vec![b'^']
+ vec![]
} else {
// Pattern is a directory name.
- [b"^", escape_pattern(pattern).as_slice(), b"/"].concat()
+ [escape_pattern(pattern).as_slice(), b"/"].concat()
};
// Anything after the pattern must be a non-directory.
res.extend(b"[^/]+$");
- res.push(b'$');
res
}
PatternSyntax::RelGlob => {
@@ -216,7 +216,7 @@
}
}
PatternSyntax::Glob | PatternSyntax::RootGlob => {
- [b"^", glob_to_re(pattern).as_slice(), GLOB_SUFFIX].concat()
+ [glob_to_re(pattern).as_slice(), GLOB_SUFFIX].concat()
}
PatternSyntax::Include | PatternSyntax::SubInclude => unreachable!(),
}
@@ -271,7 +271,7 @@
/// that don't need to be transformed into a regex.
pub fn build_single_regex(
entry: &IgnorePattern,
-) -> Result<Vec<u8>, PatternError> {
+) -> Result<Option<Vec<u8>>, PatternError> {
let IgnorePattern {
pattern, syntax, ..
} = entry;
@@ -288,16 +288,11 @@
if *syntax == PatternSyntax::RootGlob
&& !pattern.iter().any(|b| GLOB_SPECIAL_CHARACTERS.contains(b))
{
- // The `regex` crate adds `.*` to the start and end of expressions
- // if there are no anchors, so add the start anchor.
- let mut escaped = vec![b'^'];
- escaped.extend(escape_pattern(&pattern));
- escaped.extend(GLOB_SUFFIX);
- Ok(escaped)
+ Ok(None)
} else {
let mut entry = entry.clone();
entry.pattern = pattern;
- Ok(_build_single_regex(&entry))
+ Ok(Some(_build_single_regex(&entry)))
}
}
@@ -628,7 +623,16 @@
Path::new("")
))
.unwrap(),
- br"(?:.*/)?rust/target(?:/|$)".to_vec(),
+ Some(br"(?:.*/)?rust/target(?:/|$)".to_vec()),
+ );
+ assert_eq!(
+ build_single_regex(&IgnorePattern::new(
+ PatternSyntax::Regexp,
+ br"rust/target/\d+",
+ Path::new("")
+ ))
+ .unwrap(),
+ Some(br"rust/target/\d+".to_vec()),
);
}
@@ -641,7 +645,7 @@
Path::new("")
))
.unwrap(),
- br"^\.(?:/|$)".to_vec(),
+ None,
);
assert_eq!(
build_single_regex(&IgnorePattern::new(
@@ -650,7 +654,7 @@
Path::new("")
))
.unwrap(),
- br"^whatever(?:/|$)".to_vec(),
+ None,
);
assert_eq!(
build_single_regex(&IgnorePattern::new(
@@ -659,7 +663,7 @@
Path::new("")
))
.unwrap(),
- br"^[^/]*\.o(?:/|$)".to_vec(),
+ Some(br"[^/]*\.o(?:/|$)".to_vec()),
);
}
}
--- a/rust/hg-core/src/matchers.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/hg-core/src/matchers.rs Tue May 26 08:07:24 2020 -0700
@@ -24,6 +24,7 @@
PatternSyntax,
};
+use crate::filepatterns::normalize_path_bytes;
use std::borrow::ToOwned;
use std::collections::HashSet;
use std::fmt::{Display, Error, Formatter};
@@ -31,6 +32,8 @@
use std::ops::Deref;
use std::path::{Path, PathBuf};
+use micro_timer::timed;
+
#[derive(Debug, PartialEq)]
pub enum VisitChildrenSet<'a> {
/// Don't visit anything
@@ -322,6 +325,7 @@
///
/// This can fail when the pattern is invalid or not supported by the
/// underlying engine `Re2`, for instance anything with back-references.
+#[timed]
fn re_matcher(
pattern: &[u8],
) -> PatternResult<impl Fn(&HgPath) -> bool + Sync> {
@@ -337,12 +341,15 @@
/// This can fail when the pattern is invalid or not supported by the
/// underlying engine (the `regex` crate), for instance anything with
/// back-references.
+#[timed]
fn re_matcher(
pattern: &[u8],
) -> PatternResult<impl Fn(&HgPath) -> bool + Sync> {
use std::io::Write;
- let mut escaped_bytes = vec![];
+ // The `regex` crate adds `.*` to the start and end of expressions if there
+ // are no anchors, so add the start anchor.
+ let mut escaped_bytes = vec![b'^', b'(', b'?', b':'];
for byte in pattern {
if *byte > 127 {
write!(escaped_bytes, "\\x{:x}", *byte).unwrap();
@@ -350,6 +357,7 @@
escaped_bytes.push(*byte);
}
}
+ escaped_bytes.push(b')');
// Avoid the cost of UTF8 checking
//
@@ -373,15 +381,32 @@
fn build_regex_match<'a>(
ignore_patterns: &'a [&'a IgnorePattern],
) -> PatternResult<(Vec<u8>, Box<dyn Fn(&HgPath) -> bool + Sync>)> {
- let regexps: Result<Vec<_>, PatternError> = ignore_patterns
- .into_iter()
- .map(|k| build_single_regex(*k))
- .collect();
- let regexps = regexps?;
+ let mut regexps = vec![];
+ let mut exact_set = HashSet::new();
+
+ for pattern in ignore_patterns {
+ if let Some(re) = build_single_regex(pattern)? {
+ regexps.push(re);
+ } else {
+ let exact = normalize_path_bytes(&pattern.pattern);
+ exact_set.insert(HgPathBuf::from_bytes(&exact));
+ }
+ }
+
let full_regex = regexps.join(&b'|');
- let matcher = re_matcher(&full_regex)?;
- let func = Box::new(move |filename: &HgPath| matcher(filename));
+ // An empty pattern would cause the regex engine to incorrectly match the
+ // (empty) root directory
+ let func = if !(regexps.is_empty()) {
+ let matcher = re_matcher(&full_regex)?;
+ let func = move |filename: &HgPath| {
+ exact_set.contains(filename) || matcher(filename)
+ };
+ Box::new(func) as Box<dyn Fn(&HgPath) -> bool + Sync>
+ } else {
+ let func = move |filename: &HgPath| exact_set.contains(filename);
+ Box::new(func) as Box<dyn Fn(&HgPath) -> bool + Sync>
+ };
Ok((full_regex, func))
}
@@ -652,6 +677,12 @@
impl<'a> Display for IncludeMatcher<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+ // XXX What about exact matches?
+ // I'm not sure it's worth it to clone the HashSet and keep it
+ // around just in case someone wants to display the matcher, plus
+ // it's going to be unreadable after a few entries, but we need to
+ // inform in this display that exact matches are being used and are
+ // (on purpose) missing from the `includes`.
write!(
f,
"IncludeMatcher(includes='{}')",
--- a/rust/hg-cpython/src/dirstate.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/hg-cpython/src/dirstate.rs Tue May 26 08:07:24 2020 -0700
@@ -133,7 +133,8 @@
last_normal_time: i64,
list_clean: bool,
list_ignored: bool,
- list_unknown: bool
+ list_unknown: bool,
+ collect_traversed_dirs: bool
)
),
)?;
--- a/rust/hg-cpython/src/dirstate/status.rs Fri May 15 00:53:37 2020 +0200
+++ b/rust/hg-cpython/src/dirstate/status.rs Tue May 26 08:07:24 2020 -0700
@@ -104,6 +104,7 @@
list_clean: bool,
list_ignored: bool,
list_unknown: bool,
+ collect_traversed_dirs: bool,
) -> PyResult<PyTuple> {
let bytes = root_dir.extract::<PyBytes>(py)?;
let root_dir = get_path_from_bytes(bytes.data(py));
@@ -134,6 +135,7 @@
list_clean,
list_ignored,
list_unknown,
+ collect_traversed_dirs,
},
)
.map_err(|e| handle_fallback(py, e))?;
@@ -170,6 +172,7 @@
list_clean,
list_ignored,
list_unknown,
+ collect_traversed_dirs,
},
)
.map_err(|e| handle_fallback(py, e))?;
@@ -224,6 +227,7 @@
list_clean,
list_ignored,
list_unknown,
+ collect_traversed_dirs,
},
)
.map_err(|e| handle_fallback(py, e))?;
@@ -256,6 +260,7 @@
let unknown = collect_pybytes_list(py, status_res.unknown.as_ref());
let lookup = collect_pybytes_list(py, lookup.as_ref());
let bad = collect_bad_matches(py, status_res.bad.as_ref())?;
+ let traversed = collect_pybytes_list(py, status_res.traversed.as_ref());
let py_warnings = PyList::new(py, &[]);
for warning in warnings.iter() {
// We use duck-typing on the Python side for dispatch, good enough for
@@ -292,6 +297,7 @@
unknown.into_object(),
py_warnings.into_object(),
bad.into_object(),
+ traversed.into_object(),
][..],
))
}
--- a/rust/hgcli/pyoxidizer.bzl Fri May 15 00:53:37 2020 +0200
+++ b/rust/hgcli/pyoxidizer.bzl Tue May 26 08:07:24 2020 -0700
@@ -3,19 +3,16 @@
# Code to run in Python interpreter.
RUN_CODE = "import hgdemandimport; hgdemandimport.enable(); from mercurial import dispatch; dispatch.run()"
-
set_build_path(ROOT + "/build/pyoxidizer")
-
def make_distribution():
return default_python_distribution()
-
def make_distribution_windows():
- return default_python_distribution(flavor="standalone_dynamic")
-
+ return default_python_distribution(flavor = "standalone_dynamic")
def make_exe(dist):
+ """Builds a Rust-wrapped Mercurial binary."""
config = PythonInterpreterConfig(
raw_allocator = "system",
run_eval = RUN_CODE,
@@ -58,23 +55,20 @@
# On Windows, we install extra packages for convenience.
if "windows" in BUILD_TARGET_TRIPLE:
exe.add_python_resources(
- dist.pip_install(["-r", ROOT + "/contrib/packaging/requirements_win32.txt"])
+ dist.pip_install(["-r", ROOT + "/contrib/packaging/requirements_win32.txt"]),
)
return exe
-
def make_manifest(dist, exe):
m = FileManifest()
m.add_python_resource(".", exe)
return m
-
def make_embedded_resources(exe):
return exe.to_embedded_resources()
-
register_target("distribution_posix", make_distribution)
register_target("distribution_windows", make_distribution_windows)
--- a/setup.py Fri May 15 00:53:37 2020 +0200
+++ b/setup.py Tue May 26 08:07:24 2020 -0700
@@ -1396,7 +1396,7 @@
env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
- cargocmd = ['cargo', 'rustc', '-vv', '--release']
+ cargocmd = ['cargo', 'rustc', '--release']
feature_flags = []
--- a/tests/test-check-rust-format.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-check-rust-format.t Tue May 26 08:07:24 2020 -0700
@@ -5,5 +5,5 @@
$ cd "$TESTDIR"/..
$ RUSTFMT=$(rustup which --toolchain nightly rustfmt)
$ for f in `testrepohg files 'glob:**/*.rs'` ; do
- > $RUSTFMT --check --unstable-features --color=never $f
+ > $RUSTFMT --check --edition=2018 --unstable-features --color=never $f
> done
--- a/tests/test-copies-chain-merge.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-copies-chain-merge.t Tue May 26 08:07:24 2020 -0700
@@ -1,3 +1,5 @@
+#testcases filelog compatibility sidedata
+
=====================================================
Test Copy tracing for chain of copies involving merge
=====================================================
@@ -6,6 +8,7 @@
are involved. It cheks we do not have unwanted update of behavior and that the
different options to retrieve copies behave correctly.
+
Setup
=====
@@ -18,6 +21,22 @@
> logtemplate={rev} {desc}\n
> EOF
+#if compatibility
+ $ cat >> $HGRCPATH << EOF
+ > [experimental]
+ > copies.read-from = compatibility
+ > EOF
+#endif
+
+#if sidedata
+ $ cat >> $HGRCPATH << EOF
+ > [format]
+ > exp-use-side-data = yes
+ > exp-use-copies-side-data-changeset = yes
+ > EOF
+#endif
+
+
$ hg init repo-chain
$ cd repo-chain
@@ -453,17 +472,26 @@
0 4 0dd616bc7ab1 000000000000 000000000000
1 10 6da5a2eecb9c 000000000000 000000000000
2 19 eb806e34ef6b 0dd616bc7ab1 6da5a2eecb9c
+
+# Here the filelog based implementation is not looking at the rename
+# information (because the file exist on both side). However the changelog
+# based on works fine. We have different output.
+
$ hg status --copies --rev 'desc("a-2")' --rev 'desc("mAEm-0")'
M f
+ b (no-filelog !)
R b
$ hg status --copies --rev 'desc("a-2")' --rev 'desc("mEAm-0")'
M f
+ b (no-filelog !)
R b
$ hg status --copies --rev 'desc("e-2")' --rev 'desc("mAEm-0")'
M f
+ d (no-filelog !)
R d
$ hg status --copies --rev 'desc("e-2")' --rev 'desc("mEAm-0")'
M f
+ d (no-filelog !)
R d
$ hg status --copies --rev 'desc("i-2")' --rev 'desc("a-2")'
A f
@@ -473,6 +501,18 @@
A f
b
R b
+
+# From here, we run status against revision where both source file exists.
+#
+# The filelog based implementation picks an arbitrary side based on revision
+# numbers. So the same side "wins" whatever the parents order is. This is
+# sub-optimal because depending on revision numbers means the result can be
+# different from one repository to the next.
+#
+# The changeset based algorithm use the parent order to break tie on conflicting
+# information and will have a different order depending on who is p1 and p2.
+# That order is stable accross repositories. (data from p1 prevails)
+
$ hg status --copies --rev 'desc("i-2")' --rev 'desc("mAEm-0")'
A f
d
@@ -480,7 +520,8 @@
R d
$ hg status --copies --rev 'desc("i-2")' --rev 'desc("mEAm-0")'
A f
- d
+ d (filelog !)
+ b (no-filelog !)
R b
R d
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mAEm-0")'
@@ -490,7 +531,8 @@
R b
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mEAm-0")'
A f
- a
+ a (filelog !)
+ b (no-filelog !)
R a
R b
@@ -563,21 +605,25 @@
R h
$ hg status --copies --rev 'desc("b-1")' --rev 'desc("mBFm-0")'
M d
+ h (no-filelog !)
R h
$ hg status --copies --rev 'desc("f-2")' --rev 'desc("mBFm-0")'
M b
$ hg status --copies --rev 'desc("f-1")' --rev 'desc("mBFm-0")'
M b
M d
+ i (no-filelog !)
R i
$ hg status --copies --rev 'desc("b-1")' --rev 'desc("mFBm-0")'
M d
+ h (no-filelog !)
R h
$ hg status --copies --rev 'desc("f-2")' --rev 'desc("mFBm-0")'
M b
$ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFBm-0")'
M b
M d
+ i (no-filelog !)
R i
The following graphlog is wrong, the "a -> c -> d" chain was overwritten and should not appear.
@@ -645,9 +691,15 @@
|
o 0 i-0 initial commit: a b h
+One side of the merge have a long history with rename. The other side of the
+merge point to a new file with a smaller history. Each side is "valid".
+
+(and again the filelog based algorithm only explore one, with a pick based on
+revision numbers)
+
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mDGm-0")'
A d
- a
+ a (filelog !)
R a
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGDm-0")'
A d
@@ -740,7 +792,8 @@
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mFGm-0")'
A d
- a
+ h (no-filelog !)
+ a (filelog !)
R a
R h
$ hg status --copies --rev 'desc("i-0")' --rev 'desc("mGFm-0")'
@@ -754,15 +807,19 @@
M d
$ hg status --copies --rev 'desc("f-1")' --rev 'desc("mFGm-0")'
M d
+ i (no-filelog !)
R i
$ hg status --copies --rev 'desc("f-1")' --rev 'desc("mGFm-0")'
M d
+ i (no-filelog !)
R i
$ hg status --copies --rev 'desc("g-1")' --rev 'desc("mFGm-0")'
M d
+ h (no-filelog !)
R h
$ hg status --copies --rev 'desc("g-1")' --rev 'desc("mGFm-0")'
M d
+ h (no-filelog !)
R h
$ hg log -Gfr 'desc("mFGm-0")' d
--- a/tests/test-copies-in-changeset.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-copies-in-changeset.t Tue May 26 08:07:24 2020 -0700
@@ -33,28 +33,30 @@
$ cd repo
#if sidedata
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes yes no
- copies-sdc: yes yes no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes yes no
+ persistent-nodemap: no no no
+ copies-sdc: yes yes no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
#else
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
#endif
$ echo a > a
$ hg add a
@@ -424,16 +426,17 @@
downgrading (keeping some sidedata)
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes yes no
- copies-sdc: yes yes no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes yes no
+ persistent-nodemap: no no no
+ copies-sdc: yes yes no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugsidedata -c -- 0
1 sidedata entries
entry-0012 size 1
@@ -448,16 +451,17 @@
> EOF
$ hg debugupgraderepo --run --quiet --no-backup > /dev/null
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes yes no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes yes no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugsidedata -c -- 0
$ hg debugsidedata -c -- 1
$ hg debugsidedata -m -- 0
@@ -470,16 +474,17 @@
> EOF
$ hg debugupgraderepo --run --quiet --no-backup > /dev/null
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes yes no
- copies-sdc: yes yes no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes yes no
+ persistent-nodemap: no no no
+ copies-sdc: yes yes no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugsidedata -c -- 0
1 sidedata entries
entry-0012 size 1
--- a/tests/test-grep.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-grep.t Tue May 26 08:07:24 2020 -0700
@@ -645,18 +645,24 @@
$ hg init sng
$ cd sng
$ echo "unmod" >> um
- $ hg ci -A -m "adds unmod to um"
- adding um
+ $ echo old > old
+ $ hg ci -q -A -m "adds unmod to um"
$ echo "something else" >> new
$ hg ci -A -m "second commit"
adding new
$ hg grep -r "." "unmod"
um:1:unmod
-Working directory is searched by default
+Existing tracked files in the working directory are searched by default
$ echo modified >> new
- $ hg grep mod
+ $ echo 'added' > added; hg add added
+ $ echo 'added, missing' > added-missing; hg add added-missing; rm added-missing
+ $ echo 'untracked' > untracked
+ $ hg rm old
+ $ hg grep ''
+ added:added
+ new:something else
new:modified
um:unmod
@@ -670,17 +676,6 @@
$ cd ..
-Fix_Wdir(): test that passing wdir() t -r flag does greps on the
-files modified in the working directory
-
- $ cd a
- $ echo "abracadara" >> a
- $ hg add a
- $ hg grep -r "wdir()" "abra"
- a:2147483647:abracadara
-
- $ cd ..
-
Change Default of grep by ui.tweakdefaults, that is, the files not in current
working directory should not be grepp-ed on
--- a/tests/test-histedit-edit.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-histedit-edit.t Tue May 26 08:07:24 2020 -0700
@@ -373,6 +373,7 @@
transaction abort!
rollback completed
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
abort: pretxncommit.unexpectedabort hook exited with status 1
[255]
$ cat .hg/last-message.txt
@@ -397,6 +398,7 @@
transaction abort!
rollback completed
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
abort: pretxncommit.unexpectedabort hook exited with status 1
[255]
--- a/tests/test-hook.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-hook.t Tue May 26 08:07:24 2020 -0700
@@ -443,7 +443,7 @@
HG_PENDING=$TESTTMP/a
transaction abort!
- txnabort Python hook: txnid,txnname
+ txnabort Python hook: changes,txnid,txnname
txnabort hook: HG_HOOKNAME=txnabort.1
HG_HOOKTYPE=txnabort
HG_TXNID=TXN:$ID$
--- a/tests/test-lfs-serve.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-lfs-serve.t Tue May 26 08:07:24 2020 -0700
@@ -133,30 +133,6 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
- beginning upgrade...
- repository locked and read-only
- creating temporary repository to stage migrated data: * (glob)
- (it is safe to interrupt this process any time before data migration completes)
- migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
- migrating 324 bytes in store; 129 bytes tracked data
- migrating 1 filelogs containing 1 revisions (73 bytes in store; 8 bytes tracked data)
- finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
- migrating 1 manifests containing 1 revisions (117 bytes in store; 52 bytes tracked data)
- finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
- migrating changelog containing 1 revisions (134 bytes in store; 69 bytes tracked data)
- finished migrating 1 changelog revisions; change in size: 0 bytes
- finished migrating 3 total revisions; total change in store size: 0 bytes
- copying phaseroots
- data fully migrated to temporary repository
- marking source repository as being upgraded; clients will be unable to read from repository
- starting in-place swap of repository data
- replaced files will be backed up at * (glob)
- replacing store...
- store replacement complete; repository was inconsistent for *s (glob)
- finalizing requirements file and making repository readable again
- removing temporary repository * (glob)
- copy of old repository backed up at * (glob)
- the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
$ grep 'lfs' .hg/requires $SERVER_REQUIRES
[1]
--- a/tests/test-mq-qfold.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-mq-qfold.t Tue May 26 08:07:24 2020 -0700
@@ -230,6 +230,7 @@
HG: changed a
====
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
transaction abort!
rollback completed
qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
--- a/tests/test-mq-qnew.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-mq-qnew.t Tue May 26 08:07:24 2020 -0700
@@ -308,6 +308,7 @@
transaction abort!
rollback completed
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
abort: pretxncommit.unexpectedabort hook exited with status 1
[255]
$ cat .hg/last-message.txt
--- a/tests/test-mq-qrefresh-replace-log-message.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-mq-qrefresh-replace-log-message.t Tue May 26 08:07:24 2020 -0700
@@ -186,6 +186,7 @@
HG: added file2
====
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
transaction abort!
rollback completed
qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
@@ -229,6 +230,7 @@
A file2
====
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
transaction abort!
rollback completed
qrefresh interrupted while patch was popped! (revert --all, qpush to recover)
--- a/tests/test-persistent-nodemap.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-persistent-nodemap.t Tue May 26 08:07:24 2020 -0700
@@ -2,20 +2,34 @@
Test the persistent on-disk nodemap
===================================
- $ hg init test-repo
- $ cd test-repo
- $ cat << EOF >> .hg/hgrc
- > [experimental]
- > exp-persistent-nodemap=yes
+ $ cat << EOF >> $HGRCPATH
+ > [format]
+ > use-persistent-nodemap=yes
> [devel]
> persistent-nodemap=yes
> EOF
- $ hg debugbuilddag .+5000
+ $ hg init test-repo
+ $ cd test-repo
+ $ hg debugformat
+ format-variant repo
+ fncache: yes
+ dotencode: yes
+ generaldelta: yes
+ sparserevlog: yes
+ sidedata: no
+ persistent-nodemap: yes
+ copies-sdc: no
+ plain-cl-delta: yes
+ compression: zlib
+ compression-level: default
+ $ hg debugbuilddag .+5000 --new-file --config "storage.revlog.nodemap.mode=warn"
+ persistent nodemap in strict mode without efficient method (no-rust no-pure !)
+ persistent nodemap in strict mode without efficient method (no-rust no-pure !)
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5000
- tip-node: 06ddac466af534d365326c13c3879f97caca3cb1
- data-length: 122880
+ tip-node: 6b02b8c7b96654c25e86ba69eda198d7e6ad8b3c
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
$ f --size .hg/store/00changelog.n
@@ -31,53 +45,56 @@
#if rust
$ f --sha256 .hg/store/00changelog-*.nd
- .hg/store/00changelog-????????????????.nd: sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6 (glob)
+ .hg/store/00changelog-????????????????.nd: sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd (glob)
+
+ $ f --sha256 .hg/store/00manifest-*.nd
+ .hg/store/00manifest-????????????????.nd: sha256=97117b1c064ea2f86664a124589e47db0e254e8d34739b5c5cc5bf31c9da2b51 (glob)
$ hg debugnodemap --dump-new | f --sha256 --size
- size=122880, sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6
+ size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
$ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
- size=122880, sha256=1e38e9ffaa45cad13f15c1a9880ad606f4241e8beea2f61b4d5365abadfb55f6
- 0000: 00 00 00 76 00 00 01 65 00 00 00 95 00 00 01 34 |...v...e.......4|
- 0010: 00 00 00 19 00 00 01 69 00 00 00 ab 00 00 00 4b |.......i.......K|
- 0020: 00 00 00 07 00 00 01 4c 00 00 00 f8 00 00 00 8f |.......L........|
- 0030: 00 00 00 c0 00 00 00 a7 00 00 00 89 00 00 01 46 |...............F|
- 0040: 00 00 00 92 00 00 01 bc 00 00 00 71 00 00 00 ac |...........q....|
- 0050: 00 00 00 af 00 00 00 b4 00 00 00 34 00 00 01 ca |...........4....|
- 0060: 00 00 00 23 00 00 01 45 00 00 00 2d 00 00 00 b2 |...#...E...-....|
- 0070: 00 00 00 56 00 00 01 0f 00 00 00 4e 00 00 02 4c |...V.......N...L|
- 0080: 00 00 00 e7 00 00 00 cd 00 00 01 5b 00 00 00 78 |...........[...x|
- 0090: 00 00 00 e3 00 00 01 8e 00 00 00 4f 00 00 00 b1 |...........O....|
- 00a0: 00 00 00 30 00 00 00 11 00 00 00 25 00 00 00 d2 |...0.......%....|
- 00b0: 00 00 00 ec 00 00 00 69 00 00 01 2b 00 00 01 2e |.......i...+....|
- 00c0: 00 00 00 aa 00 00 00 15 00 00 00 3a 00 00 01 4e |...........:...N|
- 00d0: 00 00 00 4d 00 00 00 9d 00 00 00 8e 00 00 00 a4 |...M............|
- 00e0: 00 00 00 c3 00 00 00 eb 00 00 00 29 00 00 00 ad |...........)....|
- 00f0: 00 00 01 3a 00 00 01 32 00 00 00 04 00 00 00 53 |...:...2.......S|
+ size=121088, sha256=2e029d3200bd1a986b32784fc2ef1a3bd60dc331f025718bcf5ff44d93f026fd
+ 0000: 00 00 00 91 00 00 00 20 00 00 00 bb 00 00 00 e7 |....... ........|
+ 0010: 00 00 00 66 00 00 00 a1 00 00 01 13 00 00 01 22 |...f..........."|
+ 0020: 00 00 00 23 00 00 00 fc 00 00 00 ba 00 00 00 5e |...#...........^|
+ 0030: 00 00 00 df 00 00 01 4e 00 00 01 65 00 00 00 ab |.......N...e....|
+ 0040: 00 00 00 a9 00 00 00 95 00 00 00 73 00 00 00 38 |...........s...8|
+ 0050: 00 00 00 cc 00 00 00 92 00 00 00 90 00 00 00 69 |...............i|
+ 0060: 00 00 00 ec 00 00 00 8d 00 00 01 4f 00 00 00 12 |...........O....|
+ 0070: 00 00 02 0c 00 00 00 77 00 00 00 9c 00 00 00 8f |.......w........|
+ 0080: 00 00 00 d5 00 00 00 6b 00 00 00 48 00 00 00 b3 |.......k...H....|
+ 0090: 00 00 00 e5 00 00 00 b5 00 00 00 8e 00 00 00 ad |................|
+ 00a0: 00 00 00 7b 00 00 00 7c 00 00 00 0b 00 00 00 2b |...{...|.......+|
+ 00b0: 00 00 00 c6 00 00 00 1e 00 00 01 08 00 00 00 11 |................|
+ 00c0: 00 00 01 30 00 00 00 26 00 00 01 9c 00 00 00 35 |...0...&.......5|
+ 00d0: 00 00 00 b8 00 00 01 31 00 00 00 2c 00 00 00 55 |.......1...,...U|
+ 00e0: 00 00 00 8a 00 00 00 9a 00 00 00 0c 00 00 01 1e |................|
+ 00f0: 00 00 00 a4 00 00 00 83 00 00 00 c9 00 00 00 8c |................|
#else
$ f --sha256 .hg/store/00changelog-*.nd
- .hg/store/00changelog-????????????????.nd: sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7 (glob)
+ .hg/store/00changelog-????????????????.nd: sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79 (glob)
$ hg debugnodemap --dump-new | f --sha256 --size
- size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
+ size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
$ hg debugnodemap --dump-disk | f --sha256 --bytes=256 --hexdump --size
- size=122880, sha256=b961925120e1c9bc345c199b2cc442abc477029fdece37ef9d99cbe59c0558b7
+ size=121088, sha256=f544f5462ff46097432caf6d764091f6d8c46d6121be315ead8576d548c9dd79
0000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 0010: ff ff ff ff ff ff ff ff ff ff fa c2 ff ff ff ff |................|
- 0020: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 0030: ff ff ff ff ff ff ed b3 ff ff ff ff ff ff ff ff |................|
- 0040: ff ff ff ff ff ff ee 34 00 00 00 00 ff ff ff ff |.......4........|
- 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 0060: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 0010: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 0020: ff ff ff ff ff ff f5 06 ff ff ff ff ff ff f3 e7 |................|
+ 0030: ff ff ef ca ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 0040: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 0050: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ed 08 |................|
+ 0060: ff ff ed 66 ff ff ff ff ff ff ff ff ff ff ff ff |...f............|
0070: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 0080: ff ff ff ff ff ff f8 50 ff ff ff ff ff ff ff ff |.......P........|
- 0090: ff ff ff ff ff ff ff ff ff ff ec c7 ff ff ff ff |................|
- 00a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 00b0: ff ff ff ff ff ff fa be ff ff f2 fc ff ff ff ff |................|
- 00c0: ff ff ff ff ff ff ef ea ff ff ff ff ff ff f9 17 |................|
+ 0080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 0090: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f6 ed |................|
+ 00a0: ff ff ff ff ff ff fe 61 ff ff ff ff ff ff ff ff |.......a........|
+ 00b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 00c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
00d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
- 00f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
+ 00e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff f1 02 |................|
+ 00f0: ff ff ff ff ff ff ed 1b ff ff ff ff ff ff ff ff |................|
#endif
@@ -88,27 +105,38 @@
add a new commit
$ hg up
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ 5001 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo foo > foo
$ hg add foo
+
+#if no-pure no-rust
+
+ $ hg ci -m 'foo' --config "storage.revlog.nodemap.mode=strict"
+ transaction abort!
+ rollback completed
+ abort: persistent nodemap in strict mode without efficient method
+ [255]
+
+#endif
+
$ hg ci -m 'foo'
#if no-pure no-rust
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5001
- tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
- data-length: 122880
+ tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
#else
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5001
- tip-node: 2dd9b5258caa46469ff07d4a3da1eb3529a51f49
- data-length: 123072
- data-unused: 192
- data-unused: 0.156%
+ tip-node: 16395c3cf7e231394735e6b1717823ada303fb0c
+ data-length: 121344
+ data-unused: 256
+ data-unused: 0.211%
#endif
$ f --size .hg/store/00changelog.n
@@ -118,17 +146,17 @@
#if pure
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=123072, sha256=136472751566c8198ff09e306a7d2f9bd18bd32298d614752b73da4d6df23340 (glob)
+ .hg/store/00changelog-????????????????.nd: size=121344, sha256=cce54c5da5bde3ad72a4938673ed4064c86231b9c64376b082b163fdb20f8f66 (glob)
#endif
#if rust
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=123072, sha256=ccc8a43310ace13812fcc648683e259346754ef934c12dd238cf9b7fadfe9a4b (glob)
+ .hg/store/00changelog-????????????????.nd: size=121344, sha256=952b042fcf614ceb37b542b1b723e04f18f83efe99bee4e0f5ccd232ef470e58 (glob)
#endif
#if no-pure no-rust
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=122880, sha256=bfafebd751c4f6d116a76a37a1dee2a251747affe7efbcc4f4842ccc746d4db9 (glob)
+ .hg/store/00changelog-????????????????.nd: size=121088, sha256=df7c06a035b96cb28c7287d349d603baef43240be7736fe34eea419a49702e17 (glob)
#endif
$ hg debugnodemap --check
@@ -140,12 +168,12 @@
$ echo bar > bar
$ hg add bar
- $ hg ci -m 'bar' --config experimental.exp-persistent-nodemap.mmap=no
+ $ hg ci -m 'bar' --config storage.revlog.nodemap.mmap=no
- $ hg debugnodemap --check --config experimental.exp-persistent-nodemap.mmap=yes
+ $ hg debugnodemap --check --config storage.revlog.nodemap.mmap=yes
revision in index: 5003
revision in nodemap: 5003
- $ hg debugnodemap --check --config experimental.exp-persistent-nodemap.mmap=no
+ $ hg debugnodemap --check --config storage.revlog.nodemap.mmap=no
revision in index: 5003
revision in nodemap: 5003
@@ -154,34 +182,34 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 123328
- data-unused: 384
- data-unused: 0.311%
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121600
+ data-unused: 512
+ data-unused: 0.421%
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=123328, sha256=10d26e9776b6596af0f89143a54eba8cc581e929c38242a02a7b0760698c6c70 (glob)
+ .hg/store/00changelog-????????????????.nd: size=121600, sha256=def52503d049ccb823974af313a98a935319ba61f40f3aa06a8be4d35c215054 (glob)
#endif
#if rust
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 123328
- data-unused: 384
- data-unused: 0.311%
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121600
+ data-unused: 512
+ data-unused: 0.421%
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=123328, sha256=081eec9eb6708f2bf085d939b4c97bc0b6762bc8336bc4b93838f7fffa1516bf (glob)
+ .hg/store/00changelog-????????????????.nd: size=121600, sha256=dacf5b5f1d4585fee7527d0e67cad5b1ba0930e6a0928f650f779aefb04ce3fb (glob)
#endif
#if no-pure no-rust
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 122944
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
$ f --sha256 .hg/store/00changelog-*.nd --size
- .hg/store/00changelog-????????????????.nd: size=122944, sha256=755976b22b64ab680401b45395953504e64e7fa8c31ac570f58dee21e15f9bc0 (glob)
+ .hg/store/00changelog-????????????????.nd: size=121088, sha256=59fcede3e3cc587755916ceed29e3c33748cd1aa7d2f91828ac83e7979d935e8 (glob)
#endif
Test force warming the cache
@@ -193,16 +221,16 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 122944
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
#else
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 122944
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
#endif
@@ -231,22 +259,22 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5003
- tip-node: 5c049e9c4a4af159bdcd65dce1b6bf303a0da6cf
- data-length: 123200 (pure !)
- data-length: 123200 (rust !)
- data-length: 122944 (no-rust no-pure !)
- data-unused: 256 (pure !)
- data-unused: 256 (rust !)
+ tip-node: c9329770f979ade2d16912267c38ba5f82fd37b3
+ data-length: 121344 (pure !)
+ data-length: 121344 (rust !)
+ data-length: 121152 (no-rust no-pure !)
+ data-unused: 192 (pure !)
+ data-unused: 192 (rust !)
data-unused: 0 (no-rust no-pure !)
- data-unused: 0.208% (pure !)
- data-unused: 0.208% (rust !)
+ data-unused: 0.158% (pure !)
+ data-unused: 0.158% (rust !)
data-unused: 0.000% (no-rust no-pure !)
$ cp -f ../tmp-copies/* .hg/store/
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 122944
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
$ hg log -r "$NODE" -T '{rev}\n'
@@ -260,7 +288,7 @@
compatible with the persistent nodemap. We need to detect that.
$ hg up "$NODE~5"
- 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+ 0 files updated, 0 files merged, 4 files removed, 0 files unresolved
$ echo bar > babar
$ hg add babar
$ hg ci -m 'babar'
@@ -276,23 +304,23 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 42bf3068c7ddfdfded53c4eb11d02266faeebfee
- data-length: 123456 (pure !)
- data-length: 123008 (rust !)
- data-length: 123008 (no-pure no-rust !)
+ tip-node: b355ef8adce0949b8bdf6afc72ca853740d65944
+ data-length: 121536 (pure !)
+ data-length: 121088 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 448 (pure !)
data-unused: 0 (rust !)
data-unused: 0 (no-pure no-rust !)
data-unused: 0.000% (rust !)
- data-unused: 0.363% (pure !)
+ data-unused: 0.369% (pure !)
data-unused: 0.000% (no-pure no-rust !)
$ cp -f ../tmp-copies/* .hg/store/
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5002
- tip-node: 6ce944fafcee85af91f29ea5b51654cc6101ad7e
- data-length: 122944
+ tip-node: 880b18d239dfa9f632413a2071bfdbcc4806a4fd
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
$ hg log -r "$OTHERNODE" -T '{rev}\n'
@@ -309,36 +337,36 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5003
- tip-node: c91af76d172f1053cca41b83f7c2e4e514fe2bcf
- data-length: 123008
+ tip-node: a52c5079765b5865d97b993b303a18740113bbb2
+ data-length: 121088
data-unused: 0
data-unused: 0.000%
$ echo babar2 > babar
$ hg ci -m 'babar2' --config "hooks.pretxnclose.nodemap-test=hg debugnodemap --metadata"
uid: ???????????????? (glob)
tip-rev: 5004
- tip-node: ba87cd9559559e4b91b28cb140d003985315e031
- data-length: 123328 (pure !)
- data-length: 123328 (rust !)
- data-length: 123136 (no-pure no-rust !)
+ tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
+ data-length: 121280 (pure !)
+ data-length: 121280 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 192 (pure !)
data-unused: 192 (rust !)
data-unused: 0 (no-pure no-rust !)
- data-unused: 0.156% (pure !)
- data-unused: 0.156% (rust !)
+ data-unused: 0.158% (pure !)
+ data-unused: 0.158% (rust !)
data-unused: 0.000% (no-pure no-rust !)
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5004
- tip-node: ba87cd9559559e4b91b28cb140d003985315e031
- data-length: 123328 (pure !)
- data-length: 123328 (rust !)
- data-length: 123136 (no-pure no-rust !)
+ tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
+ data-length: 121280 (pure !)
+ data-length: 121280 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 192 (pure !)
data-unused: 192 (rust !)
data-unused: 0 (no-pure no-rust !)
- data-unused: 0.156% (pure !)
- data-unused: 0.156% (rust !)
+ data-unused: 0.158% (pure !)
+ data-unused: 0.158% (rust !)
data-unused: 0.000% (no-pure no-rust !)
Another process does not see the pending nodemap content during run.
@@ -356,28 +384,28 @@
> wait-on-file 20 sync-txn-close sync-repo-read
uid: ???????????????? (glob)
tip-rev: 5004
- tip-node: ba87cd9559559e4b91b28cb140d003985315e031
- data-length: 123328 (pure !)
- data-length: 123328 (rust !)
- data-length: 123136 (no-pure no-rust !)
+ tip-node: 2f5fb1c06a16834c5679d672e90da7c5f3b1a984
+ data-length: 121280 (pure !)
+ data-length: 121280 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 192 (pure !)
data-unused: 192 (rust !)
data-unused: 0 (no-pure no-rust !)
- data-unused: 0.156% (pure !)
- data-unused: 0.156% (rust !)
+ data-unused: 0.158% (pure !)
+ data-unused: 0.158% (rust !)
data-unused: 0.000% (no-pure no-rust !)
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5005
- tip-node: bae4d45c759e30f1cb1a40e1382cf0e0414154db
- data-length: 123584 (pure !)
- data-length: 123584 (rust !)
- data-length: 123136 (no-pure no-rust !)
+ tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
+ data-length: 121536 (pure !)
+ data-length: 121536 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 448 (pure !)
data-unused: 448 (rust !)
data-unused: 0 (no-pure no-rust !)
- data-unused: 0.363% (pure !)
- data-unused: 0.363% (rust !)
+ data-unused: 0.369% (pure !)
+ data-unused: 0.369% (rust !)
data-unused: 0.000% (no-pure no-rust !)
$ cat output.txt
@@ -386,9 +414,9 @@
$ echo plakfe > a
$ f --size --sha256 .hg/store/00changelog-*.nd
- .hg/store/00changelog-????????????????.nd: size=123584, sha256=8c6cef6fd3d3fac291968793ee19a4be6d0b8375e9508bd5c7d4a8879e8df180 (glob) (pure !)
- .hg/store/00changelog-????????????????.nd: size=123584, sha256=eb9e9a4bcafdb5e1344bc8a0cbb3288b2106413b8efae6265fb8a7973d7e97f9 (glob) (rust !)
- .hg/store/00changelog-????????????????.nd: size=123136, sha256=4f504f5a834db3811ced50ab3e9e80bcae3581bb0f9b13a7a9f94b7fc34bcebe (glob) (no-pure no-rust !)
+ .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
+ .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
+ .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
$ hg ci -m a3 --config "extensions.abort=$RUNTESTDIR/testlib/crash_transaction_late.py"
transaction abort!
rollback completed
@@ -397,17 +425,113 @@
$ hg debugnodemap --metadata
uid: ???????????????? (glob)
tip-rev: 5005
- tip-node: bae4d45c759e30f1cb1a40e1382cf0e0414154db
- data-length: 123584 (pure !)
- data-length: 123584 (rust !)
- data-length: 123136 (no-pure no-rust !)
+ tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
+ data-length: 121536 (pure !)
+ data-length: 121536 (rust !)
+ data-length: 121088 (no-pure no-rust !)
data-unused: 448 (pure !)
data-unused: 448 (rust !)
data-unused: 0 (no-pure no-rust !)
- data-unused: 0.363% (pure !)
- data-unused: 0.363% (rust !)
+ data-unused: 0.369% (pure !)
+ data-unused: 0.369% (rust !)
data-unused: 0.000% (no-pure no-rust !)
$ f --size --sha256 .hg/store/00changelog-*.nd
- .hg/store/00changelog-????????????????.nd: size=123584, sha256=8c6cef6fd3d3fac291968793ee19a4be6d0b8375e9508bd5c7d4a8879e8df180 (glob) (pure !)
- .hg/store/00changelog-????????????????.nd: size=123584, sha256=eb9e9a4bcafdb5e1344bc8a0cbb3288b2106413b8efae6265fb8a7973d7e97f9 (glob) (rust !)
- .hg/store/00changelog-????????????????.nd: size=123136, sha256=4f504f5a834db3811ced50ab3e9e80bcae3581bb0f9b13a7a9f94b7fc34bcebe (glob) (no-pure no-rust !)
+ .hg/store/00changelog-????????????????.nd: size=121536, sha256=bb414468d225cf52d69132e1237afba34d4346ee2eb81b505027e6197b107f03 (glob) (pure !)
+ .hg/store/00changelog-????????????????.nd: size=121536, sha256=909ac727bc4d1c0fda5f7bff3c620c98bd4a2967c143405a1503439e33b377da (glob) (rust !)
+ .hg/store/00changelog-????????????????.nd: size=121088, sha256=342d36d30d86dde67d3cb6c002606c4a75bcad665595d941493845066d9c8ee0 (glob) (no-pure no-rust !)
+
+Test upgrade / downgrade
+========================
+
+downgrading
+
+ $ cat << EOF >> .hg/hgrc
+ > [format]
+ > use-persistent-nodemap=no
+ > EOF
+ $ hg debugformat -v
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: yes no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
+ $ hg debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ removed: persistent-nodemap
+
+ $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
+ [1]
+ $ hg debugnodemap --metadata
+
+
+upgrading
+
+ $ cat << EOF >> .hg/hgrc
+ > [format]
+ > use-persistent-nodemap=yes
+ > EOF
+ $ hg debugformat -v
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no yes no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
+ $ hg debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ added: persistent-nodemap
+
+ $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
+ 00changelog-*.nd (glob)
+ 00changelog.n
+ 00manifest-*.nd (glob)
+ 00manifest.n
+
+ $ hg debugnodemap --metadata
+ uid: * (glob)
+ tip-rev: 5005
+ tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
+ data-length: 121088
+ data-unused: 0
+ data-unused: 0.000%
+
+Running unrelated upgrade
+
+ $ hg debugupgraderepo --run --no-backup --quiet --optimize re-delta-all
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, sparserevlog, store
+
+ optimisations: re-delta-all
+
+ $ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
+ 00changelog-*.nd (glob)
+ 00changelog.n
+ 00manifest-*.nd (glob)
+ 00manifest.n
+
+ $ hg debugnodemap --metadata
+ uid: * (glob)
+ tip-rev: 5005
+ tip-node: 90d5d3ba2fc47db50f712570487cb261a68c8ffe
+ data-length: 121088
+ data-unused: 0
+ data-unused: 0.000%
--- a/tests/test-revset.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-revset.t Tue May 26 08:07:24 2020 -0700
@@ -1864,12 +1864,12 @@
$ log 'id(2)'
$ log 'id(8)'
3
- $ hg --config experimental.revisions.prefixhexnode=yes log --template '{rev}\n' -r 'id(x8)'
+ $ hg log --template '{rev}\n' -r 'id(x8)'
3
- $ hg --config experimental.revisions.prefixhexnode=yes log --template '{rev}\n' -r 'x8'
+ $ hg log --template '{rev}\n' -r 'x8'
3
- $ hg --config experimental.revisions.prefixhexnode=yes log --template '{rev}\n' -r 'id(x)'
- $ hg --config experimental.revisions.prefixhexnode=yes log --template '{rev}\n' -r 'x'
+ $ hg log --template '{rev}\n' -r 'id(x)'
+ $ hg log --template '{rev}\n' -r 'x'
abort: 00changelog.i@: ambiguous identifier!
[255]
$ log 'id(23268)'
--- a/tests/test-rollback.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-rollback.t Tue May 26 08:07:24 2020 -0700
@@ -116,6 +116,7 @@
transaction abort!
rollback completed
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
abort: pretxncommit hook exited with status * (glob)
[255]
$ cat .hg/last-message.txt
--- a/tests/test-sidedata.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-sidedata.t Tue May 26 08:07:24 2020 -0700
@@ -50,27 +50,29 @@
$ hg init up-no-side-data --config format.exp-use-side-data=no
$ hg debugformat -v -R up-no-side-data
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat -v -R up-no-side-data --config format.exp-use-side-data=yes
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no yes no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no yes no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugupgraderepo -R up-no-side-data --config format.exp-use-side-data=yes > /dev/null
Check that we can downgrade from sidedata
@@ -78,25 +80,27 @@
$ hg init up-side-data --config format.exp-use-side-data=yes
$ hg debugformat -v -R up-side-data
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat -v -R up-side-data --config format.exp-use-side-data=no
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugupgraderepo -R up-side-data --config format.exp-use-side-data=no > /dev/null
--- a/tests/test-tag.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-tag.t Tue May 26 08:07:24 2020 -0700
@@ -323,6 +323,7 @@
transaction abort!
rollback completed
note: commit message saved in .hg/last-message.txt
+ note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
abort: pretxncommit.unexpectedabort hook exited with status 1
[255]
$ cat .hg/last-message.txt
--- a/tests/test-upgrade-repo.t Fri May 15 00:53:37 2020 +0200
+++ b/tests/test-upgrade-repo.t Tue May 26 08:07:24 2020 -0700
@@ -52,49 +52,53 @@
$ hg init empty
$ cd empty
$ hg debugformat
- format-variant repo
- fncache: yes
- dotencode: yes
- generaldelta: yes
- sparserevlog: yes
- sidedata: no
- copies-sdc: no
- plain-cl-delta: yes
- compression: zlib
- compression-level: default
+ format-variant repo
+ fncache: yes
+ dotencode: yes
+ generaldelta: yes
+ sparserevlog: yes
+ sidedata: no
+ persistent-nodemap: no
+ copies-sdc: no
+ plain-cl-delta: yes
+ compression: zlib
+ compression-level: default
$ hg debugformat --verbose
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat --verbose --config format.usefncache=no
- format-variant repo config default
- fncache: yes no yes
- dotencode: yes no yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes no yes
+ dotencode: yes no yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat --verbose --config format.usefncache=no --color=debug
- format-variant repo config default
- [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
- [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
- [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
- [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
- [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
- [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
+ format-variant repo config default
+ [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
+ [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
+ [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
+ [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
$ hg debugformat -Tjson
[
{
@@ -130,6 +134,12 @@
{
"config": false,
"default": false,
+ "name": "persistent-nodemap",
+ "repo": false
+ },
+ {
+ "config": false,
+ "default": false,
"name": "copies-sdc",
"repo": false
},
@@ -174,6 +184,11 @@
every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
+ $ hg debugupgraderepo --quiet
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+
+
--optimize can be used to add optimizations
$ hg debugupgrade --optimize redeltaparent
@@ -183,6 +198,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -207,6 +224,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -221,6 +240,12 @@
re-delta-fulladd
every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
+ $ hg debugupgrade --optimize re-delta-parent --quiet
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+
+ optimisations: re-delta-parent
+
unknown optimization:
@@ -237,49 +262,53 @@
> EOF
$ hg debugformat
- format-variant repo
- fncache: no
- dotencode: no
- generaldelta: no
- sparserevlog: no
- sidedata: no
- copies-sdc: no
- plain-cl-delta: yes
- compression: zlib
- compression-level: default
+ format-variant repo
+ fncache: no
+ dotencode: no
+ generaldelta: no
+ sparserevlog: no
+ sidedata: no
+ persistent-nodemap: no
+ copies-sdc: no
+ plain-cl-delta: yes
+ compression: zlib
+ compression-level: default
$ hg debugformat --verbose
- format-variant repo config default
- fncache: no yes yes
- dotencode: no yes yes
- generaldelta: no yes yes
- sparserevlog: no yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: no yes yes
+ dotencode: no yes yes
+ generaldelta: no yes yes
+ sparserevlog: no yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat --verbose --config format.usegeneraldelta=no
- format-variant repo config default
- fncache: no yes yes
- dotencode: no yes yes
- generaldelta: no no yes
- sparserevlog: no no yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: no yes yes
+ dotencode: no yes yes
+ generaldelta: no no yes
+ sparserevlog: no no yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
- format-variant repo config default
- [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
- [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
- [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
- [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
- [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
- [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
- [formatvariant.name.uptodate|compression-level:][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
+ format-variant repo config default
+ [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
+ [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
+ [formatvariant.name.uptodate|sidedata: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
+ [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
+ [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib]
+ [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
$ hg debugupgraderepo
repository lacks features recommended by current config options:
@@ -328,6 +357,11 @@
re-delta-fulladd
every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
+ $ hg debugupgraderepo --quiet
+ requirements
+ preserved: revlogv1, store
+ added: dotencode, fncache, generaldelta, sparserevlog
+
$ hg --config format.dotencode=false debugupgraderepo
repository lacks features recommended by current config options:
@@ -569,6 +603,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -643,6 +679,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -689,6 +727,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -735,6 +775,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -786,6 +828,8 @@
preserved: dotencode, fncache, generaldelta, revlogv1, store
removed: sparserevlog
+ optimisations: re-delta-parent
+
re-delta-parent
deltas within internal storage will choose a new base revision if needed
@@ -835,6 +879,8 @@
preserved: dotencode, fncache, generaldelta, revlogv1, store
added: sparserevlog
+ optimisations: re-delta-parent
+
sparserevlog
Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
@@ -923,6 +969,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-fulladd
+
re-delta-fulladd
each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
@@ -1135,6 +1183,8 @@
requirements
preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ optimisations: re-delta-all
+
re-delta-all
deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
@@ -1190,9 +1240,13 @@
store
Check that we can add the sparse-revlog format requirement
- $ hg --config format.sparse-revlog=yes debugupgraderepo --run >/dev/null
- copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
- the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
+ $ hg --config format.sparse-revlog=yes debugupgraderepo --run --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, store
+ added: sparserevlog
+
$ cat .hg/requires
dotencode
fncache
@@ -1202,9 +1256,13 @@
store
Check that we can remove the sparse-revlog format requirement
- $ hg --config format.sparse-revlog=no debugupgraderepo --run >/dev/null
- copy of old repository backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
- the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
+ $ hg --config format.sparse-revlog=no debugupgraderepo --run --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, store
+ removed: sparserevlog
+
$ cat .hg/requires
dotencode
fncache
@@ -1219,18 +1277,25 @@
upgrade
- $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup >/dev/null
+ $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, store
+ added: revlog-compression-zstd, sparserevlog
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zstd zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zstd zlib zlib
+ compression-level: default default default
$ cat .hg/requires
dotencode
fncache
@@ -1242,18 +1307,25 @@
downgrade
- $ hg debugupgraderepo --run --no-backup > /dev/null
+ $ hg debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ removed: revlog-compression-zstd
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zlib zlib zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib
+ compression-level: default default default
$ cat .hg/requires
dotencode
fncache
@@ -1268,18 +1340,25 @@
> [format]
> revlog-compression=zstd
> EOF
- $ hg debugupgraderepo --run --no-backup > /dev/null
+ $ hg debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store
+ added: revlog-compression-zstd
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zstd zstd zlib
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zstd zstd zlib
+ compression-level: default default default
$ cat .hg/requires
dotencode
fncache
@@ -1296,19 +1375,28 @@
upgrade
- $ hg --config format.exp-use-side-data=yes debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" >/dev/null
+ $ hg --config format.exp-use-side-data=yes debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, store (no-zstd !)
+ preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
+ added: exp-sidedata-flag (zstd !)
+ added: exp-sidedata-flag, sparserevlog (no-zstd !)
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zstd zstd zlib (zstd !)
- compression: zlib zlib zlib (no-zstd !)
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib (no-zstd !)
+ compression: zstd zstd zlib (zstd !)
+ compression-level: default default default
$ cat .hg/requires
dotencode
exp-sidedata-flag
@@ -1325,19 +1413,27 @@
downgrade
- $ hg debugupgraderepo --config format.exp-use-side-data=no --run --no-backup > /dev/null
+ $ hg debugupgraderepo --config format.exp-use-side-data=no --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd !)
+ preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
+ removed: exp-sidedata-flag
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: no no no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zstd zstd zlib (zstd !)
- compression: zlib zlib zlib (no-zstd !)
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: no no no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib (no-zstd !)
+ compression: zstd zstd zlib (zstd !)
+ compression-level: default default default
$ cat .hg/requires
dotencode
fncache
@@ -1354,19 +1450,27 @@
> [format]
> exp-use-side-data=yes
> EOF
- $ hg debugupgraderepo --run --no-backup > /dev/null
+ $ hg debugupgraderepo --run --no-backup --quiet
+ upgrade will perform the following actions:
+
+ requirements
+ preserved: dotencode, fncache, generaldelta, revlogv1, sparserevlog, store (no-zstd !)
+ preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, revlogv1, sparserevlog, store (zstd !)
+ added: exp-sidedata-flag
+
$ hg debugformat -v
- format-variant repo config default
- fncache: yes yes yes
- dotencode: yes yes yes
- generaldelta: yes yes yes
- sparserevlog: yes yes yes
- sidedata: yes yes no
- copies-sdc: no no no
- plain-cl-delta: yes yes yes
- compression: zstd zstd zlib (zstd !)
- compression: zlib zlib zlib (no-zstd !)
- compression-level: default default default
+ format-variant repo config default
+ fncache: yes yes yes
+ dotencode: yes yes yes
+ generaldelta: yes yes yes
+ sparserevlog: yes yes yes
+ sidedata: yes yes no
+ persistent-nodemap: no no no
+ copies-sdc: no no no
+ plain-cl-delta: yes yes yes
+ compression: zlib zlib zlib (no-zstd !)
+ compression: zstd zstd zlib (zstd !)
+ compression-level: default default default
$ cat .hg/requires
dotencode
exp-sidedata-flag