diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1825,8 +1825,12 @@ class localrepository(repo.repository): except ValueError: raise util.UnexpectedOutput( _('Unexpected response from remote server:'), l) - if resp != 0: + if resp == 1: raise util.Abort(_('operation forbidden by server')) + elif resp == 2: + raise util.Abort(_('locking the remote repository failed')) + elif resp != 0: + raise util.Abort(_('the server sent an unknown error code')) self.ui.status(_('streaming all changes\n')) l = fp.readline() try: diff --git a/mercurial/streamclone.py b/mercurial/streamclone.py --- a/mercurial/streamclone.py +++ b/mercurial/streamclone.py @@ -7,7 +7,7 @@ from demandload import demandload from i18n import gettext as _ -demandload(globals(), "os stat util") +demandload(globals(), "os stat util lock") # if server supports streaming clone, it advertises "stream" # capability with value that is version+flags of repo it is serving. @@ -65,18 +65,23 @@ def stream_out(repo, fileobj): fileobj.write('1\n') return - fileobj.write('0\n') - # get consistent snapshot of repo. lock during scan so lock not # needed while we stream, and commits can happen. - lock = repo.lock() + try: + repolock = repo.lock() + except (lock.LockHeld, lock.LockUnavailable), inst: + repo.ui.warn('locking the repository failed: %s\n' % (inst,)) + fileobj.write('2\n') + return + + fileobj.write('0\n') repo.ui.debug('scanning\n') entries = [] total_bytes = 0 for name, size in walkrepo(repo.path): entries.append((name, size)) total_bytes += size - lock.release() + repolock.release() repo.ui.debug('%d files, %d bytes to transfer\n' % (len(entries), total_bytes))