Patchwork D8917: requirements: introduce new requirements related module

login
register
mail settings
Submitter phabricator
Date Aug. 9, 2020, 9:28 a.m.
Message ID <differential-rev-PHID-DREV-fuynlfuezp54ficcgepz-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47018/
State Superseded
Headers show

Comments

phabricator - Aug. 9, 2020, 9:28 a.m.
pulkit created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: martinvonz.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  It was not clear where all requirements should and related APIs should be, this
  patch introduces a requirements module which will have all exitsing requirements
  and related APIs.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  hgext/narrow/__init__.py
  hgext/narrow/narrowbundle2.py
  hgext/narrow/narrowcommands.py
  hgext/remotefilelog/remotefilelogserver.py
  hgext/sqlitestore.py
  mercurial/bundle2.py
  mercurial/changegroup.py
  mercurial/cmdutil.py
  mercurial/exchange.py
  mercurial/hg.py
  mercurial/interfaces/repository.py
  mercurial/localrepo.py
  mercurial/narrowspec.py
  mercurial/phases.py
  mercurial/repair.py
  mercurial/requirements.py
  mercurial/sparse.py
  mercurial/upgrade.py
  tests/pullext.py

CHANGE DETAILS




To: pulkit, durin42, martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/pullext.py b/tests/pullext.py
--- a/tests/pullext.py
+++ b/tests/pullext.py
@@ -13,8 +13,8 @@ 
     error,
     extensions,
     localrepo,
+    requirements,
 )
-from mercurial.interfaces import repository
 
 
 def clonecommand(orig, ui, repo, *args, **kwargs):
@@ -31,7 +31,7 @@ 
 
 
 def featuresetup(ui, features):
-    features.add(repository.NARROW_REQUIREMENT)
+    features.add(requirements.NARROW_REQUIREMENT)
 
 
 def extsetup(ui):
diff --git a/mercurial/upgrade.py b/mercurial/upgrade.py
--- a/mercurial/upgrade.py
+++ b/mercurial/upgrade.py
@@ -20,13 +20,13 @@ 
     manifest,
     metadata,
     pycompat,
+    requirements,
     revlog,
     scmutil,
     util,
     vfs as vfsmod,
 )
 
-from .interfaces import repository
 from .utils import compression
 
 # list of requirements that request a clone of all revlog if added/removed
@@ -59,7 +59,7 @@ 
     return {
         # The upgrade code does not yet support these experimental features.
         # This is an artificial limitation.
-        repository.TREEMANIFEST_REQUIREMENT,
+        requirements.TREEMANIFEST_REQUIREMENT,
         # This was a precursor to generaldelta and was never enabled by default.
         # It should (hopefully) not exist in the wild.
         b'parentdelta',
diff --git a/mercurial/sparse.py b/mercurial/sparse.py
--- a/mercurial/sparse.py
+++ b/mercurial/sparse.py
@@ -21,10 +21,10 @@ 
     mergestate as mergestatemod,
     pathutil,
     pycompat,
+    requirements,
     scmutil,
     util,
 )
-from .interfaces import repository
 from .utils import hashutil
 
 
@@ -608,11 +608,11 @@ 
     # updated. But this requires massive rework to matcher() and its
     # consumers.
 
-    if repository.SPARSE_REQUIREMENT in oldrequires and removing:
-        repo.requirements.discard(repository.SPARSE_REQUIREMENT)
+    if requirements.SPARSE_REQUIREMENT in oldrequires and removing:
+        repo.requirements.discard(requirements.SPARSE_REQUIREMENT)
         scmutil.writereporequirements(repo)
-    elif repository.SPARSE_REQUIREMENT not in oldrequires:
-        repo.requirements.add(repository.SPARSE_REQUIREMENT)
+    elif requirements.SPARSE_REQUIREMENT not in oldrequires:
+        repo.requirements.add(requirements.SPARSE_REQUIREMENT)
         scmutil.writereporequirements(repo)
 
     try:
