##// END OF EJS Templates
relink: mark abort message for translation
relink: mark abort message for translation

File last commit:

r11134:33010ff1 default
r13658:6cc30609 stable
Show More
monotone.py
227 lines | 8.1 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # monotone.py - monotone support for the convert extension
#
# Copyright 2008, 2009 Mikkel Fahnoe Jorgensen <mikkel@dvide.com> 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.
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
Peter Arrenbrecht
cleanup: drop unused imports
r7873 import os, re
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 from mercurial import util
Peter Arrenbrecht
cleanup: drop unused imports
r7873 from common import NoRepo, commit, converter_source, checktool
Patrick Mezard
convert: allow missing tools not to stop source type detection
r6332 from common import commandline
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 from mercurial.i18n import _
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 class monotone_source(converter_source, commandline):
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 def __init__(self, ui, path=None, rev=None):
converter_source.__init__(self, ui, path, rev)
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 commandline.__init__(self, ui, 'mtn')
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 self.ui = ui
self.path = path
Martin Geisler
convert: write "repository" instead of "repo"...
r10938 norepo = NoRepo(_("%s does not look like a monotone repository")
% path)
Matt Mackall
convert: attempt to check repo type before checking for tool
r7973 if not os.path.exists(os.path.join(path, '_MTN')):
Patrick Mezard
convert/mtn: allow monotone database files as sources
r8052 # Could be a monotone repository (SQLite db file)
try:
header = file(path, 'rb').read(16)
except:
header = ''
if header != 'SQLite format 3\x00':
raise norepo
Matt Mackall
convert: attempt to check repo type before checking for tool
r7973
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 # regular expressions for parsing monotone output
space = r'\s*'
David Reiss
convert.monotone: fix quotes and backslashes in change descriptions.
r6632 name = r'\s+"((?:\\"|[^"])*)"\s*'
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 value = name
revision = r'\s+\[(\w+)\]\s*'
lines = r'(?:.|\n)+'
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
self.dir_re = re.compile(space + "dir" + name)
Matt Mackall
many, many trivial check-code fixups
r10282 self.file_re = re.compile(space + "file" + name +
"content" + revision)
self.add_file_re = re.compile(space + "add_file" + name +
"content" + revision)
self.patch_re = re.compile(space + "patch" + name +
"from" + revision + "to" + revision)
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.rename_re = re.compile(space + "rename" + name + "to" + name)
Patrick Mezard
convert: record deleted files in monotone source
r6376 self.delete_re = re.compile(space + "delete" + name)
Matt Mackall
many, many trivial check-code fixups
r10282 self.tag_re = re.compile(space + "tag" + name + "revision" +
revision)
self.cert_re = re.compile(lines + space + "name" + name +
"value" + value)
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
attr = space + "file" + lines + space + "attr" + space
Matt Mackall
many, many trivial check-code fixups
r10282 self.attr_execute_re = re.compile(attr + '"mtn:execute"' +
space + '"true"')
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
# cached data
self.manifest_rev = None
self.manifest = None
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.files = None
self.dirs = None
Patrick Mezard
convert: allow missing tools not to stop source type detection
r6332 checktool('mtn', abort=False)
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
# test if there are any revisions
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 self.rev = None
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 try:
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 self.getheads()
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 except:
raise norepo
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 self.rev = rev
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 def mtnrun(self, *args, **kwargs):
kwargs['d'] = self.path
return self.run0('automate', *args, **kwargs)
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 def mtnloadmanifest(self, rev):
if self.manifest_rev == rev:
return
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.manifest = self.mtnrun("get_manifest_of", rev).split("\n\n")
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 self.manifest_rev = rev
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.files = {}
self.dirs = {}
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 for e in self.manifest:
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.file_re.match(e)
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 if m:
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 attr = ""
name = m.group(1)
node = m.group(2)
if self.attr_execute_re.match(e):
attr += "x"
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.files[name] = (node, attr)
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.dir_re.match(e)
if m:
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 self.dirs[m.group(1)] = True
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
def mtnisfile(self, name, rev):
# a non-file could be a directory or a deleted or renamed file
self.mtnloadmanifest(rev)
Benoit Boissinot
convert: cleanups in monotone converter
r8458 return name in self.files
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 def mtnisdir(self, name, rev):
self.mtnloadmanifest(rev)
Benoit Boissinot
convert: cleanups in monotone converter
r8458 return name in self.dirs
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 def mtngetcerts(self, rev):
certs = {"author":"<missing>", "date":"<missing>",
"changelog":"<missing>", "branch":"<missing>"}
Patrick Mezard
convert/mtn: handle change in mtn 0.45 certs output
r9823 certlist = self.mtnrun("certs", rev)
# mtn < 0.45:
# key "test@selenic.com"
# mtn >= 0.45:
# key [ff58a7ffb771907c4ff68995eada1c4da068d328]
certlist = re.split('\n\n key ["\[]', certlist)
for e in certlist:
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.cert_re.match(e)
if m:
David Reiss
convert.monotone: fix quotes and backslashes in change descriptions.
r6632 name, value = m.groups()
value = value.replace(r'\"', '"')
value = value.replace(r'\\', '\\')
certs[name] = value
Paul Aurich
convert/mtn: handle subsecond commit dates (issue1616)
r8101 # Monotone may have subsecond dates: 2005-02-05T09:39:12.364306
Paul Aurich
convert/mtn: mtn does not record timezones, mark dates as UTC (issue1624)
r8125 # and all times are stored in UTC
certs["date"] = certs["date"].split('.')[0] + " UTC"
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 return certs
# implement the converter_source interface:
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 def getheads(self):
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 if not self.rev:
return self.mtnrun("leaves").splitlines()
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 else:
return [self.rev]
def getchanges(self, rev):
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 #revision = self.mtncmd("get_revision %s" % rev).split("\n\n")
revision = self.mtnrun("get_revision", rev).split("\n\n")
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 files = {}
Patrick Mezard
convert/mtn: handle files moved in a moved directory (issue1619/2)
r8123 ignoremove = {}
Patrick Mezard
convert/mtn: handle new files in moved directories (issue1619)...
r8099 renameddirs = []
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 copies = {}
for e in revision:
m = self.add_file_re.match(e)
if m:
files[m.group(1)] = rev
Patrick Mezard
convert/mtn: handle files moved in a moved directory (issue1619/2)
r8123 ignoremove[m.group(1)] = rev
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.patch_re.match(e)
if m:
files[m.group(1)] = rev
# Delete/rename is handled later when the convert engine
# discovers an IOError exception from getfile,
# but only if we add the "from" file to the list of changes.
Patrick Mezard
convert: record deleted files in monotone source
r6376 m = self.delete_re.match(e)
if m:
files[m.group(1)] = rev
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.rename_re.match(e)
if m:
toname = m.group(2)
fromname = m.group(1)
if self.mtnisfile(toname, rev):
Patrick Mezard
convert/mtn: handle files moved in a moved directory (issue1619/2)
r8123 ignoremove[toname] = 1
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 copies[toname] = fromname
files[toname] = rev
files[fromname] = rev
Patrick Mezard
convert/mtn: handle new files in moved directories (issue1619)...
r8099 elif self.mtnisdir(toname, rev):
renameddirs.append((fromname, toname))
# Directory renames can be handled only once we have recorded
# all new files
for fromdir, todir in renameddirs:
renamed = {}
for tofile in self.files:
Patrick Mezard
convert/mtn: handle files moved in a moved directory (issue1619/2)
r8123 if tofile in ignoremove:
Patrick Mezard
convert/mtn: handle new files in moved directories (issue1619)...
r8099 continue
if tofile.startswith(todir + '/'):
renamed[tofile] = fromdir + tofile[len(todir):]
Patrick Mezard
convert/mtn: handle directory move into moved directory (issue1619/3)
r8124 # Avoid chained moves like:
# d1(/a) => d3/d1(/a)
# d2 => d3
ignoremove[tofile] = 1
Patrick Mezard
convert/mtn: handle new files in moved directories (issue1619)...
r8099 for tofile, fromfile in renamed.items():
Patrick Mezard
Merge with crew-stable
r8100 self.ui.debug (_("copying file in renamed directory "
"from '%s' to '%s'")
Patrick Mezard
convert/mtn: handle new files in moved directories (issue1619)...
r8099 % (fromfile, tofile), '\n')
files[tofile] = rev
copies[tofile] = fromfile
for fromfile in renamed.values():
files[fromfile] = rev
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 return (files.items(), copies)
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306
def getfile(self, name, rev):
if not self.mtnisfile(name, rev):
raise IOError() # file was deleted or renamed
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 try:
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 data = self.mtnrun("get_file_of", name, r=rev)
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 except:
raise IOError() # file was deleted or renamed
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 self.mtnloadmanifest(rev)
node, attr = self.files.get(name, (None, ""))
return data, attr
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307
def getcommit(self, rev):
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 certs = self.mtngetcerts(rev)
return commit(
author=certs["author"],
date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")),
desc=certs["changelog"],
rev=rev,
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 parents=self.mtnrun("parents", rev).splitlines(),
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 branch=certs["branch"])
def gettags(self):
tags = {}
Mikkel Fahnøe Jørgensen
cleanup monotone conversion and use commandline class
r6307 for e in self.mtnrun("tags").split("\n\n"):
Mikkel Fahnøe Jørgensen
initial version of monotone source for convert extension
r6306 m = self.tag_re.match(e)
if m:
tags[m.group(1)] = m.group(2)
return tags
def getchangedfiles(self, rev, i):
# This function is only needed to support --filemap
# ... and we don't support that
raise NotImplementedError()