##// END OF EJS Templates
convert/darcs: fix file renaming (issue1853)
Patrick Mezard -
r9526:457a30ed default
parent child Browse files
Show More
@@ -1,135 +1,136 b''
1 # darcs.py - darcs support for the convert extension
1 # darcs.py - darcs support for the convert extension
2 #
2 #
3 # Copyright 2007-2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2007-2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2, incorporated herein by reference.
6 # GNU General Public License version 2, incorporated herein by reference.
7
7
8 from common import NoRepo, checktool, commandline, commit, converter_source
8 from common import NoRepo, checktool, commandline, commit, converter_source
9 from mercurial.i18n import _
9 from mercurial.i18n import _
10 from mercurial import util
10 from mercurial import util
11 import os, shutil, tempfile
11 import os, shutil, tempfile
12
12
13 # The naming drift of ElementTree is fun!
13 # The naming drift of ElementTree is fun!
14
14
15 try: from xml.etree.cElementTree import ElementTree
15 try: from xml.etree.cElementTree import ElementTree
16 except ImportError:
16 except ImportError:
17 try: from xml.etree.ElementTree import ElementTree
17 try: from xml.etree.ElementTree import ElementTree
18 except ImportError:
18 except ImportError:
19 try: from elementtree.cElementTree import ElementTree
19 try: from elementtree.cElementTree import ElementTree
20 except ImportError:
20 except ImportError:
21 try: from elementtree.ElementTree import ElementTree
21 try: from elementtree.ElementTree import ElementTree
22 except ImportError: ElementTree = None
22 except ImportError: ElementTree = None
23
23
24
24
25 class darcs_source(converter_source, commandline):
25 class darcs_source(converter_source, commandline):
26 def __init__(self, ui, path, rev=None):
26 def __init__(self, ui, path, rev=None):
27 converter_source.__init__(self, ui, path, rev=rev)
27 converter_source.__init__(self, ui, path, rev=rev)
28 commandline.__init__(self, ui, 'darcs')
28 commandline.__init__(self, ui, 'darcs')
29
29
30 # check for _darcs, ElementTree, _darcs/inventory so that we can
30 # check for _darcs, ElementTree, _darcs/inventory so that we can
31 # easily skip test-convert-darcs if ElementTree is not around
31 # easily skip test-convert-darcs if ElementTree is not around
32 if not os.path.exists(os.path.join(path, '_darcs', 'inventories')):
32 if not os.path.exists(os.path.join(path, '_darcs', 'inventories')):
33 raise NoRepo("%s does not look like a darcs repo" % path)
33 raise NoRepo("%s does not look like a darcs repo" % path)
34
34
35 if not os.path.exists(os.path.join(path, '_darcs')):
35 if not os.path.exists(os.path.join(path, '_darcs')):
36 raise NoRepo("%s does not look like a darcs repo" % path)
36 raise NoRepo("%s does not look like a darcs repo" % path)
37
37
38 checktool('darcs')
38 checktool('darcs')
39 version = self.run0('--version').splitlines()[0].strip()
39 version = self.run0('--version').splitlines()[0].strip()
40 if version < '2.1':
40 if version < '2.1':
41 raise util.Abort(_('darcs version 2.1 or newer needed (found %r)') %
41 raise util.Abort(_('darcs version 2.1 or newer needed (found %r)') %
42 version)
42 version)
43
43
44 if ElementTree is None:
44 if ElementTree is None:
45 raise util.Abort(_("Python ElementTree module is not available"))
45 raise util.Abort(_("Python ElementTree module is not available"))
46
46
47 self.path = os.path.realpath(path)
47 self.path = os.path.realpath(path)
48
48
49 self.lastrev = None
49 self.lastrev = None
50 self.changes = {}
50 self.changes = {}
51 self.parents = {}
51 self.parents = {}
52 self.tags = {}
52 self.tags = {}
53
53
54 def before(self):
54 def before(self):
55 self.tmppath = tempfile.mkdtemp(
55 self.tmppath = tempfile.mkdtemp(
56 prefix='convert-' + os.path.basename(self.path) + '-')
56 prefix='convert-' + os.path.basename(self.path) + '-')
57 output, status = self.run('init', repodir=self.tmppath)
57 output, status = self.run('init', repodir=self.tmppath)
58 self.checkexit(status)
58 self.checkexit(status)
59
59
60 tree = self.xml('changes', xml_output=True, summary=True,
60 tree = self.xml('changes', xml_output=True, summary=True,
61 repodir=self.path)
61 repodir=self.path)
62 tagname = None
62 tagname = None
63 child = None
63 child = None
64 for elt in tree.findall('patch'):
64 for elt in tree.findall('patch'):
65 node = elt.get('hash')
65 node = elt.get('hash')
66 name = elt.findtext('name', '')
66 name = elt.findtext('name', '')
67 if name.startswith('TAG '):
67 if name.startswith('TAG '):
68 tagname = name[4:].strip()
68 tagname = name[4:].strip()
69 elif tagname is not None:
69 elif tagname is not None:
70 self.tags[tagname] = node
70 self.tags[tagname] = node
71 tagname = None
71 tagname = None
72 self.changes[node] = elt
72 self.changes[node] = elt
73 self.parents[child] = [node]
73 self.parents[child] = [node]
74 child = node
74 child = node
75 self.parents[child] = []
75 self.parents[child] = []
76
76
77 def after(self):
77 def after(self):
78 self.ui.debug(_('cleaning up %s\n') % self.tmppath)
78 self.ui.debug(_('cleaning up %s\n') % self.tmppath)
79 shutil.rmtree(self.tmppath, ignore_errors=True)
79 shutil.rmtree(self.tmppath, ignore_errors=True)
80
80
81 def xml(self, cmd, **kwargs):
81 def xml(self, cmd, **kwargs):
82 etree = ElementTree()
82 etree = ElementTree()
83 fp = self._run(cmd, **kwargs)
83 fp = self._run(cmd, **kwargs)
84 etree.parse(fp)
84 etree.parse(fp)
85 self.checkexit(fp.close())
85 self.checkexit(fp.close())
86 return etree.getroot()
86 return etree.getroot()
87
87
88 def getheads(self):
88 def getheads(self):
89 return self.parents[None]
89 return self.parents[None]
90
90
91 def getcommit(self, rev):
91 def getcommit(self, rev):
92 elt = self.changes[rev]
92 elt = self.changes[rev]
93 date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y')
93 date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y')
94 desc = elt.findtext('name') + '\n' + elt.findtext('comment', '')
94 desc = elt.findtext('name') + '\n' + elt.findtext('comment', '')
95 return commit(author=elt.get('author'), date=util.datestr(date),
95 return commit(author=elt.get('author'), date=util.datestr(date),
96 desc=desc.strip(), parents=self.parents[rev])
96 desc=desc.strip(), parents=self.parents[rev])
97
97
98 def pull(self, rev):
98 def pull(self, rev):
99 output, status = self.run('pull', self.path, all=True,
99 output, status = self.run('pull', self.path, all=True,
100 match='hash %s' % rev,
100 match='hash %s' % rev,
101 no_test=True, no_posthook=True,
101 no_test=True, no_posthook=True,
102 external_merge='/bin/false',
102 external_merge='/bin/false',
103 repodir=self.tmppath)
103 repodir=self.tmppath)
104 if status:
104 if status:
105 if output.find('We have conflicts in') == -1:
105 if output.find('We have conflicts in') == -1:
106 self.checkexit(status, output)
106 self.checkexit(status, output)
107 output, status = self.run('revert', all=True, repodir=self.tmppath)
107 output, status = self.run('revert', all=True, repodir=self.tmppath)
108 self.checkexit(status, output)
108 self.checkexit(status, output)
109
109
110 def getchanges(self, rev):
110 def getchanges(self, rev):
111 self.pull(rev)
111 self.pull(rev)
112 copies = {}
112 copies = {}
113 changes = []
113 changes = []
114 for elt in self.changes[rev].find('summary').getchildren():
114 for elt in self.changes[rev].find('summary').getchildren():
115 if elt.tag in ('add_directory', 'remove_directory'):
115 if elt.tag in ('add_directory', 'remove_directory'):
116 continue
116 continue
117 if elt.tag == 'move':
117 if elt.tag == 'move':
118 changes.append((elt.get('from'), rev))
118 changes.append((elt.get('from'), rev))
119 copies[elt.get('from')] = elt.get('to')
119 changes.append((elt.get('to'), rev))
120 copies[elt.get('to')] = elt.get('from')
120 else:
121 else:
121 changes.append((elt.text.strip(), rev))
122 changes.append((elt.text.strip(), rev))
122 self.lastrev = rev
123 self.lastrev = rev
123 return sorted(changes), copies
124 return sorted(changes), copies
124
125
125 def getfile(self, name, rev):
126 def getfile(self, name, rev):
126 if rev != self.lastrev:
127 if rev != self.lastrev:
127 raise util.Abort(_('internal calling inconsistency'))
128 raise util.Abort(_('internal calling inconsistency'))
128 return open(os.path.join(self.tmppath, name), 'rb').read()
129 return open(os.path.join(self.tmppath, name), 'rb').read()
129
130
130 def getmode(self, name, rev):
131 def getmode(self, name, rev):
131 mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
132 mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
132 return (mode & 0111) and 'x' or ''
133 return (mode & 0111) and 'x' or ''
133
134
134 def gettags(self):
135 def gettags(self):
135 return self.tags
136 return self.tags
@@ -1,63 +1,68 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 "$TESTDIR/hghave" darcs || exit 80
3 "$TESTDIR/hghave" darcs || exit 80
4
4
5 echo "[extensions]" >> $HGRCPATH
5 echo "[extensions]" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
7 echo 'hgext.graphlog =' >> $HGRCPATH
7 echo 'hgext.graphlog =' >> $HGRCPATH
8
8
9 DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
9 DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
10 HOME=`pwd`/do_not_use_HOME_darcs; export HOME
10 HOME=`pwd`/do_not_use_HOME_darcs; export HOME
11
11
12 # skip if we can't import elementtree
12 # skip if we can't import elementtree
13 mkdir dummy
13 mkdir dummy
14 mkdir dummy/_darcs
14 mkdir dummy/_darcs
15 if hg convert dummy 2>&1 | grep ElementTree > /dev/null; then
15 if hg convert dummy 2>&1 | grep ElementTree > /dev/null; then
16 echo 'skipped: missing feature: elementtree module'
16 echo 'skipped: missing feature: elementtree module'
17 exit 80
17 exit 80
18 fi
18 fi
19
19
20 echo % initialize darcs repo
20 echo % initialize darcs repo
21 mkdir darcs-repo
21 mkdir darcs-repo
22 cd darcs-repo
22 cd darcs-repo
23 darcs init
23 darcs init
24 echo a > a
24 echo a > a
25 darcs record -a -l -m p0
25 darcs record -a -l -m p0
26 cd ..
26 cd ..
27
27
28 echo % branch and update
28 echo % branch and update
29 darcs get darcs-repo darcs-clone >/dev/null
29 darcs get darcs-repo darcs-clone >/dev/null
30 cd darcs-clone
30 cd darcs-clone
31 echo c >> a
31 echo c >> a
32 echo c > c
32 echo c > c
33 darcs record -a -l -m p1.1
33 darcs record -a -l -m p1.1
34 cd ..
34 cd ..
35
35
36 echo % update source
36 echo % update source
37 cd darcs-repo
37 cd darcs-repo
38 echo b >> a
38 echo b >> a
39 echo b > b
39 echo b > b
40 darcs record -a -l -m p1.2
40 darcs record -a -l -m p1.2
41
41
42 echo % merge branch
42 echo % merge branch
43 darcs pull -a ../darcs-clone
43 darcs pull -a ../darcs-clone
44 sleep 1
44 sleep 1
45 echo e > a
45 echo e > a
46 echo f > f
46 darcs record -a -l -m p2
47 darcs record -a -l -m p2
48
49 echo % test file and directory move
50 darcs mv f ff
51 darcs record -a -l -m p3
47 cd ..
52 cd ..
48
53
49 glog()
54 glog()
50 {
55 {
51 hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
56 hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
52 }
57 }
53
58
54 hg convert darcs-repo darcs-repo-hg
59 hg convert darcs-repo darcs-repo-hg
55 # The converter does not currently handle patch conflicts very well.
60 # The converter does not currently handle patch conflicts very well.
56 # When they occur, it reverts *all* changes and moves forward,
61 # When they occur, it reverts *all* changes and moves forward,
57 # letting the conflict resolving patch fix collisions.
62 # letting the conflict resolving patch fix collisions.
58 # Unfortunately, non-conflicting changes, like the addition of the
63 # Unfortunately, non-conflicting changes, like the addition of the
59 # "c" file in p1.1 patch are reverted too.
64 # "c" file in p1.1 patch are reverted too.
60 # Just to say that manifest not listing "c" here is a bug.
65 # Just to say that manifest not listing "c" here is a bug.
61 glog -R darcs-repo-hg
66 glog -R darcs-repo-hg
62 hg up -q -R darcs-repo-hg
67 hg up -q -R darcs-repo-hg
63 hg -R darcs-repo-hg manifest --debug
68 hg -R darcs-repo-hg manifest --debug
@@ -1,30 +1,36 b''
1 % initialize darcs repo
1 % initialize darcs repo
2 Finished recording patch 'p0'
2 Finished recording patch 'p0'
3 % branch and update
3 % branch and update
4 Finished recording patch 'p1.1'
4 Finished recording patch 'p1.1'
5 % update source
5 % update source
6 Finished recording patch 'p1.2'
6 Finished recording patch 'p1.2'
7 % merge branch
7 % merge branch
8 Backing up ./a(-darcs-backup0)
8 Backing up ./a(-darcs-backup0)
9 We have conflicts in the following files:
9 We have conflicts in the following files:
10 ./a
10 ./a
11 Finished pulling and applying.
11 Finished pulling and applying.
12 Finished recording patch 'p2'
12 Finished recording patch 'p2'
13 % test file and directory move
14 Finished recording patch 'p3'
13 initializing destination darcs-repo-hg repository
15 initializing destination darcs-repo-hg repository
14 scanning source...
16 scanning source...
15 sorting...
17 sorting...
16 converting...
18 converting...
17 3 p0
19 4 p0
18 2 p1.2
20 3 p1.2
19 1 p1.1
21 2 p1.1
20 0 p2
22 1 p2
21 o 3 "p2" files: a
23 0 p3
24 o 4 "p3" files: f ff
25 |
26 o 3 "p2" files: a f
22 |
27 |
23 o 2 "p1.1" files:
28 o 2 "p1.1" files:
24 |
29 |
25 o 1 "p1.2" files: a b
30 o 1 "p1.2" files: a b
26 |
31 |
27 o 0 "p0" files: a
32 o 0 "p0" files: a
28
33
29 7225b30cdf38257d5cc7780772c051b6f33e6d6b 644 a
34 7225b30cdf38257d5cc7780772c051b6f33e6d6b 644 a
30 1e88685f5ddec574a34c70af492f95b6debc8741 644 b
35 1e88685f5ddec574a34c70af492f95b6debc8741 644 b
36 ef5c76581d78340f568d5f48d679bf307452cbc9 644 ff
General Comments 0
You need to be logged in to leave comments. Login now