diff --git a/mercurial/requirements.py b/mercurial/requirements.py
new file mode 100644
--- /dev/null
+++ b/mercurial/requirements.py
@@ -0,0 +1,22 @@ 
+# requirements.py - objects and functions related to repository requirements
+#
+# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from __future__ import absolute_import
+
+# When narrowing is finalized and no longer subject to format changes,
+# we should move this to just "narrow" or similar.
+NARROW_REQUIREMENT = b'narrowhg-experimental'
+
+# Enables sparse working directory usage
+SPARSE_REQUIREMENT = b'exp-sparse'
+
+# Enables the internal phase which is used to hide changesets instead
+# of stripping them
+INTERNAL_PHASE_REQUIREMENT = b'internal-phase'
+
+# Stores manifest in Tree structure
+TREEMANIFEST_REQUIREMENT = b'treemanifest'
diff --git a/mercurial/repair.py b/mercurial/repair.py
--- a/mercurial/repair.py
+++ b/mercurial/repair.py
@@ -26,9 +26,9 @@ 
     pathutil,
     phases,
     pycompat,
+    requirements,
     util,
 )
-from .interfaces import repository
 from .utils import (
     hashutil,
     stringutil,
@@ -419,7 +419,7 @@ 
 
 def manifestrevlogs(repo):
     yield repo.manifestlog.getstorage(b'')
-    if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+    if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
         # This logic is safe if treemanifest isn't enabled, but also
         # pointless, so we skip it if treemanifest isn't enabled.
         for unencoded, encoded, size in repo.store.datafiles():
@@ -477,7 +477,7 @@ 
 
         progress.complete()
 
-        if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+        if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
             # This logic is safe if treemanifest isn't enabled, but also
             # pointless, so we skip it if treemanifest isn't enabled.
             for dir in pathutil.dirs(seenfiles):
diff --git a/mercurial/phases.py b/mercurial/phases.py
--- a/mercurial/phases.py
+++ b/mercurial/phases.py
@@ -121,11 +121,11 @@ 
 from . import (
     error,
     pycompat,
+    requirements,
     smartset,
     txnutil,
     util,
 )
-from .interfaces import repository
 
 _fphasesentry = struct.Struct(b'>i20s')
 
@@ -155,7 +155,7 @@ 
 
 def supportinternal(repo):
     """True if the internal phase can be used on a repository"""
-    return repository.INTERNAL_PHASE_REQUIREMENT in repo.requirements
+    return requirements.INTERNAL_PHASE_REQUIREMENT in repo.requirements
 
 
 def _readroots(repo, phasedefaults=None):
diff --git a/mercurial/narrowspec.py b/mercurial/narrowspec.py
--- a/mercurial/narrowspec.py
+++ b/mercurial/narrowspec.py
@@ -9,12 +9,12 @@ 
 
 from .i18n import _
 from .pycompat import getattr
-from .interfaces import repository
 from . import (
     error,
     match as matchmod,
     merge,
     mergestate as mergestatemod,
+    requirements,
     scmutil,
     sparse,
     util,
@@ -186,7 +186,7 @@ 
 
 
 def savebackup(repo, backupname):
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return
     svfs = repo.svfs
     svfs.tryunlink(backupname)
@@ -194,13 +194,13 @@ 
 
 
 def restorebackup(repo, backupname):
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return
     util.rename(repo.svfs.join(backupname), repo.svfs.join(FILENAME))
 
 
 def savewcbackup(repo, backupname):
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return
     vfs = repo.vfs
     vfs.tryunlink(backupname)
@@ -212,7 +212,7 @@ 
 
 
 def restorewcbackup(repo, backupname):
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return
     # It may not exist in old repos
     if repo.vfs.exists(backupname):
@@ -220,7 +220,7 @@ 
 
 
 def clearwcbackup(repo, backupname):
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return
     repo.vfs.tryunlink(backupname)
 
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -56,6 +56,7 @@ 
     pycompat,
     rcutil,
     repoview,
+    requirements as requirementsmod,
     revset,
     revsetlang,
     scmutil,
@@ -816,7 +817,10 @@ 
 
     ``error.RepoError`` should be raised on failure.
     """
-    if repository.SPARSE_REQUIREMENT in requirements and not sparse.enabled:
+    if (
+        requirementsmod.SPARSE_REQUIREMENT in requirements
+        and not sparse.enabled
+    ):
         raise error.RepoError(
             _(
                 b'repository is using sparse feature but '
@@ -846,7 +850,7 @@ 
     """
     options = {}
 
-    if repository.TREEMANIFEST_REQUIREMENT in requirements:
+    if requirementsmod.TREEMANIFEST_REQUIREMENT in requirements:
         options[b'treemanifest'] = True
 
     # experimental config: format.manifestcachesize
@@ -963,7 +967,7 @@ 
             msg = _(b'invalid value for `storage.revlog.zstd.level` config: %d')
             raise error.Abort(msg % options[b'zstd.level'])
 
-    if repository.NARROW_REQUIREMENT in requirements:
+    if requirementsmod.NARROW_REQUIREMENT in requirements:
         options[b'enableellipsis'] = True
 
     if ui.configbool(b'experimental', b'rust.index'):
@@ -1012,7 +1016,7 @@ 
     features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
     features.add(repository.REPO_FEATURE_STREAM_CLONE)
 
-    if repository.NARROW_REQUIREMENT in requirements:
+    if requirementsmod.NARROW_REQUIREMENT in requirements:
         return revlognarrowfilestorage
     else:
         return revlogfilestorage
@@ -1053,7 +1057,7 @@ 
     supportedformats = {
         b'revlogv1',
         b'generaldelta',
-        repository.TREEMANIFEST_REQUIREMENT,
+        requirementsmod.TREEMANIFEST_REQUIREMENT,
         COPIESSDC_REQUIREMENT,
         REVLOGV2_REQUIREMENT,
         SIDEDATA_REQUIREMENT,
@@ -1067,8 +1071,8 @@ 
         b'shared',
         b'relshared',
         b'dotencode',
-        repository.SPARSE_REQUIREMENT,
-        repository.INTERNAL_PHASE_REQUIREMENT,
+        requirementsmod.SPARSE_REQUIREMENT,
+        requirementsmod.INTERNAL_PHASE_REQUIREMENT,
     }
 
     # list of prefix for file which can be written without 'wlock'
@@ -1529,14 +1533,14 @@ 
 
     @storecache(narrowspec.FILENAME)
     def _storenarrowmatch(self):
-        if repository.NARROW_REQUIREMENT not in self.requirements:
+        if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
             return matchmod.always()
         include, exclude = self.narrowpats
         return narrowspec.match(self.root, include=include, exclude=exclude)
 
     @storecache(narrowspec.FILENAME)
     def _narrowmatch(self):
-        if repository.NARROW_REQUIREMENT not in self.requirements:
+        if requirementsmod.NARROW_REQUIREMENT not in self.requirements:
             return matchmod.always()
         narrowspec.checkworkingcopynarrowspec(self)
         include, exclude = self.narrowpats
@@ -3314,7 +3318,7 @@ 
         requirements.add(SIDEDATA_REQUIREMENT)
         requirements.add(COPIESSDC_REQUIREMENT)
     if ui.configbool(b'experimental', b'treemanifest'):
-        requirements.add(repository.TREEMANIFEST_REQUIREMENT)
+        requirements.add(requirementsmod.TREEMANIFEST_REQUIREMENT)
 
     revlogv2 = ui.config(b'experimental', b'revlogv2')
     if revlogv2 == b'enable-unstable-format-and-corrupt-my-data':
@@ -3324,10 +3328,10 @@ 
         requirements.add(REVLOGV2_REQUIREMENT)
     # experimental config: format.internal-phase
     if ui.configbool(b'format', b'internal-phase'):
-        requirements.add(repository.INTERNAL_PHASE_REQUIREMENT)
+        requirements.add(requirementsmod.INTERNAL_PHASE_REQUIREMENT)
 
     if createopts.get(b'narrowfiles'):
-        requirements.add(repository.NARROW_REQUIREMENT)
+        requirements.add(requirementsmod.NARROW_REQUIREMENT)
 
     if createopts.get(b'lfs'):
         requirements.add(b'lfs')
diff --git a/mercurial/interfaces/repository.py b/mercurial/interfaces/repository.py
--- a/mercurial/interfaces/repository.py
+++ b/mercurial/interfaces/repository.py
@@ -11,20 +11,6 @@ 
 from .. import error
 from . import util as interfaceutil
 
-# When narrowing is finalized and no longer subject to format changes,
-# we should move this to just "narrow" or similar.
-NARROW_REQUIREMENT = b'narrowhg-experimental'
-
-# Enables sparse working directory usage
-SPARSE_REQUIREMENT = b'exp-sparse'
-
-# Enables the internal phase which is used to hide changesets instead
-# of stripping them
-INTERNAL_PHASE_REQUIREMENT = b'internal-phase'
-
-# Stores manifest in Tree structure
-TREEMANIFEST_REQUIREMENT = b'treemanifest'
-
 # Local repository feature string.
 
 # Revlogs are being used for file storage.
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -38,6 +38,7 @@ 
     node,
     phases,
     pycompat,
+    requirements,
     scmutil,
     sshpeer,
     statichttprepo,
@@ -49,7 +50,6 @@ 
     vfs as vfsmod,
 )
 from .utils import hashutil
-from .interfaces import repository as repositorymod
 
 release = lock.release
 
@@ -388,7 +388,7 @@ 
     if default:
         template = b'[paths]\ndefault = %s\n'
         destrepo.vfs.write(b'hgrc', util.tonativeeol(template % default))
-    if repositorymod.NARROW_REQUIREMENT in sourcerepo.requirements:
+    if requirements.NARROW_REQUIREMENT in sourcerepo.requirements:
         with destrepo.wlock():
             narrowspec.copytoworkingcopy(destrepo)
 
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -32,6 +32,7 @@ 
     phases,
     pushkey,
     pycompat,
+    requirements,
     scmutil,
     sslutil,
     streamclone,
@@ -39,7 +40,6 @@ 
     util,
     wireprototypes,
 )
