[Updated] [++--- ] D9480: node: import symbols explicitly

joerg.sonnenberger (Joerg Sonnenberger) phabricator at mercurial-scm.org
Tue Dec 15 23:07:08 UTC 2020


joerg.sonnenberger updated this revision to Diff 24286.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D9480?vs=23966&id=24286

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D9480/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D9480

AFFECTED FILES
  contrib/dumprevlog
  contrib/undumprevlog
  hgext/absorb.py
  hgext/convert/git.py
  hgext/convert/hg.py
  hgext/fastannotate/context.py
  hgext/fastannotate/formatter.py
  hgext/git/dirstate.py
  hgext/git/gitlog.py
  hgext/git/index.py
  hgext/gpg.py
  hgext/histedit.py
  hgext/infinitepush/bundleparts.py
  hgext/infinitepush/store.py
  hgext/journal.py
  hgext/largefiles/lfcommands.py
  hgext/largefiles/lfutil.py
  hgext/lfs/__init__.py
  hgext/lfs/blobstore.py
  hgext/narrow/narrowcommands.py
  hgext/patchbomb.py
  hgext/rebase.py
  hgext/releasenotes.py
  hgext/remotefilelog/__init__.py
  hgext/remotefilelog/basepack.py
  hgext/remotefilelog/debugcommands.py
  hgext/remotefilelog/fileserverclient.py
  hgext/remotefilelog/shallowutil.py
  hgext/transplant.py
  hgext/uncommit.py
  mercurial/bundle2.py
  mercurial/bundlerepo.py
  mercurial/chgserver.py
  mercurial/copies.py
  mercurial/dagop.py
  mercurial/hg.py
  mercurial/keepalive.py
  mercurial/metadata.py
  mercurial/obsolete.py
  mercurial/obsutil.py
  mercurial/revlogutils/nodemap.py
  mercurial/revset.py
  mercurial/revsetlang.py
  mercurial/rewriteutil.py
  mercurial/shelve.py
  mercurial/simplemerge.py
  mercurial/sslutil.py
  mercurial/store.py
  mercurial/strip.py
  mercurial/subrepo.py
  mercurial/tagmerge.py
  mercurial/templatefilters.py
  mercurial/util.py
  tests/drawdag.py
  tests/test-parseindex2.py
  tests/test-revlog-raw.py
  tests/test-rust-ancestor.py
  tests/testlib/ext-sidedata.py

CHANGE DETAILS

diff --git a/tests/testlib/ext-sidedata.py b/tests/testlib/ext-sidedata.py
--- a/tests/testlib/ext-sidedata.py
+++ b/tests/testlib/ext-sidedata.py
@@ -10,9 +10,12 @@
 import hashlib
 import struct
 
+from mercurial.node import (
+    nullid,
+    nullrev,
+)
 from mercurial import (
     extensions,
-    node,
     requirements,
     revlog,
 )
@@ -41,7 +44,7 @@
     text = orig(self, nodeorrev, *args, **kwargs)
     if getattr(self, 'sidedatanocheck', False):
         return text
-    if nodeorrev != node.nullrev and nodeorrev != node.nullid:
+    if nodeorrev != nullrev and nodeorrev != nullid:
         sd = self.sidedata(nodeorrev)
         if len(text) != struct.unpack('>I', sd[sidedata.SD_TEST1])[0]:
             raise RuntimeError('text size mismatch')
diff --git a/tests/test-rust-ancestor.py b/tests/test-rust-ancestor.py
--- a/tests/test-rust-ancestor.py
+++ b/tests/test-rust-ancestor.py
@@ -2,10 +2,8 @@
 import sys
 import unittest
 
-from mercurial import (
-    error,
-    node,
-)
+from mercurial.node import wdirrev
+from mercurial import error
 
 from mercurial.testing import revlog as revlogtesting
 
@@ -150,7 +148,7 @@
         # WdirUnsupported directly
         idx = self.parseindex()
         with self.assertRaises(error.WdirUnsupported):
-            list(AncestorsIterator(idx, [node.wdirrev], -1, False))
+            list(AncestorsIterator(idx, [wdirrev], -1, False))
 
     def testheadrevs(self):
         idx = self.parseindex()
diff --git a/tests/test-revlog-raw.py b/tests/test-revlog-raw.py
--- a/tests/test-revlog-raw.py
+++ b/tests/test-revlog-raw.py
@@ -6,9 +6,9 @@
 import hashlib
 import sys
 
