Show More
@@ -291,6 +291,15 b' def convert(ui, src, dest=None, revmapfi' | |||||
291 | leading 'refs/heads' stripped. Git submodules are converted to Git |
|
291 | leading 'refs/heads' stripped. Git submodules are converted to Git | |
292 | subrepos in Mercurial. |
|
292 | subrepos in Mercurial. | |
293 |
|
293 | |||
|
294 | The following options can be set with ``--config``: | |||
|
295 | ||||
|
296 | :convert.git.similarity: specify how similar files modified in a | |||
|
297 | commit must be to be imported as renames or copies, as a | |||
|
298 | percentage between ``0`` (disabled) and ``100`` (files must be | |||
|
299 | identical). For example, ``90`` means that a delete/add pair will | |||
|
300 | be imported as a rename if more than 90% of the file hasn't | |||
|
301 | changed. The default is ``0``. | |||
|
302 | ||||
294 | Perforce Source |
|
303 | Perforce Source | |
295 | ############### |
|
304 | ############### | |
296 |
|
305 |
@@ -94,6 +94,17 b' class convert_git(converter_source):' | |||||
94 | if not os.path.exists(path + "/objects"): |
|
94 | if not os.path.exists(path + "/objects"): | |
95 | raise NoRepo(_("%s does not look like a Git repository") % path) |
|
95 | raise NoRepo(_("%s does not look like a Git repository") % path) | |
96 |
|
96 | |||
|
97 | try: | |||
|
98 | similarity = int(ui.config('convert', 'git.similarity') or 0) | |||
|
99 | except ValueError: | |||
|
100 | raise util.Abort('convert.git.similarity must be a number') | |||
|
101 | if similarity < 0 or similarity > 100: | |||
|
102 | raise util.Abort(_('similarity must be between 0 and 100')) | |||
|
103 | if similarity > 0: | |||
|
104 | self.simopt = '--find-copies=%d%%' % similarity | |||
|
105 | else: | |||
|
106 | self.simopt = '' | |||
|
107 | ||||
97 | checktool('git', 'git') |
|
108 | checktool('git', 'git') | |
98 |
|
109 | |||
99 | self.path = path |
|
110 | self.path = path | |
@@ -184,8 +195,10 b' class convert_git(converter_source):' | |||||
184 | if full: |
|
195 | if full: | |
185 | raise util.Abort(_("convert from git do not support --full")) |
|
196 | raise util.Abort(_("convert from git do not support --full")) | |
186 | self.modecache = {} |
|
197 | self.modecache = {} | |
187 |
fh = self.gitopen("git diff-tree -z --root -m -r %s" % |
|
198 | fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % ( | |
|
199 | self.simopt, version)) | |||
188 | changes = [] |
|
200 | changes = [] | |
|
201 | copies = {} | |||
189 | seen = set() |
|
202 | seen = set() | |
190 | entry = None |
|
203 | entry = None | |
191 | subexists = [False] |
|
204 | subexists = [False] | |
@@ -194,15 +207,16 b' class convert_git(converter_source):' | |||||
194 | lcount = len(difftree) |
|
207 | lcount = len(difftree) | |
195 | i = 0 |
|
208 | i = 0 | |
196 |
|
209 | |||
197 | def add(entry, f): |
|
210 | def add(entry, f, isdest): | |
198 | seen.add(f) |
|
211 | seen.add(f) | |
199 | h = entry[3] |
|
212 | h = entry[3] | |
200 | p = (entry[1] == "100755") |
|
213 | p = (entry[1] == "100755") | |
201 | s = (entry[1] == "120000") |
|
214 | s = (entry[1] == "120000") | |
|
215 | renamesource = (not isdest and entry[4][0] == 'R') | |||
202 |
|
216 | |||
203 | if f == '.gitmodules': |
|
217 | if f == '.gitmodules': | |
204 | subexists[0] = True |
|
218 | subexists[0] = True | |
205 | if entry[4] == 'D': |
|
219 | if entry[4] == 'D' or renamesource: | |
206 | subdeleted[0] = True |
|
220 | subdeleted[0] = True | |
207 | changes.append(('.hgsub', hex(nullid))) |
|
221 | changes.append(('.hgsub', hex(nullid))) | |
208 | else: |
|
222 | else: | |
@@ -210,6 +224,8 b' class convert_git(converter_source):' | |||||
210 | elif entry[1] == '160000' or entry[0] == ':160000': |
|
224 | elif entry[1] == '160000' or entry[0] == ':160000': | |
211 | subexists[0] = True |
|
225 | subexists[0] = True | |
212 | else: |
|
226 | else: | |
|
227 | if renamesource: | |||
|
228 | h = hex(nullid) | |||
213 | self.modecache[(f, h)] = (p and "x") or (s and "l") or "" |
|
229 | self.modecache[(f, h)] = (p and "x") or (s and "l") or "" | |
214 | changes.append((f, h)) |
|
230 | changes.append((f, h)) | |
215 |
|
231 | |||
@@ -223,7 +239,19 b' class convert_git(converter_source):' | |||||
223 | continue |
|
239 | continue | |
224 | f = l |
|
240 | f = l | |
225 | if f not in seen: |
|
241 | if f not in seen: | |
226 | add(entry, f) |
|
242 | add(entry, f, False) | |
|
243 | # A file can be copied multiple times, or modified and copied | |||
|
244 | # simultaneously. So f can be repeated even if fdest isn't. | |||
|
245 | if entry[4][0] in 'RC': | |||
|
246 | # rename or copy: next line is the destination | |||
|
247 | fdest = difftree[i] | |||
|
248 | i += 1 | |||
|
249 | if fdest not in seen: | |||
|
250 | add(entry, fdest, True) | |||
|
251 | # .gitmodules isn't imported at all, so it being copied to | |||
|
252 | # and fro doesn't really make sense | |||
|
253 | if f != '.gitmodules' and fdest != '.gitmodules': | |||
|
254 | copies[fdest] = f | |||
227 | entry = None |
|
255 | entry = None | |
228 | if fh.close(): |
|
256 | if fh.close(): | |
229 | raise util.Abort(_('cannot read changes in %s') % version) |
|
257 | raise util.Abort(_('cannot read changes in %s') % version) | |
@@ -234,7 +262,7 b' class convert_git(converter_source):' | |||||
234 | else: |
|
262 | else: | |
235 | self.retrievegitmodules(version) |
|
263 | self.retrievegitmodules(version) | |
236 | changes.append(('.hgsubstate', '')) |
|
264 | changes.append(('.hgsubstate', '')) | |
237 |
return (changes, |
|
265 | return (changes, copies) | |
238 |
|
266 | |||
239 | def getcommit(self, version): |
|
267 | def getcommit(self, version): | |
240 | c = self.catfile(version, "commit") # read the commit hash |
|
268 | c = self.catfile(version, "commit") # read the commit hash |
@@ -241,8 +241,45 b' full conversion' | |||||
241 | 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo |
|
241 | 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo | |
242 | 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux |
|
242 | 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux | |
243 |
|
243 | |||
|
244 | test importing git renames and copies | |||
|
245 | ||||
|
246 | $ cd git-repo2 | |||
|
247 | $ git mv foo foo-renamed | |||
|
248 | since bar is not touched in this commit, this copy will not be detected | |||
|
249 | $ cp bar bar-copied | |||
|
250 | $ cp baz baz-copied | |||
|
251 | $ cp baz baz-copied2 | |||
|
252 | $ echo baz2 >> baz | |||
|
253 | $ git add bar-copied baz-copied baz-copied2 | |||
|
254 | $ commit -a -m 'rename and copy' | |||
|
255 | $ cd .. | |||
|
256 | ||||
|
257 | input validation | |||
|
258 | $ hg convert --config convert.git.similarity=foo --datesort git-repo2 fullrepo | |||
|
259 | abort: convert.git.similarity must be a number | |||
|
260 | [255] | |||
|
261 | $ hg convert --config convert.git.similarity=-1 --datesort git-repo2 fullrepo | |||
|
262 | abort: similarity must be between 0 and 100 | |||
|
263 | [255] | |||
|
264 | $ hg convert --config convert.git.similarity=101 --datesort git-repo2 fullrepo | |||
|
265 | abort: similarity must be between 0 and 100 | |||
|
266 | [255] | |||
|
267 | ||||
|
268 | $ hg -q convert --config convert.git.similarity=100 --datesort git-repo2 fullrepo | |||
|
269 | $ hg -R fullrepo status -C --change master | |||
|
270 | M baz | |||
|
271 | A bar-copied | |||
|
272 | A baz-copied | |||
|
273 | baz | |||
|
274 | A baz-copied2 | |||
|
275 | baz | |||
|
276 | A foo-renamed | |||
|
277 | foo | |||
|
278 | R foo | |||
|
279 | ||||
244 | test binary conversion (issue1359) |
|
280 | test binary conversion (issue1359) | |
245 |
|
281 | |||
|
282 | $ count=19 | |||
246 | $ mkdir git-repo3 |
|
283 | $ mkdir git-repo3 | |
247 | $ cd git-repo3 |
|
284 | $ cd git-repo3 | |
248 | $ git init-db >/dev/null 2>/dev/null |
|
285 | $ git init-db >/dev/null 2>/dev/null | |
@@ -398,6 +435,29 b' convert sub modules' | |||||
398 |
|
435 | |||
399 | $ cd ../.. |
|
436 | $ cd ../.. | |
400 |
|
437 | |||
|
438 | make sure rename detection doesn't break removing and adding gitmodules | |||
|
439 | ||||
|
440 | $ cd git-repo6 | |||
|
441 | $ git mv .gitmodules .gitmodules-renamed | |||
|
442 | $ commit -a -m 'rename .gitmodules' | |||
|
443 | $ git mv .gitmodules-renamed .gitmodules | |||
|
444 | $ commit -a -m 'rename .gitmodules back' | |||
|
445 | $ cd .. | |||
|
446 | ||||
|
447 | $ hg --config convert.git.similarity=100 convert -q git-repo6 git-repo6-hg | |||
|
448 | $ hg -R git-repo6-hg log -r 'tip^' -T "{desc|firstline}\n" | |||
|
449 | rename .gitmodules | |||
|
450 | $ hg -R git-repo6-hg status -C --change 'tip^' | |||
|
451 | A .gitmodules-renamed | |||
|
452 | R .hgsub | |||
|
453 | R .hgsubstate | |||
|
454 | $ hg -R git-repo6-hg log -r tip -T "{desc|firstline}\n" | |||
|
455 | rename .gitmodules back | |||
|
456 | $ hg -R git-repo6-hg status -C --change tip | |||
|
457 | A .hgsub | |||
|
458 | A .hgsubstate | |||
|
459 | R .gitmodules-renamed | |||
|
460 | ||||
401 | convert the revision removing '.gitmodules' itself (and related |
|
461 | convert the revision removing '.gitmodules' itself (and related | |
402 | submodules) |
|
462 | submodules) | |
403 |
|
463 |
@@ -244,6 +244,16 b'' | |||||
244 | converted to bookmarks with the same name, with the leading 'refs/heads' |
|
244 | converted to bookmarks with the same name, with the leading 'refs/heads' | |
245 | stripped. Git submodules are converted to Git subrepos in Mercurial. |
|
245 | stripped. Git submodules are converted to Git subrepos in Mercurial. | |
246 |
|
246 | |||
|
247 | The following options can be set with "--config": | |||
|
248 | ||||
|
249 | convert.git.similarity | |||
|
250 | specify how similar files modified in a commit must be to be | |||
|
251 | imported as renames or copies, as a percentage between "0" | |||
|
252 | (disabled) and "100" (files must be identical). For example, | |||
|
253 | "90" means that a delete/add pair will be imported as a | |||
|
254 | rename if more than 90% of the file hasn't changed. The | |||
|
255 | default is "0". | |||
|
256 | ||||
247 | Perforce Source |
|
257 | Perforce Source | |
248 | ############### |
|
258 | ############### | |
249 |
|
259 |
General Comments 0
You need to be logged in to leave comments.
Login now