-from .interfaces import repository
 from .utils import (
     hashutil,
     stringutil,
@@ -1068,7 +1068,7 @@ 
     cgpart = bundler.newpart(b'changegroup', data=cgstream)
     if cgversions:
         cgpart.addparam(b'version', version)
-    if repository.TREEMANIFEST_REQUIREMENT in pushop.repo.requirements:
+    if requirements.TREEMANIFEST_REQUIREMENT in pushop.repo.requirements:
         cgpart.addparam(b'treemanifest', b'1')
     if b'exp-sidedata-flag' in pushop.repo.requirements:
         cgpart.addparam(b'exp-sidedata', b'1')
@@ -1691,7 +1691,7 @@ 
         old_heads = unficl.heads()
         clstart = len(unficl)
         _pullbundle2(pullop)
-        if repository.NARROW_REQUIREMENT in repo.requirements:
+        if requirements.NARROW_REQUIREMENT in repo.requirements:
             # XXX narrow clones filter the heads on the server side during
             # XXX getbundle and result in partial replies as well.
             # XXX Disable pull bundles in this case as band aid to avoid
@@ -2557,7 +2557,7 @@ 
 
     part.addparam(b'nbchanges', b'%d' % len(outgoing.missing), mandatory=False)
 
-    if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+    if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
         part.addparam(b'treemanifest', b'1')
 
     if b'exp-sidedata-flag' in repo.requirements:
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -46,6 +46,7 @@ 
     phases,
     pycompat,
     repair,
+    requirements,
     revlog,
     rewriteutil,
     scmutil,
@@ -58,8 +59,6 @@ 
     vfs as vfsmod,
 )
 
