##// END OF EJS Templates
keyword: no expansion in web diffs...
keyword: no expansion in web diffs Expansion in hgweb view of changesets and diffs is not needed and only distracting. Expansion stays enable in file and archive requests where it makes sense.

File last commit:

r6055:a3d8b1f8 default
r6072:e521ec1a default
Show More
gnuarch.py
292 lines | 10.4 KiB | text/x-python | PythonLexer
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 # GNU Arch support for the convert extension
from common import NoRepo, checktool, commandline, commit, converter_source
from mercurial.i18n import _
from mercurial import util
import os, shutil, tempfile, stat
class gnuarch_source(converter_source, commandline):
class gnuarch_rev:
def __init__(self, rev):
self.rev = rev
self.summary = ''
self.date = None
self.author = ''
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}')):
raise NoRepo(_("couldn't open GNU Arch repo %s" % path))
# Could use checktool, but we want to check for baz or tla.
self.execmd = None
if util.find_exe('tla'):
self.execmd = 'tla'
else:
if util.find_exe('baz'):
self.execmd = 'baz'
else:
raise util.Abort(_('cannot find a GNU Arch tool'))
commandline.__init__(self, ui, self.execmd)
self.path = os.path.realpath(path)
self.tmppath = None
self.treeversion = None
self.lastrev = None
self.changes = {}
self.parents = {}
self.tags = {}
self.modecache = {}
def before(self):
if self.execmd == 'tla':
output = self.run0('tree-version', self.path)
else:
output = self.run0('tree-version', '-d', self.path)
self.treeversion = output.strip()
self.ui.status(_('analyzing tree version %s...\n' % self.treeversion))
# Get name of temporary directory
version = self.treeversion.split('/')
self.tmppath = os.path.join(tempfile.gettempdir(),
'hg-%s' % version[1])
# Generate parents dictionary
child = []
output, status = self.runlines('revisions', self.treeversion)
self.checkexit(status, 'archive registered?')
for l in output:
rev = l.strip()
self.changes[rev] = self.gnuarch_rev(rev)
# Read author, date and summary
catlog = self.runlines0('cat-log', '-d', self.path, rev)
self._parsecatlog(catlog, rev)
self.parents[rev] = child
child = [rev]
if rev == self.rev:
break
self.parents[None] = child
def after(self):
self.ui.debug(_('cleaning up %s\n' % self.tmppath))
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).
if not os.path.exists(os.path.join(self.tmppath, name)):
raise IOError
data, mode = self._getfile(name, rev)
self.modecache[(name, rev)] = mode
return data
def getmode(self, name, rev):
return self.modecache[(name, rev)]
def getchanges(self, rev):
self.modecache = {}
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))
copies[src] = to
for src in self.changes[rev].ren_dirs:
to = self.changes[rev].ren_dirs[src]
chgs, cps = self._rendirchanges(src, to);
changes += [(f, rev) for f in chgs]
for c in cps:
copies[c] = cps[c]
changes.sort()
self.lastrev = rev
return changes, copies
def getcommit(self, rev):
changes = self.changes[rev]
return commit(author = changes.author, date = changes.date,
desc = changes.summary, parents = self.parents[rev])
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]
cmdline += ['>', util.nulldev, '2>', util.nulldev]
cmdline = util.quotecommand(' '.join(cmdline))
self.ui.debug(cmdline, '\n')
return os.system(cmdline)
def _update(self, rev):
if rev == 'base-0':
# Initialise 'base-0' revision
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:
self.ui.debug(_('applying revision %s...\n' % rev))
revision = '%s--%s' % (self.treeversion, rev)
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 changeset, status = self.runlines('replay', '-d', self.tmppath,
revision)
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)
self._obtainrevision(rev)
else:
old_rev = self.parents[rev][0]
self.ui.debug(_('computing changeset between %s and %s...\n' \
% (old_rev, rev)))
rev_a = '%s--%s' % (self.treeversion, old_rev)
rev_b = '%s--%s' % (self.treeversion, 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):
exclude = [ '{arch}', '.arch-ids', '.arch-inventory' ]
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)
copies[s] = d
return changes, copies
Aleix Conchillo Flaque
convert: improve gnu arch source performance and other fixes...
r6049 def _obtainrevision(self, rev):
self.ui.debug(_('obtaining revision %s...\n' % rev))
revision = '%s--%s' % (self.treeversion, rev)
output = self._execute('get', revision, self.tmppath)
self.checkexit(output)
self.ui.debug(_('analysing revision %s...\n' % rev))
files = self._readcontents(self.tmppath)
self.changes[rev].add_files += files
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 def _parsecatlog(self, data, rev):
Aleix Conchillo Flaque
convert: do not skip some lines in gnu arch summaries
r6044 summary = []
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 for l in data:
l = l.strip()
Aleix Conchillo Flaque
convert: do not skip some lines in gnu arch summaries
r6044 if summary:
summary.append(l)
elif l.startswith('Summary:'):
summary.append(l[len('Summary: '):])
elif l.startswith('Standard-date:'):
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 date = l[len('Standard-date: '):]
strdate = util.strdate(date, '%Y-%m-%d %H:%M:%S')
self.changes[rev].date = util.datestr(strdate)
Aleix Conchillo Flaque
convert: do not skip some lines in gnu arch summaries
r6044 elif l.startswith('Creator:'):
Aleix Conchillo Flaque
convert: added GNU Arch source converter
r6035 self.changes[rev].author = l[len('Creator: '):]
Aleix Conchillo Flaque
convert: do not skip some lines in gnu arch summaries
r6044 self.changes[rev].summary = '\n'.join(summary)
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/'):
file = l[1:].strip()
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/'):
file = l[1:].strip()
if not self._exclude(file):
self.changes[rev].del_files.append(file)
# Modified binary file
elif l.startswith('Mb'):
file = l[2:].strip()
if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Modified link
elif l.startswith('M->'):
file = l[3:].strip()
if not self._exclude(file):
self.changes[rev].mod_files.append(file)
# Modified file
elif l.startswith('M'):
file = l[1:].strip()
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')
if not self._exclude(files[0]) and not self._exclude(files[1]):
self.changes[rev].ren_files[files[0]] = files[1]
# Conversion from file to link or from link to file (modified)
elif l.startswith('ch'):
file = l[2:].strip()
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')
if not self._exclude(dirs[0]) and not self._exclude(dirs[1]):
self.changes[rev].ren_dirs[dirs[0]] = dirs[1]