changeset 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 93cf9931c2c3
children 8aff8c9d04d7
files hggit/git_handler.py tests/test-octopus.out tests/test-tree-decomposition tests/test-tree-decomposition.out
diffstat 4 files changed, 55 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/hggit/git_handler.py	Thu Nov 26 20:47:38 2009 +0100
+++ b/hggit/git_handler.py	Fri Dec 25 08:56:20 2009 +0100
@@ -404,8 +404,6 @@
 
     def import_git_commit(self, commit):
         self.ui.debug(_("importing: %s\n") % commit.id)
-        # TODO: Do something less coarse-grained than try/except on the
-        #        get_file call for removed files
 
         (strip_message, hg_renames, hg_branch, extra) = self.extract_hg_metadata(commit.message)
 
@@ -450,15 +448,14 @@
         oldenc = self.swap_out_encoding()
 
         def getfilectx(repo, memctx, f):
-            try:
-                (mode, sha, data) = self.get_file(commit, f)
-                e = self.convert_git_int_mode(mode)
-            except (TypeError, KeyError):
-                raise IOError()
-            if f in hg_renames:
-                copied_path = hg_renames[f]
-            else:
-                copied_path = None
+            delete, mode, sha = files[f]
+            if delete:
+                raise IOError
+
+            data = self.git[sha].data
+            copied_path = hg_renames.get(f)
+            e = self.convert_git_int_mode(mode)
+
             return context.memfilectx(f, data, 'l' in e, 'x' in e, copied_path)
 
         gparents = map(self.map_hg_get, commit.parents)
@@ -468,7 +465,7 @@
         if len(gparents) > 1:
             # merge, possibly octopus
             def commit_octopus(p1, p2):
-                ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx,
+                ctx = context.memctx(self.repo, (p1, p2), text, list(files), getfilectx,
                                      author, date, {'hg-git': 'octopus'})
                 return hex(self.repo.commitctx(ctx))
 
@@ -482,8 +479,6 @@
             if gparents:
                 p1 = gparents.pop()
 
-        files = list(set(files))
-
         pa = None
         if not (p2 == nullid):
             node1 = self.repo.changectx(p1)
@@ -509,7 +504,7 @@
         if octopus:
             extra['hg-git'] ='octopus-done'
 
-        ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx,
+        ctx = context.memctx(self.repo, (p1, p2), text, list(files), getfilectx,
                              author, date, extra)
 
         node = self.repo.commitctx(ctx)
@@ -754,57 +749,25 @@
                 otree = obj
 
     def get_files_changed(self, commit):
-        def filenames(basetree, comptree, prefix):
-            basefiles = set()
-            changes = list()
-            csha = None
-            cmode = None
-            if basetree is not None:
-                for (bmode, bname, bsha) in basetree.entries():
-                    if bmode == 0160000: # TODO: properly handle submodules
-                        continue
-                    basefiles.add(bname)
-                    bobj = self.git.get_object(bsha)
-                    if comptree is not None:
-                        if bname in comptree:
-                            (cmode, csha) = comptree[bname]
-                        else:
-                            (cmode, csha) = (None, None)
-                    if not ((csha == bsha) and (cmode == bmode)):
-                        if isinstance (bobj, Blob):
-                            changes.append (prefix + bname)
-                        elif isinstance(bobj, Tree):
-                            ctree = None
-                            if csha:
-                                ctree = self.git.get_object(csha)
-                            changes.extend(filenames(bobj,
-                                                     ctree,
-                                                     prefix + bname + '/'))
+        tree = commit.tree
+        btree = None
+
+        if commit.parents:
+            btree = self.git[commit.parents[0]].tree
 
-            # handle removals
-            if comptree is not None:
-                for (bmode, bname, bsha) in comptree.entries():
-                    if bmode == 0160000: # TODO: handle submodles
-                        continue
-                    if bname not in basefiles:
-                        bobj = self.git.get_object(bsha)
-                        if isinstance(bobj, Blob):
-                            changes.append(prefix + bname)
-                        elif isinstance(bobj, Tree):
-                            changes.extend(filenames(None, bobj,
-                                                     prefix + bname + '/'))
-            return changes
+        changes = self.git.object_store.tree_changes(btree, tree)
+        files = {}
+        for (oldfile, newfile), (oldmode, newmode), (oldsha, newsha) in changes:
+            if newfile is None:
+                file = oldfile
+                delete = True
+            else:
+                file = newfile
+                delete = False
 
-        all_changes = list()
-        otree = self.git.tree(commit.tree)
-        if len(commit.parents) == 0:
-            all_changes = filenames(otree, None, '')
-        for parent in commit.parents:
-            pcommit = self.git.commit(parent)
-            ptree = self.git.tree(pcommit.tree)
-            all_changes.extend(filenames(otree, ptree, ''))
+            files[file] = (delete, newmode, newsha)
 