-from .interfaces import repository
-
 from .utils import (
     dateutil,
     stringutil,
@@ -1360,7 +1359,7 @@ 
         if cl:
             r = repo.unfiltered().changelog
         elif dir:
-            if repository.TREEMANIFEST_REQUIREMENT not in repo.requirements:
+            if requirements.TREEMANIFEST_REQUIREMENT not in repo.requirements:
                 raise error.Abort(
                     _(
                         b"--dir can only be used on repos with "
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -26,6 +26,7 @@ 
     mdiff,
     phases,
     pycompat,
+    requirements,
     util,
 )
 
@@ -949,7 +950,7 @@ 
         # either, because we don't discover which directory nodes to
         # send along with files. This could probably be fixed.
         fastpathlinkrev = fastpathlinkrev and (
-            repository.TREEMANIFEST_REQUIREMENT not in repo.requirements
+            requirements.TREEMANIFEST_REQUIREMENT not in repo.requirements
         )
 
         fnodes = {}  # needed file nodes
@@ -1467,7 +1468,7 @@ 
     if (
         repo.ui.configbool(b'experimental', b'changegroup3')
         or repo.ui.configbool(b'experimental', b'treemanifest')
-        or repository.TREEMANIFEST_REQUIREMENT in repo.requirements
+        or requirements.TREEMANIFEST_REQUIREMENT in repo.requirements
     ):
         # we keep version 03 because we need to to exchange treemanifest data
         #
@@ -1495,7 +1496,7 @@ 
 # Changegroup versions that can be created from the repo
 def supportedoutgoingversions(repo):
     versions = allsupportedversions(repo)
-    if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+    if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
         # Versions 01 and 02 support only flat manifests and it's just too
         # expensive to convert between the flat manifest and tree manifest on
         # the fly. Since tree manifests are hashed differently, all of history
@@ -1503,7 +1504,7 @@ 
         # support versions 01 and 02.
         versions.discard(b'01')
         versions.discard(b'02')
-    if repository.NARROW_REQUIREMENT in repo.requirements:
+    if requirements.NARROW_REQUIREMENT in repo.requirements:
         # Versions 01 and 02 don't support revlog flags, and we need to
         # support that for stripping and unbundling to work.
         versions.discard(b'01')
diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -166,13 +166,13 @@ 
     phases,
     pushkey,
     pycompat,
+    requirements,
     scmutil,
     streamclone,
     tags,
     url,
     util,
 )
-from .interfaces import repository
 from .utils import stringutil
 
 urlerr = util.urlerr
@@ -1966,7 +1966,7 @@ 
         nbchangesets = int(inpart.params.get(b'nbchanges'))
     if (
         b'treemanifest' in inpart.params
-        and repository.TREEMANIFEST_REQUIREMENT not in op.repo.requirements
+        and requirements.TREEMANIFEST_REQUIREMENT not in op.repo.requirements
     ):
         if len(op.repo.changelog) != 0:
             raise error.Abort(
@@ -1975,7 +1975,7 @@ 
                     b"non-empty and does not use tree manifests"
                 )
             )
