##// END OF EJS Templates
rebase: catch RepoLookupError at restoring rebase state for summary...
rebase: catch RepoLookupError at restoring rebase state for summary Before this patch, "hg summary" may fail, when there is inconsistent rebase state: for example, the root of rebase destination revisions recorded in rebase state file is already stripped manually. Mercurial earlier than 2.7 allows users to do anything other than starting new rebase, even though current rebase is not finished or aborted yet. So, such inconsistent rebase states may be left and forgotten in repositories. This patch catches RepoLookupError at restoring rebase state for summary hook, and treat such state as "broken".

File last commit:

r17424:e7cfe358 default
r19849:e7fa36d2 2.7.2 stable
Show More
gnuarch.py
338 lines | 12.4 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # gnuarch.py - GNU Arch support for the convert extension
#
# Copyright 2008, 2009 Aleix Conchillo Flaque <aleix@member.fsf.org>
# and others
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
Joel Rosdahl
Remove unused imports
r6212 from common import NoRepo, commandline, commit, converter_source
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 from mercurial.i18n import _
Brodie Rao
convert: use encoding.encoding instead of locale.getpreferredencoding()...
r11987 from mercurial import encoding, util
import os, shutil, tempfile, stat
Edouard Gomez
convert/gnuarch: fix cat-log parsing...
r7578 from email.Parser import Parser
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
class gnuarch_source(converter_source, commandline):
Benoit Boissinot
use new style classes
r8778 class gnuarch_rev(object):
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 def __init__(self, rev):
self.rev = rev
self.summary = ''
self.date = None
self.author = ''
Edouard Gomez
convert/gnuarch: parse continuation-of revisions in gnuarch source...
r7583 self.continuationof = None
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 self.add_files = []
self.mod_files = []
self.del_files = []
self.ren_files = {}
self.ren_dirs = {}
def __init__(self, ui, path, rev=None):
super(gnuarch_source, self).__init__(ui, path, rev=rev)
if not os.path.exists(os.path.join(path, '{arch}')):
Martin Geisler
convert: write "repository" instead of "repo"...
r10938 raise NoRepo(_("%s does not look like a GNU Arch repository")
% path)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
# Could use checktool, but we want to check for baz or tla.
self.execmd = None
Adrian Buehlmann
rename util.find_exe to findexe
r14271 if util.findexe('baz'):
Patrick Mezard
convert: detect baz before tla...
r6083 self.execmd = 'baz'
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 else:
Adrian Buehlmann
rename util.find_exe to findexe
r14271 if util.findexe('tla'):
Patrick Mezard
convert: detect baz before tla...
r6083 self.execmd = 'tla'
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 else:
raise util.Abort(_('cannot find a GNU Arch tool'))
commandline.__init__(self, ui, self.execmd)
Matt Mackall
backout dbdb777502dc (issue3077) (issue3071)...
r15381 self.path = os.path.realpath(path)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 self.tmppath = None
self.treeversion = None
self.lastrev = None
self.changes = {}
self.parents = {}
self.tags = {}
Edouard Gomez
convert/gnuarch: fix cat-log parsing...
r7578 self.catlogparser = Parser()
Brodie Rao
convert: use encoding.encoding instead of locale.getpreferredencoding()...
r11987 self.encoding = encoding.encoding
Edouard Gomez
convert/gnuarch: retrieve known archive names list...
r7584 self.archives = []
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def before(self):
Edouard Gomez
convert/gnuarch: retrieve known archive names list...
r7584 # Get registered archives
self.archives = [i.rstrip('\n')
for i in self.runlines0('archives', '-n')]
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 if self.execmd == 'tla':
output = self.run0('tree-version', self.path)
else:
output = self.run0('tree-version', '-d', self.path)
self.treeversion = output.strip()
# Get name of temporary directory
version = self.treeversion.split('/')
self.tmppath = os.path.join(tempfile.gettempdir(),
'hg-%s' % version[1])
# Generate parents dictionary
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 self.parents[None] = []
treeversion = self.treeversion
child = None
while treeversion:
self.ui.status(_('analyzing tree version %s...\n') % treeversion)
archive = treeversion.split('/')[0]
if archive not in self.archives:
Martin Geisler
convert/gnuarch: wrap long line, format kwargs without spaces
r8662 self.ui.status(_('tree analysis stopped because it points to '
'an unregistered archive %s...\n') % archive)
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 break
# Get the complete list of revisions for that tree version
output, status = self.runlines('revisions', '-r', '-f', treeversion)
Mads Kiilerich
fix trivial spelling errors
r17424 self.checkexit(status, 'failed retrieving revisions for %s'
Matt Mackall
many, many trivial check-code fixups
r10282 % treeversion)
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585
# No new iteration unless a revision has a continuation-of header
treeversion = None
for l in output:
rev = l.strip()
self.changes[rev] = self.gnuarch_rev(rev)
self.parents[rev] = []
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 # Read author, date and summary
catlog, status = self.run('cat-log', '-d', self.path, rev)
if status:
catlog = self.run0('cat-archive-log', rev)
self._parsecatlog(catlog, rev)
# Populate the parents map
self.parents[child].append(rev)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 # Keep track of the current revision as the child of the next
# revision scanned
child = rev
# Check if we have to follow the usual incremental history
# or if we have to 'jump' to a different treeversion given
# by the continuation-of header.
if self.changes[rev].continuationof:
Matt Mackall
many, many trivial check-code fixups
r10282 treeversion = '--'.join(
self.changes[rev].continuationof.split('--')[:-1])
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 break
# If we reached a base-0 revision w/o any continuation-of
# header, it means the tree history ends here.
if rev[-6:] == 'base-0':
break
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def after(self):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('cleaning up %s\n' % self.tmppath)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 shutil.rmtree(self.tmppath, ignore_errors=True)
def getheads(self):
return self.parents[None]
def getfile(self, name, rev):
if rev != self.lastrev:
raise util.Abort(_('internal calling inconsistency'))
# Raise IOError if necessary (i.e. deleted files).
Patrick Mezard
Use lexists() instead of exists() where appropriate
r12344 if not os.path.lexists(os.path.join(self.tmppath, name)):
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 raise IOError
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 return self._getfile(name, rev)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def getchanges(self, rev):
self._update(rev)
changes = []
copies = {}
for f in self.changes[rev].add_files:
changes.append((f, rev))
for f in self.changes[rev].mod_files:
changes.append((f, rev))
for f in self.changes[rev].del_files:
changes.append((f, rev))
for src in self.changes[rev].ren_files:
to = self.changes[rev].ren_files[src]
changes.append((src, rev))
changes.append((to, rev))
Patrick Mezard
convert/gnuarch: fix switched copy source and destination...
r7567 copies[to] = src
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
for src in self.changes[rev].ren_dirs:
to = self.changes[rev].ren_dirs[src]
Benoit Boissinot
fix coding style (reported by pylint)
r10394 chgs, cps = self._rendirchanges(src, to)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 changes += [(f, rev) for f in chgs]
Patrick Mezard
convert/gnuarch: fix switched copy source and destination...
r7567 copies.update(cps)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
self.lastrev = rev
Matt Mackall
replace util.sort with sorted built-in...
r8209 return sorted(set(changes)), copies
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def getcommit(self, rev):
changes = self.changes[rev]
Martin Geisler
convert/gnuarch: wrap long line, format kwargs without spaces
r8662 return commit(author=changes.author, date=changes.date,
desc=changes.summary, parents=self.parents[rev], rev=rev)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def gettags(self):
return self.tags
def _execute(self, cmd, *args, **kwargs):
cmdline = [self.execmd, cmd]
cmdline += args
cmdline = [util.shellquote(arg) for arg in cmdline]
Ross Lagerwall
util: replace util.nulldev with os.devnull...
r17391 cmdline += ['>', os.devnull, '2>', os.devnull]
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 cmdline = util.quotecommand(' '.join(cmdline))
self.ui.debug(cmdline, '\n')
return os.system(cmdline)
def _update(self, rev):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('applying revision %s...\n' % rev)
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 changeset, status = self.runlines('replay', '-d', self.tmppath,
rev)
if status:
# Something went wrong while merging (baz or tla
# issue?), get latest revision and try from there
shutil.rmtree(self.tmppath, ignore_errors=True)
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 self._obtainrevision(rev)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 else:
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 old_rev = self.parents[rev][0]
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('computing changeset between %s and %s...\n'
Edouard Gomez
convert/gnuarch: follow continuation-of revisions...
r7585 % (old_rev, rev))
self._parsechangeset(changeset, rev)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035
def _getfile(self, name, rev):
mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
if stat.S_ISLNK(mode):
data = os.readlink(os.path.join(self.tmppath, name))
mode = mode and 'l' or ''
else:
data = open(os.path.join(self.tmppath, name), 'rb').read()
mode = (mode & 0111) and 'x' or ''
return data, mode
def _exclude(self, name):
Matt Mackall
many, many trivial check-code fixups
r10282 exclude = ['{arch}', '.arch-ids', '.arch-inventory']
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 for exc in exclude:
if name.find(exc) != -1:
return True
return False
def _readcontents(self, path):
files = []
contents = os.listdir(path)
while len(contents) > 0:
c = contents.pop()
p = os.path.join(path, c)
Aleix Conchillo Flaque
convert: do not skip some lines in gnu arch summaries
r6044 # os.walk could be used, but here we avoid internal GNU
# Arch files and directories, thus saving a lot time.
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 if not self._exclude(p):
if os.path.isdir(p):
contents += [os.path.join(c, f) for f in os.listdir(p)]
else:
files.append(c)
return files
def _rendirchanges(self, src, dest):
changes = []
copies = {}
files = self._readcontents(os.path.join(self.tmppath, dest))
for f in files:
s = os.path.join(src, f)
d = os.path.join(dest, f)
changes.append(s)
changes.append(d)
Patrick Mezard
convert/gnuarch: fix switched copy source and destination...
r7567 copies[d] = s
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 return changes, copies
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 def _obtainrevision(self, rev):
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('obtaining revision %s...\n' % rev)
Edouard Gomez
convert/gnuarch: use fully qualified revisions...
r7582 output = self._execute('get', rev, self.tmppath)
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 self.checkexit(output)
Martin Geisler
do not attempt to translate ui.debug output
r9467 self.ui.debug('analyzing revision %s...\n' % rev)
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 files = self._readcontents(self.tmppath)
self.changes[rev].add_files += files
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 def _stripbasepath(self, path):
if path.startswith('./'):
return path[2:]
return path
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 def _parsecatlog(self, data, rev):
Edouard Gomez
convert/gnuarch: fix cat-log parsing...
r7578 try:
catlog = self.catlogparser.parsestr(data)
Edouard Gomez
convert/gnuarch: recode cat-log parts to utf-8 to be hg.description friendly
r7592
# Commit date
Edouard Gomez
convert/gnuarch: fix cat-log parsing...
r7578 self.changes[rev].date = util.datestr(
util.strdate(catlog['Standard-date'],
'%Y-%m-%d %H:%M:%S'))
Edouard Gomez
convert/gnuarch: recode cat-log parts to utf-8 to be hg.description friendly
r7592
# Commit author
self.changes[rev].author = self.recode(catlog['Creator'])
# Commit description
self.changes[rev].summary = '\n\n'.join((catlog['Summary'],
catlog.get_payload()))
self.changes[rev].summary = self.recode(self.changes[rev].summary)
# Commit revision origin when dealing with a branch or tag
Nicolas Dumazet
use 'x in dict' instead of 'dict.has_key(x)'...
r9391 if 'Continuation-of' in catlog:
Matt Mackall
many, many trivial check-code fixups
r10282 self.changes[rev].continuationof = self.recode(
catlog['Continuation-of'])
Peter Arrenbrecht
cleanup: drop unused assignments
r7875 except Exception:
Edouard Gomez
convert/gnuarch: fix cat-log parsing...
r7578 raise util.Abort(_('could not parse cat-log of %s') % rev)
Aleix Conchillo Flaque
convert: add full description for gnu arch revisions
r6037
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 def _parsechangeset(self, data, rev):
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 for l in data:
l = l.strip()
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 # Added file (ignore added directory)
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 if l.startswith('A') and not l.startswith('A/'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[1:].strip())
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 if not self._exclude(file):
self.changes[rev].add_files.append(file)
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 # Deleted file (ignore deleted directory)
elif l.startswith('D') and not l.startswith('D/'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[1:].strip())
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 if not self._exclude(file):
self.changes[rev].del_files.append(file)
# Modified binary file
elif l.startswith('Mb'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[2:].strip())
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Modified link
elif l.startswith('M->'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[3:].strip())
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Modified file
elif l.startswith('M'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[1:].strip())
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Renamed file (or link)
elif l.startswith('=>'):
files = l[2:].strip().split(' ')
if len(files) == 1:
files = l[2:].strip().split('\t')
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 src = self._stripbasepath(files[0])
dst = self._stripbasepath(files[1])
if not self._exclude(src) and not self._exclude(dst):
self.changes[rev].ren_files[src] = dst
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 # Conversion from file to link or from link to file (modified)
elif l.startswith('ch'):
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 file = self._stripbasepath(l[2:].strip())
Aleix Conchillo Flaque
convert: support binary files, link to files (viceversa) in gnu arch
r6055 if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Renamed directory
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 elif l.startswith('/>'):
dirs = l[2:].strip().split(' ')
if len(dirs) == 1:
dirs = l[2:].strip().split('\t')
Aleix Conchillo Flaque
convert: added GNU Arch (tla) tests and related fixes
r6079 src = self._stripbasepath(dirs[0])
dst = self._stripbasepath(dirs[1])
if not self._exclude(src) and not self._exclude(dst):
self.changes[rev].ren_dirs[src] = dst