unpack-trees: fix D/F conflict bugs in verify_absent

Previous thread: [PATCH] Documentation/git-merge: at least one <remote> not two by jidanni on Thursday, January 1, 2009 - 11:41 am. (2 messages)

Next thread: Re: [PATCH] Git.pm: let a "false" Directory parameter (such as "0") be used correctly by the constructor" by Junio C Hamano on Thursday, January 1, 2009 - 2:00 pm. (2 messages)
From: Clemens Buchacher
Date: Thursday, January 1, 2009 - 1:54 pm

I came across a few bugs while investigating the changes I proposed in the
modify/delete conflict thread. The first two are quite obvious. The third I'm
not so sure about. I could not find a testcase where it matters. Junio, do you
recall the original intention of that code?

[PATCH 1/3] unpack-trees: handle failure in verify_absent
[PATCH 2/3] unpack-trees: fix path search bug in verify_absent
[PATCH 3/3] unpack-trees: remove redundant path search in verify_absent

 t/t1001-read-tree-m-2way.sh |   51 +++++++++++++++++++++++++++++++++++++++++++
 unpack-trees.c              |   37 +++++++++++++++----------------
 2 files changed, 69 insertions(+), 19 deletions(-)
--

From: Clemens Buchacher
Date: Thursday, January 1, 2009 - 1:54 pm

Commit 203a2fe1 (Allow callers of unpack_trees() to handle failure)
changed the &quot;die on error&quot; behavior to &quot;return failure code&quot;.
verify_absent did not handle errors returned by
verify_clean_subdirectory, however.
---
 t/t1001-read-tree-m-2way.sh |   24 ++++++++++++++++++++++++
 unpack-trees.c              |    8 +++++---
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 4b44e13..7f6ab31 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -341,4 +341,28 @@ test_expect_success \
      check_cache_at DF/DF dirty &amp;&amp;
      :'
 
+test_expect_success \
+    'a/b (untracked) vs a case setup.' \
+    'rm -f .git/index &amp;&amp;
+     : &gt;a &amp;&amp;
+     git update-index --add a &amp;&amp;
+     treeM=`git write-tree` &amp;&amp;
+     echo treeM $treeM &amp;&amp;
+     git ls-tree $treeM &amp;&amp;
+     git ls-files --stage &gt;treeM.out &amp;&amp;
+
+     rm -f a &amp;&amp;
+     git update-index --remove a &amp;&amp;
+     mkdir a &amp;&amp;
+     : &gt;a/b &amp;&amp;
+     treeH=`git write-tree` &amp;&amp;
+     echo treeH $treeH &amp;&amp;
+     git ls-tree $treeH'
+
+test_expect_success \
+    'a/b (untracked) vs a, plus c/d case test.' \
+    '! git read-tree -u -m &quot;$treeH&quot; &quot;$treeM&quot; &amp;&amp;
+     git ls-files --stage &amp;&amp;
+     test -f a/b'
+
 test_done
