diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -from node import hex, nullid, nullrev, short +from node import hex, bin, nullid, nullrev, short from lock import release from i18n import _, gettext import os, re, sys, difflib, time, tempfile @@ -1218,6 +1218,18 @@ def showconfig(ui, repo, *values, **opts ui.configsource(section, name, untrusted)) ui.write('%s=%s\n' % (sectname, value)) +def debugknown(ui, repopath, *ids, **opts): + """test whether node ids are known to a repo + + Every ID must be a full-length hex node id string. Returns a list of 0s and 1s + indicating unknown/known. + """ + repo = hg.repository(ui, repopath) + if not repo.capable('known'): + raise util.Abort("known() not supported by target repository") + flags = repo.known([bin(s) for s in ids]) + ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags]))) + def debugpushkey(ui, repopath, namespace, *keyinfo): '''access the pushkey key/value protocol @@ -4446,6 +4458,7 @@ table = { _('FILE')), "debugindexdot": (debugindexdot, [], _('FILE')), "debuginstall": (debuginstall, [], ''), + "debugknown": (debugknown, [], _('REPO ID...')), "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')), "debugrebuildstate": (debugrebuildstate, @@ -4810,6 +4823,7 @@ table = { } norepo = ("clone init version help debugcommands debugcomplete" - " debugdate debuginstall debugfsinfo debugpushkey debugwireargs") + " debugdate debuginstall debugfsinfo debugpushkey debugwireargs" + " debugknown") optionalrepo = ("identify paths serve showconfig debugancestor debugdag" " debugdata debugindex debugindexdot") diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -20,7 +20,8 @@ import weakref, errno, os, time, inspect propertycache = util.propertycache class localrepository(repo.repository): - capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey')) + capabilities = set(('lookup', 'changegroupsubset', 'branchmap', 'pushkey', + 'known')) supportedformats = set(('revlogv1', 'parentdelta')) supported = supportedformats | set(('store', 'fncache', 'shared', 'dotencode')) @@ -558,6 +559,10 @@ class localrepository(repo.repository): repo = (remote and remote.local()) and remote or self return repo[key].branch() + def known(self, nodes): + nm = self.changelog.nodemap + return [(n in nm) for n in nodes] + def local(self): return True diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -40,6 +40,14 @@ class wirerepository(repo.repository): except: self._abort(error.ResponseError(_("unexpected response:"), d)) + def known(self, nodes): + n = encodelist(nodes) + d = self._call("known", nodes=n) + try: + return [bool(int(f)) for f in d] + except: + self._abort(error.ResponseError(_("unexpected response:"), d)) + def branchmap(self): d = self._call("branchmap") try: @@ -198,7 +206,7 @@ def branches(repo, proto, nodes): return "".join(r) def capabilities(repo, proto): - caps = 'lookup changegroupsubset branchmap pushkey'.split() + caps = 'lookup changegroupsubset branchmap pushkey known'.split() if _allowstream(repo.ui): requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap @@ -255,6 +263,9 @@ def lookup(repo, proto, key): success = 0 return "%s %s\n" % (success, r) +def known(repo, proto, nodes): + return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes))) + def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally # sending raw binary nodes rather than utf-8-encoded hex @@ -373,6 +384,7 @@ commands = { 'debugwireargs': (debugwireargs, 'one two *'), 'heads': (heads, ''), 'hello': (hello, ''), + 'known': (known, 'nodes'), 'listkeys': (listkeys, 'namespace'), 'lookup': (lookup, 'key'), 'pushkey': (pushkey, 'namespace key old new'), diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t --- a/tests/test-debugcomplete.t +++ b/tests/test-debugcomplete.t @@ -79,6 +79,7 @@ Show debug commands if there are no othe debugindex debugindexdot debuginstall + debugknown debugpushkey debugrebuildstate debugrename @@ -220,6 +221,7 @@ Show all commands + options debugindex: format debugindexdot: debuginstall: + debugknown: debugpushkey: debugrebuildstate: rev debugrename: rev diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t --- a/tests/test-hgweb-commands.t +++ b/tests/test-hgweb-commands.t @@ -905,7 +905,7 @@ capabilities $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo 200 Script output follows - lookup changegroupsubset branchmap pushkey unbundle=HG10GZ,HG10BZ,HG10UN + lookup changegroupsubset branchmap pushkey known unbundle=HG10GZ,HG10BZ,HG10UN heads diff --git a/tests/test-known.t b/tests/test-known.t new file mode 100644 --- /dev/null +++ b/tests/test-known.t @@ -0,0 +1,37 @@ + += Test the known() protocol function = + +Create a test repository: + + $ hg init repo + $ cd repo + $ touch a ; hg add a ; hg ci -ma + $ touch b ; hg add b ; hg ci -mb + $ touch c ; hg add c ; hg ci -mc + $ hg log --template '{node}\n' + 991a3460af53952d10ec8a295d3d2cc2e5fa9690 + 0e067c57feba1a5694ca4844f05588bb1bf82342 + 3903775176ed42b1458a6281db4a0ccf4d9f287a + $ cd .. + +Test locally: + + $ hg debugknown repo 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a + 111 + $ hg debugknown repo 000a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0003775176ed42b1458a6281db4a0ccf4d9f287a + 010 + $ hg debugknown repo + + +Test via HTTP: + + $ hg serve -R repo -p $HGPORT -d --pid-file=hg.pid -E error.log -A access.log + $ cat hg.pid >> $DAEMON_PIDS + $ hg debugknown http://localhost:$HGPORT/ 991a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 3903775176ed42b1458a6281db4a0ccf4d9f287a + 111 + $ hg debugknown http://localhost:$HGPORT/ 000a3460af53952d10ec8a295d3d2cc2e5fa9690 0e067c57feba1a5694ca4844f05588bb1bf82342 0003775176ed42b1458a6281db4a0ccf4d9f287a + 010 + $ hg debugknown http://localhost:$HGPORT/ + + $ cat error.log +