Mercurial > hg-stable
diff hgext/convert/p4.py @ 8829:ce4b92f5cea7
convert: Make P4 conversion cope with keywords, binary files and symbolic links.
Convert now handles errors from p4 during conversion more gracefully.
If keyword expansion is enabled in a P4 file then keywords will be
unexpanded in hg.
Added testcase for p4 filetypes and keyword (un)expansion.
This testcase ignores UTF and Apple files to avoid binary data.
Edited by pmezard: fixed collation issue on OSX
author | Frank Kingswood <frank@kingswood-consulting.co.uk> |
---|---|
date | Thu, 18 Jun 2009 10:39:04 +0100 |
parents | 46293a0c7e9f |
children | eb7b247a98ea |
line wrap: on
line diff
--- a/hgext/convert/p4.py Thu Jun 18 21:13:56 2009 +0200 +++ b/hgext/convert/p4.py Thu Jun 18 10:39:04 2009 +0100 @@ -12,6 +12,7 @@ from common import commit, converter_source, checktool, NoRepo import marshal +import re def loaditer(f): "Yield the dictionary objects generated by p4" @@ -28,7 +29,7 @@ def __init__(self, ui, path, rev=None): super(p4_source, self).__init__(ui, path, rev=rev) - if not path.startswith('//'): + if "/" in path and not path.startswith('//'): raise NoRepo('%s does not look like a P4 repo' % path) checktool('p4', abort=False) @@ -43,6 +44,9 @@ self.encoding = "latin_1" self.depotname = {} # mapping from local name to depot name self.modecache = {} + self.re_type = re.compile("([a-z]+)?(text|binary|symlink|apple|resource|unicode|utf\d+)(\+\w+)?$") + self.re_keywords = re.compile(r"\$(Id|Header|Date|DateTime|Change|File|Revision|Author):[^$\n]*\$") + self.re_keywords_old = re.compile("\$(Id|Header):[^$\n]*\$") self._parse(ui, path) @@ -146,22 +150,44 @@ stdout = util.popen(cmd) mode = None - data = "" + contents = "" + keywords = None for d in loaditer(stdout): - if d["code"] == "stat": - if "+x" in d["type"]: - mode = "x" - else: + code = d["code"] + data = d.get("data") + + if code == "error": + raise IOError(d["generic"], data) + + elif code == "stat": + p4type = self.re_type.match(d["type"]) + if p4type: mode = "" - elif d["code"] == "text": - data += d["data"] + flags = (p4type.group(1) or "") + (p4type.group(3) or "") + if "x" in flags: + mode = "x" + if p4type.group(2) == "symlink": + mode = "l" + if "ko" in flags: + keywords = self.re_keywords_old + elif "k" in flags: + keywords = self.re_keywords + + elif code == "text" or code == "binary": + contents += data if mode is None: - raise IOError() + raise IOError(0, "bad stat") self.modecache[(name, rev)] = mode - return data + + if keywords: + contents = keywords.sub("$\\1$", contents) + if mode == "l" and contents.endswith("\n"): + contents = contents[:-1] + + return contents def getmode(self, name, rev): return self.modecache[(name, rev)]