##// END OF EJS Templates
phabricator: teach `getoldnodedrevmap()` to handle folded reviews...
phabricator: teach `getoldnodedrevmap()` to handle folded reviews The tricky part here is reasoning through all of the possible predecessor scenarios. In the typical case of submitting a folded range and then resubmitting it (also folded), filtering the list of commits for the diff stored on Phabricator through the local predecessor list for each single node will result in the typical 1:1 mapping to the old node. There are edge cases like using `hg fold` within the range prior to resubmitting, that will result in mapping to multiple old nodes. In that case, the first direct predecessor is needed for the base of the diff, and the last direct predecessor is needed for the head of the diff in order to make sure that the entire range is included in the diff content. And none of this matters for commits in the middle of the range, as they are never used. Fortunately the only crucial thing here is the `drev` number for each node. For these complicated cases where there are multiple old nodes, simply ignore them all. This will cause `createdifferentialrevision()` to generate a new diff (within the same Differential), and avoids complicating the code. Differential Revision: https://phab.mercurial-scm.org/D8311

File last commit:

r43347:687b865b default
r45136:5f9c917e default
Show More
darcs.py
242 lines | 8.4 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # darcs.py - darcs support for the convert extension
#
# Copyright 2007-2009 Matt Mackall <mpm@selenic.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.
timeless
convert: darcs use absolute_import
r28368 from __future__ import absolute_import
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
timeless
convert: darcs use absolute_import
r28368 import errno
import os
import re
import shutil
Yuya Nishihara
py3: wrap tempfile.mkdtemp() to use bytes path...
r38183
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 from mercurial.i18n import _
timeless
convert: darcs use absolute_import
r28368 from mercurial import (
error,
Yuya Nishihara
py3: wrap tempfile.mkdtemp() to use bytes path...
r38183 pycompat,
timeless
convert: darcs use absolute_import
r28368 util,
)
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 from mercurial.utils import dateutil
timeless
convert: darcs use absolute_import
r28368 from . import common
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
convert: darcs use absolute_import
r28368 NoRepo = common.NoRepo
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
# The naming drift of ElementTree is fun!
Matt Mackall
many, many trivial check-code fixups
r10282 try:
timeless
convert: darcs use absolute_import
r28368 import xml.etree.cElementTree.ElementTree as ElementTree
import xml.etree.cElementTree.XMLParser as XMLParser
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 except ImportError:
Matt Mackall
many, many trivial check-code fixups
r10282 try:
timeless
convert: darcs use absolute_import
r28368 import xml.etree.ElementTree.ElementTree as ElementTree
import xml.etree.ElementTree.XMLParser as XMLParser
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 except ImportError:
Matt Mackall
many, many trivial check-code fixups
r10282 try:
timeless
convert: darcs use absolute_import
r28368 import elementtree.cElementTree.ElementTree as ElementTree
import elementtree.cElementTree.XMLParser as XMLParser
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 except ImportError:
Matt Mackall
many, many trivial check-code fixups
r10282 try:
timeless
convert: darcs use absolute_import
r28368 import elementtree.ElementTree.ElementTree as ElementTree
Augie Fackler
formatting: blacken the codebase...
r43346 import elementtree.ElementTree.XMLParser as XMLParser
Matt Mackall
many, many trivial check-code fixups
r10282 except ImportError:
Matt Mackall
check-code: enable camelcase check, fix up problems
r15457 pass
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
Augie Fackler
formatting: blacken the codebase...
r43346
timeless
convert: darcs use absolute_import
r28368 class darcs_source(common.converter_source, common.commandline):
Matt Harbison
convert: save an indicator of the repo type for sources and sinks...
r35168 def __init__(self, ui, repotype, path, revs=None):
common.converter_source.__init__(self, ui, repotype, path, revs=revs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 common.commandline.__init__(self, ui, b'darcs')
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393 # check for _darcs, ElementTree so that we can easily skip
# test-convert-darcs if ElementTree is not around
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not os.path.exists(os.path.join(path, b'_darcs')):
raise NoRepo(_(b"%s does not look like a darcs repository") % path)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 common.checktool(b'darcs')
version = self.run0(b'--version').splitlines()[0].strip()
if version < b'2.1':
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'darcs version 2.1 or newer needed (found %r)') % version
Augie Fackler
formatting: blacken the codebase...
r43346 )
Patrick Mezard
convert: fail if an external required tool is not found
r5497
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b"ElementTree" not in globals():
raise error.Abort(_(b"Python ElementTree module is not available"))
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
Matt Mackall
backout dbdb777502dc (issue3077) (issue3071)...
r15381 self.path = os.path.realpath(path)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
self.lastrev = None
self.changes = {}
self.parents = {}
self.tags = {}
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393 # Check darcs repository format
format = self.format()
if format:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if format in (b'darcs-1.0', b'hashed'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise NoRepo(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(
b"%s repository format is unsupported, "
b"please upgrade"
)
Augie Fackler
formatting: blacken the codebase...
r43346 % format
)
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.warn(_(b'failed to detect repository format!'))
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 def before(self):
Yuya Nishihara
py3: wrap tempfile.mkdtemp() to use bytes path...
r38183 self.tmppath = pycompat.mkdtemp(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prefix=b'convert-' + os.path.basename(self.path) + b'-'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 output, status = self.run(b'init', repodir=self.tmppath)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.checkexit(status)
Augie Fackler
formatting: blacken the codebase...
r43346 tree = self.xml(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'changes', xml_output=True, summary=True, repodir=self.path
Augie Fackler
formatting: blacken the codebase...
r43346 )
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 tagname = None
child = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for elt in tree.findall(b'patch'):
node = elt.get(b'hash')
name = elt.findtext(b'name', b'')
if name.startswith(b'TAG '):
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 tagname = name[4:].strip()
elif tagname is not None:
self.tags[tagname] = node
tagname = None
self.changes[node] = elt
self.parents[child] = [node]
child = node
self.parents[child] = []
def after(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.ui.debug(b'cleaning up %s\n' % self.tmppath)
Bryan O'Sullivan
convert: fix a few residual bugs in darcs importer
r5362 shutil.rmtree(self.tmppath, ignore_errors=True)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
Brodie Rao
convert/darcs: support changelogs with bytes 0x7F-0xFF (issue2411)...
r12717 def recode(self, s, encoding=None):
Pulkit Goyal
py3: replace `unicode` with pycompat.unicode...
r38332 if isinstance(s, pycompat.unicode):
Brodie Rao
convert/darcs: support changelogs with bytes 0x7F-0xFF (issue2411)...
r12717 # XMLParser returns unicode objects for anything it can't
# encode into ASCII. We convert them back to str to get
# recode's normal conversion behavior.
s = s.encode('latin-1')
return super(darcs_source, self).recode(s, encoding)
Bryan O'Sullivan
convert: abstract darcs's commandline handling
r5512 def xml(self, cmd, **kwargs):
Brodie Rao
convert/darcs: handle non-ASCII metadata in darcs changelog (issue2354)...
r12252 # NOTE: darcs is currently encoding agnostic and will print
# patch metadata byte-for-byte, even in the XML changelog.
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 etree = ElementTree()
Brodie Rao
convert/darcs: support changelogs with bytes 0x7F-0xFF (issue2411)...
r12717 # While we are decoding the XML as latin-1 to be as liberal as
# possible, etree will still raise an exception if any
# non-printable characters are in the XML changelog.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 parser = XMLParser(encoding=b'latin-1')
Patrick Mezard
convert: use subprocess for all commandline calls...
r17413 p = self._run(cmd, **kwargs)
etree.parse(p.stdout, parser=parser)
p.wait()
self.checkexit(p.returncode)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 return etree.getroot()
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393 def format(self):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 output, status = self.run(b'show', b'repo', repodir=self.path)
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393 self.checkexit(status)
m = re.search(r'^\s*Format:\s*(.*)$', output, re.MULTILINE)
if not m:
return None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b','.join(sorted(f.strip() for f in m.group(1).split(b',')))
Patrick Mezard
convert/darcs: improve unsupported format detection (issue2172)
r12393
Patrick Mezard
convert/darcs: handle directory renaming
r9527 def manifest(self):
man = []
Augie Fackler
formatting: blacken the codebase...
r43346 output, status = self.run(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'show', b'files', no_directories=True, repodir=self.tmppath
Augie Fackler
formatting: blacken the codebase...
r43346 )
Patrick Mezard
convert/darcs: handle directory renaming
r9527 self.checkexit(status)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for line in output.split(b'\n'):
Patrick Mezard
convert/darcs: handle directory renaming
r9527 path = line[2:]
if path:
man.append(path)
return man
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 def getheads(self):
return self.parents[None]
def getcommit(self, rev):
elt = self.changes[rev]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 dateformat = b'%a %b %d %H:%M:%S %Z %Y'
date = dateutil.strdate(elt.get(b'local_date'), dateformat)
desc = elt.findtext(b'name') + b'\n' + elt.findtext(b'comment', b'')
Brodie Rao
convert/darcs: handle non-ASCII metadata in darcs changelog (issue2354)...
r12252 # etree can return unicode objects for name, comment, and author,
# so recode() is used to ensure str objects are emitted.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 newdateformat = b'%Y-%m-%d %H:%M:%S %1%2'
Augie Fackler
formatting: blacken the codebase...
r43346 return common.commit(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 author=self.recode(elt.get(b'author')),
Augie Fackler
formatting: blacken the codebase...
r43346 date=dateutil.datestr(date, newdateformat),
desc=self.recode(desc).strip(),
parents=self.parents[rev],
)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
def pull(self, rev):
Augie Fackler
formatting: blacken the codebase...
r43346 output, status = self.run(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'pull',
Augie Fackler
formatting: blacken the codebase...
r43346 self.path,
all=True,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 match=b'hash %s' % rev,
Augie Fackler
formatting: blacken the codebase...
r43346 no_test=True,
no_posthook=True,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 external_merge=b'/bin/false',
Augie Fackler
formatting: blacken the codebase...
r43346 repodir=self.tmppath,
)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 if status:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if output.find(b'We have conflicts in') == -1:
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.checkexit(status, output)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 output, status = self.run(b'revert', all=True, repodir=self.tmppath)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.checkexit(status, output)
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def getchanges(self, rev, full):
if full:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"convert from darcs does not support --full"))
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 copies = {}
changes = []
Patrick Mezard
convert/darcs: handle directory renaming
r9527 man = None
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for elt in self.changes[rev].find(b'summary').getchildren():
if elt.tag in (b'add_directory', b'remove_directory'):
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if elt.tag == b'move':
Patrick Mezard
convert/darcs: handle directory renaming
r9527 if man is None:
man = self.manifest()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 source, dest = elt.get(b'from'), elt.get(b'to')
Patrick Mezard
convert/darcs: handle directory renaming
r9527 if source in man:
# File move
changes.append((source, rev))
changes.append((dest, rev))
copies[dest] = source
else:
# Directory move, deduce file moves from manifest
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 source = source + b'/'
Patrick Mezard
convert/darcs: handle directory renaming
r9527 for f in man:
if not f.startswith(source):
continue
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fdest = dest + b'/' + f[len(source) :]
Patrick Mezard
convert/darcs: handle directory renaming
r9527 changes.append((f, rev))
changes.append((fdest, rev))
copies[fdest] = f
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 else:
changes.append((elt.text.strip(), rev))
Patrick Mezard
convert/darcs: handle directory renaming
r9527 self.pull(rev)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.lastrev = rev
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 return sorted(changes), copies, set()
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
def getfile(self, name, rev):
if rev != self.lastrev:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b'internal calling inconsistency'))
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 path = os.path.join(self.tmppath, name)
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 try:
data = util.readfile(path)
mode = os.lstat(path).st_mode
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 if inst.errno == errno.ENOENT:
return None, None
raise
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 mode = (mode & 0o111) and b'x' or b''
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 return data, mode
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
def gettags(self):
return self.tags