+from mercurial.node import nullid
 from mercurial import (
     encoding,
-    node,
     revlog,
     transaction,
     vfs,
@@ -93,7 +93,7 @@
     """
     nextrev = len(rlog)
     p1 = rlog.node(nextrev - 1)
-    p2 = node.nullid
+    p2 = nullid
     if isext:
         flags = revlog.REVIDX_EXTSTORED
     else:
@@ -127,7 +127,7 @@
     class dummychangegroup(object):
         @staticmethod
         def deltachunk(pnode):
-            pnode = pnode or node.nullid
+            pnode = pnode or nullid
             parentrev = rlog.rev(pnode)
             r = parentrev + 1
             if r >= len(rlog):
@@ -142,7 +142,7 @@
             return {
                 b'node': rlog.node(r),
                 b'p1': pnode,
-                b'p2': node.nullid,
+                b'p2': nullid,
                 b'cs': rlog.node(rlog.linkrev(r)),
                 b'flags': rlog.flags(r),
                 b'deltabase': rlog.node(deltaparent),
@@ -181,7 +181,7 @@
     dlog = newrevlog(destname, recreate=True)
     for r in rlog:
         p1 = rlog.node(r - 1)
-        p2 = node.nullid
+        p2 = nullid
         if r == 0 or (rlog.flags(r) & revlog.REVIDX_EXTSTORED):
             text = rlog.rawdata(r)
             cachedelta = None
diff --git a/tests/test-parseindex2.py b/tests/test-parseindex2.py
--- a/tests/test-parseindex2.py
+++ b/tests/test-parseindex2.py
@@ -12,11 +12,12 @@
 import unittest
 
 from mercurial.node import (
+    bin,
+    hex,
     nullid,
     nullrev,
 )
 from mercurial import (
-    node as nodemod,
     policy,
     pycompat,
 )
@@ -232,7 +233,7 @@
                 self.assertEqual(
                     ix[r[7]],
                     i,
-                    'Reverse lookup inconsistent for %r' % nodemod.hex(r[7]),
+                    'Reverse lookup inconsistent for %r' % hex(r[7]),
                 )
             except TypeError:
                 # pure version doesn't support this
@@ -255,7 +256,7 @@
             if rev == nullrev:
                 return b'\xff\xff\xff\xff'
             else:
-                return nodemod.bin('%08x' % rev)
+                return bin('%08x' % rev)
 
         def appendrev(p1, p2=nullrev):
             # node won't matter for this test, let's just make sure
diff --git a/tests/drawdag.py b/tests/drawdag.py
--- a/tests/drawdag.py
+++ b/tests/drawdag.py
@@ -86,11 +86,11 @@
 import itertools
 import re
 
+from mercurial.node import nullid
 from mercurial.i18n import _
 from mercurial import (
     context,
     error,
-    node,
     obsolete,
     pycompat,
     registrar,
@@ -299,7 +299,7 @@
         self._added = added
         self._parents = parentctxs
         while len(self._parents) < 2:
-            self._parents.append(repo[node.nullid])
+            self._parents.append(repo[nullid])
 
     def filectx(self, key):
         return simplefilectx(key, self._added[key])
@@ -388,7 +388,7 @@
         content = content.replace(br'\n', b'\n').replace(br'\1', b'\1')
         files[name][path] = content
 
-    committed = {None: node.nullid}  # {name: node}
+    committed = {None: nullid}  # {name: node}
 
     # for leaf nodes, try to find existing nodes in repo
     for name, parents in edges.items():
diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -42,12 +42,12 @@
     open,
     setattr,
 )
+from .node import hex
 from hgdemandimport import tracing
 from . import (
     encoding,
     error,
     i18n,
-    node as nodemod,
     policy,
     pycompat,
     urllibcompat,
@@ -254,7 +254,7 @@
     def __getitem__(self, key):
         if key not in DIGESTS:
             raise error.Abort(_(b'unknown digest type: %s') % k)
-        return nodemod.hex(self._hashes[key].digest())
+        return hex(self._hashes[key].digest())
 
     def __iter__(self):
         return iter(self._hashes)
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -12,10 +12,10 @@
 import time
 
 from .i18n import _
+from .node import hex
 from . import (
     encoding,
     error,
-    node,
     pycompat,
     registrar,
     smartset,
@@ -280,7 +280,7 @@
     """Any text. Convert a binary Mercurial node identifier into
     its long hexadecimal representation.
     """
-    return node.hex(text)
+    return hex(text)
 
 
 @templatefilter(b'hgdate', intype=templateutil.date)
diff --git a/mercurial/tagmerge.py b/mercurial/tagmerge.py
--- a/mercurial/tagmerge.py
+++ b/mercurial/tagmerge.py
@@ -76,6 +76,7 @@
 from .i18n import _
 from .node import (
     hex,
+    nullhex,
     nullid,
 )
 from . import (
@@ -83,8 +84,6 @@
     util,
 )
 
-hexnullid = hex(nullid)
-
 
 def readtagsformerge(ui, repo, lines, fn=b'', keeplinenums=False):
     """read the .hgtags file into a structure that is suitable for merging
@@ -246,8 +245,8 @@
         pnlosttagset = basetagset - pntagset
         for t in pnlosttagset:
             pntags[t] = basetags[t]
-            if pntags[t][-1][0] != hexnullid:
-                pntags[t].append([hexnullid, None])
+            if pntags[t][-1][0] != nullhex:
+                pntags[t].append([nullhex, None])
 
     conflictedtags = []  # for reporting purposes
     mergedtags = util.sortdict(p1tags)
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -18,6 +18,12 @@
 import xml.dom.minidom
 
 from .i18n import _
+from .node import (
+    bin,
+    hex,
+    nullid,
+    short,
+)
 from . import (
     cmdutil,
     encoding,
@@ -26,7 +32,6 @@
     logcmdutil,
     match as matchmod,
     merge as merge,
-    node,
     pathutil,
     phases,
     pycompat,
@@ -61,7 +66,7 @@
 
 def _getstorehashcachename(remotepath):
     '''get a unique filename for the store hash cache of a remote repository'''
-    return node.hex(hashutil.sha1(_expandedabspath(remotepath)).digest())[0:12]
+    return hex(hashutil.sha1(_expandedabspath(remotepath)).digest())[0:12]
 
 
 class SubrepoAbort(error.Abort):
@@ -508,7 +513,7 @@
         yield b'# %s\n' % _expandedabspath(remotepath)
         vfs = self._repo.vfs
         for relname in filelist:
-            filehash = node.hex(hashutil.sha1(vfs.tryread(relname)).digest())
+            filehash = hex(hashutil.sha1(vfs.tryread(relname)).digest())
             yield b'%s = %s\n' % (relname, filehash)
 
     @propertycache
@@ -601,11 +606,11 @@
     @annotatesubrepoerror
     def diff(self, ui, diffopts, node2, match, prefix, **opts):
         try:
-            node1 = node.bin(self._state[1])
+            node1 = bin(self._state[1])
             # We currently expect node2 to come from substate and be
             # in hex format
             if node2 is not None:
-                node2 = node.bin(node2)
+                node2 = bin(node2)
             logcmdutil.diffordiffstat(
                 ui,
                 self._repo,
@@ -669,7 +674,7 @@
         n = self._repo.commit(text, user, date)
         if not n:
             return self._repo[b'.'].hex()  # different version checked out
-        return node.hex(n)
+        return hex(n)
 
     @annotatesubrepoerror
     def phase(self, state):
@@ -680,7 +685,7 @@
         # we can't fully delete the repository as it may contain
         # local-only history
         self.ui.note(_(b'removing subrepo %s\n') % subrelpath(self))
-        hg.clean(self._repo, node.nullid, False)
+        hg.clean(self._repo, nullid, False)
 
     def _get(self, state):
         source, revision, kind = state
@@ -1019,7 +1024,7 @@
                 # explicit warning.
                 msg = _(b"subrepo '%s' is hidden in revision %s") % (
                     self._relpath,
-                    node.short(self._ctx.node()),
+                    short(self._ctx.node()),
                 )
 
                 if onpush:
@@ -1032,7 +1037,7 @@
             # don't treat this as an error for `hg verify`.
             msg = _(b"subrepo '%s' not found in revision %s") % (
                 self._relpath,
-                node.short(self._ctx.node()),
+                short(self._ctx.node()),
             )
 
             if onpush:
diff --git a/mercurial/strip.py b/mercurial/strip.py
--- a/mercurial/strip.py
+++ b/mercurial/strip.py
@@ -2,6 +2,7 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import nullid
 from . import (
     bookmarks as bookmarksmod,
     cmdutil,
@@ -9,7 +10,6 @@
     hg,
     lock as lockmod,
     mergestate as mergestatemod,
-    node as nodemod,
     pycompat,
     registrar,
     repair,
@@ -17,7 +17,6 @@
     util,
 )
 
-nullid = nodemod.nullid
 release = lockmod.release
 
 cmdtable = {}
diff --git a/mercurial/store.py b/mercurial/store.py
--- a/mercurial/store.py
+++ b/mercurial/store.py
@@ -14,11 +14,11 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import hex
 from . import (
     changelog,
     error,
     manifest,
-    node,
     policy,
     pycompat,
     util,
@@ -273,7 +273,7 @@
 
 
 def _hashencode(path, dotencode):
-    digest = node.hex(hashutil.sha1(path).digest())
+    digest = hex(hashutil.sha1(path).digest())
     le = lowerencode(path[5:]).split(b'/')  # skips prefix 'data/' or 'meta/'
     parts = _auxencode(le, dotencode)
     basename = parts[-1]
diff --git a/mercurial/sslutil.py b/mercurial/sslutil.py
--- a/mercurial/sslutil.py
+++ b/mercurial/sslutil.py
@@ -16,10 +16,10 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import hex
 from . import (
     encoding,
     error,
-    node,
     pycompat,
     util,
 )
@@ -762,9 +762,9 @@
     # If a certificate fingerprint is pinned, use it and only it to
     # validate the remote cert.
     peerfingerprints = {
-        b'sha1': node.hex(hashutil.sha1(peercert).digest()),
-        b'sha256': node.hex(hashlib.sha256(peercert).digest()),
-        b'sha512': node.hex(hashlib.sha512(peercert).digest()),
+        b'sha1': hex(hashutil.sha1(peercert).digest()),
+        b'sha256': hex(hashlib.sha256(peercert).digest()),
+        b'sha512': hex(hashlib.sha512(peercert).digest()),
     }
 
     def fmtfingerprint(s):
diff --git a/mercurial/simplemerge.py b/mercurial/simplemerge.py
--- a/mercurial/simplemerge.py
+++ b/mercurial/simplemerge.py
@@ -19,10 +19,10 @@
 from __future__ import absolute_import
 
 from .i18n import _
+from .node import nullid
 from . import (
     error,
     mdiff,
-    node as nodemod,
     pycompat,
     util,
 )
@@ -452,7 +452,7 @@
 def is_not_null(ctx):
     if not util.safehasattr(ctx, "node"):
         return False
-    return ctx.node() != nodemod.nullid
+    return ctx.node() != nullid
 
 
 def _mergediff(m3, name_a, name_b, name_base):
diff --git a/mercurial/shelve.py b/mercurial/shelve.py
--- a/mercurial/shelve.py
+++ b/mercurial/shelve.py
@@ -29,6 +29,12 @@
 
 from .i18n import _
 from .pycompat import open
+from .node import (
+    bin,
+    hex,
+    nullid,
+    nullrev,
+)
 from . import (
     bookmarks,
     bundle2,
@@ -43,7 +49,6 @@
     mdiff,
     merge,
     mergestate as mergestatemod,
-    node as nodemod,
     patch,
     phases,
     pycompat,
@@ -196,11 +201,11 @@
     def _verifyandtransform(cls, d):
         """Some basic shelvestate syntactic verification and transformation"""
         try:
-            d[b'originalwctx'] = nodemod.bin(d[b'originalwctx'])
-            d[b'pendingctx'] = nodemod.bin(d[b'pendingctx'])
-            d[b'parents'] = [nodemod.bin(h) for h in d[b'parents'].split(b' ')]
+            d[b'originalwctx'] = bin(d[b'originalwctx'])
+            d[b'pendingctx'] = bin(d[b'pendingctx'])
+            d[b'parents'] = [bin(h) for h in d[b'parents'].split(b' ')]
             d[b'nodestoremove'] = [
-                nodemod.bin(h) for h in d[b'nodestoremove'].split(b' ')
+                bin(h) for h in d[b'nodestoremove'].split(b' ')
             ]
         except (ValueError, TypeError, KeyError) as err:
             raise error.CorruptedState(pycompat.bytestr(err))
@@ -296,13 +301,13 @@
     ):
         info = {
             b"name": name,
-            b"originalwctx": nodemod.hex(originalwctx.node()),
-            b"pendingctx": nodemod.hex(pendingctx.node()),
+            b"originalwctx": hex(originalwctx.node()),
+            b"pendingctx": hex(pendingctx.node()),
             b"parents": b' '.join(
-                [nodemod.hex(p) for p in repo.dirstate.parents()]
+                [hex(p) for p in repo.dirstate.parents()]
             ),
             b"nodestoremove": b' '.join(
-                [nodemod.hex(n) for n in nodestoremove]
+                [hex(n) for n in nodestoremove]
             ),
             b"branchtorestore": branchtorestore,
             b"keep": cls._keep if keep else cls._nokeep,
@@ -400,7 +405,7 @@
     """return all mutable ancestors for ctx (included)
 
     Much faster than the revset ancestors(ctx) & draft()"""
-    seen = {nodemod.nullrev}
+    seen = {nullrev}
     visit = collections.deque()
     visit.append(ctx)
     while visit:
@@ -464,7 +469,7 @@
 
 
 def _shelvecreatedcommit(repo, node, name, match):
-    info = {b'node': nodemod.hex(node)}
+    info = {b'node': hex(node)}
     shelvedfile(repo, name, b'shelve').writeinfo(info)
     bases = list(mutableancestors(repo[node]))
     shelvedfile(repo, name, b'hg').writebundle(bases, node)
@@ -501,7 +506,7 @@
     parent = parents[0]
     origbranch = wctx.branch()
 
-    if parent.node() != nodemod.nullid:
+    if parent.node() != nullid:
         desc = b"changes to: %s" % parent.description().split(b'\n', 1)[0]
     else:
         desc = b'(changes in empty repository)'
@@ -816,7 +821,7 @@
         pendingctx = state.pendingctx
 
         with repo.dirstate.parentchange():
-            repo.setparents(state.pendingctx.node(), nodemod.nullid)
+            repo.setparents(state.pendingctx.node(), nullid)
             repo.dirstate.write(repo.currenttransaction())
 
         targetphase = phases.internal
@@ -825,7 +830,7 @@
         overrides = {(b'phases', b'new-commit'): targetphase}
         with repo.ui.configoverride(overrides, b'unshelve'):
             with repo.dirstate.parentchange():
-                repo.setparents(state.parents[0], nodemod.nullid)
+                repo.setparents(state.parents[0], nullid)
                 newnode, ispartialunshelve = _createunshelvectx(
                     ui, repo, shelvectx, basename, interactive, opts
                 )
@@ -901,7 +906,7 @@
         # We might not strip the unbundled changeset, so we should keep track of
         # the unshelve node in case we need to reuse it (eg: unshelve --keep)
         if node is None:
-            info = {b'node': nodemod.hex(shelvectx.node())}
+            info = {b'node': hex(shelvectx.node())}
             shelvedfile(repo, basename, b'shelve').writeinfo(info)
     else:
         shelvectx = repo[node]
@@ -1020,7 +1025,7 @@
             raise error.ConflictResolutionRequired(b'unshelve')
 
         with repo.dirstate.parentchange():
-            repo.setparents(tmpwctx.node(), nodemod.nullid)
+            repo.setparents(tmpwctx.node(), nullid)
             newnode, ispartialunshelve = _createunshelvectx(
                 ui, repo, shelvectx, basename, interactive, opts
             )
diff --git a/mercurial/rewriteutil.py b/mercurial/rewriteutil.py
--- a/mercurial/rewriteutil.py
+++ b/mercurial/rewriteutil.py
@@ -10,10 +10,13 @@
 import re
 
 from .i18n import _
+from .node import (
+    hex,
+    nullrev,
+)
 
 from . import (
     error,
-    node,
     obsolete,
     obsutil,
     revset,
@@ -30,7 +33,7 @@
 
     Make sure this function is called after taking the lock.
     """
-    if node.nullrev in revs:
+    if nullrev in revs:
         msg = _(b"cannot %s null changeset") % action
         hint = _(b"no changeset checked out")
         raise error.InputError(msg, hint=hint)
@@ -113,7 +116,7 @@
         if len(successors) == 1 and len(successors[0]) == 1:
             successor = successors[0][0]
             if successor is not None:
-                newhash = node.hex(successor)
+                newhash = hex(successor)
                 commitmsg = commitmsg.replace(h, newhash[: len(h)])
             else:
                 repo.ui.note(
diff --git a/mercurial/revsetlang.py b/mercurial/revsetlang.py
--- a/mercurial/revsetlang.py
+++ b/mercurial/revsetlang.py
@@ -11,9 +11,9 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import hex
 from . import (
     error,
-    node,
     parser,
     pycompat,
     smartset,
@@ -687,7 +687,7 @@
         parse(arg)  # make sure syntax errors are confined
         return b'(%s)' % arg
     elif c == b'n':
-        return _quote(node.hex(arg))
+        return _quote(hex(arg))
     elif c == b'b':
         try:
             return _quote(arg.branch())
@@ -707,7 +707,7 @@
     elif t == b's':
         return b"_list(%s)" % _quote(b"\0".join(s))
     elif t == b'n':
-        return b"_hexlist('%s')" % b"\0".join(node.hex(a) for a in s)
+        return b"_hexlist('%s')" % b"\0".join(hex(a) for a in s)
     elif t == b'b':
         try:
             return b"_list('%s')" % b"\0".join(a.branch() for a in s)
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -11,6 +11,11 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import (
+    bin,
+    nullrev,
+    wdirrev,
+)
 from . import (
     dagop,
     destutil,
@@ -20,7 +25,6 @@
     grep as grepmod,
     hbisect,
     match as matchmod,
-    node,
     obsolete as obsmod,
     obsutil,
     pathutil,
@@ -55,7 +59,7 @@
 fullreposet = smartset.fullreposet
 
 # revisions not included in all(), but populated if specified
-_virtualrevs = (node.nullrev, node.wdirrev)
+_virtualrevs = (nullrev, wdirrev)
 
 # Constants for ordering requirement, used in getset():
 #
@@ -177,9 +181,9 @@
 def _makerangeset(repo, subset, m, n, order):
     if m == n:
         r = baseset([m])
-    elif n == node.wdirrev:
+    elif n == wdirrev:
         r = spanset(repo, m, len(repo)) + baseset([n])
-    elif m == node.wdirrev:
+    elif m == wdirrev:
         r = baseset([m]) + spanset(repo, repo.changelog.tiprev(), n - 1)
     elif m < n:
         r = spanset(repo, m, n + 1)
@@ -597,7 +601,7 @@
                 bms.add(repo[bmrev].rev())
     else:
         bms = {repo[r].rev() for r in repo._bookmarks.values()}
-    bms -= {node.nullrev}
+    bms -= {nullrev}
     return subset & bms
 
 
@@ -722,7 +726,6 @@
     cs = set()
     pr = repo.changelog.parentrevs
     minrev = parentset.min()
-    nullrev = node.nullrev
     for r in subset:
         if r <= minrev:
             continue
@@ -1396,7 +1399,7 @@
                     b'_matchfiles expected at most one revision'
                 )
             if value == b'':  # empty means working directory
-                rev = node.wdirrev
+                rev = wdirrev
             else:
                 rev = value
         elif prefix == b'd:':
@@ -1416,7 +1419,6 @@
     # This directly read the changelog data as creating changectx for all
     # revisions is quite expensive.
     getfiles = repo.changelog.readfiles
-    wdirrev = node.wdirrev
 
     def matches(x):
         if x == wdirrev:
@@ -1490,15 +1492,15 @@
         order = followorder
     inputset = getset(repo, fullreposet(repo), x, order=order)
     wdirparents = None
-    if node.wdirrev in inputset:
+    if wdirrev in inputset:
         # a bit slower, but not common so good enough for now
         wdirparents = [p.rev() for p in repo[None].parents()]
         inputset = set(inputset)
-        inputset.discard(node.wdirrev)
+        inputset.discard(wdirrev)
     heads = repo.changelog.headrevs(inputset)
     if wdirparents is not None:
         heads.difference_update(wdirparents)
-        heads.add(node.wdirrev)
+        heads.add(wdirrev)
     heads = baseset(heads)
     return subset & heads
 
@@ -1598,7 +1600,6 @@
     # i18n: "merge" is a keyword
     getargs(x, 0, 0, _(b"merge takes no arguments"))
     cl = repo.changelog
-    nullrev = node.nullrev
 
     def ismerge(r):
         try:
@@ -1692,7 +1693,7 @@
             if name not in ns.deprecated:
                 names.update(repo[n].rev() for n in ns.nodes(repo, name))
 
-    names -= {node.nullrev}
+    names -= {nullrev}
     return subset & names
 
 
@@ -1705,9 +1706,9 @@
     n = getstring(l[0], _(b"id requires a string"))
     if len(n) == 40:
         try:
-            rn = repo.changelog.rev(node.bin(n))
+            rn = repo.changelog.rev(bin(n))
         except error.WdirUnsupported:
-            rn = node.wdirrev
+            rn = wdirrev
         except (LookupError, TypeError):
             rn = None
     else:
@@ -1719,7 +1720,7 @@
         except LookupError:
             pass
         except error.WdirUnsupported:
-            rn = node.wdirrev
+            rn = wdirrev
 
     if rn is None:
         return baseset()
@@ -1864,7 +1865,7 @@
             ps.add(cl.parentrevs(r)[0])
         except error.WdirUnsupported:
             ps.add(repo[r].p1().rev())
-    ps -= {node.nullrev}
+    ps -= {nullrev}
     # XXX we should turn this into a baseset instead of a set, smartset may do
     # some optimizations from the fact this is a baseset.
     return subset & ps
@@ -1892,7 +1893,7 @@
             parents = repo[r].parents()
             if len(parents) == 2:
                 ps.add(parents[1])
-    ps -= {node.nullrev}
+    ps -= {nullrev}
     # XXX we should turn this into a baseset instead of a set, smartset may do
     # some optimizations from the fact this is a baseset.
     return subset & ps
@@ -1919,7 +1920,7 @@
                 up(parentrevs(r))
             except error.WdirUnsupported:
                 up(p.rev() for p in repo[r].parents())
-    ps -= {node.nullrev}
+    ps -= {nullrev}
     return subset & ps
 
 
@@ -1994,7 +1995,7 @@
         else:
             try:
                 parents = cl.parentrevs(r)
-                if parents[1] != node.nullrev:
+                if parents[1] != nullrev:
                     ps.add(parents[1])
             except error.WdirUnsupported:
                 parents = repo[r].parents()
@@ -2567,8 +2568,8 @@
     """Working directory. (EXPERIMENTAL)"""
     # i18n: "wdir" is a keyword
     getargs(x, 0, 0, _(b"wdir takes no arguments"))
-    if node.wdirrev in subset or isinstance(subset, fullreposet):
-        return baseset([node.wdirrev])
+    if wdirrev in subset or isinstance(subset, fullreposet):
+        return baseset([wdirrev])
     return baseset()
 
 
@@ -2638,7 +2639,7 @@
     if not s:
         return baseset()
     cl = repo.changelog
-    ls = [cl.rev(node.bin(r)) for r in s.split(b'\0')]
+    ls = [cl.rev(bin(r)) for r in s.split(b'\0')]
     s = subset
     return baseset([r for r in ls if r in s])
 
diff --git a/mercurial/revlogutils/nodemap.py b/mercurial/revlogutils/nodemap.py
--- a/mercurial/revlogutils/nodemap.py
+++ b/mercurial/revlogutils/nodemap.py
@@ -14,10 +14,10 @@
 import struct
 
 from ..i18n import _
+from ..node import hex
 
 from .. import (
     error,
-    node as nodemod,
     util,
 )
 
@@ -278,7 +278,7 @@
     """return a new unique identifier.
 
     The identifier is random and composed of ascii characters."""
-    return nodemod.hex(os.urandom(ID_SIZE))
+    return hex(os.urandom(ID_SIZE))
 
 
 class NodeMapDocket(object):
@@ -461,8 +461,8 @@
     """
     root = Block()
     for rev in range(len(index)):
-        hex = nodemod.hex(index[rev][7])
-        _insert_into_block(index, 0, root, rev, hex)
+        current_hex = hex(index[rev][7])
+        _insert_into_block(index, 0, root, rev, current_hex)
     return root
 
 
@@ -470,8 +470,8 @@
     """consume"""
     changed = 0
     for rev in range(last_rev + 1, len(index)):
-        hex = nodemod.hex(index[rev][7])
-        changed += _insert_into_block(index, 0, root, rev, hex)
+        current_hex = hex(index[rev][7])
+        changed += _insert_into_block(index, 0, root, rev, current_hex)
     return changed, root
 
 
@@ -500,7 +500,7 @@
     else:
         # collision with a previously unique prefix, inserting new
         # vertices to fit both entry.
-        other_hex = nodemod.hex(index[entry][7])
+        other_hex = hex(index[entry][7])
         other_rev = entry
         new = Block()
         block[hex_digit] = new
@@ -604,7 +604,7 @@
             ret = 1
         else:
             all_revs.remove(r)
-        nm_rev = _find_node(root, nodemod.hex(index[r][7]))
+        nm_rev = _find_node(root, hex(index[r][7]))
         if nm_rev is None:
             msg = b"  revision node does not match any entries: %d\n" % r
             ui.write_err(msg)
diff --git a/mercurial/obsutil.py b/mercurial/obsutil.py
--- a/mercurial/obsutil.py
+++ b/mercurial/obsutil.py
@@ -10,11 +10,14 @@
 import re
 
 from .i18n import _
+from .node import (
+    hex,
+    short,
+)
 from . import (
     diffutil,
     encoding,
     error,
-    node as nodemod,
     phases,
     pycompat,
     util,
@@ -957,13 +960,13 @@
     elif fate == b'diverged':
         return filteredmsgtable[b'diverged'] % changeid
     elif fate == b'superseded':
-        single_successor = nodemod.short(successors[0][0])
+        single_successor = short(successors[0][0])
         return filteredmsgtable[b'superseded'] % (changeid, single_successor)
     elif fate == b'superseded_split':
 
         succs = []
         for node_id in successors[0]:
-            succs.append(nodemod.short(node_id))
+            succs.append(short(node_id))
 
         if len(succs) <= 2:
             fmtsuccs = b', '.join(succs)
@@ -1040,7 +1043,7 @@
                     b'instability': b'content-divergent',
                     b'divergentnodes': divnodes,
                     b'reason': b'predecessor',
-                    b'node': nodemod.hex(dset[b'commonpredecessor']),
+                    b'node': hex(dset[b'commonpredecessor']),
                 }
             )
     return result
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -74,10 +74,14 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import (
+    bin,
+    hex,
+    nullid,
+)
 from . import (
     encoding,
     error,
-    node,
     obsutil,
     phases,
     policy,
@@ -235,7 +239,7 @@
             parents = ()
         if parents is not None:
             try:
-                parents = tuple(node.bin(p) for p in parents)
+                parents = tuple(bin(p) for p in parents)
                 # if parent content is not a nodeid, drop the data
                 for p in parents:
                     if len(p) != 20:
@@ -262,7 +266,7 @@
             # mark that we explicitly recorded no parents
             metadata[b'p0'] = b''
         for i, p in enumerate(parents, 1):
-            metadata[b'p%i' % i] = node.hex(p)
+            metadata[b'p%i' % i] = hex(p)
     metadata = _fm0encodemeta(metadata)
     numsuc = len(sucs)
     format = _fm0fixed + (_fm0node * numsuc)
@@ -529,7 +533,7 @@
     subtle handling.
     """
     for mark in markers:
-        if node.nullid in mark[1]:
+        if nullid in mark[1]:
             raise error.Abort(
                 _(
                     b'bad obsolescence marker detected: '
@@ -639,7 +643,7 @@
                     raise ValueError(succ)
         if prec in succs:
             raise ValueError(
-                'in-marker cycle with %s' % pycompat.sysstr(node.hex(prec))
+                'in-marker cycle with %s' % pycompat.sysstr(hex(prec))
             )
 
         metadata = tuple(sorted(pycompat.iteritems(metadata)))
@@ -1031,7 +1035,7 @@
         folddigest.update(p.node())
     # Since fold only has to compete against fold for the same successors, it
     # seems fine to use a small ID. Smaller ID save space.
-    return node.hex(folddigest.digest())[:8]
+    return hex(folddigest.digest())[:8]
 
 
 def createmarkers(
diff --git a/mercurial/metadata.py b/mercurial/metadata.py
--- a/mercurial/metadata.py
+++ b/mercurial/metadata.py
@@ -11,9 +11,12 @@
 import multiprocessing
 import struct
 
+from .node import (
+    nullid,
+    nullrev,
+)
 from . import (
     error,
-    node,
     pycompat,
     util,
 )
@@ -239,11 +242,11 @@
     """compute the files changed by a revision"""
     p1 = ctx.p1()
     p2 = ctx.p2()
-    if p1.rev() == node.nullrev and p2.rev() == node.nullrev:
+    if p1.rev() == nullrev and p2.rev() == nullrev:
         return _process_root(ctx)
-    elif p1.rev() != node.nullrev and p2.rev() == node.nullrev:
+    elif p1.rev() != nullrev and p2.rev() == nullrev:
         return _process_linear(p1, ctx)
-    elif p1.rev() == node.nullrev and p2.rev() != node.nullrev:
+    elif p1.rev() == nullrev and p2.rev() != nullrev:
         # In the wild, one can encounter changeset where p1 is null but p2 is not
         return _process_linear(p1, ctx, parent=2)
     elif p1.rev() == p2.rev():
@@ -423,7 +426,7 @@
         p1_ctx.node(), p2_ctx.node()
     )
     if not cahs:
-        cahs = [node.nullrev]
+        cahs = [nullrev]
     mas = [ctx.repo()[r].manifest() for r in cahs]
 
     copy_candidates = []
@@ -560,7 +563,7 @@
         p2n = p2.node()
         cahs = ctx.repo().changelog.commonancestorsheads(p1n, p2n)
         if not cahs:
-            cahs = [node.nullrev]
+            cahs = [nullrev]
         return [ctx.repo()[r].manifest() for r in cahs]
 
     def deletionfromparent(f):
@@ -597,7 +600,7 @@
         if f in ctx:
             fctx = ctx[f]
             parents = fctx._filelog.parents(fctx._filenode)
-            if parents[1] != node.nullid:
+            if parents[1] != nullid:
                 merged.append(f)
     return merged
 
diff --git a/mercurial/keepalive.py b/mercurial/keepalive.py
--- a/mercurial/keepalive.py
+++ b/mercurial/keepalive.py
@@ -93,8 +93,8 @@
 
 from .i18n import _
 from .pycompat import getattr
+from .node import hex
 from . import (
-    node,
     pycompat,
     urllibcompat,
     util,
@@ -723,7 +723,7 @@
     foo = fo.read()
     fo.close()
     m = md5(foo)
-    print(format % (b'normal urllib', node.hex(m.digest())))
+    print(format % (b'normal urllib', hex(m.digest())))
 
     # now install the keepalive handler and try again
     opener = urlreq.buildopener(HTTPHandler())
@@ -733,7 +733,7 @@
     foo = fo.read()
     fo.close()
     m = md5(foo)
-    print(format % (b'keepalive read', node.hex(m.digest())))
+    print(format % (b'keepalive read', hex(m.digest())))
 
     fo = urlreq.urlopen(url)
     foo = b''
@@ -745,7 +745,7 @@
             break
     fo.close()
     m = md5(foo)
-    print(format % (b'keepalive readline', node.hex(m.digest())))
+    print(format % (b'keepalive readline', hex(m.digest())))
 
 
 def comp(N, url):
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -14,7 +14,12 @@
 import stat
 
 from .i18n import _
-from .node import nullid
+from .node import (
+    hex,
+    nullhex,
+    nullid,
+    short,
+)
 from .pycompat import getattr
 
 from . import (
@@ -35,7 +40,6 @@
     merge as mergemod,
     mergestate as mergestatemod,
     narrowspec,
-    node,
     phases,
     pycompat,
     requirements,
@@ -108,7 +112,7 @@
                 raise error.Abort(_(b"dirstate branch not accessible"))
             branch = lrepo.dirstate.branch()
         if branch in branchmap:
-            revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
+            revs.extend(hex(r) for r in reversed(branchmap[branch]))
             return True
         else:
             return False
@@ -762,8 +766,8 @@
                         },
                     ).result()
 
-                if rootnode != node.nullid:
-                    sharepath = os.path.join(sharepool, node.hex(rootnode))
+                if rootnode != nullid:
+                    sharepath = os.path.join(sharepool, hex(rootnode))
                 else:
                     ui.status(
                         _(
@@ -780,7 +784,7 @@
                 )
         elif sharenamemode == b'remote':
             sharepath = os.path.join(
-                sharepool, node.hex(hashutil.sha1(source).digest())
+                sharepool, hex(hashutil.sha1(source).digest())
             )
         else:
             raise error.Abort(
@@ -873,7 +877,7 @@
             # into it
             destpeer = peer(srcrepo, peeropts, dest)
             srcrepo.hook(
-                b'outgoing', source=b'clone', node=node.hex(node.nullid)
+                b'outgoing', source=b'clone', node=nullhex
             )
         else:
             try:
@@ -1379,7 +1383,7 @@
             except Exception:
                 repo.ui.warn(
                     _(b'.hgsubstate is corrupt in revision %s\n')
-                    % node.short(ctx.node())
+                    % short(ctx.node())
                 )
 
     return ret
diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -11,10 +11,10 @@
 
 from .node import nullrev
 from .thirdparty import attr
+from .node import nullrev
 from . import (
     error,
     mdiff,
-    node,
     patch,
     pycompat,
     scmutil,
@@ -77,7 +77,7 @@
         pdepth = curdepth + 1
         if foundnew and pdepth < stopdepth:
             for prev in pfunc(currev):
-                if prev != node.nullrev:
+                if prev != nullrev:
                     heapq.heappush(pendingheap, (heapsign * prev, pdepth))
 
 
@@ -183,7 +183,6 @@
 
     cl = repo.changelog
     first = revs.min()
-    nullrev = node.nullrev
     if first == nullrev:
         # Are there nodes with a null first parent and a non-null
         # second one? Maybe. Do we care? Probably not.
@@ -206,7 +205,6 @@
 def _builddescendantsmap(repo, startrev, followfirst):
     """Build map of 'rev -> child revs', offset from startrev"""
     cl = repo.changelog
-    nullrev = node.nullrev
     descmap = [[] for _rev in pycompat.xrange(startrev, len(cl))]
     for currev in cl.revs(startrev + 1):
         p1rev, p2rev = cl.parentrevs(currev)
@@ -971,7 +969,7 @@
             if rev == currentrev:  # only display stuff in rev
                 gr[0].append(rev)
             gr[1].remove(rev)
-            parents = [p for p in parentsfunc(rev) if p > node.nullrev]
+            parents = [p for p in parentsfunc(rev) if p > nullrev]
             gr[1].update(parents)
             for p in parents:
                 if p not in pendingset:
@@ -1030,7 +1028,7 @@
     the input set.
     """
     headrevs = set(revs)
-    parents = {node.nullrev}
+    parents = {nullrev}
     up = parents.update
 
     for rev in revs:
@@ -1104,7 +1102,7 @@
             visit.append(-rev - 1)
 
             for prev in parentsfn(rev):
-                if prev == node.nullrev or prev not in revs or prev in finished:
+                if prev == nullrev or prev not in revs or prev in finished:
                     continue
 
                 visit.append(prev)
diff --git a/mercurial/copies.py b/mercurial/copies.py
--- a/mercurial/copies.py
+++ b/mercurial/copies.py
@@ -11,11 +11,13 @@
 import os
 
 from .i18n import _
-
+from .node import (
+    nullid,
+    nullrev,
+)
 
 from . import (
     match as matchmod,
-    node,
     pathutil,
     policy,
     pycompat,
@@ -147,7 +149,7 @@
     # optimization, since the ctx.files() for a merge commit is not correct for
     # this comparison.
     forwardmissingmatch = match
-    if b.p1() == a and b.p2().node() == node.nullid:
+    if b.p1() == a and b.p2().node() == nullid:
         filesmatcher = matchmod.exact(b.files())
         forwardmissingmatch = matchmod.intersectmatchers(match, filesmatcher)
     missing = _computeforwardmissing(a, b, match=forwardmissingmatch)
@@ -233,7 +235,7 @@
             else:
                 raw = None
             value = (p1, p2, raw)
-            if p1 != node.nullrev and p2 != node.nullrev:
+            if p1 != nullrev and p2 != nullrev:
                 # XXX some case we over cache, IGNORE
                 merge_caches[rev] = value
             return value
@@ -250,7 +252,7 @@
             if flags(rev) & HASCOPIESINFO:
                 changes = changelogrevision(rev).changes
             value = (p1, p2, changes)
-            if p1 != node.nullrev and p2 != node.nullrev:
+            if p1 != nullrev and p2 != nullrev:
                 # XXX some case we over cache, IGNORE
                 merge_caches[rev] = value
             return value
@@ -277,7 +279,7 @@
 
 
 def _changesetforwardcopies(a, b, match):
-    if a.rev() in (node.nullrev, b.rev()):
+    if a.rev() in (nullrev, b.rev()):
         return {}
 
     repo = a.repo().unfiltered()
@@ -290,7 +292,7 @@
     roots = set()
     for r in missingrevs:
         for p in cl.parentrevs(r):
-            if p == node.nullrev:
+            if p == nullrev:
                 continue
             if p not in children:
                 children[p] = [r]
@@ -494,7 +496,7 @@
             parents = fctx._filelog.parents(fctx._filenode)
             nb_parents = 0
             for n in parents:
-                if n != node.nullid:
+                if n != nullid:
                     nb_parents += 1
             return nb_parents >= 2
 
@@ -668,7 +670,7 @@
         if debug:
             repo.ui.debug(b'debug.copies: search mode: combined\n')
         base = None
-        if a.rev() != node.nullrev:
+        if a.rev() != nullrev:
             base = x
         copies = _chain(
             _backwardrenames(x, a, match=match),
diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -54,13 +54,13 @@
     getattr,
     setattr,
 )
+from .node import hex
 
 from . import (
     commandserver,
     encoding,
     error,
     extensions,
-    node,
     pycompat,
     util,
 )
@@ -74,7 +74,7 @@
 
 def _hashlist(items):
     """return sha1 hexdigest for a list"""
-    return node.hex(hashutil.sha1(stringutil.pprint(items)).digest())
+    return hex(hashutil.sha1(stringutil.pprint(items)).digest())
 
 
 # sensitive config sections affecting confighash
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -17,7 +17,11 @@
 import shutil
 
 from .i18n import _
-from .node import nullid, nullrev
+from .node import (
+    hex,
+    nullid,
+    nullrev,
+)
 
 from . import (
     bundle2,
@@ -32,7 +36,6 @@
     localrepo,
     manifest,
     mdiff,
-    node as nodemod,
     pathutil,
     phases,
     pycompat,
@@ -437,9 +440,9 @@
         p2rev = self.changelog.rev(p2)
         msg = _(b"setting parent to node %s that only exists in the bundle\n")
         if self.changelog.repotiprev < p1rev:
-            self.ui.warn(msg % nodemod.hex(p1))
+            self.ui.warn(msg % hex(p1))
         if self.changelog.repotiprev < p2rev:
-            self.ui.warn(msg % nodemod.hex(p2))
+            self.ui.warn(msg % hex(p2))
         return super(bundlerepository, self).setparents(p1, p2)
 
 
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -156,12 +156,16 @@
 import sys
 
 from .i18n import _
+from .node import (
+    hex,
+    nullid,
+    short,
+)
 from . import (
     bookmarks,
     changegroup,
     encoding,
     error,
-    node as nodemod,
     obsolete,
     phases,
     pushkey,
@@ -2131,14 +2135,14 @@
         currentnode = op.repo._bookmarks.get(book)
         if currentnode != node:
             if node is None:
-                finalmsg = msgexist % (book, nodemod.short(currentnode))
+                finalmsg = msgexist % (book, short(currentnode))
             elif currentnode is None:
-                finalmsg = msgmissing % (book, nodemod.short(node))
+                finalmsg = msgmissing % (book, short(node))
             else:
                 finalmsg = msgstandard % (
                     book,
-                    nodemod.short(node),
-                    nodemod.short(currentnode),
+                    short(node),
+                    short(currentnode),
                 )
             raise error.PushRaced(finalmsg)
 
@@ -2215,7 +2219,7 @@
             actualphase = phasecache.phase(unfi, cl.rev(n))
             if actualphase != expectedphase:
                 finalmsg = msg % (
-                    nodemod.short(n),
+                    short(n),
                     phases.phasenames[actualphase],
                     phases.phasenames[expectedphase],
                 )
@@ -2360,8 +2364,8 @@
                 hookargs[b'pushkeycompat'] = b'1'
                 hookargs[b'namespace'] = b'bookmarks'
                 hookargs[b'key'] = book
-                hookargs[b'old'] = nodemod.hex(bookstore.get(book, b''))
-                hookargs[b'new'] = nodemod.hex(
+                hookargs[b'old'] = hex(bookstore.get(book, b''))
+                hookargs[b'new'] = hex(
                     node if node is not None else b''
                 )
                 allhooks.append(hookargs)
@@ -2569,7 +2573,7 @@
             fullnodes=commonnodes,
         )
         cgdata = packer.generate(
-            {nodemod.nullid},
+            {nullid},
             list(commonnodes),
             False,
             b'narrow_widen',
diff --git a/hgext/uncommit.py b/hgext/uncommit.py
--- a/hgext/uncommit.py
+++ b/hgext/uncommit.py
@@ -20,6 +20,7 @@
 from __future__ import absolute_import
 
 from mercurial.i18n import _
+from mercurial.node import nullid
 
 from mercurial import (
     cmdutil,
@@ -27,7 +28,6 @@
     context,
     copies as copiesmod,
     error,
-    node,
     obsutil,
     pathutil,
     pycompat,
@@ -113,7 +113,7 @@
 
     new = context.memctx(
         repo,
-        parents=[base.node(), node.nullid],
+        parents=[base.node(), nullid],
         text=message,
         files=files,
         filectxfn=filectxfn,
diff --git a/hgext/transplant.py b/hgext/transplant.py
--- a/hgext/transplant.py
+++ b/hgext/transplant.py
@@ -19,6 +19,12 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import open
+from mercurial.node import (
+    bin,
+    hex,
+    nullid,
+    short,
+)
 from mercurial import (
     bundlerepo,
     cmdutil,
@@ -28,7 +34,6 @@
     logcmdutil,
     match,
     merge,
-    node as nodemod,
     patch,
     pycompat,
     registrar,
@@ -95,7 +100,7 @@
         abspath = os.path.join(self.path, self.transplantfile)
         if self.transplantfile and os.path.exists(abspath):
             for line in self.opener.read(self.transplantfile).splitlines():
-                lnode, rnode = map(revlog.bin, line.split(b':'))
+                lnode, rnode = map(bin, line.split(b':'))
                 list = self.transplants.setdefault(rnode, [])
                 list.append(transplantentry(lnode, rnode))
 
@@ -106,7 +111,7 @@
             fp = self.opener(self.transplantfile, b'w')
             for list in pycompat.itervalues(self.transplants):
                 for t in list:
-                    l, r = map(nodemod.hex, (t.lnode, t.rnode))
+                    l, r = map(hex, (t.lnode, t.rnode))
                     fp.write(l + b':' + r + b'\n')
             fp.close()
         self.dirty = False
@@ -183,7 +188,7 @@
             tr = repo.transaction(b'transplant')
             for rev in revs:
                 node = revmap[rev]
-                revstr = b'%d:%s' % (rev, nodemod.short(node))
+                revstr = b'%d:%s' % (rev, short(node))
 
                 if self.applied(repo, node, p1):
                     self.ui.warn(
@@ -216,11 +221,11 @@
                         exchange.pull(repo, source.peer(), heads=[node])
 
                 skipmerge = False
-                if parents[1] != revlog.nullid:
+                if parents[1] != nullid:
                     if not opts.get(b'parent'):
                         self.ui.note(
                             _(b'skipping merge changeset %d:%s\n')
-                            % (rev, nodemod.short(node))
+                            % (rev, short(node))
                         )
                         skipmerge = True
                     else:
@@ -228,7 +233,7 @@
                         if parent not in parents:
                             raise error.Abort(
                                 _(b'%s is not a parent of %s')
-                                % (nodemod.short(parent), nodemod.short(node))
+                                % (short(parent), short(node))
                             )
                 else:
                     parent = parents[0]
@@ -264,12 +269,12 @@
                         if n and domerge:
                             self.ui.status(
                                 _(b'%s merged at %s\n')
-                                % (revstr, nodemod.short(n))
+                                % (revstr, short(n))
                             )
                         elif n:
                             self.ui.status(
                                 _(b'%s transplanted to %s\n')
-                                % (nodemod.short(node), nodemod.short(n))
+                                % (short(node), short(n))
                             )
                     finally:
                         if patchfile:
@@ -309,7 +314,7 @@
                 ),
                 environ={
                     b'HGUSER': changelog[1],
-                    b'HGREVISION': nodemod.hex(node),
+                    b'HGREVISION': hex(node),
                 },
                 onerr=error.Abort,
                 errprefix=_(b'filter failed'),
@@ -333,9 +338,9 @@
 
         if log:
             # we don't translate messages inserted into commits
-            message += b'\n(transplanted from %s)' % nodemod.hex(node)
+            message += b'\n(transplanted from %s)' % hex(node)
 
-        self.ui.status(_(b'applying %s\n') % nodemod.short(node))
+        self.ui.status(_(b'applying %s\n') % short(node))
         self.ui.note(b'%s %s\n%s\n' % (user, date, message))
 
         if not patchfile and not merge:
@@ -378,7 +383,7 @@
         )
         if not n:
             self.ui.warn(
-                _(b'skipping emptied changeset %s\n') % nodemod.short(node)
+                _(b'skipping emptied changeset %s\n') % short(node)
             )
             return None
         if not merge:
@@ -396,12 +401,12 @@
             if n:
                 self.ui.status(
                     _(b'%s transplanted as %s\n')
-                    % (nodemod.short(node), nodemod.short(n))
+                    % (short(node), short(n))
                 )
             else:
                 self.ui.status(
                     _(b'%s skipped due to empty diff\n')
-                    % (nodemod.short(node),)
+                    % (short(node),)
                 )
         seriespath = os.path.join(self.path, b'series')
         if not os.path.exists(seriespath):
@@ -430,7 +435,7 @@
                 if parent not in parents:
                     raise error.Abort(
                         _(b'%s is not a parent of %s')
-                        % (nodemod.short(parent), nodemod.short(node))
+                        % (short(parent), short(node))
                     )
             else:
                 merge = True
@@ -441,7 +446,7 @@
             if p1 != parent:
                 raise error.Abort(
                     _(b'working directory not at transplant parent %s')
-                    % nodemod.hex(parent)
+                    % hex(parent)
                 )
             if merge:
                 repo.setparents(p1, parents[1])
@@ -494,7 +499,7 @@
             if line.startswith(b'# Merges'):
                 cur = merges
                 continue
-            cur.append(revlog.bin(line))
+            cur.append(bin(line))
 
         return (nodes, merges)
 
@@ -506,17 +511,17 @@
             os.mkdir(self.path)
         series = self.opener(b'series', b'w')
         for rev in sorted(revmap):
-            series.write(nodemod.hex(revmap[rev]) + b'\n')
+            series.write(hex(revmap[rev]) + b'\n')
         if merges:
             series.write(b'# Merges\n')
             for m in merges:
-                series.write(nodemod.hex(m) + b'\n')
+                series.write(hex(m) + b'\n')
         series.close()
 
     def parselog(self, fp):
         parents = []
         message = []
-        node = revlog.nullid
+        node = nullid
         inmsg = False
         user = None
         date = None
@@ -528,9 +533,9 @@
             elif line.startswith(b'# Date '):
                 date = line[7:]
             elif line.startswith(b'# Node ID '):
-                node = revlog.bin(line[10:])
+                node = bin(line[10:])
             elif line.startswith(b'# Parent '):
-                parents.append(revlog.bin(line[9:]))
+                parents.append(bin(line[9:]))
             elif not line.startswith(b'# '):
                 inmsg = True
                 message.append(line)
@@ -548,10 +553,10 @@
         fp = self.opener(b'journal', b'w')
         fp.write(b'# User %s\n' % user)
         fp.write(b'# Date %s\n' % date)
-        fp.write(b'# Node ID %s\n' % nodemod.hex(p2))
-        fp.write(b'# Parent ' + nodemod.hex(p1) + b'\n')
+        fp.write(b'# Node ID %s\n' % hex(p2))
+        fp.write(b'# Parent ' + hex(p1) + b'\n')
         if merge:
-            fp.write(b'# Parent ' + nodemod.hex(p2) + b'\n')
+            fp.write(b'# Parent ' + hex(p2) + b'\n')
         fp.write(message.rstrip() + b'\n')
         fp.close()
 
@@ -568,7 +573,7 @@
         def matchfn(node):
             if self.applied(repo, node, root):
                 return False
-            if source.changelog.parents(node)[1] != revlog.nullid:
+            if source.changelog.parents(node)[1] != nullid:
                 return False
             extra = source.changelog.read(node)[5]
             cnode = extra.get(b'transplant_source')
@@ -804,7 +809,7 @@
     tp = transplanter(ui, repo, opts)
 
     p1 = repo.dirstate.p1()
-    if len(repo) > 0 and p1 == revlog.nullid:
+    if len(repo) > 0 and p1 == nullid:
         raise error.Abort(_(b'no revision checked out'))
     if opts.get(b'continue'):
         if not tp.canresume():
@@ -909,7 +914,7 @@
     changeset if any."""
     ctx = context.resource(mapping, b'ctx')
     n = ctx.extra().get(b'transplant_source')
-    return n and nodemod.hex(n) or b''
+    return n and hex(n) or b''
 
 
 def extsetup(ui):
diff --git a/hgext/remotefilelog/shallowutil.py b/hgext/remotefilelog/shallowutil.py
--- a/hgext/remotefilelog/shallowutil.py
+++ b/hgext/remotefilelog/shallowutil.py
@@ -15,9 +15,9 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import open
+from mercurial.node import hex
 from mercurial import (
     error,
-    node,
     pycompat,
     revlog,
     util,
@@ -39,12 +39,12 @@
 
 
 def getcachekey(reponame, file, id):
-    pathhash = node.hex(hashutil.sha1(file).digest())
+    pathhash = hex(hashutil.sha1(file).digest())
     return os.path.join(reponame, pathhash[:2], pathhash[2:], id)
 
 
 def getlocalkey(file, id):
-    pathhash = node.hex(hashutil.sha1(file).digest())
+    pathhash = hex(hashutil.sha1(file).digest())
     return os.path.join(pathhash, id)
 
 
diff --git a/hgext/remotefilelog/fileserverclient.py b/hgext/remotefilelog/fileserverclient.py
--- a/hgext/remotefilelog/fileserverclient.py
+++ b/hgext/remotefilelog/fileserverclient.py
@@ -17,7 +17,6 @@
 from mercurial.node import bin, hex, nullid
 from mercurial import (
     error,
-    node,
     pycompat,
     revlog,
     sshpeer,
@@ -47,12 +46,12 @@
 
 
 def getcachekey(reponame, file, id):
-    pathhash = node.hex(hashutil.sha1(file).digest())
+    pathhash = hex(hashutil.sha1(file).digest())
     return os.path.join(reponame, pathhash[:2], pathhash[2:], id)
 
 
 def getlocalkey(file, id):
-    pathhash = node.hex(hashutil.sha1(file).digest())
+    pathhash = hex(hashutil.sha1(file).digest())
     return os.path.join(pathhash, id)
 
 
diff --git a/hgext/remotefilelog/debugcommands.py b/hgext/remotefilelog/debugcommands.py
--- a/hgext/remotefilelog/debugcommands.py
+++ b/hgext/remotefilelog/debugcommands.py
@@ -9,14 +9,18 @@
 import os
 import zlib
 
-from mercurial.node import bin, hex, nullid, short
+from mercurial.node import (
+    bin,
+    hex,
+    nullid,
+    short,
+)
 from mercurial.i18n import _
 from mercurial.pycompat import open
 from mercurial import (
     error,
     filelog,
     lock as lockmod,
-    node as nodemod,
     pycompat,
     revlog,
 )
@@ -61,7 +65,7 @@
 
 def buildtemprevlog(repo, file):
     # get filename key
-    filekey = nodemod.hex(hashutil.sha1(file).digest())
+    filekey = hex(hashutil.sha1(file).digest())
     filedir = os.path.join(repo.path, b'store/data', filekey)
 
     # sort all entries based on linkrev
@@ -421,7 +425,7 @@
             % (
                 hashformatter(node),
                 hashformatter(deltabasenode),
-                nodemod.hex(hashutil.sha1(delta).digest()),
+                hex(hashutil.sha1(delta).digest()),
                 len(delta),
             )
         )
diff --git a/hgext/remotefilelog/basepack.py b/hgext/remotefilelog/basepack.py
--- a/hgext/remotefilelog/basepack.py
+++ b/hgext/remotefilelog/basepack.py
@@ -12,8 +12,8 @@
     getattr,
     open,
 )
+from mercurial.node import hex
 from mercurial import (
-    node as nodemod,
     policy,
     pycompat,
     util,
@@ -429,7 +429,7 @@
             return
 
         try:
-            sha = nodemod.hex(self.sha.digest())
+            sha = hex(self.sha.digest())
             self.packfp.close()
             self.writeindex()
 
diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py
--- a/hgext/remotefilelog/__init__.py
+++ b/hgext/remotefilelog/__init__.py
@@ -130,7 +130,10 @@
 import time
 import traceback
 
-from mercurial.node import hex
+from mercurial.node import (
+    hex,
+    wdirrev,
+)
 from mercurial.i18n import _
 from mercurial.pycompat import open
 from mercurial import (
@@ -150,7 +153,6 @@
     match as matchmod,
     merge,
     mergestate as mergestatemod,
-    node as nodemod,
     patch,
     pycompat,
     registrar,
@@ -1091,7 +1093,7 @@
     if isenabled(repo):
         allfiles = []
         for rev, match in revmatches:
-            if rev == nodemod.wdirrev or rev is None:
+            if rev == wdirrev or rev is None:
                 continue
             ctx = repo[rev]
             mf = ctx.manifest()
diff --git a/hgext/releasenotes.py b/hgext/releasenotes.py
--- a/hgext/releasenotes.py
+++ b/hgext/releasenotes.py
@@ -19,12 +19,12 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import open
+from mercurial.node import hex
 from mercurial import (
     cmdutil,
     config,
     error,
     minirst,
-    node,
     pycompat,
     registrar,
     scmutil,
@@ -381,7 +381,7 @@
             if not paragraphs:
                 repo.ui.warn(
                     _(b"error parsing releasenotes for revision: '%s'\n")
-                    % node.hex(ctx.node())
+                    % hex(ctx.node())
                 )
             if title:
                 notes.addtitleditem(directive, title, paragraphs)
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -23,6 +23,7 @@
 from mercurial.node import (
     nullrev,
     short,
+    wdirrev,
 )
 from mercurial.pycompat import open
 from mercurial import (
@@ -37,7 +38,6 @@
     merge as mergemod,
     mergestate as mergestatemod,
     mergeutil,
-    node as nodemod,
     obsolete,
     obsutil,
     patch,
@@ -1374,7 +1374,7 @@
                 )
             return None
 
-    if nodemod.wdirrev in rebaseset:
+    if wdirrev in rebaseset:
         raise error.Abort(_(b'cannot rebase the working copy'))
     rebasingwcp = repo[b'.'].rev() in rebaseset
     ui.log(
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -83,6 +83,7 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import open
+from mercurial.node import bin
 from mercurial import (
     cmdutil,
     commands,
@@ -91,7 +92,6 @@
     formatter,
     hg,
     mail,
-    node as nodemod,
     patch,
     pycompat,
     registrar,
@@ -306,7 +306,7 @@
         p = mail.mimetextpatch(
             b'\n'.join(patchlines), 'x-patch', opts.get(b'test')
         )
-        binnode = nodemod.bin(node)
+        binnode = bin(node)
         # if node is mq patch, it will have the patch file's name as a tag
         if not patchname:
             patchtags = [
diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py
--- a/hgext/narrow/narrowcommands.py
+++ b/hgext/narrow/narrowcommands.py
@@ -10,6 +10,11 @@
 import os
 
 from mercurial.i18n import _
+from mercurial.node import (
+    hex,
+    nullid,
+    short,
+)
 from mercurial import (
     bundle2,
     cmdutil,
@@ -21,7 +26,6 @@
     extensions,
     hg,
     narrowspec,
-    node,
     pathutil,
     pycompat,
     registrar,
@@ -184,9 +188,9 @@
     # we have all the nodes
     if wireprototypes.ELLIPSESCAP1 in pullop.remote.capabilities():
         kwargs[b'known'] = [
-            node.hex(ctx.node())
+            hex(ctx.node())
             for ctx in repo.set(b'::%ln', pullop.common)
-            if ctx.node() != node.nullid
+            if ctx.node() != nullid
         ]
         if not kwargs[b'known']:
             # Mercurial serializes an empty list as '' and deserializes it as
@@ -239,10 +243,10 @@
         maxnodes = 10
         if ui.verbose or len(visibletostrip) <= maxnodes:
             for n in visibletostrip:
-                ui.status(b'%s\n' % node.short(n))
+                ui.status(b'%s\n' % short(n))
         else:
             for n in visibletostrip[:maxnodes]:
-                ui.status(b'%s\n' % node.short(n))
+                ui.status(b'%s\n' % short(n))
             ui.status(
                 _(b'...and %d more, use --verbose to list all\n')
                 % (len(visibletostrip) - maxnodes)
@@ -362,7 +366,7 @@
             ds = repo.dirstate
             p1, p2 = ds.p1(), ds.p2()
             with ds.parentchange():
-                ds.setparents(node.nullid, node.nullid)
+                ds.setparents(nullid, nullid)
         if isoldellipses:
             with wrappedextraprepare:
                 exchange.pull(repo, remote, heads=common)
@@ -372,7 +376,7 @@
                 known = [
                     ctx.node()
                     for ctx in repo.set(b'::%ln', common)
-                    if ctx.node() != node.nullid
+                    if ctx.node() != nullid
                 ]
             with remote.commandexecutor() as e:
                 bundle = e.callcommand(
diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py
--- a/hgext/lfs/blobstore.py
+++ b/hgext/lfs/blobstore.py
@@ -17,12 +17,12 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import getattr
+from mercurial.node import hex
 
 from mercurial import (
     encoding,
     error,
     httpconnection as httpconnectionmod,
-    node,
     pathutil,
     pycompat,
     url as urlmod,
@@ -173,7 +173,7 @@
                 )
                 raise LfsRemoteError(_(msg) % (size, int(content_length)))
 
-            realoid = node.hex(sha256.digest())
+            realoid = hex(sha256.digest())
             if realoid != oid:
                 raise LfsCorruptionError(
                     _(b'corrupt remote lfs object: %s') % oid
@@ -224,7 +224,7 @@
             # Don't abort if corruption is detected, because `hg verify` will
             # give more useful info about the corruption- simply don't add the
             # hardlink.
-            if verify or node.hex(hashlib.sha256(blob).digest()) == oid:
+            if verify or hex(hashlib.sha256(blob).digest()) == oid:
                 self.ui.note(_(b'lfs: found %s in the usercache\n') % oid)
                 lfutil.link(self.cachevfs.join(oid), self.vfs.join(oid))
         else:
@@ -248,7 +248,7 @@
             for chunk in util.filechunkiter(fp, size=1048576):
                 sha256.update(chunk)
 
-        return oid == node.hex(sha256.digest())
+        return oid == hex(sha256.digest())
 
     def has(self, oid):
         """Returns True if the local blobstore contains the requested blob,
@@ -706,7 +706,7 @@
 
 
 def _verify(oid, content):
-    realoid = node.hex(hashlib.sha256(content).digest())
+    realoid = hex(hashlib.sha256(content).digest())
     if realoid != oid:
         raise LfsCorruptionError(
             _(b'detected corrupt lfs object: %s') % oid,
diff --git a/hgext/lfs/__init__.py b/hgext/lfs/__init__.py
--- a/hgext/lfs/__init__.py
+++ b/hgext/lfs/__init__.py
@@ -125,6 +125,7 @@
 import sys
 
 from mercurial.i18n import _
+from mercurial.node import bin
 
 from mercurial import (
     bundlecaches,
@@ -137,7 +138,6 @@
     filesetlang,
     localrepo,
     minifileset,
-    node,
     pycompat,
     revlog,
     scmutil,
@@ -260,11 +260,10 @@
                 return 0
 
             last = kwargs.get('node_last')
-            _bin = node.bin
             if last:
-                s = repo.set(b'%n:%n', _bin(kwargs['node']), _bin(last))
+                s = repo.set(b'%n:%n', bin(kwargs['node']), bin(last))
             else:
-                s = repo.set(b'%n', _bin(kwargs['node']))
+                s = repo.set(b'%n', bin(kwargs['node']))
             match = repo._storenarrowmatch
             for ctx in s:
                 # TODO: is there a way to just walk the files in the commit?
diff --git a/hgext/largefiles/lfutil.py b/hgext/largefiles/lfutil.py
--- a/hgext/largefiles/lfutil.py
+++ b/hgext/largefiles/lfutil.py
@@ -15,7 +15,10 @@
 import stat
 
 from mercurial.i18n import _
-from mercurial.node import hex
+from mercurial.node import (
+    hex,
+    nullid,
+)
 from mercurial.pycompat import open
 
 from mercurial import (
@@ -24,7 +27,6 @@
     error,
     httpconnection,
     match as matchmod,
-    node,
     pycompat,
     scmutil,
     sparse,
@@ -610,7 +612,7 @@
     ) as progress:
         for i, n in enumerate(missing):
             progress.update(i)
-            parents = [p for p in repo[n].parents() if p != node.nullid]
+            parents = [p for p in repo[n].parents() if p != nullid]
 
             with lfstatus(repo, value=False):
                 ctx = repo[n]
diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -14,6 +14,11 @@
 import shutil
 
 from mercurial.i18n import _
+from mercurial.node import (
+    bin,
+    hex,
+    nullid,
+)
 
 from mercurial import (
     cmdutil,
@@ -23,7 +28,6 @@
     hg,
     lock,
     match as matchmod,
-    node,
     pycompat,
     scmutil,
     util,
@@ -111,7 +115,7 @@
             rsrc[ctx]
             for ctx in rsrc.changelog.nodesbetween(None, rsrc.heads())[0]
         )
-        revmap = {node.nullid: node.nullid}
+        revmap = {nullid: nullid}
         if tolfile:
             # Lock destination to prevent modification while it is converted to.
             # Don't need to lock src because we are just reading from its
@@ -275,7 +279,7 @@
                 # largefile was modified, update standins
                 m = hashutil.sha1(b'')
                 m.update(ctx[f].data())
-                hash = node.hex(m.digest())
+                hash = hex(m.digest())
                 if f not in lfiletohash or lfiletohash[f] != hash:
                     rdst.wwrite(f, ctx[f].data(), ctx[f].flags())
                     executable = b'x' in ctx[f].flags()
@@ -336,7 +340,7 @@
 # Generate list of changed files
 def _getchangedfiles(ctx, parents):
     files = set(ctx.files())
-    if node.nullid not in parents:
+    if nullid not in parents:
         mc = ctx.manifest()
         for pctx in ctx.parents():
             for fn in pctx.manifest().diff(mc):
@@ -350,7 +354,7 @@
     for p in ctx.parents():
         parents.append(revmap[p.node()])
     while len(parents) < 2:
-        parents.append(node.nullid)
+        parents.append(nullid)
     return parents
 
 
@@ -380,12 +384,12 @@
             ui.warn(_(b'skipping incorrectly formatted tag %s\n') % line)
             continue
         try:
-            newid = node.bin(id)
+            newid = bin(id)
         except TypeError:
             ui.warn(_(b'skipping incorrectly formatted id %s\n') % id)
             continue
         try:
-            newdata.append(b'%s %s\n' % (node.hex(revmap[newid]), name))
+            newdata.append(b'%s %s\n' % (hex(revmap[newid]), name))
         except KeyError:
             ui.warn(_(b'no mapping for id %s\n') % id)
             continue
diff --git a/hgext/journal.py b/hgext/journal.py
--- a/hgext/journal.py
+++ b/hgext/journal.py
@@ -19,6 +19,11 @@
 import weakref
 
 from mercurial.i18n import _
+from mercurial.node import (
+    bin,
+    hex,
+    nullid,
+)
 
 from mercurial import (
     bookmarks,
@@ -31,7 +36,6 @@
     localrepo,
     lock,
     logcmdutil,
-    node,
     pycompat,
     registrar,
     util,
@@ -113,8 +117,8 @@
     new = list(new)
     if util.safehasattr(dirstate, 'journalstorage'):
         # only record two hashes if there was a merge
-        oldhashes = old[:1] if old[1] == node.nullid else old
-        newhashes = new[:1] if new[1] == node.nullid else new
+        oldhashes = old[:1] if old[1] == nullid else old
+        newhashes = new[:1] if new[1] == nullid else new
         dirstate.journalstorage.record(
             wdirparenttype, b'.', oldhashes, newhashes
         )
@@ -127,7 +131,7 @@
     if util.safehasattr(repo, 'journal'):
         oldmarks = bookmarks.bmstore(repo)
         for mark, value in pycompat.iteritems(store):
-            oldvalue = oldmarks.get(mark, node.nullid)
+            oldvalue = oldmarks.get(mark, nullid)
             if value != oldvalue:
                 repo.journal.record(bookmarktype, mark, oldvalue, value)
     return orig(store, fp)
@@ -248,8 +252,8 @@
         ) = line.split(b'\n')
         timestamp, tz = time.split()
         timestamp, tz = float(timestamp), int(tz)
-        oldhashes = tuple(node.bin(hash) for hash in oldhashes.split(b','))
-        newhashes = tuple(node.bin(hash) for hash in newhashes.split(b','))
+        oldhashes = tuple(bin(hash) for hash in oldhashes.split(b','))
+        newhashes = tuple(bin(hash) for hash in newhashes.split(b','))
         return cls(
             (timestamp, tz),
             user,
@@ -263,8 +267,8 @@
     def __bytes__(self):
         """bytes representation for storage"""
         time = b' '.join(map(pycompat.bytestr, self.timestamp))
-        oldhashes = b','.join([node.hex(hash) for hash in self.oldhashes])
-        newhashes = b','.join([node.hex(hash) for hash in self.newhashes])
+        oldhashes = b','.join([hex(hash) for hash in self.oldhashes])
+        newhashes = b','.join([hex(hash) for hash in self.newhashes])
         return b'\n'.join(
             (
                 time,
diff --git a/hgext/infinitepush/store.py b/hgext/infinitepush/store.py
--- a/hgext/infinitepush/store.py
+++ b/hgext/infinitepush/store.py
@@ -9,11 +9,9 @@
 import os
 import subprocess
 
+from mercurial.node import hex
 from mercurial.pycompat import open
-from mercurial import (
-    node,
-    pycompat,
-)
+from mercurial import pycompat
 from mercurial.utils import (
     hashutil,
     procutil,
@@ -86,7 +84,7 @@
         return os.path.join(self._dirpath(filename), filename)
 
     def write(self, data):
-        filename = node.hex(hashutil.sha1(data).digest())
+        filename = hex(hashutil.sha1(data).digest())
         dirpath = self._dirpath(filename)
 
         if not os.path.exists(dirpath):
diff --git a/hgext/infinitepush/bundleparts.py b/hgext/infinitepush/bundleparts.py
--- a/hgext/infinitepush/bundleparts.py
+++ b/hgext/infinitepush/bundleparts.py
@@ -6,13 +6,13 @@
 from __future__ import absolute_import
 
 from mercurial.i18n import _
+from mercurial.node import hex
 
 from mercurial import (
     bundle2,
     changegroup,
     error,
     extensions,
-    node as nodemod,
     pycompat,
     revsetlang,
     util,
@@ -54,7 +54,7 @@
         params[b'bookprevnode'] = b''
         bookmarks = repo._bookmarks
         if bookmark in bookmarks:
-            params[b'bookprevnode'] = nodemod.hex(bookmarks[bookmark])
+            params[b'bookprevnode'] = hex(bookmarks[bookmark])
 
     # Do not send pushback bundle2 part with bookmarks if remotenames extension
     # is enabled. It will be handled manually in `_push()`
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -209,6 +209,11 @@
     getattr,
     open,
 )
+from mercurial.node import (
+    bin,
+    hex,
+    short,
+)
 from mercurial import (
     bundle2,
     cmdutil,
@@ -225,7 +230,6 @@
     merge as mergemod,
     mergestate as mergestatemod,
     mergeutil,
-    node,
     obsolete,
     pycompat,
     registrar,
@@ -404,8 +408,8 @@
 
     def _write(self, fp):
         fp.write(b'v1\n')
-        fp.write(b'%s\n' % node.hex(self.parentctxnode))
-        fp.write(b'%s\n' % node.hex(self.topmost))
+        fp.write(b'%s\n' % hex(self.parentctxnode))
+        fp.write(b'%s\n' % hex(self.topmost))
         fp.write(b'%s\n' % (b'True' if self.keep else b'False'))
         fp.write(b'%d\n' % len(self.actions))
         for action in self.actions:
@@ -415,8 +419,8 @@
             fp.write(
                 b'%s%s\n'
                 % (
-                    node.hex(replacement[0]),
-                    b''.join(node.hex(r) for r in replacement[1]),
+                    hex(replacement[0]),
+                    b''.join(hex(r) for r in replacement[1]),
                 )
             )
         backupfile = self.backupfile
@@ -432,10 +436,10 @@
         lines[index]  # version number
         index += 1
 
-        parentctxnode = node.bin(lines[index])
+        parentctxnode = bin(lines[index])
         index += 1
 
-        topmost = node.bin(lines[index])
+        topmost = bin(lines[index])
         index += 1
 
         keep = lines[index] == b'True'
@@ -458,9 +462,9 @@
         index += 1
         for i in pycompat.xrange(replacementlen):
             replacement = lines[index]
-            original = node.bin(replacement[:40])
+            original = bin(replacement[:40])
             succ = [
-                node.bin(replacement[i : i + 40])
+                bin(replacement[i : i + 40])
                 for i in range(40, len(replacement), 40)
             ]
             replacements.append((original, succ))
@@ -494,12 +498,12 @@
         # ruleid can be anything from rev numbers, hashes, "bookmarks" etc
         # Check for validation of rule ids and get the rulehash
         try:
-            rev = node.bin(ruleid)
+            rev = bin(ruleid)
         except TypeError:
             try:
                 _ctx = scmutil.revsingle(state.repo, ruleid)
                 rulehash = _ctx.hex()
-                rev = node.bin(rulehash)
+                rev = bin(rulehash)
             except error.RepoLookupError:
                 raise error.ParseError(_(b"invalid changeset %s") % ruleid)
         return cls(state, rev)
@@ -507,7 +511,7 @@
     def verify(self, prev, expected, seen):
         """ Verifies semantic correctness of the rule"""
         repo = self.repo
-        ha = node.hex(self.node)
+        ha = hex(self.node)
         self.node = scmutil.resolvehexnodeidprefix(repo, ha)
         if self.node is None:
             raise error.ParseError(_(b'unknown changeset %s listed') % ha[:12])
@@ -518,14 +522,14 @@
         if self.node not in expected:
             raise error.ParseError(
                 _(b'%s "%s" changeset was not a candidate')
-                % (self.verb, node.short(self.node)),
+                % (self.verb, short(self.node)),
                 hint=_(b'only use listed changesets'),
             )
         # and only one command per node
         if self.node in seen:
             raise error.ParseError(
                 _(b'duplicated command for changeset %s')
-                % node.short(self.node)
+                % short(self.node)
             )
 
     def torule(self):
@@ -557,7 +561,7 @@
         """Print an action in format used by histedit state files
         (the first line is a verb, the remainder is the second)
         """
-        return b"%s\n%s" % (self.verb, node.hex(self.node))
+        return b"%s\n%s" % (self.verb, hex(self.node))
 
     def run(self):
         """Runs the action. The default behavior is simply apply the action's
@@ -579,7 +583,7 @@
         if stats.unresolvedcount:
             raise error.InterventionRequired(
                 _(b'Fix up the change (%s %s)')
-                % (self.verb, node.short(self.node)),
+                % (self.verb, short(self.node)),
                 hint=_(b'hg histedit --continue to resume'),
             )
 
@@ -615,7 +619,7 @@
         if ctx.node() == self.state.parentctxnode:
             self.repo.ui.warn(
                 _(b'%s: skipping changeset (no changes)\n')
-                % node.short(self.node)
+                % short(self.node)
             )
             return ctx, [(self.node, tuple())]
         if ctx.node() == self.node:
@@ -684,7 +688,7 @@
     for c in ctxs:
         if not c.mutable():
             raise error.ParseError(
-                _(b"cannot fold into public change %s") % node.short(c.node())
+                _(b"cannot fold into public change %s") % short(c.node())
             )
     base = firstctx.p1()
 
@@ -786,7 +790,7 @@
     def run(self):
         rulectx = self.repo[self.node]
         if rulectx.p1().node() == self.state.parentctxnode:
-            self.repo.ui.debug(b'node %s unchanged\n' % node.short(self.node))
+            self.repo.ui.debug(b'node %s unchanged\n' % short(self.node))
             return rulectx, []
 
         return super(pick, self).run()
@@ -802,8 +806,8 @@
         hint = _(b'to edit %s, `hg histedit --continue` after making changes')
         raise error.InterventionRequired(
             _(b'Editing (%s), commit as needed now to split the change')
-            % node.short(self.node),
-            hint=hint % node.short(self.node),
+            % short(self.node),
+            hint=hint % short(self.node),
         )
 
     def commiteditor(self):
@@ -824,7 +828,7 @@
             c = repo[prev.node]
         if not c.mutable():
             raise error.ParseError(
-                _(b"cannot fold into public change %s") % node.short(c.node())
+                _(b"cannot fold into public change %s") % short(c.node())
             )
 
     def continuedirty(self):
@@ -833,7 +837,7 @@
 
         commit = commitfuncfor(repo, rulectx)
         commit(
-            text=b'fold-temp-revision %s' % node.short(self.node),
+            text=b'fold-temp-revision %s' % short(self.node),
             user=rulectx.user(),
             date=rulectx.date(),
             extra=rulectx.extra(),
@@ -845,7 +849,7 @@
         rulectx = repo[self.node]
         parentctxnode = self.state.parentctxnode
         if ctx.node() == parentctxnode:
-            repo.ui.warn(_(b'%s: empty changeset\n') % node.short(self.node))
+            repo.ui.warn(_(b'%s: empty changeset\n') % short(self.node))
             return ctx, [(self.node, (parentctxnode,))]
 
         parentctx = repo[parentctxnode]
@@ -859,7 +863,7 @@
                     b'%s: cannot fold - working copy is not a '
                     b'descendant of previous commit %s\n'
                 )
-                % (node.short(self.node), node.short(parentctxnode))
+                % (short(self.node), short(parentctxnode))
             )
             return ctx, [(self.node, (ctx.node(),))]
 
@@ -973,7 +977,7 @@
         if self.node in expected:
             msg = _(b'%s "%s" changeset was an edited list candidate')
             raise error.ParseError(
-                msg % (self.verb, node.short(self.node)),
+                msg % (self.verb, short(self.node)),
                 hint=_(b'base must only use unlisted changesets'),
             )
 
@@ -1718,7 +1722,7 @@
         if not revs:
             raise error.Abort(
                 _(b'%s is not an ancestor of working directory')
-                % node.short(root)
+                % short(root)
             )
 
         ctxs = []
@@ -2071,16 +2075,16 @@
     if mapping:
         for prec, succs in pycompat.iteritems(mapping):
             if not succs:
-                ui.debug(b'histedit: %s is dropped\n' % node.short(prec))
+                ui.debug(b'histedit: %s is dropped\n' % short(prec))
             else:
                 ui.debug(
                     b'histedit: %s is replaced by %s\n'
-                    % (node.short(prec), node.short(succs[0]))
+                    % (short(prec), short(succs[0]))
                 )
                 if len(succs) > 1:
                     m = b'histedit:                            %s'
                     for n in succs[1:]:
-                        ui.debug(m % node.short(n))
+                        ui.debug(m % short(n))
 
     if not state.keep:
         if mapping:
@@ -2125,7 +2129,7 @@
     try:
         state.read()
         __, leafs, tmpnodes, __ = processreplacement(state)
-        ui.debug(b'restore wc to old parent %s\n' % node.short(state.topmost))
+        ui.debug(b'restore wc to old parent %s\n' % short(state.topmost))
 
         # Recover our old commits if necessary
         if not state.topmost in repo and state.backupfile:
@@ -2179,7 +2183,7 @@
     state.read()
     if not rules:
         comment = geteditcomment(
-            ui, node.short(state.parentctxnode), node.short(state.topmost)
+            ui, short(state.parentctxnode), short(state.topmost)
         )
         rules = ruleeditor(repo, ui, state.actions, comment)
     else:
@@ -2220,7 +2224,7 @@
     revs = between(repo, root, topmost, state.keep)
     if not revs:
         raise error.Abort(
-            _(b'%s is not an ancestor of working directory') % node.short(root)
+            _(b'%s is not an ancestor of working directory') % short(root)
         )
 
     ctxs = [repo[r] for r in revs]
@@ -2257,7 +2261,7 @@
             )
 
     if not rules:
-        comment = geteditcomment(ui, node.short(root), node.short(topmost))
+        comment = geteditcomment(ui, short(root), short(topmost))
         actions = [pick(state, r) for r in revs]
         rules = ruleeditor(repo, ui, actions, comment)
     else:
@@ -2461,12 +2465,12 @@
         actions[:0] = drops
     elif missing:
         raise error.ParseError(
-            _(b'missing rules for changeset %s') % node.short(missing[0]),
+            _(b'missing rules for changeset %s') % short(missing[0]),
             hint=_(
                 b'use "drop %s" to discard, see also: '
                 b"'hg help -e histedit.config'"
             )
-            % node.short(missing[0]),
+            % short(missing[0]),
         )
 
 
@@ -2620,7 +2624,7 @@
         if common_nodes:
             raise error.Abort(
                 _(b"histedit in progress, can't strip %s")
-                % b', '.join(node.short(x) for x in common_nodes)
+                % b', '.join(short(x) for x in common_nodes)
             )
     return orig(ui, repo, nodelist, *args, **kwargs)
 
diff --git a/hgext/gpg.py b/hgext/gpg.py
--- a/hgext/gpg.py
+++ b/hgext/gpg.py
@@ -11,12 +11,17 @@
 import os
 
 from mercurial.i18n import _
+from mercurial.node import (
+    bin,
+    hex,
+    nullid,
+    short,
+)
 from mercurial import (
     cmdutil,
     error,
     help,
     match,
-    node as hgnode,
     pycompat,
     registrar,
 )
@@ -155,7 +160,7 @@
     # read the heads
     fl = repo.file(b".hgsigs")
     for r in reversed(fl.heads()):
-        fn = b".hgsigs|%s" % hgnode.short(r)
+        fn = b".hgsigs|%s" % short(r)
         for item in parsefile(fl.read(r).splitlines(), fn):
             yield item
     try:
@@ -172,7 +177,7 @@
     fn, ln = context
     node, version, sig = sigdata
     prefix = b"%s:%d" % (fn, ln)
-    node = hgnode.bin(node)
+    node = bin(node)
 
     data = node2txt(repo, node, version)
     sig = binascii.a2b_base64(sig)
@@ -223,7 +228,7 @@
         revs[r].extend(keys)
     for rev in sorted(revs, reverse=True):
         for k in revs[rev]:
-            r = b"%5d:%s" % (rev, hgnode.hex(repo.changelog.node(rev)))
+            r = b"%5d:%s" % (rev, hex(repo.changelog.node(rev)))
             ui.write(b"%-30s %s\n" % (keystr(ui, k), r))
 
 
@@ -232,7 +237,7 @@
     """verify all the signatures there may be for a particular revision"""
     mygpg = newgpg(ui)
     rev = repo.lookup(rev)
-    hexrev = hgnode.hex(rev)
+    hexrev = hex(rev)
     keys = []
 
     for data, context in sigwalk(repo):
@@ -243,11 +248,11 @@
                 keys.extend(k)
 
     if not keys:
-        ui.write(_(b"no valid signature for %s\n") % hgnode.short(rev))
+        ui.write(_(b"no valid signature for %s\n") % short(rev))
         return
 
     # print summary
-    ui.write(_(b"%s is signed by:\n") % hgnode.short(rev))
+    ui.write(_(b"%s is signed by:\n") % short(rev))
     for key in keys:
         ui.write(b" %s\n" % keystr(ui, key))
 
@@ -310,7 +315,7 @@
         nodes = [repo.lookup(n) for n in revs]
     else:
         nodes = [
-            node for node in repo.dirstate.parents() if node != hgnode.nullid
+            node for node in repo.dirstate.parents() if node != nullid
         ]
         if len(nodes) > 1:
             raise error.Abort(
@@ -320,9 +325,9 @@
             nodes = [repo.changelog.tip()]
 
     for n in nodes:
-        hexnode = hgnode.hex(n)
+        hexnode = hex(n)
         ui.write(
-            _(b"signing %d:%s\n") % (repo.changelog.rev(n), hgnode.short(n))
+            _(b"signing %d:%s\n") % (repo.changelog.rev(n), short(n))
         )
         # build data
         data = node2txt(repo, n, sigver)
@@ -361,7 +366,7 @@
         # we don't translate commit messages
         message = b"\n".join(
             [
-                b"Added signature for changeset %s" % hgnode.short(n)
+                b"Added signature for changeset %s" % short(n)
                 for n in nodes
             ]
         )
@@ -379,7 +384,7 @@
 def node2txt(repo, node, ver):
     """map a manifest into some text"""
     if ver == b"0":
-        return b"%s\n" % hgnode.hex(node)
+        return b"%s\n" % hex(node)
     else:
         raise error.Abort(_(b"unknown signature version"))
 
diff --git a/hgext/git/index.py b/hgext/git/index.py
--- a/hgext/git/index.py
+++ b/hgext/git/index.py
@@ -5,11 +5,14 @@
 import sqlite3
 
 from mercurial.i18n import _
+from mercurial.node import (
+    nullhex,
+    nullid,
+)
 
 from mercurial import (
     encoding,
     error,
-    node as nodemod,
     pycompat,
 )
 
@@ -278,7 +281,7 @@
     for pos, commit in enumerate(walker):
         if prog is not None:
             prog.update(pos)
-        p1 = p2 = nodemod.nullhex
+        p1 = p2 = nullhex
         if len(commit.parents) > 2:
             raise error.ProgrammingError(
                 (
@@ -317,7 +320,7 @@
             files = {
                 nf.path: nf.id.hex
                 for nf in new_files
-                if nf.id.raw != nodemod.nullid
+                if nf.id.raw != nullid
             }
             for p, n in files.items():
                 # We intentionally set NULLs for any file parentage
diff --git a/hgext/git/gitlog.py b/hgext/git/gitlog.py
--- a/hgext/git/gitlog.py
+++ b/hgext/git/gitlog.py
@@ -2,6 +2,13 @@
 
 from mercurial.i18n import _
 
+from mercurial.node import (
+    bin,
+    nullhex,
+    nullid,
+    nullrev,
+    wdirhex,
+)
 from mercurial import (
     ancestor,
     changelog as hgchangelog,
@@ -9,7 +16,6 @@
     encoding,
     error,
     manifest,
-    node as nodemod,
     pycompat,
 )
 from mercurial.interfaces import (
@@ -39,7 +45,7 @@
         )
 
     def rev(self, n):
-        if n == nodemod.nullid:
+        if n == nullid:
             return -1
         t = self._db.execute(
             'SELECT rev FROM changelog WHERE node = ?', (gitutil.togitnode(n),)
@@ -49,14 +55,14 @@
         return t[0]
 
     def node(self, r):
-        if r == nodemod.nullrev:
-            return nodemod.nullid
+        if r == nullrev:
+            return nullid
         t = self._db.execute(
             'SELECT node FROM changelog WHERE rev = ?', (r,)
         ).fetchone()
         if t is None:
             raise error.LookupError(r, b'00changelog.i', _(b'no node'))
-        return nodemod.bin(t[0])
+        return bin(t[0])
 
     def hasnode(self, n):
         t = self._db.execute(
@@ -123,10 +129,10 @@
     @property
     def nodemap(self):
         r = {
-            nodemod.bin(v[0]): v[1]
+            bin(v[0]): v[1]
             for v in self._db.execute('SELECT node, rev FROM changelog')
         }
-        r[nodemod.nullid] = nodemod.nullrev
+        r[nullid] = nullrev
         return r
 
     def tip(self):
@@ -134,8 +140,8 @@
             'SELECT node FROM changelog ORDER BY rev DESC LIMIT 1'
         ).fetchone()
         if t:
-            return nodemod.bin(t[0])
-        return nodemod.nullid
+            return bin(t[0])
+        return nullid
 
     def revs(self, start=0, stop=None):
         if stop is None:
@@ -155,16 +161,16 @@
         return next(t)
 
     def _partialmatch(self, id):
-        if nodemod.wdirhex.startswith(id):
+        if wdirhex.startswith(id):
             raise error.WdirUnsupported
         candidates = [
-            nodemod.bin(x[0])
+            bin(x[0])
             for x in self._db.execute(
                 'SELECT node FROM changelog WHERE node LIKE ?', (id + b'%',)
             )
         ]
-        if nodemod.nullhex.startswith(id):
-            candidates.append(nodemod.nullid)
+        if nullhex.startswith(id):
+            candidates.append(nullid)
         if len(candidates) > 1:
             raise error.AmbiguousPrefixLookupError(
                 id, b'00changelog.i', _(b'ambiguous identifier')
@@ -177,7 +183,7 @@
         return 0
 
     def shortest(self, node, minlength=1):
-        nodehex = nodemod.hex(node)
+        nodehex = hex(node)
         for attempt in pycompat.xrange(minlength, len(nodehex) + 1):
             candidate = nodehex[:attempt]
             matches = int(
@@ -209,7 +215,7 @@
         else:
             n = nodeorrev
         # handle looking up nullid
-        if n == nodemod.nullid:
+        if n == nullid:
             return hgchangelog._changelogrevision(extra={})
         hn = gitutil.togitnode(n)
         # We've got a real commit!
@@ -226,7 +232,7 @@
             for r in self._db.execute(
                 'SELECT filename FROM changedfiles '
                 'WHERE node = ? and filenode = ?',
-                (hn, nodemod.nullhex),
+                (hn, nullhex),
             )
         ]
         c = self.gitrepo[hn]
@@ -267,7 +273,7 @@
         nullrev.
         """
         if common is None:
-            common = [nodemod.nullrev]
+            common = [nullrev]
 
         return ancestor.incrementalmissingancestors(self.parentrevs, common)
 
@@ -287,7 +293,7 @@
         not supplied, uses all of the revlog's heads.  If common is not
         supplied, uses nullid."""
         if common is None:
-            common = [nodemod.nullid]
+            common = [nullid]
         if heads is None:
             heads = self.heads()
 
@@ -302,12 +308,12 @@
         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]
+            prevs = [pr for pr in self.parentrevs(r) if pr != nullrev]
             if prevs:
                 for pr in prevs:
                     if pr == p:
                         c.append(self.node(r))
-            elif p == nodemod.nullrev:
+            elif p == nullrev:
                 c.append(self.node(r))
         return c
 
@@ -323,7 +329,7 @@
 
     # Cleanup opportunity: this is *identical* to the revlog.py version
     def isancestorrev(self, a, b):
-        if a == nodemod.nullrev:
+        if a == nullrev:
             return True
         elif a == b:
             return True
@@ -337,8 +343,8 @@
         if hn != gitutil.nullgit:
             c = self.gitrepo[hn]
         else:
-            return nodemod.nullrev, nodemod.nullrev
-        p1 = p2 = nodemod.nullrev
+            return nullrev, nullrev
+        p1 = p2 = nullrev
         if c.parents:
             p1 = self.rev(c.parents[0].id.raw)
             if len(c.parents) > 2:
@@ -386,9 +392,9 @@
     ):
         parents = []
         hp1, hp2 = gitutil.togitnode(p1), gitutil.togitnode(p2)
-        if p1 != nodemod.nullid:
+        if p1 != nullid:
             parents.append(hp1)
-        if p2 and p2 != nodemod.nullid:
+        if p2 and p2 != nullid:
             parents.append(hp2)
         assert date is not None
         timestamp, tz = date
@@ -419,7 +425,7 @@
         return self.get(b'', node)
 
     def get(self, relpath, node):
-        if node == nodemod.nullid:
+        if node == nullid:
             # TODO: this should almost certainly be a memgittreemanifestctx
             return manifest.memtreemanifestctx(self, relpath)
         commit = self.gitrepo[gitutil.togitnode(node)]
@@ -440,7 +446,7 @@
         self.path = path
 
     def read(self, node):
-        if node == nodemod.nullid:
+        if node == nullid:
             return b''
         return self.gitrepo[gitutil.togitnode(node)].data
 
@@ -450,7 +456,7 @@
         if isinstance(node, int):
             assert False, b'todo revnums for nodes'
         if len(node) == 40:
-            node = nodemod.bin(node)
+            node = bin(node)
         hnode = gitutil.togitnode(node)
         if hnode in self.gitrepo:
             return node
@@ -500,7 +506,7 @@
         ).fetchone()
         if maybe is None:
             raise IndexError('gitlog %r out of range %d' % (self.path, rev))
-        return nodemod.bin(maybe[0])
+        return bin(maybe[0])
 
     def parents(self, node):
         gn = gitutil.togitnode(node)
@@ -525,7 +531,7 @@
                 index.fill_in_filelog(self.gitrepo, self._db, commit, gp, gn)
                 return self.parents(node)
             else:
-                ps.append(nodemod.bin(p))
+                ps.append(bin(p))
         return ps
 
     def renamed(self, node):
diff --git a/hgext/git/dirstate.py b/hgext/git/dirstate.py
--- a/hgext/git/dirstate.py
+++ b/hgext/git/dirstate.py
@@ -4,11 +4,11 @@
 import errno
 import os
 
+from mercurial.node import nullid
 from mercurial import (
     error,
     extensions,
     match as matchmod,
-    node as nodemod,
     pycompat,
     scmutil,
     util,
@@ -81,14 +81,14 @@
         except pygit2.GitError:
             # Typically happens when peeling HEAD fails, as in an
             # empty repository.
-            return nodemod.nullid
+            return nullid
 
     def p2(self):
         # TODO: MERGE_HEAD? something like that, right?
-        return nodemod.nullid
+        return nullid
 
-    def setparents(self, p1, p2=nodemod.nullid):
-        assert p2 == nodemod.nullid, b'TODO merging support'
+    def setparents(self, p1, p2=nullid):
+        assert p2 == nullid, b'TODO merging support'
         self.git.head.set_target(gitutil.togitnode(p1))
 
     @util.propertycache
@@ -102,7 +102,7 @@
 
     def parents(self):
         # TODO how on earth do we find p2 if a merge is in flight?
-        return self.p1(), nodemod.nullid
+        return self.p1(), nullid
 
     def __iter__(self):
         return (pycompat.fsencode(f.path) for f in self.git.index)
diff --git a/hgext/fastannotate/formatter.py b/hgext/fastannotate/formatter.py
--- a/hgext/fastannotate/formatter.py
+++ b/hgext/fastannotate/formatter.py
@@ -6,9 +6,12 @@
 # GNU General Public License version 2 or any later version.
 from __future__ import absolute_import
 
+from mercurial.node import (
+    hex,
+    short,
+)
 from mercurial import (
     encoding,
-    node,
     pycompat,
     templatefilters,
     util,
@@ -116,9 +119,9 @@
     @util.propertycache
     def _hexfunc(self):
         if self.ui.debugflag or self.opts.get(b'long_hash'):
-            return node.hex
+            return hex
         else:
-            return node.short
+            return short
 
     def end(self):
         pass
@@ -168,7 +171,7 @@
 
     @util.propertycache
     def _hexfunc(self):
-        return node.hex
+        return hex
 
     def end(self):
         self.ui.write(b'\n]\n')
diff --git a/hgext/fastannotate/context.py b/hgext/fastannotate/context.py
--- a/hgext/fastannotate/context.py
+++ b/hgext/fastannotate/context.py
@@ -17,12 +17,16 @@
     open,
     setattr,
 )
+from mercurial.node import (
+    bin,
+    hex,
+    short,
+)
 from mercurial import (
     error,
     linelog as linelogmod,
     lock as lockmod,
     mdiff,
-    node,
     pycompat,
     scmutil,
     util,
@@ -150,7 +154,7 @@
     diffoptstr = stringutil.pprint(
         sorted((k, getattr(diffopts, k)) for k in mdiff.diffopts.defaults)
     )
-    return node.hex(hashutil.sha1(diffoptstr).digest())[:6]
+    return hex(hashutil.sha1(diffoptstr).digest())[:6]
 
 
 _defaultdiffopthash = hashdiffopts(mdiff.defaultopts)
@@ -308,7 +312,7 @@
         # command could give us a revision number even if the user passes a
         # commit hash.
         if isinstance(rev, int):
-            rev = node.hex(self.repo.changelog.node(rev))
+            rev = hex(self.repo.changelog.node(rev))
 
         # fast path: if rev is in the main branch already
         directly, revfctx = self.canannotatedirectly(rev)
@@ -493,7 +497,7 @@
         result = True
         f = None
         if not isinstance(rev, int) and rev is not None:
-            hsh = {20: bytes, 40: node.bin}.get(len(rev), lambda x: None)(rev)
+            hsh = {20: bytes, 40: bin}.get(len(rev), lambda x: None)(rev)
             if hsh is not None and (hsh, self.path) in self.revmap:
                 f = hsh
         if f is None:
@@ -598,7 +602,7 @@
                             self.ui.debug(
                                 b'fastannotate: reading %s line #%d '
                                 b'to resolve lines %r\n'
-                                % (node.short(hsh), linenum, idxs)
+                                % (short(hsh), linenum, idxs)
                             )
                         fctx = self._resolvefctx(hsh, revmap.rev2path(rev))
                         lines = mdiff.splitnewlines(fctx.data())
@@ -611,7 +615,7 @@
             # run the annotate and the lines should match to the file content
             self.ui.debug(
                 b'fastannotate: annotate %s to resolve lines\n'
-                % node.short(hsh)
+                % short(hsh)
             )
             linelog.annotate(rev)
             fctx = self._resolvefctx(hsh, revmap.rev2path(rev))
@@ -641,11 +645,11 @@
         llrev = self.revmap.hsh2rev(hsh)
         if not llrev:
             raise faerror.CorruptedFileError(
-                b'%s is not in revmap' % node.hex(hsh)
+                b'%s is not in revmap' % hex(hsh)
             )
         if (self.revmap.rev2flag(llrev) & revmapmod.sidebranchflag) != 0:
             raise faerror.CorruptedFileError(
-                b'%s is not in revmap mainbranch' % node.hex(hsh)
+                b'%s is not in revmap mainbranch' % hex(hsh)
             )
         self.linelog.annotate(llrev)
         result = [
diff --git a/hgext/convert/hg.py b/hgext/convert/hg.py
--- a/hgext/convert/hg.py
+++ b/hgext/convert/hg.py
@@ -24,6 +24,12 @@
 
 from mercurial.i18n import _
 from mercurial.pycompat import open
+from mercurial.node import (
+    bin,
+    hex,
+    nullhex,
+    nullid,
+)
 from mercurial import (
     bookmarks,
     context,
@@ -32,7 +38,6 @@
     hg,
     lock as lockmod,
     merge as mergemod,
-    node as nodemod,
     phases,
     pycompat,
     scmutil,
@@ -155,7 +160,7 @@
                 continue
             revid = revmap.get(source.lookuprev(s[0]))
             if not revid:
-                if s[0] == nodemod.nullhex:
+                if s[0] == nullhex:
                     revid = s[0]
                 else:
                     # missing, but keep for hash stability
@@ -174,7 +179,7 @@
 
             revid = s[0]
             subpath = s[1]
-            if revid != nodemod.nullhex:
+            if revid != nullhex:
                 revmap = self.subrevmaps.get(subpath)
                 if revmap is None:
                     revmap = mapfile(
@@ -295,13 +300,13 @@
         parents = pl
         nparents = len(parents)
         if self.filemapmode and nparents == 1:
-            m1node = self.repo.changelog.read(nodemod.bin(parents[0]))[0]
+            m1node = self.repo.changelog.read(bin(parents[0]))[0]
             parent = parents[0]
 
         if len(parents) < 2:
-            parents.append(nodemod.nullid)
+            parents.append(nullid)
         if len(parents) < 2:
-            parents.append(nodemod.nullid)
+            parents.append(nullid)
         p2 = parents.pop(0)
 
         text = commit.desc
@@ -332,12 +337,12 @@
 
             # Only transplant stores its reference in binary
             if label == b'transplant_source':
-                node = nodemod.hex(node)
+                node = hex(node)
 
             newrev = revmap.get(node)
             if newrev is not None:
                 if label == b'transplant_source':
-                    newrev = nodemod.bin(newrev)
+                    newrev = bin(newrev)
 
                 extra[label] = newrev
 
@@ -351,7 +356,7 @@
             p2 = parents.pop(0)
             p1ctx = self.repo[p1]
             p2ctx = None
-            if p2 != nodemod.nullid:
+            if p2 != nullid:
                 p2ctx = self.repo[p2]
             fileset = set(files)
             if full:
@@ -389,7 +394,7 @@
                     origctx = commit.ctx
                 else:
                     origctx = None
-                node = nodemod.hex(self.repo.commitctx(ctx, origctx=origctx))
+                node = hex(self.repo.commitctx(ctx, origctx=origctx))
 
                 # If the node value has changed, but the phase is lower than
                 # draft, set it back to draft since it hasn't been exposed
@@ -406,7 +411,7 @@
 
         if self.filemapmode and nparents == 1:
             man = self.repo.manifestlog.getstorage(b'')
-            mnode = self.repo.changelog.read(nodemod.bin(p2))[0]
+            mnode = self.repo.changelog.read(bin(p2))[0]
             closed = b'close' in commit.extra
             if not closed and not man.cmp(m1node, man.revision(mnode)):
                 self.ui.status(_(b"filtering out empty revision\n"))
@@ -416,7 +421,7 @@
 
     def puttags(self, tags):
         tagparent = self.repo.branchtip(self.tagsbranch, ignoremissing=True)
-        tagparent = tagparent or nodemod.nullid
+        tagparent = tagparent or nullid
 
         oldlines = set()
         for branch, heads in pycompat.iteritems(self.repo.branchmap()):
@@ -468,7 +473,7 @@
             extra,
         )
         node = self.repo.commitctx(ctx)
-        return nodemod.hex(node), nodemod.hex(tagparent)
+        return hex(node), hex(tagparent)
 
     def setfilemapmode(self, active):
         self.filemapmode = active
@@ -484,7 +489,7 @@
             self.ui.status(_(b"updating bookmarks\n"))
             destmarks = self.repo._bookmarks
             changes = [
-                (bookmark, nodemod.bin(updatedbookmark[bookmark]))
+                (bookmark, bin(updatedbookmark[bookmark]))
                 for bookmark in updatedbookmark
             ]
             destmarks.applychanges(self.repo, tr, changes)
@@ -577,7 +582,7 @@
         return [p for p in ctx.parents() if p and self.keep(p.node())]
 
     def getheads(self):
-        return [nodemod.hex(h) for h in self._heads if self.keep(h)]
+        return [hex(h) for h in self._heads if self.keep(h)]
 
     def getfile(self, name, rev):
         try:
@@ -679,7 +684,7 @@
             if self.repo.tagtype(t[0]) == b'global'
         ]
         return {
-            name: nodemod.hex(node) for name, node in tags if self.keep(node)
+            name: hex(node) for name, node in tags if self.keep(node)
         }
 
     def getchangedfiles(self, rev, i):
@@ -718,7 +723,7 @@
 
     def lookuprev(self, rev):
         try:
-            return nodemod.hex(self.repo.lookup(rev))
+            return hex(self.repo.lookup(rev))
         except (error.RepoError, error.LookupError):
             return None
 
diff --git a/hgext/convert/git.py b/hgext/convert/git.py
--- a/hgext/convert/git.py
+++ b/hgext/convert/git.py
@@ -9,10 +9,10 @@
 import os
 
 from mercurial.i18n import _
+from mercurial.node import nullhex
 from mercurial import (
     config,
     error,
-    node as nodemod,
     pycompat,
 )
 
@@ -192,7 +192,7 @@
         return heads
 
     def catfile(self, rev, ftype):
-        if rev == nodemod.nullhex:
+        if rev == nullhex:
             raise IOError
         self.catfilepipe[0].write(rev + b'\n')
         self.catfilepipe[0].flush()
@@ -214,7 +214,7 @@
         return data
 
     def getfile(self, name, rev):
-        if rev == nodemod.nullhex:
+        if rev == nullhex:
             return None, None
         if name == b'.hgsub':
             data = b'\n'.join([m.hgsub() for m in self.submoditer()])
@@ -228,7 +228,7 @@
         return data, mode
 
     def submoditer(self):
-        null = nodemod.nullhex
+        null = nullhex
         for m in sorted(self.submodules, key=lambda p: p.path):
             if m.node != null:
                 yield m
@@ -316,7 +316,7 @@
                 subexists[0] = True
                 if entry[4] == b'D' or renamesource:
                     subdeleted[0] = True
-                    changes.append((b'.hgsub', nodemod.nullhex))
+                    changes.append((b'.hgsub', nullhex))
                 else:
                     changes.append((b'.hgsub', b''))
             elif entry[1] == b'160000' or entry[0] == b':160000':
@@ -324,7 +324,7 @@
                     subexists[0] = True
             else:
                 if renamesource:
-                    h = nodemod.nullhex
+                    h = nullhex
                 self.modecache[(f, h)] = (p and b"x") or (s and b"l") or b""
                 changes.append((f, h))
 
@@ -361,7 +361,7 @@
 
         if subexists[0]:
             if subdeleted[0]:
-                changes.append((b'.hgsubstate', nodemod.nullhex))
+                changes.append((b'.hgsubstate', nullhex))
             else:
                 self.retrievegitmodules(version)
                 changes.append((b'.hgsubstate', b''))
diff --git a/hgext/absorb.py b/hgext/absorb.py
--- a/hgext/absorb.py
+++ b/hgext/absorb.py
@@ -36,6 +36,11 @@
 import collections
 
 from mercurial.i18n import _
+from mercurial.node import (
+    hex,
+    nullid,
+    short,
+)
 from mercurial import (
     cmdutil,
     commands,
@@ -44,7 +49,6 @@
     error,
     linelog,
     mdiff,
-    node,
     obsolete,
     patch,
     phases,
@@ -102,7 +106,7 @@
         return b''
 
     def node(self):
-        return node.nullid
+        return nullid
 
 
 def uniq(lst):
@@ -367,7 +371,7 @@
                 idx = (max(rev - 1, 0)) // 2
                 self.ui.write(
                     _(b'%s: chunk %d:%d -> %d lines\n')
-                    % (node.short(self.fctxs[idx].node()), a1, a2, len(blines))
+                    % (short(self.fctxs[idx].node()), a1, a2, len(blines))
                 )
             self.linelog.replacelines(rev, a1, a2, b1, b2)
         if self.opts.get(b'edit_lines', False):
@@ -486,7 +490,7 @@
             editortext += _(b'HG: %s/%s %s %s\n') % (
                 b'|' * i,
                 b'-' * (len(visiblefctxs) - i + 1),
-                node.short(f.node()),
+                short(f.node()),
                 f.description().split(b'\n', 1)[0],
             )
         editortext += _(b'HG: %s\n') % (b'|' * len(visiblefctxs))
@@ -816,7 +820,7 @@
         if self.ui.debugflag:
             return b'%d:%s' % (ctx.rev(), ctx.hex())
         else:
-            return b'%d:%s' % (ctx.rev(), node.short(ctx.node()))
+            return b'%d:%s' % (ctx.rev(), short(ctx.node()))
 
     def _getnewfilecontents(self, ctx):
         """(ctx) -> {path: str}
@@ -849,7 +853,7 @@
                 changes.append((name, hsh))
                 if self.ui.verbose:
                     self.ui.write(
-                        _(b'moving bookmark %s to %s\n') % (name, node.hex(hsh))
+                        _(b'moving bookmark %s to %s\n') % (name, hex(hsh))
                     )
             else:
                 changes.append((name, None))
@@ -920,7 +924,7 @@
         the commit is a clone from ctx, with a (optionally) different p1, and
         different file contents replaced by memworkingcopy.
         """
-        parents = p1 and (p1, node.nullid)
+        parents = p1 and (p1, nullid)
         extra = ctx.extra()
         if self._useobsolete and self.ui.configbool(b'absorb', b'add-noise'):
             extra[b'absorb_source'] = ctx.hex()
diff --git a/contrib/undumprevlog b/contrib/undumprevlog
--- a/contrib/undumprevlog
+++ b/contrib/undumprevlog
@@ -6,9 +6,9 @@
 from __future__ import absolute_import, print_function
 
 import sys
+from mercurial.node import bin
 from mercurial import (
     encoding,
-    node,
     revlog,
     transaction,
     vfs as vfsmod,
@@ -31,13 +31,13 @@
         r = revlog.revlog(opener, f)
         procutil.stdout.write(b'%s\n' % f)
     elif l.startswith("node:"):
-        n = node.bin(l[6:-1])
+        n = bin(l[6:-1])
     elif l.startswith("linkrev:"):
         lr = int(l[9:-1])
     elif l.startswith("parents:"):
         p = l[9:-1].split()
-        p1 = node.bin(p[0])
-        p2 = node.bin(p[1])
+        p1 = bin(p[0])
+        p2 = bin(p[1])
     elif l.startswith("length:"):
         length = int(l[8:-1])
         sys.stdin.readline()  # start marker
diff --git a/contrib/dumprevlog b/contrib/dumprevlog
--- a/contrib/dumprevlog
+++ b/contrib/dumprevlog
@@ -5,9 +5,9 @@
 from __future__ import absolute_import, print_function
 
 import sys
+from mercurial.node import hex
 from mercurial import (
     encoding,
-    node,
     pycompat,
     revlog,
 )
@@ -38,9 +38,9 @@
         n = r.node(i)
         p = r.parents(n)
         d = r.revision(n)
-        printb(b"node: %s" % node.hex(n))
+        printb(b"node: %s" % hex(n))
         printb(b"linkrev: %d" % r.linkrev(i))
-        printb(b"parents: %s %s" % (node.hex(p[0]), node.hex(p[1])))
+        printb(b"parents: %s %s" % (hex(p[0]), hex(p[1])))
         printb(b"length: %d" % len(d))
         printb(b"-start-")
         printb(d)



To: joerg.sonnenberger, durin42, martinvonz, #hg-reviewers, Alphare
Cc: Alphare, mercurial-patches


More information about the Mercurial-patches mailing list