##// END OF EJS Templates
Fix file-changed-to-dir and dir-to-file commits (issue660)....
Fix file-changed-to-dir and dir-to-file commits (issue660). Allow adding to dirstate files that clash with previously existing but marked for removal. Protect from reintroducing clashes by revert. This change doesn't address related issues with update. Current workaround is to do "clean" update by manually removing conflicting files/dirs from working directory.

File last commit:

r5481:003d1f17 default
r5487:7a64931e default
Show More
darcs.py
140 lines | 4.8 KiB | text/x-python | PythonLexer
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 # darcs support for the convert extension
from common import NoRepo, commit, converter_source
from mercurial.i18n import _
from mercurial import util
import os, shutil, tempfile
# The naming drift of ElementTree is fun!
try: from xml.etree.cElementTree import ElementTree
except ImportError:
try: from xml.etree.ElementTree import ElementTree
except ImportError:
try: from elementtree.cElementTree import ElementTree
except ImportError:
try: from elementtree.ElementTree import ElementTree
except ImportError: ElementTree = None
class darcs_source(converter_source):
def __init__(self, ui, path, rev=None):
super(darcs_source, self).__init__(ui, path, rev=rev)
if not os.path.exists(os.path.join(path, '_darcs', 'inventory')):
raise NoRepo("couldn't open darcs repo %s" % path)
if ElementTree is None:
raise util.Abort(_("Python ElementTree module is not available"))
self.path = os.path.realpath(path)
self.lastrev = None
self.changes = {}
self.parents = {}
self.tags = {}
def before(self):
self.tmppath = tempfile.mkdtemp(
prefix='convert-' + os.path.basename(self.path) + '-')
output, status = self.run('init', repodir=self.tmppath)
self.checkexit(status)
tree = self.xml('changes', '--xml-output', '--summary')
tagname = None
child = None
for elt in tree.findall('patch'):
node = elt.get('hash')
name = elt.findtext('name', '')
if name.startswith('TAG '):
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):
self.ui.debug('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
def _run(self, cmd, *args, **kwargs):
Patrick Mezard
convert: fix darcs_source._run() under windows
r5411 cmdline = ['darcs', cmd, '--repodir', kwargs.get('repodir', self.path)]
cmdline += args
cmdline = [util.shellquote(arg) for arg in cmdline]
cmdline += ['<', util.nulldev]
Patrick Mezard
Fix Windows os.popen bug with interleaved stdout/stderr output...
r5481 cmdline = ' '.join(cmdline)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.ui.debug(cmdline, '\n')
Patrick Mezard
Fix Windows os.popen bug with interleaved stdout/stderr output...
r5481 return util.popen(cmdline)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359
def run(self, cmd, *args, **kwargs):
fp = self._run(cmd, *args, **kwargs)
output = fp.read()
return output, fp.close()
def checkexit(self, status, output=''):
if status:
if output:
Bryan O'Sullivan
convert: fix a few residual bugs in darcs importer
r5362 self.ui.warn(_('darcs error:\n'))
self.ui.warn(output)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 msg = util.explain_exit(status)[0]
raise util.Abort(_('darcs %s') % msg)
def xml(self, cmd, *opts):
etree = ElementTree()
fp = self._run(cmd, *opts)
etree.parse(fp)
self.checkexit(fp.close())
return etree.getroot()
def getheads(self):
return self.parents[None]
def getcommit(self, rev):
elt = self.changes[rev]
date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y')
desc = elt.findtext('name') + '\n' + elt.findtext('comment', '')
return commit(author=elt.get('author'), date=util.datestr(date),
desc=desc.strip(), parents=self.parents[rev])
def pull(self, rev):
Patrick Mezard
convert: fix darcs_source.pull() under windows
r5412 output, status = self.run('pull', self.path, '--all',
'--match', 'hash %s' % rev,
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 '--no-test', '--no-posthook',
Patrick Mezard
convert: fix darcs_source.pull() under windows
r5412 '--external-merge', '/bin/false',
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 repodir=self.tmppath)
if status:
if output.find('We have conflicts in') == -1:
self.checkexit(status, output)
Patrick Mezard
convert: fix darcs_source.pull() under windows
r5412 output, status = self.run('revert', '--all', repodir=self.tmppath)
Bryan O'Sullivan
convert: support darcs as a source repo
r5359 self.checkexit(status, output)
def getchanges(self, rev):
self.pull(rev)
copies = {}
changes = []
for elt in self.changes[rev].find('summary').getchildren():
if elt.tag in ('add_directory', 'remove_directory'):
continue
if elt.tag == 'move':
changes.append((elt.get('from'), rev))
copies[elt.get('from')] = elt.get('to')
else:
changes.append((elt.text.strip(), rev))
changes.sort()
self.lastrev = rev
return changes, copies
def getfile(self, name, rev):
if rev != self.lastrev:
raise util.Abort(_('internal calling inconsistency'))
return open(os.path.join(self.tmppath, name), 'rb').read()
def getmode(self, name, rev):
mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
return (mode & 0111) and 'x' or ''
def gettags(self):
return self.tags