Show More
@@ -0,0 +1,91 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | "$TESTDIR/hghave" svn svn-bindings || exit 80 | |||
|
4 | ||||
|
5 | echo "[extensions]" >> $HGRCPATH | |||
|
6 | echo "convert = " >> $HGRCPATH | |||
|
7 | ||||
|
8 | hg init a | |||
|
9 | ||||
|
10 | echo a > a/a | |||
|
11 | echo % add | |||
|
12 | hg --cwd a ci -d '0 0' -A -m 'add a file' | |||
|
13 | ||||
|
14 | echo a >> a/a | |||
|
15 | echo % modify | |||
|
16 | hg --cwd a ci -d '1 0' -m 'modify a file' | |||
|
17 | hg --cwd a tip -q | |||
|
18 | ||||
|
19 | hg convert -d svn a | |||
|
20 | (cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=2 | sed 's,<date>.*,<date/>,') | |||
|
21 | ls a a-hg-wc | |||
|
22 | cmp a/a a-hg-wc/a && echo same || echo different | |||
|
23 | ||||
|
24 | hg --cwd a mv a b | |||
|
25 | echo % rename | |||
|
26 | hg --cwd a ci -d '2 0' -m 'rename a file' | |||
|
27 | hg --cwd a tip -q | |||
|
28 | ||||
|
29 | hg convert -d svn a | |||
|
30 | (cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,') | |||
|
31 | ls a a-hg-wc | |||
|
32 | ||||
|
33 | hg --cwd a cp b c | |||
|
34 | echo % copy | |||
|
35 | hg --cwd a ci -d '3 0' -m 'copy a file' | |||
|
36 | hg --cwd a tip -q | |||
|
37 | ||||
|
38 | hg convert -d svn a | |||
|
39 | (cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,') | |||
|
40 | ls a a-hg-wc | |||
|
41 | ||||
|
42 | hg --cwd a rm b | |||
|
43 | echo % remove | |||
|
44 | hg --cwd a ci -d '4 0' -m 'remove a file' | |||
|
45 | hg --cwd a tip -q | |||
|
46 | ||||
|
47 | hg convert -d svn a | |||
|
48 | (cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,') | |||
|
49 | ls a a-hg-wc | |||
|
50 | ||||
|
51 | chmod +x a/c | |||
|
52 | echo % executable | |||
|
53 | hg --cwd a ci -d '5 0' -m 'make a file executable' | |||
|
54 | hg --cwd a tip -q | |||
|
55 | ||||
|
56 | hg convert -d svn a | |||
|
57 | (cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,') | |||
|
58 | test -x a-hg-wc/c && echo executable || echo not executable | |||
|
59 | ||||
|
60 | echo % branchy history | |||
|
61 | ||||
|
62 | hg init b | |||
|
63 | echo base > b/b | |||
|
64 | hg --cwd b ci -d '0 0' -Ambase | |||
|
65 | ||||
|
66 | echo left-1 >> b/b | |||
|
67 | echo left-1 > b/left-1 | |||
|
68 | hg --cwd b ci -d '1 0' -Amleft-1 | |||
|
69 | ||||
|
70 | echo left-2 >> b/b | |||
|
71 | echo left-2 > b/left-2 | |||
|
72 | hg --cwd b ci -d '2 0' -Amleft-2 | |||
|
73 | ||||
|
74 | hg --cwd b up 0 | |||
|
75 | ||||
|
76 | echo right-1 >> b/b | |||
|
77 | echo right-1 > b/right-1 | |||
|
78 | hg --cwd b ci -d '3 0' -Amright-1 | |||
|
79 | ||||
|
80 | echo right-2 >> b/b | |||
|
81 | echo right-2 > b/right-2 | |||
|
82 | hg --cwd b ci -d '4 0' -Amright-2 | |||
|
83 | ||||
|
84 | hg --cwd b up -C 2 | |||
|
85 | hg --cwd b merge | |||
|
86 | hg --cwd b revert -r 2 b | |||
|
87 | hg --cwd b ci -d '5 0' -m 'merge' | |||
|
88 | ||||
|
89 | hg convert -d svn b | |||
|
90 | echo % expect 4 changes | |||
|
91 | (cd b-hg-wc; svn up; svn st -v; svn log --xml -v | sed 's,<date>.*,<date/>,') |
@@ -0,0 +1,251 b'' | |||||
|
1 | % add | |||
|
2 | adding a | |||
|
3 | % modify | |||
|
4 | 1:10307c220ed9 | |||
|
5 | assuming destination a-hg | |||
|
6 | initializing svn repo 'a-hg' | |||
|
7 | initializing svn wc 'a-hg-wc' | |||
|
8 | scanning source... | |||
|
9 | sorting... | |||
|
10 | converting... | |||
|
11 | 1 add a file | |||
|
12 | 0 modify a file | |||
|
13 | At revision 2. | |||
|
14 | 2 2 test . | |||
|
15 | 2 2 test a | |||
|
16 | <?xml version="1.0"?> | |||
|
17 | <log> | |||
|
18 | <logentry | |||
|
19 | revision="2"> | |||
|
20 | <author>test</author> | |||
|
21 | <date/> | |||
|
22 | <paths> | |||
|
23 | <path | |||
|
24 | action="M">/a</path> | |||
|
25 | </paths> | |||
|
26 | <msg>modify a file</msg> | |||
|
27 | </logentry> | |||
|
28 | <logentry | |||
|
29 | revision="1"> | |||
|
30 | <author>test</author> | |||
|
31 | <date/> | |||
|
32 | <paths> | |||
|
33 | <path | |||
|
34 | action="A">/a</path> | |||
|
35 | </paths> | |||
|
36 | <msg>add a file</msg> | |||
|
37 | </logentry> | |||
|
38 | </log> | |||
|
39 | a: | |||
|
40 | a | |||
|
41 | ||||
|
42 | a-hg-wc: | |||
|
43 | a | |||
|
44 | same | |||
|
45 | % rename | |||
|
46 | 2:6e45a219686e | |||
|
47 | assuming destination a-hg | |||
|
48 | initializing svn wc 'a-hg-wc' | |||
|
49 | scanning source... | |||
|
50 | sorting... | |||
|
51 | converting... | |||
|
52 | 0 rename a file | |||
|
53 | At revision 3. | |||
|
54 | 3 3 test . | |||
|
55 | 3 3 test b | |||
|
56 | <?xml version="1.0"?> | |||
|
57 | <log> | |||
|
58 | <logentry | |||
|
59 | revision="3"> | |||
|
60 | <author>test</author> | |||
|
61 | <date/> | |||
|
62 | <paths> | |||
|
63 | <path | |||
|
64 | action="D">/a</path> | |||
|
65 | <path | |||
|
66 | copyfrom-path="/a" | |||
|
67 | copyfrom-rev="2" | |||
|
68 | action="A">/b</path> | |||
|
69 | </paths> | |||
|
70 | <msg>rename a file</msg> | |||
|
71 | </logentry> | |||
|
72 | </log> | |||
|
73 | a: | |||
|
74 | b | |||
|
75 | ||||
|
76 | a-hg-wc: | |||
|
77 | b | |||
|
78 | % copy | |||
|
79 | 3:d811dc81efbb | |||
|
80 | assuming destination a-hg | |||
|
81 | initializing svn wc 'a-hg-wc' | |||
|
82 | scanning source... | |||
|
83 | sorting... | |||
|
84 | converting... | |||
|
85 | 0 copy a file | |||
|
86 | At revision 4. | |||
|
87 | 4 4 test . | |||
|
88 | 4 3 test b | |||
|
89 | 4 4 test c | |||
|
90 | <?xml version="1.0"?> | |||
|
91 | <log> | |||
|
92 | <logentry | |||
|
93 | revision="4"> | |||
|
94 | <author>test</author> | |||
|
95 | <date/> | |||
|
96 | <paths> | |||
|
97 | <path | |||
|
98 | copyfrom-path="/b" | |||
|
99 | copyfrom-rev="3" | |||
|
100 | action="A">/c</path> | |||
|
101 | </paths> | |||
|
102 | <msg>copy a file</msg> | |||
|
103 | </logentry> | |||
|
104 | </log> | |||
|
105 | a: | |||
|
106 | b | |||
|
107 | c | |||
|
108 | ||||
|
109 | a-hg-wc: | |||
|
110 | b | |||
|
111 | c | |||
|
112 | % remove | |||
|
113 | 4:045e93063aca | |||
|
114 | assuming destination a-hg | |||
|
115 | initializing svn wc 'a-hg-wc' | |||
|
116 | scanning source... | |||
|
117 | sorting... | |||
|
118 | converting... | |||
|
119 | 0 remove a file | |||
|
120 | At revision 5. | |||
|
121 | 5 5 test . | |||
|
122 | 5 4 test c | |||
|
123 | <?xml version="1.0"?> | |||
|
124 | <log> | |||
|
125 | <logentry | |||
|
126 | revision="5"> | |||
|
127 | <author>test</author> | |||
|
128 | <date/> | |||
|
129 | <paths> | |||
|
130 | <path | |||
|
131 | action="D">/b</path> | |||
|
132 | </paths> | |||
|
133 | <msg>remove a file</msg> | |||
|
134 | </logentry> | |||
|
135 | </log> | |||
|
136 | a: | |||
|
137 | c | |||
|
138 | ||||
|
139 | a-hg-wc: | |||
|
140 | c | |||
|
141 | % executable | |||
|
142 | 5:7eda3f4b5331 | |||
|
143 | svn: Path 'b' does not exist | |||
|
144 | assuming destination a-hg | |||
|
145 | initializing svn wc 'a-hg-wc' | |||
|
146 | scanning source... | |||
|
147 | sorting... | |||
|
148 | converting... | |||
|
149 | 0 make a file executable | |||
|
150 | abort: svn exited with status 1 | |||
|
151 | At revision 5. | |||
|
152 | 5 5 test . | |||
|
153 | M 5 4 test c | |||
|
154 | <?xml version="1.0"?> | |||
|
155 | <log> | |||
|
156 | <logentry | |||
|
157 | revision="5"> | |||
|
158 | <author>test</author> | |||
|
159 | <date/> | |||
|
160 | <paths> | |||
|
161 | <path | |||
|
162 | action="D">/b</path> | |||
|
163 | </paths> | |||
|
164 | <msg>remove a file</msg> | |||
|
165 | </logentry> | |||
|
166 | </log> | |||
|
167 | executable | |||
|
168 | % branchy history | |||
|
169 | adding b | |||
|
170 | adding left-1 | |||
|
171 | adding left-2 | |||
|
172 | 1 files updated, 0 files merged, 2 files removed, 0 files unresolved | |||
|
173 | adding right-1 | |||
|
174 | adding right-2 | |||
|
175 | 3 files updated, 0 files merged, 2 files removed, 0 files unresolved | |||
|
176 | warning: conflicts during merge. | |||
|
177 | merging b | |||
|
178 | merging b failed! | |||
|
179 | 2 files updated, 0 files merged, 0 files removed, 1 files unresolved | |||
|
180 | There are unresolved merges, you can redo the full merge using: | |||
|
181 | hg update -C 2 | |||
|
182 | hg merge 4 | |||
|
183 | assuming destination b-hg | |||
|
184 | initializing svn repo 'b-hg' | |||
|
185 | initializing svn wc 'b-hg-wc' | |||
|
186 | scanning source... | |||
|
187 | sorting... | |||
|
188 | converting... | |||
|
189 | 5 base | |||
|
190 | 4 left-1 | |||
|
191 | 3 left-2 | |||
|
192 | 2 right-1 | |||
|
193 | 1 right-2 | |||
|
194 | 0 merge | |||
|
195 | % expect 4 changes | |||
|
196 | At revision 4. | |||
|
197 | 4 4 test . | |||
|
198 | 4 3 test b | |||
|
199 | 4 2 test left-1 | |||
|
200 | 4 3 test left-2 | |||
|
201 | 4 4 test right-1 | |||
|
202 | 4 4 test right-2 | |||
|
203 | <?xml version="1.0"?> | |||
|
204 | <log> | |||
|
205 | <logentry | |||
|
206 | revision="4"> | |||
|
207 | <author>test</author> | |||
|
208 | <date/> | |||
|
209 | <paths> | |||
|
210 | <path | |||
|
211 | action="A">/right-1</path> | |||
|
212 | <path | |||
|
213 | action="A">/right-2</path> | |||
|
214 | </paths> | |||
|
215 | <msg>merge</msg> | |||
|
216 | </logentry> | |||
|
217 | <logentry | |||
|
218 | revision="3"> | |||
|
219 | <author>test</author> | |||
|
220 | <date/> | |||
|
221 | <paths> | |||
|
222 | <path | |||
|
223 | action="M">/b</path> | |||
|
224 | <path | |||
|
225 | action="A">/left-2</path> | |||
|
226 | </paths> | |||
|
227 | <msg>left-2</msg> | |||
|
228 | </logentry> | |||
|
229 | <logentry | |||
|
230 | revision="2"> | |||
|
231 | <author>test</author> | |||
|
232 | <date/> | |||
|
233 | <paths> | |||
|
234 | <path | |||
|
235 | action="M">/b</path> | |||
|
236 | <path | |||
|
237 | action="A">/left-1</path> | |||
|
238 | </paths> | |||
|
239 | <msg>left-1</msg> | |||
|
240 | </logentry> | |||
|
241 | <logentry | |||
|
242 | revision="1"> | |||
|
243 | <author>test</author> | |||
|
244 | <date/> | |||
|
245 | <paths> | |||
|
246 | <path | |||
|
247 | action="A">/b</path> | |||
|
248 | </paths> | |||
|
249 | <msg>base</msg> | |||
|
250 | </logentry> | |||
|
251 | </log> |
@@ -10,7 +10,7 b' from cvs import convert_cvs' | |||||
10 | from darcs import darcs_source |
|
10 | from darcs import darcs_source | |
11 | from git import convert_git |
|
11 | from git import convert_git | |
12 | from hg import mercurial_source, mercurial_sink |
|
12 | from hg import mercurial_source, mercurial_sink | |
13 |
from subversion import svn_source, |
|
13 | from subversion import debugsvnlog, svn_source, svn_sink | |
14 | import filemap |
|
14 | import filemap | |
15 |
|
15 | |||
16 | import os, shutil |
|
16 | import os, shutil | |
@@ -29,6 +29,7 b' source_converters = [' | |||||
29 |
|
29 | |||
30 | sink_converters = [ |
|
30 | sink_converters = [ | |
31 | ('hg', mercurial_sink), |
|
31 | ('hg', mercurial_sink), | |
|
32 | ('svn', svn_sink), | |||
32 | ] |
|
33 | ] | |
33 |
|
34 | |||
34 | def convertsource(ui, path, type, rev): |
|
35 | def convertsource(ui, path, type, rev): | |
@@ -283,6 +284,7 b' def convert(ui, src, dest=None, revmapfi' | |||||
283 |
|
284 | |||
284 | Accepted destination formats: |
|
285 | Accepted destination formats: | |
285 | - Mercurial |
|
286 | - Mercurial | |
|
287 | - Subversion (history on branches is not preserved) | |||
286 |
|
288 | |||
287 | If no revision is given, all revisions will be converted. Otherwise, |
|
289 | If no revision is given, all revisions will be converted. Otherwise, | |
288 | convert will only import up to the named revision (given in a format |
|
290 | convert will only import up to the named revision (given in a format |
@@ -2,6 +2,7 b'' | |||||
2 | import base64, errno |
|
2 | import base64, errno | |
3 | import cPickle as pickle |
|
3 | import cPickle as pickle | |
4 | from mercurial import util |
|
4 | from mercurial import util | |
|
5 | from mercurial.i18n import _ | |||
5 |
|
6 | |||
6 | def encodeargs(args): |
|
7 | def encodeargs(args): | |
7 | def encodearg(s): |
|
8 | def encodearg(s): |
@@ -17,9 +17,13 b'' | |||||
17 |
|
17 | |||
18 | import locale |
|
18 | import locale | |
19 | import os |
|
19 | import os | |
|
20 | import re | |||
20 | import sys |
|
21 | import sys | |
21 | import cPickle as pickle |
|
22 | import cPickle as pickle | |
22 | from mercurial import util |
|
23 | import tempfile | |
|
24 | ||||
|
25 | from mercurial import strutil, util | |||
|
26 | from mercurial.i18n import _ | |||
23 |
|
27 | |||
24 | # Subversion stuff. Works best with very recent Python SVN bindings |
|
28 | # Subversion stuff. Works best with very recent Python SVN bindings | |
25 | # e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing |
|
29 | # e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing | |
@@ -28,6 +32,7 b' from mercurial import util' | |||||
28 | from cStringIO import StringIO |
|
32 | from cStringIO import StringIO | |
29 |
|
33 | |||
30 | from common import NoRepo, commit, converter_source, encodeargs, decodeargs |
|
34 | from common import NoRepo, commit, converter_source, encodeargs, decodeargs | |
|
35 | from common import commandline, converter_sink, mapfile | |||
31 |
|
36 | |||
32 | try: |
|
37 | try: | |
33 | from svn.core import SubversionException, Pool |
|
38 | from svn.core import SubversionException, Pool | |
@@ -664,3 +669,198 b' class svn_source(converter_source):' | |||||
664 | pool = Pool() |
|
669 | pool = Pool() | |
665 | rpath = '/'.join([self.base, path]).strip('/') |
|
670 | rpath = '/'.join([self.base, path]).strip('/') | |
666 | return ['%s/%s' % (path, x) for x in svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool).keys()] |
|
671 | return ['%s/%s' % (path, x) for x in svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool).keys()] | |
|
672 | ||||
|
673 | pre_revprop_change = '''#!/bin/sh | |||
|
674 | ||||
|
675 | REPOS="$1" | |||
|
676 | REV="$2" | |||
|
677 | USER="$3" | |||
|
678 | PROPNAME="$4" | |||
|
679 | ACTION="$5" | |||
|
680 | ||||
|
681 | if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi | |||
|
682 | if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-branch" ]; then exit 0; fi | |||
|
683 | if [ "$ACTION" = "A" -a "$PROPNAME" = "hg:convert-rev" ]; then exit 0; fi | |||
|
684 | ||||
|
685 | echo "Changing prohibited revision property" >&2 | |||
|
686 | exit 1 | |||
|
687 | ''' | |||
|
688 | ||||
|
689 | class svn_sink(converter_sink, commandline): | |||
|
690 | commit_re = re.compile(r'Committed revision (\d+).', re.M) | |||
|
691 | ||||
|
692 | def prerun(self): | |||
|
693 | if self.wc: | |||
|
694 | os.chdir(self.wc) | |||
|
695 | ||||
|
696 | def postrun(self): | |||
|
697 | if self.wc: | |||
|
698 | os.chdir(self.cwd) | |||
|
699 | ||||
|
700 | def join(self, name): | |||
|
701 | return os.path.join(self.wc, '.svn', name) | |||
|
702 | ||||
|
703 | def revmapfile(self): | |||
|
704 | return self.join('hg-shamap') | |||
|
705 | ||||
|
706 | def authorfile(self): | |||
|
707 | return self.join('hg-authormap') | |||
|
708 | ||||
|
709 | def __init__(self, ui, path): | |||
|
710 | converter_sink.__init__(self, ui, path) | |||
|
711 | commandline.__init__(self, ui, 'svn') | |||
|
712 | self.delete = [] | |||
|
713 | self.wc = None | |||
|
714 | self.cwd = os.getcwd() | |||
|
715 | ||||
|
716 | path = os.path.realpath(path) | |||
|
717 | ||||
|
718 | created = False | |||
|
719 | if os.path.isfile(os.path.join(path, '.svn', 'entries')): | |||
|
720 | self.wc = path | |||
|
721 | self.run0('update') | |||
|
722 | else: | |||
|
723 | if os.path.isdir(os.path.dirname(path)): | |||
|
724 | if not os.path.exists(os.path.join(path, 'db', 'fs-type')): | |||
|
725 | ui.status(_('initializing svn repo %r\n') % | |||
|
726 | os.path.basename(path)) | |||
|
727 | commandline(ui, 'svnadmin').run0('create', path) | |||
|
728 | created = path | |||
|
729 | path = 'file://' + path | |||
|
730 | wcpath = os.path.join(os.getcwd(), os.path.basename(path) + '-wc') | |||
|
731 | ui.status(_('initializing svn wc %r\n') % os.path.basename(wcpath)) | |||
|
732 | self.run0('checkout', path, wcpath) | |||
|
733 | ||||
|
734 | self.wc = wcpath | |||
|
735 | self.opener = util.opener(self.wc) | |||
|
736 | self.wopener = util.opener(self.wc) | |||
|
737 | self.childmap = mapfile(ui, self.join('hg-childmap')) | |||
|
738 | ||||
|
739 | if created: | |||
|
740 | hook = os.path.join(created, 'hooks', 'pre-revprop-change') | |||
|
741 | fp = open(hook, 'w') | |||
|
742 | fp.write(pre_revprop_change) | |||
|
743 | fp.close() | |||
|
744 | util.set_exec(hook, True) | |||
|
745 | ||||
|
746 | def wjoin(self, *names): | |||
|
747 | return os.path.join(self.wc, *names) | |||
|
748 | ||||
|
749 | def putfile(self, filename, flags, data): | |||
|
750 | if 'l' in flags: | |||
|
751 | self.wopener.symlink(data, filename) | |||
|
752 | else: | |||
|
753 | try: | |||
|
754 | if os.path.islink(self.wjoin(filename)): | |||
|
755 | os.unlink(filename) | |||
|
756 | except OSError: | |||
|
757 | pass | |||
|
758 | self.wopener(filename, 'w').write(data) | |||
|
759 | was_exec = util.is_exec(self.wjoin(filename)) | |||
|
760 | util.set_exec(self.wjoin(filename), 'x' in flags) | |||
|
761 | if was_exec: | |||
|
762 | if 'x' not in flags: | |||
|
763 | self.run0('propdel', 'svn:executable', filename) | |||
|
764 | else: | |||
|
765 | if 'x' in flags: | |||
|
766 | self.run0('propset', 'svn:executable', '*', filename) | |||
|
767 | ||||
|
768 | def delfile(self, name): | |||
|
769 | self.delete.append(name) | |||
|
770 | ||||
|
771 | def copyfile(self, source, dest): | |||
|
772 | # SVN's copy command pukes if the destination file exists, but | |||
|
773 | # our copyfile method expects to record a copy that has | |||
|
774 | # already occurred. Cross the semantic gap. | |||
|
775 | wdest = self.wjoin(dest) | |||
|
776 | exists = os.path.exists(wdest) | |||
|
777 | if exists: | |||
|
778 | fd, tempname = tempfile.mkstemp( | |||
|
779 | prefix='hg-copy-', dir=os.path.dirname(wdest)) | |||
|
780 | os.close(fd) | |||
|
781 | os.unlink(tempname) | |||
|
782 | os.rename(wdest, tempname) | |||
|
783 | try: | |||
|
784 | self.run0('copy', source, dest) | |||
|
785 | finally: | |||
|
786 | if exists: | |||
|
787 | try: | |||
|
788 | os.unlink(wdest) | |||
|
789 | except OSError: | |||
|
790 | pass | |||
|
791 | os.rename(tempname, wdest) | |||
|
792 | ||||
|
793 | def dirs_of(self, files): | |||
|
794 | dirs = set() | |||
|
795 | for f in files: | |||
|
796 | if os.path.isdir(self.wjoin(f)): | |||
|
797 | dirs.add(f) | |||
|
798 | for i in strutil.rfindall(f, '/'): | |||
|
799 | dirs.add(f[:i]) | |||
|
800 | return dirs | |||
|
801 | ||||
|
802 | def add_files(self, files): | |||
|
803 | add_dirs = [d for d in self.dirs_of(files) | |||
|
804 | if not os.path.exists(self.wjoin(d, '.svn', 'entries'))] | |||
|
805 | if add_dirs: | |||
|
806 | self.run('add', non_recursive=True, quiet=True, *add) | |||
|
807 | if files: | |||
|
808 | self.run('add', quiet=True, *files) | |||
|
809 | return files.union(add_dirs) | |||
|
810 | ||||
|
811 | def tidy_dirs(self, names): | |||
|
812 | dirs = list(self.dirs_of(names)) | |||
|
813 | dirs.sort(reverse=True) | |||
|
814 | deleted = [] | |||
|
815 | for d in dirs: | |||
|
816 | wd = self.wjoin(d) | |||
|
817 | if os.listdir(wd) == '.svn': | |||
|
818 | self.run0('delete', d) | |||
|
819 | deleted.append(d) | |||
|
820 | return deleted | |||
|
821 | ||||
|
822 | def addchild(self, parent, child): | |||
|
823 | self.childmap[parent] = child | |||
|
824 | ||||
|
825 | def putcommit(self, files, parents, commit): | |||
|
826 | for parent in parents: | |||
|
827 | try: | |||
|
828 | return self.childmap[parent] | |||
|
829 | except KeyError: | |||
|
830 | pass | |||
|
831 | entries = set(self.delete) | |||
|
832 | if self.delete: | |||
|
833 | self.run0('delete', *self.delete) | |||
|
834 | self.delete = [] | |||
|
835 | files = util.frozenset(files) | |||
|
836 | entries.update(self.add_files(files.difference(entries))) | |||
|
837 | entries.update(self.tidy_dirs(entries)) | |||
|
838 | fd, messagefile = tempfile.mkstemp(prefix='hg-convert-') | |||
|
839 | fp = os.fdopen(fd, 'w') | |||
|
840 | fp.write(commit.desc) | |||
|
841 | fp.close() | |||
|
842 | try: | |||
|
843 | output = self.run0('commit', | |||
|
844 | username=util.shortuser(commit.author), | |||
|
845 | file=messagefile, | |||
|
846 | *list(entries)) | |||
|
847 | try: | |||
|
848 | rev = self.commit_re.search(output).group(1) | |||
|
849 | except AttributeError: | |||
|
850 | self.ui.warn(_('unexpected svn output:\n')) | |||
|
851 | self.ui.warn(output) | |||
|
852 | raise util.Abort(_('unable to cope with svn output')) | |||
|
853 | if commit.rev: | |||
|
854 | self.run('propset', 'hg:convert-rev', commit.rev, | |||
|
855 | revprop=True, revision=rev) | |||
|
856 | if commit.branch and commit.branch != 'default': | |||
|
857 | self.run('propset', 'hg:convert-branch', commit.branch, | |||
|
858 | revprop=True, revision=rev) | |||
|
859 | for parent in parents: | |||
|
860 | self.addchild(parent, rev) | |||
|
861 | return rev | |||
|
862 | finally: | |||
|
863 | os.unlink(messagefile) | |||
|
864 | ||||
|
865 | def puttags(self, tags): | |||
|
866 | self.ui.warn(_('XXX TAGS NOT IMPLEMENTED YET\n')) |
1 | NO CONTENT: file renamed from tests/test-convert-svn to tests/test-convert-svn-source |
|
NO CONTENT: file renamed from tests/test-convert-svn to tests/test-convert-svn-source |
1 | NO CONTENT: file renamed from tests/test-convert-svn.out to tests/test-convert-svn-source.out |
|
NO CONTENT: file renamed from tests/test-convert-svn.out to tests/test-convert-svn-source.out |
@@ -11,6 +11,7 b' Convert a foreign SCM repository to a Me' | |||||
11 |
|
11 | |||
12 | Accepted destination formats: |
|
12 | Accepted destination formats: | |
13 | - Mercurial |
|
13 | - Mercurial | |
|
14 | - Subversion (history on branches is not preserved) | |||
14 |
|
15 | |||
15 | If no revision is given, all revisions will be converted. Otherwise, |
|
16 | If no revision is given, all revisions will be converted. Otherwise, | |
16 | convert will only import up to the named revision (given in a format |
|
17 | convert will only import up to the named revision (given in a format |
General Comments 0
You need to be logged in to leave comments.
Login now