changeset 854:89bfb9994732

git_handler: handle symlink <-> regular file transitions properly See comment inline for explanation. Also add tests for this (the bug was masked with rename detection disabled -- it only appeared with rename detection enabled).
author Siddharth Agarwal <sid0@fb.com>
date Tue, 30 Dec 2014 13:25:55 -0800
parents 8e17f8a16269
children eba7dcfab1bb
files hggit/git_handler.py tests/test-file-removal.t
diffstat 2 files changed, 71 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/hggit/git_handler.py
+++ b/hggit/git_handler.py
@@ -1337,6 +1337,18 @@
             #  gitlink       no     |  delete gitlink
             #  gitlink      file    |  delete gitlink and record file
             #  gitlink    gitlink   |  record gitlink
+            #
+            # There's an edge case here -- symlink <-> regular file transitions
+            # are returned by dulwich as separate deletes and adds, not
+            # modifications. The order of those results is unspecified and could
+            # be either way round. Handle both cases:
+            # delete first, then add -- delete stored in 'old = file' case, then
+            # overwritten by 'new = file' case.
+            # add first, then delete -- record stored in 'new = file' case, then
+            # membership check fails in 'old = file' case so is not overwritten
+            # there.
+            # This is not an issue for gitlink <-> {symlink, regular file}
+            # transitions because they write to separate dictionaries.
             if newmode == 0160000:
                 # new = gitlink
                 gitlinks[newfile] = newsha
@@ -1361,7 +1373,9 @@
                         files[oldfile] = True, None, None
             else:
                 # old = file
-                files[oldfile] = True, None, None
+                # the membership check is explained in a comment above
+                if oldfile not in files:
+                    files[oldfile] = True, None, None
 
         return files, gitlinks, renames
 
--- a/tests/test-file-removal.t
+++ b/tests/test-file-removal.t
@@ -223,3 +223,59 @@
   Date:   Mon Jan 1 00:00:10 2007 +0000
   
       add alpha
+
+test with rename detection enabled
+  $ hg --config git.similarity=100 clone gitrepo hgreporenames | grep -v '^updating'
+  importing git objects into hg
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cd hgreporenames
+  $ hg log --graph | grep -v ': master'
+  @  changeset:   8:0995b8a0a943
+  |  bookmark:    master
+  |  tag:         default/master
+  |  tag:         tip
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:18 2007 +0000
+  |  summary:     remove betalink
+  |
+  o  changeset:   7:a316d3a96c89
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:17 2007 +0000
+  |  summary:     replace file with symlink
+  |
+  o  changeset:   6:1804acb71f3e
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:16 2007 +0000
+  |  summary:     replace symlink with file
+  |
+  o  changeset:   5:e19c85becc87
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:15 2007 +0000
+  |  summary:     add symlink to beta
+  |
+  o  changeset:   4:0d3086c3f8c3
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:14 2007 +0000
+  |  summary:     remove foo/bar
+  |
+  o  changeset:   3:b2406125ef5c
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:13 2007 +0000
+  |  summary:     remove alpha
+  |
+  o  changeset:   2:8b3b2f4b4158
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:12 2007 +0000
+  |  summary:     add foo
+  |
+  o  changeset:   1:7fe02317c63d
+  |  user:        test <test@example.org>
+  |  date:        Mon Jan 01 00:00:11 2007 +0000
+  |  summary:     add beta
+  |
+  o  changeset:   0:ff7a2f2d8d70
+     user:        test <test@example.org>
+     date:        Mon Jan 01 00:00:10 2007 +0000
+     summary:     add alpha
+