##// END OF EJS Templates
convert: add support to detect git renames and copies...
Siddharth Agarwal -
r22470:8e0c4df2 default
parent child Browse files
Show More
@@ -291,6 +291,15 b' def convert(ui, src, dest=None, revmapfi'
291 291 leading 'refs/heads' stripped. Git submodules are converted to Git
292 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 303 Perforce Source
295 304 ###############
296 305
@@ -94,6 +94,17 b' class convert_git(converter_source):'
94 94 if not os.path.exists(path + "/objects"):
95 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 108 checktool('git', 'git')
98 109
99 110 self.path = path
@@ -184,8 +195,10 b' class convert_git(converter_source):'
184 195 if full:
185 196 raise util.Abort(_("convert from git do not support --full"))
186 197 self.modecache = {}
187 fh = self.gitopen("git diff-tree -z --root -m -r %s" % version)
198 fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
199 self.simopt, version))
188 200 changes = []
201 copies = {}
189 202 seen = set()
190 203 entry = None
191 204 subexists = [False]
@@ -194,15 +207,16 b' class convert_git(converter_source):'
194 207 lcount = len(difftree)
195 208 i = 0
196 209
197 def add(entry, f):
210 def add(entry, f, isdest):
198 211 seen.add(f)
199 212 h = entry[3]
200 213 p = (entry[1] == "100755")
201 214 s = (entry[1] == "120000")
215 renamesource = (not isdest and entry[4][0] == 'R')
202 216
203 217 if f == '.gitmodules':
204 218 subexists[0] = True
205 if entry[4] == 'D':
219 if entry[4] == 'D' or renamesource:
206 220 subdeleted[0] = True
207 221 changes.append(('.hgsub', hex(nullid)))
208 222 else:
@@ -210,6 +224,8 b' class convert_git(converter_source):'
210 224 elif entry[1] == '160000' or entry[0] == ':160000':
211 225 subexists[0] = True
212 226 else:
227 if renamesource:
228 h = hex(nullid)
213 229 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
214 230 changes.append((f, h))
215 231
@@ -223,7 +239,19 b' class convert_git(converter_source):'
223 239 continue
224 240 f = l
225 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 255 entry = None
228 256 if fh.close():
229 257 raise util.Abort(_('cannot read changes in %s') % version)
@@ -234,7 +262,7 b' class convert_git(converter_source):'
234 262 else:
235 263 self.retrievegitmodules(version)
236 264 changes.append(('.hgsubstate', ''))
237 return (changes, {})
265 return (changes, copies)
238 266
239 267 def getcommit(self, version):
240 268 c = self.catfile(version, "commit") # read the commit hash
@@ -241,8 +241,45 b' full conversion'
241 241 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
242 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 280 test binary conversion (issue1359)
245 281
282 $ count=19
246 283 $ mkdir git-repo3
247 284 $ cd git-repo3
248 285 $ git init-db >/dev/null 2>/dev/null
@@ -398,6 +435,29 b' convert sub modules'
398 435
399 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 461 convert the revision removing '.gitmodules' itself (and related
402 462 submodules)
403 463
@@ -244,6 +244,16 b''
244 244 converted to bookmarks with the same name, with the leading 'refs/heads'
245 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 257 Perforce Source
248 258 ###############
249 259
General Comments 0
You need to be logged in to leave comments. Login now