-        op.repo.requirements.add(repository.TREEMANIFEST_REQUIREMENT)
+        op.repo.requirements.add(requirements.TREEMANIFEST_REQUIREMENT)
         op.repo.svfs.options = localrepo.resolvestorevfsoptions(
             op.repo.ui, op.repo.requirements, op.repo.features
         )
@@ -2577,7 +2577,7 @@ 
 
         part = bundler.newpart(b'changegroup', data=cgdata)
         part.addparam(b'version', cgversion)
-        if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+        if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
             part.addparam(b'treemanifest', b'1')
         if b'exp-sidedata-flag' in repo.requirements:
             part.addparam(b'exp-sidedata', b'1')
diff --git a/hgext/sqlitestore.py b/hgext/sqlitestore.py
--- a/hgext/sqlitestore.py
+++ b/hgext/sqlitestore.py
@@ -67,6 +67,7 @@ 
     mdiff,
     pycompat,
     registrar,
+    requirements,
     util,
     verify,
 )
@@ -1151,7 +1152,7 @@ 
     supported.add(REQUIREMENT_ZLIB)
     supported.add(REQUIREMENT_NONE)
     supported.add(REQUIREMENT_SHALLOW_FILES)
-    supported.add(repository.NARROW_REQUIREMENT)
+    supported.add(requirements.NARROW_REQUIREMENT)
 
 
 def newreporequirements(orig, ui, createopts):
diff --git a/hgext/remotefilelog/remotefilelogserver.py b/hgext/remotefilelog/remotefilelogserver.py
--- a/hgext/remotefilelog/remotefilelogserver.py
+++ b/hgext/remotefilelog/remotefilelogserver.py
@@ -23,6 +23,7 @@ 
     extensions,
     match,
     pycompat,
+    requirements,
     store,
     streamclone,
     util,
@@ -30,7 +31,6 @@ 
     wireprototypes,
     wireprotov1server,
 )