diff --git a/unpack-trees.c b/unpack-trees.c
index 54f301d..a736947 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -588,7 +588,7 @@ static int verify_absent(struct cache_entry *ce, const char *action,
 		return 0;
 
 	if (!lstat(ce-&gt;name, &amp;st)) {
-		int cnt;
+		int ret;
 		int dtype = ce_to_dtype(ce);
 		struct cache_entry *result;
 
@@ -616,7 +616,9 @@ static int verify_absent(struct cache_entry *ce, const char *action,
 			 * files that are in &quot;foo/&quot; we would lose
 			 * it.
 			 */
-			cnt = verify_clean_subdirectory(ce, action, o);
+			ret = verify_clean_subdirectory(ce, action, o);
+			if (ret &lt; 0)
+				return ret;
 
 			/*
 			 * If this removed entries from the index,
@@ -635,7 +637,7 @@ static ...
From: Clemens Buchacher
Date: Thursday, January 1, 2009 - 1:54 pm

Commit 0cf73755 (unpack-trees.c: assume submodules are clean during
check-out) changed an argument to verify_absent from 'path' to 'ce',
which is however shadowed by a local variable of the same name.

The bug triggers if verify_absent is used on a tree entry, for which
the index contains one or more subsequent directories of the same
length. The affected subdirectories are removed from the index. The
testcase included in this commit bisects to 55218834 (checkout: do not
lose staged removal), which reveals the bug in this case, but is
otherwise unrelated.
---
 t/t1001-read-tree-m-2way.sh |   27 +++++++++++++++++++++++++++
 unpack-trees.c              |   23 ++++++++++++-----------
 2 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 7f6ab31..271bc4e 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -365,4 +365,31 @@ test_expect_success \
      git ls-files --stage &amp;&amp;
      test -f a/b'
 
+test_expect_success \
+    'a/b vs a, plus c/d case setup.' \
+    'rm -f .git/index &amp;&amp;
+     rm -fr a &amp;&amp;
+     : &gt;a &amp;&amp;
+     mkdir c &amp;&amp;
+     : &gt;c/d &amp;&amp;
+     git update-index --add a c/d &amp;&amp;
+     treeM=`git write-tree` &amp;&amp;
+     echo treeM $treeM &amp;&amp;
+     git ls-tree $treeM &amp;&amp;
+     git ls-files --stage &gt;treeM.out &amp;&amp;
+
+     rm -f a &amp;&amp;
+     mkdir a
+     : &gt;a/b &amp;&amp;
+     git update-index --add --remove a a/b &amp;&amp;
+     treeH=`git write-tree` &amp;&amp;
+     echo treeH $treeH &amp;&amp;
+     git ls-tree $treeH'
+
+test_expect_success \
+    'a/b vs a, plus c/d case test.' \
+    'git read-tree -u -m &quot;$treeH&quot; &quot;$treeM&quot; &amp;&amp;
+     git ls-files --stage | tee &gt;treeMcheck.out &amp;&amp;
+     test_cmp treeM.out treeMcheck.out'
+
 test_done
diff --git a/unpack-trees.c b/unpack-trees.c
index a736947..f8e2484 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -289,7 +289,8 @@ static int unpack_nondirectories(int n, unsigned long mask, unsigned long dirmas
 	return 0;
 }
 
-static int ...
From: Clemens Buchacher
Date: Thursday, January 1, 2009 - 1:54 pm

Since the only caller, verify_absent, relies on the fact that o-&gt;pos
points to the next index entry anyways, there is no need to recompute
its position.

Furthermore, if a nondirectory entry were found, this would return too
early, because there could still be an untracked directory in the way.
This is currently not a problem, because verify_absent is only called
if the index does not have this entry.
---
 unpack-trees.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/unpack-trees.c b/unpack-trees.c
index f8e2484..c4dc6dc 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -495,7 +495,7 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
 	 * anything in the existing directory there.
 	 */
 	int namelen;
-	int pos, i;
+	int i;
 	struct dir_struct d;
 	char *pathbuf;
 	int cnt = 0;
@@ -516,11 +516,7 @@ static int verify_clean_subdirectory(struct cache_entry *ce, const char *action,
 	 * in that directory.
 	 */
 	namelen = strlen(ce-&gt;name);
-	pos = index_name_pos(o-&gt;src_index, ce-&gt;name, namelen);
-	if (0 &lt;= pos)
-		return 0; /* we have it as nondirectory */
-	pos = -pos - 1;
-	for (i = pos; i &lt; o-&gt;src_index-&gt;cache_nr; i++) {
+	for (i = o-&gt;pos; i &lt; o-&gt;src_index-&gt;cache_nr; i++) {
 		struct cache_entry *ce2 = o-&gt;src_index-&gt;cache[i];
 		int len = ce_namelen(ce2);
 		if (len &lt; namelen ||
-- 
1.6.1

--

From: Johannes Schindelin
Date: Friday, January 2, 2009 - 2:59 pm

Sign-off?

Just for the record, this patch fixes the testcase Miklos reported 
earlier.

Ciao,
Dscho

--

From: Miklos Vajna
Date: Saturday, January 3, 2009 - 7:01 am

On Fri, Jan 02, 2009 at 10:59:43PM +0100, Johannes Schindelin &lt;Johannes.Sch=

Indeed, thanks for the notice.
From: Johannes Schindelin
Date: Friday, January 2, 2009 - 2:59 pm

Hi,




... is not accounted for in the commit message.  Intended or not, that is 
the question.

Ciao,
Dscho &quot;whether 'tis noble&quot;


--

From: Clemens Buchacher
Date: Saturday, January 3, 2009 - 3:39 am

Those are trivial readability improvements in the context of the patch.


Signed-off-by: Clemens Buchacher &lt;drizzd@aon.at&gt;

on all three patches.
--

From: Johannes Schindelin
Date: Saturday, January 3, 2009 - 5:53 am

Hi,


They are not trivial enough for me not to be puzzled.  Reason enough to 
explain in the commit message?

Ciao,
Dscho
--

From: Junio C Hamano
Date: Thursday, January 1, 2009 - 2:28 pm

Thanks, but I see only [PATCH 1/3] and [PATCH 2/3] (both of which look
sane, by the way).
--

Previous thread: [PATCH] Documentation/git-merge: at least one <remote> not two by jidanni on Thursday, January 1, 2009 - 11:41 am. (2 messages)

Next thread: Re: [PATCH] Git.pm: let a "false" Directory parameter (such as "0") be used correctly by the constructor" by Junio C Hamano on Thursday, January 1, 2009 - 2:00 pm. (2 messages)