##// END OF EJS Templates
ui.prompt: Show prompt and selection in non-interactive mode...
ui.prompt: Show prompt and selection in non-interactive mode ui.prompt was completely silent in non-interactive mode, unless in verbose mode. It is fine that it chooses the default automatically, but it is confusing that the message and prompt shown interactively can't be found in scripted tests. The prompt and selection is now .write'ed instead of .note'ed.

File last commit:

r8843:eb7b247a default
r8940:01ada7b1 default
Show More
p4.py
205 lines | 6.6 KiB | text/x-python | PythonLexer
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 #
# Perforce source for convert extension.
#
# Copyright 2009, Frank Kingswood <frank@kingswood-consulting.co.uk>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
# GNU General Public License version 2, incorporated herein by reference.
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 #
from mercurial import util
from mercurial.i18n import _
Matt Mackall
convert: attempt to check repo type before checking for tool
r7973 from common import commit, converter_source, checktool, NoRepo
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 import marshal
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 import re
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
def loaditer(f):
"Yield the dictionary objects generated by p4"
try:
while True:
d = marshal.load(f)
if not d:
break
yield d
except EOFError:
pass
class p4_source(converter_source):
def __init__(self, ui, path, rev=None):
super(p4_source, self).__init__(ui, path, rev=rev)
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 if "/" in path and not path.startswith('//'):
Matt Mackall
convert: attempt to check repo type before checking for tool
r7973 raise NoRepo('%s does not look like a P4 repo' % path)
Mads Kiilerich
convert: missing p4 tool is only slightly fatal...
r7905 checktool('p4', abort=False)
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
self.p4changes = {}
self.heads = {}
self.changeset = {}
self.files = {}
self.tags = {}
self.lastbranch = {}
self.parent = {}
self.encoding = "latin_1"
self.depotname = {} # mapping from local name to depot name
self.modecache = {}
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 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]*\$")
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
self._parse(ui, path)
def _parse_view(self, path):
"Read changes affecting the path"
Patrick Mezard
convert/p4: win32 fixes...
r8063 cmd = 'p4 -G changes -s submitted "%s"' % path
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 stdout = util.popen(cmd)
for d in loaditer(stdout):
c = d.get("change", None)
if c:
self.p4changes[c] = True
def _parse(self, ui, path):
"Prepare list of P4 filenames and revisions to import"
ui.status(_('reading p4 views\n'))
# read client spec or view
if "/" in path:
self._parse_view(path)
if path.startswith("//") and path.endswith("/..."):
views = {path[:-3]:""}
else:
views = {"//": ""}
else:
Patrick Mezard
convert/p4: win32 fixes...
r8063 cmd = 'p4 -G client -o "%s"' % path
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 clientspec = marshal.load(util.popen(cmd))
Dirkjan Ochtman
cleanup: remove all trailing whitespace
r7869
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 views = {}
for client in clientspec:
if client.startswith("View"):
sview, cview = clientspec[client].split()
self._parse_view(sview)
if sview.endswith("...") and cview.endswith("..."):
sview = sview[:-3]
cview = cview[:-3]
cview = cview[2:]
cview = cview[cview.find("/") + 1:]
views[sview] = cview
# list of changes that affect our source files
self.p4changes = self.p4changes.keys()
self.p4changes.sort(key=int)
# list with depot pathnames, longest first
vieworder = views.keys()
vieworder.sort(key=lambda x: -len(x))
# handle revision limiting
startrev = self.ui.config('convert', 'p4.startrev', default=0)
Dirkjan Ochtman
cleanup: remove all trailing whitespace
r7869 self.p4changes = [x for x in self.p4changes
if ((not startrev or int(x) >= int(startrev)) and
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 (not self.rev or int(x) <= int(self.rev)))]
# now read the full changelists to get the list of file revisions
ui.status(_('collecting p4 changelists\n'))
lastid = None
for change in self.p4changes:
cmd = "p4 -G describe %s" % change
stdout = util.popen(cmd)
d = marshal.load(stdout)
desc = self.recode(d["desc"])
shortdesc = desc.split("\n", 1)[0]
t = '%s %s' % (d["change"], repr(shortdesc)[1:-1])
ui.status(util.ellipsis(t, 80) + '\n')
if lastid:
parents = [lastid]
else:
parents = []
Dirkjan Ochtman
cleanup: remove all trailing whitespace
r7869
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 date = (int(d["time"]), 0) # timezone not set
c = commit(author=self.recode(d["user"]), date=util.datestr(date),
parents=parents, desc=desc, branch='', extra={"p4": change})
files = []
i = 0
while ("depotFile%d" % i) in d and ("rev%d" % i) in d:
oldname = d["depotFile%d" % i]
filename = None
for v in vieworder:
if oldname.startswith(v):
filename = views[v] + oldname[len(v):]
break
if filename:
files.append((filename, d["rev%d" % i]))
self.depotname[filename] = oldname
i += 1
self.changeset[change] = c
self.files[change] = files
lastid = change
Dirkjan Ochtman
cleanup: remove all trailing whitespace
r7869
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 if lastid:
self.heads = [lastid]
def getheads(self):
return self.heads
def getfile(self, name, rev):
Patrick Mezard
convert/p4: win32 fixes...
r8063 cmd = 'p4 -G print "%s#%s"' % (self.depotname[name], rev)
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 stdout = util.popen(cmd)
mode = None
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 contents = ""
keywords = None
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
for d in loaditer(stdout):
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 code = d["code"]
data = d.get("data")
if code == "error":
raise IOError(d["generic"], data)
Dirkjan Ochtman
kill trailing whitespace
r8843
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 elif code == "stat":
p4type = self.re_type.match(d["type"])
if p4type:
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823 mode = ""
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 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
Dirkjan Ochtman
kill trailing whitespace
r8843
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 elif code == "text" or code == "binary":
contents += data
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
if mode is None:
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829 raise IOError(0, "bad stat")
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
self.modecache[(name, rev)] = mode
Frank Kingswood
convert: Make P4 conversion cope with keywords, binary files and symbolic links....
r8829
if keywords:
contents = keywords.sub("$\\1$", contents)
if mode == "l" and contents.endswith("\n"):
contents = contents[:-1]
return contents
Frank Kingswood
convert: Perforce source for conversion to Mercurial
r7823
def getmode(self, name, rev):
return self.modecache[(name, rev)]
def getchanges(self, rev):
return self.files[rev], {}
def getcommit(self, rev):
return self.changeset[rev]
def gettags(self):
return self.tags
def getchangedfiles(self, rev, i):
Matt Mackall
replace util.sort with sorted built-in...
r8209 return sorted([x[0] for x in self.files[rev]])