-from mercurial.interfaces import repository
 from . import (
     constants,
     shallowutil,
@@ -170,7 +170,7 @@ 
                         if kind == stat.S_IFDIR:
                             visit.append(fp)
 
-            if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+            if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
                 for (u, e, s) in repo.store.datafiles():
                     if u.startswith(b'meta/') and (
                         u.endswith(b'.i') or u.endswith(b'.d')
diff --git a/hgext/narrow/narrowcommands.py b/hgext/narrow/narrowcommands.py
--- a/hgext/narrow/narrowcommands.py
+++ b/hgext/narrow/narrowcommands.py
@@ -27,11 +27,11 @@ 
     registrar,
     repair,
     repoview,
+    requirements,
     sparse,
     util,
     wireprototypes,
 )
-from mercurial.interfaces import repository
 
 table = {}
 command = registrar.command(table)
@@ -133,7 +133,7 @@ 
 def pullnarrowcmd(orig, ui, repo, *args, **opts):
     """Wraps pull command to allow modifying narrow spec."""
     wrappedextraprepare = util.nullcontextmanager()
-    if repository.NARROW_REQUIREMENT in repo.requirements:
+    if requirements.NARROW_REQUIREMENT in repo.requirements:
 
         def pullbundle2extraprepare_widen(orig, pullop, kwargs):
             orig(pullop, kwargs)
@@ -150,7 +150,7 @@ 
 
 def archivenarrowcmd(orig, ui, repo, *args, **opts):
     """Wraps archive command to narrow the default includes."""
-    if repository.NARROW_REQUIREMENT in repo.requirements:
+    if requirements.NARROW_REQUIREMENT in repo.requirements:
         repo_includes, repo_excludes = repo.narrowpats
         includes = set(opts.get('include', []))
         excludes = set(opts.get('exclude', []))
@@ -166,7 +166,7 @@ 
 
 def pullbundle2extraprepare(orig, pullop, kwargs):
     repo = pullop.repo
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         return orig(pullop, kwargs)
 
     if wireprototypes.NARROWCAP not in pullop.remote.capabilities():
@@ -482,7 +482,7 @@ 
     exclude switches, the changes are applied immediately.
     """
     opts = pycompat.byteskwargs(opts)
-    if repository.NARROW_REQUIREMENT not in repo.requirements:
+    if requirements.NARROW_REQUIREMENT not in repo.requirements:
         raise error.Abort(
             _(
                 b'the tracked command is only supported on '
diff --git a/hgext/narrow/narrowbundle2.py b/hgext/narrow/narrowbundle2.py
--- a/hgext/narrow/narrowbundle2.py
+++ b/hgext/narrow/narrowbundle2.py
@@ -20,11 +20,11 @@ 
     localrepo,
     narrowspec,
     repair,
+    requirements,
     scmutil,
     util,
     wireprototypes,
 )
-from mercurial.interfaces import repository
 from mercurial.utils import stringutil
 
 _NARROWACL_SECTION = b'narrowacl'
@@ -108,7 +108,7 @@ 
 
         part = bundler.newpart(b'changegroup', data=cgdata)
         part.addparam(b'version', version)
-        if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+        if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
             part.addparam(b'treemanifest', b'1')
 
 
@@ -163,7 +163,7 @@ 
 
         part = bundler.newpart(b'changegroup', data=cgdata)
         part.addparam(b'version', version)
-        if repository.TREEMANIFEST_REQUIREMENT in repo.requirements:
+        if requirements.TREEMANIFEST_REQUIREMENT in repo.requirements:
             part.addparam(b'treemanifest', b'1')
 
 
@@ -178,8 +178,8 @@ 
     narrowspec.validatepatterns(includepats)
     narrowspec.validatepatterns(excludepats)
 
-    if not repository.NARROW_REQUIREMENT in op.repo.requirements:
-        op.repo.requirements.add(repository.NARROW_REQUIREMENT)
+    if not requirements.NARROW_REQUIREMENT in op.repo.requirements:
+        op.repo.requirements.add(requirements.NARROW_REQUIREMENT)
         scmutil.writereporequirements(op.repo)
     op.repo.setnarrowpats(includepats, excludepats)
     narrowspec.copytoworkingcopy(op.repo)
@@ -194,8 +194,8 @@ 
     narrowspec.validatepatterns(includepats)
     narrowspec.validatepatterns(excludepats)
 
-    if repository.NARROW_REQUIREMENT not in op.repo.requirements:
-        op.repo.requirements.add(repository.NARROW_REQUIREMENT)
+    if requirements.NARROW_REQUIREMENT not in op.repo.requirements:
+        op.repo.requirements.add(requirements.NARROW_REQUIREMENT)
         scmutil.writereporequirements(op.repo)
     op.repo.setnarrowpats(includepats, excludepats)
     narrowspec.copytoworkingcopy(op.repo)
diff --git a/hgext/narrow/__init__.py b/hgext/narrow/__init__.py
--- a/hgext/narrow/__init__.py
+++ b/hgext/narrow/__init__.py
@@ -11,9 +11,9 @@ 
 from mercurial import (
     localrepo,
     registrar,
+    requirements,
 )
 
-from mercurial.interfaces import repository
 
 from . import (
     narrowbundle2,
@@ -52,7 +52,7 @@ 
 
 
 def featuresetup(ui, features):
-    features.add(repository.NARROW_REQUIREMENT)
+    features.add(requirements.NARROW_REQUIREMENT)
 
 
 def uisetup(ui):
@@ -69,7 +69,7 @@ 
         return
 
     repo.ui.setconfig(b'experimental', b'narrow', True, b'narrow-ext')
-    if repository.NARROW_REQUIREMENT in repo.requirements:
+    if requirements.NARROW_REQUIREMENT in repo.requirements:
         narrowrepo.wraprepo(repo)
         narrowwirepeer.reposetup(repo)