update hg_import_helper.py to invalidate the repo if an error occurs

Summary:
The hg_import_helper script that eden uses to import data from mercurial keeps
a long-lived repository object open.  This caches some data about the
repository, and if new commits are added after it was created, it can fail to
see them.

This updates hg_import_helper.py to catch errors that occur when trying to use
the repository objects.  The code will invalidate the repository object and
then retry the operation once, in the hopes that it will now succeed after
invalidation.

Reviewed By: bolinfest

Differential Revision: D4752659

fbshipit-source-id: 1c75c84766d6bbda0710882a338eaa09e0cb0030
This commit is contained in:
Adam Simpkins 2017-03-31 13:58:27 -07:00 committed by Facebook Github Bot
parent 080134ea84
commit 82cc79b694
2 changed files with 40 additions and 4 deletions

View File

@ -295,8 +295,17 @@ class HgServer(object):
Send the manifest data.
'''
start = time.time()
ctx = mercurial.scmutil.revsingle(self.repo, rev)
mf = ctx.manifest()
try:
ctx = mercurial.scmutil.revsingle(self.repo, rev)
mf = ctx.manifest()
except Exception:
# The mercurial call may fail with a "no node" error if this
# revision in question has added to the repository after we
# originally opened it. Invalidate the repository and try again,
# in case our cached repo data is just stale.
self.repo.invalidate()
ctx = mercurial.scmutil.revsingle(self.repo, rev)
mf = ctx.manifest()
# How many paths to send in each chunk
# Empirically, 100 seems like a decent number.
@ -327,7 +336,11 @@ class HgServer(object):
num_paths, time.time() - start)
def get_file(self, path, rev_hash):
fctx = self.repo.filectx(path, fileid=rev_hash)
try:
fctx = self.repo.filectx(path, fileid=rev_hash)
except Exception:
self.repo.invalidate()
fctx = self.repo.filectx(path, fileid=rev_hash)
return fctx.data()
def prefetch(self, rev):
@ -335,7 +348,12 @@ class HgServer(object):
# This repo isn't using remotefilelog, so nothing to do.
return
rev_range = mercurial.scmutil.revrange(self.repo, rev)
try:
rev_range = mercurial.scmutil.revrange(self.repo, rev)
except Exception:
self.repo.invalidate()
rev_range = mercurial.scmutil.revrange(self.repo, rev)
self.debug('prefetching')
self.repo.prefetch(rev_range)
self.debug('done prefetching')

View File

@ -63,3 +63,21 @@ class UpdateTest(HgExtensionTestBase):
self.assertEqual('? foo/_data\n', self.status(),
msg='now only test.log should be ignored')
self.assertEqual('*.log\n', self.read_file('foo/.gitignore'))
def test_update_with_new_commits(self):
'''
Test running `hg update` to check out commits that were created after
the edenfs daemon originally started.
This makes sure edenfs can correctly import new commits that appear in
the backing store repository.
'''
new_contents = 'changed in commit 3\n'
self.backing_repo.write_file('foo/bar.txt', new_contents)
new_commit = self.backing_repo.commit('Update foo/bar.txt')
self.assertEqual('', self.status())
self.repo.update(new_commit)
self.assertEqual(new_contents, self.read_file('foo/bar.txt'))
self.assertEqual('', self.status())