Bug 1168607 - Add mode to MercurialFileFinder to support non-relative paths; r=glandium

The moz.build reader uses absolute paths when referencing moz.build
files. *Finder classes expect paths to be relative to a base. When we
switched the reader to use *Finder instances for I/O, we simply provided
a default FileFinder based at the filesystem root. This was quick and
easy. Things worked.

Unfortunately, that solution isn't ideal because not all *Finder
instances can accept absolute paths like that. The
MercurialRevisionFinder is one of them.

Changing the moz.build reader to talk in terms of relative paths is a
lot of work. While this would be ideal, it is significantly easier to
defer the problem until later and hack up MercurialRevisionFinder to
accept absolute paths. This commit does exactly that.

Bug 1171069 has been filed to track converting BuildReader to relative
paths.
This commit is contained in:
Gregory Szorc 2015-06-08 09:33:46 -07:00
parent d64a7e66e6
commit a0f182b4e8
2 changed files with 44 additions and 2 deletions

View File

@ -978,17 +978,28 @@ class MercurialFile(BaseFile):
class MercurialRevisionFinder(BaseFinder):
"""A finder that operates on a specific Mercurial revision."""
def __init__(self, repo, rev='.', **kwargs):
def __init__(self, repo, rev='.', recognize_repo_paths=False, **kwargs):
"""Create a finder attached to a specific revision in a repository.
If no revision is given, open the parent of the working directory.
``recognize_repo_paths`` will enable a mode where ``.get()`` will
recognize full paths that include the repo's path. Typically Finder
instances are "bound" to a base directory and paths are relative to
that directory. This mode changes that. When this mode is activated,
``.find()`` will not work! This mode exists to support the moz.build
reader, which uses absolute paths instead of relative paths. The reader
should eventually be rewritten to use relative paths and this hack
should be removed (TODO bug 1171069).
"""
if not hglib:
raise Exception('hglib package not found')
super(MercurialRevisionFinder, self).__init__(base=repo, **kwargs)
self._root = repo
self._root = mozpath.normpath(repo).rstrip('/')
self._recognize_repo_paths = recognize_repo_paths
# We change directories here otherwise we have to deal with relative
# paths.
oldcwd = os.getcwd()
@ -1007,9 +1018,18 @@ class MercurialRevisionFinder(BaseFinder):
self._files[relpath] = None
def _find(self, pattern):
if self._recognize_repo_paths:
raise NotImplementedError('cannot use find with recognize_repo_path')
return self._find_helper(pattern, self._files, self._get)
def get(self, path):
if self._recognize_repo_paths:
if not path.startswith(self._root):
raise ValueError('lookups in recognize_repo_paths mode must be '
'prefixed with repo path: %s' % path)
path = path[len(self._root) + 1:]
try:
return self._get(path)
except KeyError:

View File

@ -1081,6 +1081,28 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir):
f = finder.get('bar')
self.assertEqual(f.read(), 'bar second')
def test_recognize_repo_paths(self):
c = hglib.open(self.tmpdir)
with open(self.tmppath('foo'), 'wb') as fh:
fh.write('initial')
c.add(self.tmppath('foo'))
c.commit('initial')
c.rawcommand(['update', 'null'])
finder = MercurialRevisionFinder(self.tmpdir, rev='0',
recognize_repo_paths=True)
with self.assertRaises(NotImplementedError):
list(finder.find(''))
with self.assertRaises(ValueError):
finder.get('foo')
with self.assertRaises(ValueError):
finder.get('')
f = finder.get(self.tmppath('foo'))
self.assertIsInstance(f, MercurialFile)
self.assertEqual(f.read(), 'initial')
if __name__ == '__main__':
mozunit.main()