Mercurial > hg-git
comparison hggit/git_handler.py @ 275:c2d6b1093e7e
fix a bug when a directory is replaced with a file
also use ObjectStore.tree_changes from dulwich instead of our own func
(the change to test octopus is legitimate, there were some duplicate
entries)
author | Abderrahim Kitouni <a.kitouni@gmail.com> |
---|---|
date | Fri, 25 Dec 2009 08:56:20 +0100 |
parents | 29e5072ddaab |
children | 8aff8c9d04d7 |
comparison
equal
deleted
inserted
replaced
274:93cf9931c2c3 | 275:c2d6b1093e7e |
---|---|
402 commit = convert_list[csha] | 402 commit = convert_list[csha] |
403 self.import_git_commit(commit) | 403 self.import_git_commit(commit) |
404 | 404 |
405 def import_git_commit(self, commit): | 405 def import_git_commit(self, commit): |
406 self.ui.debug(_("importing: %s\n") % commit.id) | 406 self.ui.debug(_("importing: %s\n") % commit.id) |
407 # TODO: Do something less coarse-grained than try/except on the | |
408 # get_file call for removed files | |
409 | 407 |
410 (strip_message, hg_renames, hg_branch, extra) = self.extract_hg_metadata(commit.message) | 408 (strip_message, hg_renames, hg_branch, extra) = self.extract_hg_metadata(commit.message) |
411 | 409 |
412 # get a list of the changed, added, removed files | 410 # get a list of the changed, added, removed files |
413 files = self.get_files_changed(commit) | 411 files = self.get_files_changed(commit) |
448 extra['author'] = create_delta(author, origauthor) | 446 extra['author'] = create_delta(author, origauthor) |
449 | 447 |
450 oldenc = self.swap_out_encoding() | 448 oldenc = self.swap_out_encoding() |
451 | 449 |
452 def getfilectx(repo, memctx, f): | 450 def getfilectx(repo, memctx, f): |
453 try: | 451 delete, mode, sha = files[f] |
454 (mode, sha, data) = self.get_file(commit, f) | 452 if delete: |
455 e = self.convert_git_int_mode(mode) | 453 raise IOError |
456 except (TypeError, KeyError): | 454 |
457 raise IOError() | 455 data = self.git[sha].data |
458 if f in hg_renames: | 456 copied_path = hg_renames.get(f) |
459 copied_path = hg_renames[f] | 457 e = self.convert_git_int_mode(mode) |
460 else: | 458 |
461 copied_path = None | |
462 return context.memfilectx(f, data, 'l' in e, 'x' in e, copied_path) | 459 return context.memfilectx(f, data, 'l' in e, 'x' in e, copied_path) |
463 | 460 |
464 gparents = map(self.map_hg_get, commit.parents) | 461 gparents = map(self.map_hg_get, commit.parents) |
465 p1, p2 = (nullid, nullid) | 462 p1, p2 = (nullid, nullid) |
466 octopus = False | 463 octopus = False |
467 | 464 |
468 if len(gparents) > 1: | 465 if len(gparents) > 1: |
469 # merge, possibly octopus | 466 # merge, possibly octopus |
470 def commit_octopus(p1, p2): | 467 def commit_octopus(p1, p2): |
471 ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx, | 468 ctx = context.memctx(self.repo, (p1, p2), text, list(files), getfilectx, |
472 author, date, {'hg-git': 'octopus'}) | 469 author, date, {'hg-git': 'octopus'}) |
473 return hex(self.repo.commitctx(ctx)) | 470 return hex(self.repo.commitctx(ctx)) |
474 | 471 |
475 octopus = len(gparents) > 2 | 472 octopus = len(gparents) > 2 |
476 p2 = gparents.pop() | 473 p2 = gparents.pop() |
480 p1 = gparents.pop() | 477 p1 = gparents.pop() |
481 else: | 478 else: |
482 if gparents: | 479 if gparents: |
483 p1 = gparents.pop() | 480 p1 = gparents.pop() |
484 | 481 |
485 files = list(set(files)) | |
486 | |
487 pa = None | 482 pa = None |
488 if not (p2 == nullid): | 483 if not (p2 == nullid): |
489 node1 = self.repo.changectx(p1) | 484 node1 = self.repo.changectx(p1) |
490 node2 = self.repo.changectx(p2) | 485 node2 = self.repo.changectx(p2) |
491 pa = node1.ancestor(node2) | 486 pa = node1.ancestor(node2) |
507 extra['branch'] = hg_branch | 502 extra['branch'] = hg_branch |
508 | 503 |
509 if octopus: | 504 if octopus: |
510 extra['hg-git'] ='octopus-done' | 505 extra['hg-git'] ='octopus-done' |
511 | 506 |
512 ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx, | 507 ctx = context.memctx(self.repo, (p1, p2), text, list(files), getfilectx, |
513 author, date, extra) | 508 author, date, extra) |
514 | 509 |
515 node = self.repo.commitctx(ctx) | 510 node = self.repo.commitctx(ctx) |
516 | 511 |
517 self.swap_out_encoding(oldenc) | 512 self.swap_out_encoding(oldenc) |
752 return (mode, sha, obj._text) | 747 return (mode, sha, obj._text) |
753 elif isinstance(obj, Tree): | 748 elif isinstance(obj, Tree): |
754 otree = obj | 749 otree = obj |
755 | 750 |
756 def get_files_changed(self, commit): | 751 def get_files_changed(self, commit): |
757 def filenames(basetree, comptree, prefix): | 752 tree = commit.tree |
758 basefiles = set() | 753 btree = None |
759 changes = list() | 754 |
760 csha = None | 755 if commit.parents: |
761 cmode = None | 756 btree = self.git[commit.parents[0]].tree |
762 if basetree is not None: | 757 |
763 for (bmode, bname, bsha) in basetree.entries(): | 758 changes = self.git.object_store.tree_changes(btree, tree) |
764 if bmode == 0160000: # TODO: properly handle submodules | 759 files = {} |
765 continue | 760 for (oldfile, newfile), (oldmode, newmode), (oldsha, newsha) in changes: |
766 basefiles.add(bname) | 761 if newfile is None: |
767 bobj = self.git.get_object(bsha) | 762 file = oldfile |
768 if comptree is not None: | 763 delete = True |
769 if bname in comptree: | 764 else: |
770 (cmode, csha) = comptree[bname] | 765 file = newfile |
771 else: | 766 delete = False |
772 (cmode, csha) = (None, None) | 767 |
773 if not ((csha == bsha) and (cmode == bmode)): | 768 files[file] = (delete, newmode, newsha) |
774 if isinstance (bobj, Blob): | 769 |
775 changes.append (prefix + bname) | 770 return files |
776 elif isinstance(bobj, Tree): | |
777 ctree = None | |
778 if csha: | |
779 ctree = self.git.get_object(csha) | |
780 changes.extend(filenames(bobj, | |
781 ctree, | |
782 prefix + bname + '/')) | |
783 | |
784 # handle removals | |
785 if comptree is not None: | |
786 for (bmode, bname, bsha) in comptree.entries(): | |
787 if bmode == 0160000: # TODO: handle submodles | |
788 continue | |
789 if bname not in basefiles: | |
790 bobj = self.git.get_object(bsha) | |
791 if isinstance(bobj, Blob): | |
792 changes.append(prefix + bname) | |
793 elif isinstance(bobj, Tree): | |
794 changes.extend(filenames(None, bobj, | |
795 prefix + bname + '/')) | |
796 return changes | |
797 | |
798 all_changes = list() | |
799 otree = self.git.tree(commit.tree) | |
800 if len(commit.parents) == 0: | |
801 all_changes = filenames(otree, None, '') | |
802 for parent in commit.parents: | |
803 pcommit = self.git.commit(parent) | |
804 ptree = self.git.tree(pcommit.tree) | |
805 all_changes.extend(filenames(otree, ptree, '')) | |
806 | |
807 return all_changes | |
808 | 771 |
809 def remote_name(self, remote): | 772 def remote_name(self, remote): |
810 names = [name for name, path in self.paths if path == remote] | 773 names = [name for name, path in self.paths if path == remote] |
811 if names: | 774 if names: |
812 return names[0] | 775 return names[0] |