зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1168607 - Add a native Mercurial finder; r=glandium
The hglib Mercurial finder was nice. But it is somewhat slow, as it involves a separate Mercurial process. This commit introduces a native Mercurial finder that speaks directly to a Mercurial repository instance. It is significantly faster. The new code is isolated to its own file because it imports Mercurial code, which is GPL. --HG-- extra : commitid : 8CzDFt3lQmx extra : rebase_source : 1540ad20d795086926b316612062e2a1f10c4958
This commit is contained in:
Родитель
d5d6c72dd3
Коммит
013f437636
|
@ -1013,7 +1013,7 @@ class MercurialRevisionFinder(BaseFinder):
|
|||
|
||||
# Immediately populate the list of files in the repo since nearly every
|
||||
# operation requires this list.
|
||||
out = self._client.rawcommand([b'files', b'--rev', self._rev])
|
||||
out = self._client.rawcommand([b'files', b'--rev', str(self._rev)])
|
||||
for relpath in out.splitlines():
|
||||
self._files[relpath] = None
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
# Copyright (C) 2015 Mozilla Contributors
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# As a special exception, the copyright holders of this code give you
|
||||
# permission to combine this code with the software known as 'mozbuild',
|
||||
# and to distribute those combinations without any restriction
|
||||
# coming from the use of this file. (The General Public License
|
||||
# restrictions do apply in other respects; for example, they cover
|
||||
# modification of the file, and distribution when not combined with
|
||||
# mozbuild.)
|
||||
#
|
||||
# If you modify this code, you may extend this exception to your
|
||||
# version of the code, but you are not obliged to do so. If you
|
||||
# do not wish to do so, delete this exception statement from your
|
||||
# version.
|
||||
|
||||
import mercurial.error as error
|
||||
import mercurial.hg as hg
|
||||
import mercurial.ui as hgui
|
||||
|
||||
from .files import (
|
||||
BaseFinder,
|
||||
MercurialFile,
|
||||
)
|
||||
import mozpack.path as mozpath
|
||||
|
||||
|
||||
# This isn't a complete implementation of BaseFile. But it is complete
|
||||
# enough for moz.build reading.
|
||||
class MercurialNativeFile(MercurialFile):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
|
||||
def read(self):
|
||||
return self.data
|
||||
|
||||
|
||||
class MercurialNativeRevisionFinder(BaseFinder):
|
||||
def __init__(self, repo, rev='.', recognize_repo_paths=False):
|
||||
"""Create a finder attached to a specific changeset.
|
||||
|
||||
Accepts a Mercurial localrepo and changectx instance.
|
||||
"""
|
||||
if isinstance(repo, (str, unicode)):
|
||||
path = repo
|
||||
repo = hg.repository(hgui.ui(), repo)
|
||||
else:
|
||||
path = repo.root
|
||||
|
||||
super(MercurialNativeRevisionFinder, self).__init__(base=repo.root)
|
||||
|
||||
self._repo = repo
|
||||
self._rev = rev
|
||||
self._root = mozpath.normpath(path)
|
||||
self._recognize_repo_paths = recognize_repo_paths
|
||||
|
||||
def _find(self, pattern):
|
||||
if self._recognize_repo_paths:
|
||||
raise NotImplementedError('cannot use find with recognize_repo_path')
|
||||
|
||||
return self._find_helper(pattern, self._repo[self._rev], 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:]
|
||||
|
||||
return self._get(path)
|
||||
|
||||
def _get(self, path):
|
||||
if isinstance(path, unicode):
|
||||
path = path.encode('utf-8', 'replace')
|
||||
|
||||
try:
|
||||
fctx = self._repo.filectx(path, self._rev)
|
||||
return MercurialNativeFile(fctx.data())
|
||||
except error.LookupError:
|
||||
return None
|
|
@ -33,6 +33,11 @@ try:
|
|||
except ImportError:
|
||||
hglib = None
|
||||
|
||||
try:
|
||||
from mozpack.hg import MercurialNativeRevisionFinder
|
||||
except ImportError:
|
||||
MercurialNativeRevisionFinder = None
|
||||
|
||||
from mozpack.mozjar import (
|
||||
JarReader,
|
||||
JarWriter,
|
||||
|
@ -1042,11 +1047,14 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir):
|
|||
def do_check(self, pattern, result):
|
||||
do_check(self, self.finder, pattern, result)
|
||||
|
||||
def _get_finder(self, *args, **kwargs):
|
||||
return MercurialRevisionFinder(*args, **kwargs)
|
||||
|
||||
def test_default_revision(self):
|
||||
self.prepare_match_test()
|
||||
c = hglib.open(self.tmpdir)
|
||||
c.commit('initial commit')
|
||||
self.finder = MercurialRevisionFinder(self.tmpdir)
|
||||
self.finder = self._get_finder(self.tmpdir)
|
||||
self.do_match_test()
|
||||
|
||||
self.assertIsNone(self.finder.get('does-not-exist'))
|
||||
|
@ -1069,13 +1077,13 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir):
|
|||
# finding anything from the filesystem.
|
||||
c.rawcommand(['update', 'null'])
|
||||
|
||||
finder = MercurialRevisionFinder(self.tmpdir, rev='0')
|
||||
finder = self._get_finder(self.tmpdir, 0)
|
||||
f = finder.get('foo')
|
||||
self.assertEqual(f.read(), 'foo initial')
|
||||
self.assertEqual(f.read(), 'foo initial', 'read again for good measure')
|
||||
self.assertIsNone(finder.get('bar'))
|
||||
|
||||
finder = MercurialRevisionFinder(self.tmpdir, rev='1')
|
||||
finder = MercurialRevisionFinder(self.tmpdir, rev=1)
|
||||
f = finder.get('foo')
|
||||
self.assertEqual(f.read(), 'foo second')
|
||||
f = finder.get('bar')
|
||||
|
@ -1089,8 +1097,8 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir):
|
|||
c.commit('initial')
|
||||
c.rawcommand(['update', 'null'])
|
||||
|
||||
finder = MercurialRevisionFinder(self.tmpdir, rev='0',
|
||||
recognize_repo_paths=True)
|
||||
finder = self._get_finder(self.tmpdir, 0,
|
||||
recognize_repo_paths=True)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
list(finder.find(''))
|
||||
|
||||
|
@ -1104,5 +1112,11 @@ class TestMercurialRevisionFinder(MatchTestTemplate, TestWithTmpDir):
|
|||
self.assertEqual(f.read(), 'initial')
|
||||
|
||||
|
||||
@unittest.skipUnless(MercurialNativeRevisionFinder, 'hgnative not available')
|
||||
class TestMercurialNativeRevisionFinder(TestMercurialRevisionFinder):
|
||||
def _get_finder(self, *args, **kwargs):
|
||||
return MercurialNativeRevisionFinder(*args, **kwargs)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
||||
|
|
Загрузка…
Ссылка в новой задаче