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]