-        return all_changes
+        return files
 
     def remote_name(self, remote):
         names = [name for name, path in self.paths if path == remote]
--- a/tests/test-octopus.out	Thu Nov 26 20:47:38 2009 +0100
+++ b/tests/test-octopus.out	Fri Dec 25 08:56:20 2009 +0100
@@ -20,17 +20,17 @@
 importing Git objects into Hg
 at: 0/5
 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@    changeset:   5:7acfed59bdde
+@    changeset:   5:6523aa9f4775
 |\   tag:         master
 | |  tag:         default/master
 | |  tag:         tip
 | |  parent:      1:1436150b86c2
-| |  parent:      4:6e0acfc91939
+| |  parent:      4:7f6c791a169f
 | |  user:        test <test@example.org>
 | |  date:        Mon Jan 01 00:00:13 2007 +0000
 | |  summary:     Merge branches 'branch1' and 'branch2'
 | |
-| o    changeset:   4:6e0acfc91939
+| o    changeset:   4:7f6c791a169f
 | |\   parent:      2:7bcd915dc873
 | | |  parent:      3:37c124f2d0a0
 | | |  user:        test <test@example.org>
--- a/tests/test-tree-decomposition	Thu Nov 26 20:47:38 2009 +0100
+++ b/tests/test-tree-decomposition	Fri Dec 25 08:56:20 2009 +0100
@@ -34,7 +34,8 @@
 git init | python -c "import sys; print sys.stdin.read().replace('$(dirname $(pwd))/', '')"
 
 mkdir d1
-touch d1/f1 d1/f2
+echo a > d1/f1
+echo b > d1/f2
 git add d1/f1 d1/f2
 commit -m initial
 
@@ -42,6 +43,12 @@
 git mv d1/f2 d2/f2
 commit -m 'rename'
 
+rm -r d1
+echo c > d1
+git add d1
+commit -m 'replace a dir with a file'
+
+
 cd ..
 mkdir gitrepo2
 cd gitrepo2
@@ -58,7 +65,7 @@
 
 hg clone git://localhost/gitrepo hgrepo | grep -v '^updating'
 cd hgrepo
-hg log -r tip --template 'adds: {file_adds}\ndels: {file_dels}\n'
+hg log --template 'adds: {file_adds}\ndels: {file_dels}\n'
 
 hg gclear
 hg push git://localhost/gitrepo2
--- a/tests/test-tree-decomposition.out	Thu Nov 26 20:47:38 2009 +0100
+++ b/tests/test-tree-decomposition.out	Fri Dec 25 08:56:20 2009 +0100
@@ -3,26 +3,36 @@
 Initialized empty Git repository in gitrepo2/.git/
 
 importing Hg objects into Git
-Counting objects: 8, done.
-Compressing objects:  25% (1/4)   
Compressing objects:  50% (2/4)   
Compressing objects:  75% (3/4)   
Compressing objects: 100% (4/4)   
Compressing objects: 100% (4/4), done.
-Total 8 (delta 0), reused 0 (delta 0)
+Counting objects: 12, done.
+Compressing objects:  16% (1/6)   
Compressing objects:  33% (2/6)   
Compressing objects:  50% (3/6)   
Compressing objects:  66% (4/6)   
Compressing objects:  83% (5/6)   
Compressing objects: 100% (6/6)   
Compressing objects: 100% (6/6), done.
+Total 12 (delta 0), reused 0 (delta 0)
 importing Git objects into Hg
-at: 0/2
+at: 0/3
 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adds: d1
+dels: d1/f1
 adds: d2/f2
 dels: d1/f2
+adds: d1/f1 d1/f2
+dels: 
 clearing out the git cache data
 pushing to git://localhost/gitrepo2
 importing Hg objects into Git
-at: 0/2
+at: 0/3
 creating and sending data
-commit 7d84da95f2caf7a65833ae580fe5a08a0c3cb6b2
+commit 6e0dbd8cd92ed4823c69cb48d8a2b81f904e6e69
+Author: test <test@example.org>
+Date:   Mon Jan 1 00:00:12 2007 +0000
+
+    replace a dir with a file
+
+commit a1874d5cd0b1549ed729e36f0da4a93ed36259ee
 Author: test <test@example.org>
 Date:   Mon Jan 1 00:00:11 2007 +0000
 
     rename
 
-commit 48e6424b6487f2a16e901f72fe52168b40278f5b
+commit 102c17a5deda49db3f10ec5573f9378867098b7c
 Author: test <test@example.org>
 Date:   Mon Jan 1 00:00:10 2007 +0000