Re: [PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-13 Thread Junio C Hamano
Jonathan Nieder jrnie...@gmail.com writes:

 twoway_merge() is missing an o-gently check in the case where a file
 that needs to be modified is missing from the index but present in the
 old and new trees.  As a result, in this case 'git checkout -m' errors
 out instead of trying to perform a merge.

I see two hunks in threeway_merge(), so two existing callers there
will not change their behaviour.  Two hunks in twoway_merge() means
that among three existing callers in that function, this one at the
end (not shown in your patch) changes its behaviour:

else if (newtree) {
if (oldtree  !o-initial_checkout) {
/*
 * deletion of the path was staged;
 */
if (same(oldtree, newtree))
return 1;
return reject_merge(oldtree, o);
}
return merged_entry(newtree, current, o);
}
return deleted_entry(oldtree, current, o);

 This is the most iffy of the three patches, mostly because I was too
 lazy to write a test.

You would trigger this codepath by jumping from an old revision to a
new revision after git rm $path any path that has been modified
between the two.  The only behaviour difference is that it will stop
issuing an error message---the checkout -m will successfully switch
between the revs and leave the index in a we modified, they removed
conflicting state with or without your patch.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-13 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 Jonathan Nieder jrnie...@gmail.com writes:

 twoway_merge() is missing an o-gently check in the case where a file
 that needs to be modified is missing from the index but present in the
 old and new trees.  As a result, in this case 'git checkout -m' errors
 out instead of trying to perform a merge.

 I see two hunks in threeway_merge(), so two existing callers there
 will not change their behaviour.  Two hunks in twoway_merge() means
 that among three existing callers in that function, this one at the
 end (not shown in your patch) changes its behaviour:

   else if (newtree) {
   if (oldtree  !o-initial_checkout) {
   /*
* deletion of the path was staged;
*/
   if (same(oldtree, newtree))
   return 1;
   return reject_merge(oldtree, o);
   }
   return merged_entry(newtree, current, o);
   }
   return deleted_entry(oldtree, current, o);

 This is the most iffy of the three patches, mostly because I was too
 lazy to write a test.

 You would trigger this codepath by jumping from an old revision to a
 new revision after git rm $path any path that has been modified
 between the two.  The only behaviour difference is that it will stop
 issuing an error message---the checkout -m will successfully switch
 between the revs and leave the index in a we modified, they removed
 conflicting state with or without your patch.

IOW, something like this perhaps?

diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 0c9ec0a..cedbb6a 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 
branch' '
test_cmp two expect
 '
 
+test_expect_success 'switch to another branch while carrying a deletion' '
+
+   git checkout -f master  git reset --hard  git clean -f 
+   git rm two 
+
+   test_must_fail git checkout simple 2errs 
+   test_i18ngrep overwritten errs 
+
+   git checkout --merge simple 2errs 
+   ! test_i18ngrep overwritten errs 
+   git ls-files -u 
+   test_must_fail git cat-file -t :0:two 
+   test $(git cat-file -t :1:two) = blob 
+   test $(git cat-file -t :2:two) = blob 
+   test_must_fail git cat-file -t :3:two
+'
+
 test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
git config advice.detachedHead false 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-13 Thread Johannes Sixt
Am 13.08.2014 20:59, schrieb Junio C Hamano:
 diff --git a/t/t7201-co.sh b/t/t7201-co.sh
 index 0c9ec0a..cedbb6a 100755
 --- a/t/t7201-co.sh
 +++ b/t/t7201-co.sh
 @@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 
 branch' '
   test_cmp two expect
  '
  
 +test_expect_success 'switch to another branch while carrying a deletion' '
 +
 + git checkout -f master  git reset --hard  git clean -f 
 + git rm two 
 +
 + test_must_fail git checkout simple 2errs 
 + test_i18ngrep overwritten errs 
 +
 + git checkout --merge simple 2errs 
 + ! test_i18ngrep overwritten errs 

This must be written as

test_i18ngrep ! overwritten errs 

 + git ls-files -u 
 + test_must_fail git cat-file -t :0:two 
 + test $(git cat-file -t :1:two) = blob 
 + test $(git cat-file -t :2:two) = blob 
 + test_must_fail git cat-file -t :3:two
 +'
 +
  test_expect_success 'checkout to detach HEAD (with advice declined)' '
  
   git config advice.detachedHead false 
 

I see a few wrong usages in the current code base. Here's a fix.

--- 8 ---
Subject: [PATCH] tests: fix negated test_i18ngrep calls

The helper function test_i18ngrep pretends that it found the expected
results when it is running under GETTEXT_POISON. For this reason, it must
not be used negated like so

   ! test_i18ngrep foo bar

because the test case would fail under GETTEXT_POISON. The function offers
a special syntax to test that a pattern is *not* found:

   test_i18ngrep ! foo bar

Convert incorrect uses to this syntax.

Signed-off-by: Johannes Sixt j...@kdbg.org
---
 t/t4018-diff-funcname.sh | 8 
 t/t9800-git-p4-basic.sh  | 2 +-
 t/t9807-git-p4-submit.sh | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 34591c2..1dbaa38 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -52,15 +52,15 @@ do
echo *.java diff=$p .gitattributes 
test_expect_code 1 git diff --no-index \
A.java B.java 2msg 
-   ! test_i18ngrep fatal msg 
-   ! test_i18ngrep error msg
+   test_i18ngrep ! fatal msg 
+   test_i18ngrep ! error msg
'
test_expect_success builtin $p wordRegex pattern compiles '
echo *.java diff=$p .gitattributes 
test_expect_code 1 git diff --no-index --word-diff \
A.java B.java 2msg 
-   ! test_i18ngrep fatal msg 
-   ! test_i18ngrep error msg
+   test_i18ngrep ! fatal msg 
+   test_i18ngrep ! error msg
'
 done
 
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index 665607c..5b56212 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -145,7 +145,7 @@ test_expect_success 'exit when p4 fails to produce 
marshaled output' '
test_expect_code 1 git p4 clone --dest=$git //depot errs 21
) 
cat errs 
-   ! test_i18ngrep Traceback errs
+   test_i18ngrep ! Traceback errs
 '
 
 # Hide a file from p4d, make sure we catch its complaint.  This won't fail in
diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh
index 7fab2ed..1f74a88 100755
--- a/t/t9807-git-p4-submit.sh
+++ b/t/t9807-git-p4-submit.sh
@@ -404,7 +404,7 @@ test_expect_success 'submit --prepare-p4-only' '
git p4 submit --prepare-p4-only out 
test_i18ngrep prepared for submission out 
test_i18ngrep must be deleted out 
-   ! test_i18ngrep everything below this line is just the diff 
out
+   test_i18ngrep ! everything below this line is just the diff 
out
) 
(
cd $cli 
-- 
2.0.0.12.gbcf935e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-13 Thread Junio C Hamano
Johannes Sixt j...@kdbg.org writes:

 Am 13.08.2014 20:59, schrieb Junio C Hamano:
 diff --git a/t/t7201-co.sh b/t/t7201-co.sh
 index 0c9ec0a..cedbb6a 100755
 --- a/t/t7201-co.sh
 +++ b/t/t7201-co.sh
 @@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 
 branch' '
  test_cmp two expect
  '
  
 +test_expect_success 'switch to another branch while carrying a deletion' '
 +
 +git checkout -f master  git reset --hard  git clean -f 
 +git rm two 
 +
 +test_must_fail git checkout simple 2errs 
 +test_i18ngrep overwritten errs 
 +
 +git checkout --merge simple 2errs 
 +! test_i18ngrep overwritten errs 

 This must be written as

   test_i18ngrep ! overwritten errs 

Oops. Thanks for spotting.

 I see a few wrong usages in the current code base. Here's a fix.

Will apply; thanks.

 --- 8 ---
 Subject: [PATCH] tests: fix negated test_i18ngrep calls

 The helper function test_i18ngrep pretends that it found the expected
 results when it is running under GETTEXT_POISON. For this reason, it must
 not be used negated like so

! test_i18ngrep foo bar

 because the test case would fail under GETTEXT_POISON. The function offers
 a special syntax to test that a pattern is *not* found:

test_i18ngrep ! foo bar

 Convert incorrect uses to this syntax.

 Signed-off-by: Johannes Sixt j...@kdbg.org
 ---
  t/t4018-diff-funcname.sh | 8 
  t/t9800-git-p4-basic.sh  | 2 +-
  t/t9807-git-p4-submit.sh | 2 +-
  3 files changed, 6 insertions(+), 6 deletions(-)

 diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
 index 34591c2..1dbaa38 100755
 --- a/t/t4018-diff-funcname.sh
 +++ b/t/t4018-diff-funcname.sh
 @@ -52,15 +52,15 @@ do
   echo *.java diff=$p .gitattributes 
   test_expect_code 1 git diff --no-index \
   A.java B.java 2msg 
 - ! test_i18ngrep fatal msg 
 - ! test_i18ngrep error msg
 + test_i18ngrep ! fatal msg 
 + test_i18ngrep ! error msg
   '
   test_expect_success builtin $p wordRegex pattern compiles '
   echo *.java diff=$p .gitattributes 
   test_expect_code 1 git diff --no-index --word-diff \
   A.java B.java 2msg 
 - ! test_i18ngrep fatal msg 
 - ! test_i18ngrep error msg
 + test_i18ngrep ! fatal msg 
 + test_i18ngrep ! error msg
   '
  done
  
 diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
 index 665607c..5b56212 100755
 --- a/t/t9800-git-p4-basic.sh
 +++ b/t/t9800-git-p4-basic.sh
 @@ -145,7 +145,7 @@ test_expect_success 'exit when p4 fails to produce 
 marshaled output' '
   test_expect_code 1 git p4 clone --dest=$git //depot errs 21
   ) 
   cat errs 
 - ! test_i18ngrep Traceback errs
 + test_i18ngrep ! Traceback errs
  '
  
  # Hide a file from p4d, make sure we catch its complaint.  This won't fail in
 diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh
 index 7fab2ed..1f74a88 100755
 --- a/t/t9807-git-p4-submit.sh
 +++ b/t/t9807-git-p4-submit.sh
 @@ -404,7 +404,7 @@ test_expect_success 'submit --prepare-p4-only' '
   git p4 submit --prepare-p4-only out 
   test_i18ngrep prepared for submission out 
   test_i18ngrep must be deleted out 
 - ! test_i18ngrep everything below this line is just the diff 
 out
 + test_i18ngrep ! everything below this line is just the diff 
 out
   ) 
   (
   cd $cli 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-12 Thread Jonathan Nieder
twoway_merge() is missing an o-gently check in the case where a file
that needs to be modified is missing from the index but present in the
old and new trees.  As a result, in this case 'git checkout -m' errors
out instead of trying to perform a merge.

Fix it by checking o-gently.  While at it, inline the o-gently check
into reject_merge to prevent future call sites from making the same
mistake.

Noticed by code inspection.  The motivating case hasn't been tested.

Signed-off-by: Jonathan Nieder jrnie...@gmail.com
---
This is the most iffy of the three patches, mostly because I was too
lazy to write a test.  I believe it's safe as-is nonetheless.

Thanks for reading.

 unpack-trees.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/unpack-trees.c b/unpack-trees.c
index 187b15b..6c45af7 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1178,7 +1178,8 @@ return_failed:
 static int reject_merge(const struct cache_entry *ce,
struct unpack_trees_options *o)
 {
-   return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce-name);
+   return o-gently ? -1 :
+   add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce-name);
 }
 
 static int same(const struct cache_entry *a, const struct cache_entry *b)
@@ -1633,7 +1634,7 @@ int threeway_merge(const struct cache_entry * const 
*stages,
/* #14, #14ALT, #2ALT */
if (remote  !df_conflict_head  head_match  !remote_match) {
if (index  !same(index, remote)  !same(index, head))
-   return o-gently ? -1 : reject_merge(index, o);
+   return reject_merge(index, o);
return merged_entry(remote, index, o);
}
/*
@@ -1641,7 +1642,7 @@ int threeway_merge(const struct cache_entry * const 
*stages,
 * make sure that it matches head.
 */
if (index  !same(index, head))
-   return o-gently ? -1 : reject_merge(index, o);
+   return reject_merge(index, o);
 
if (head) {
/* #5ALT, #15 */
@@ -1770,7 +1771,7 @@ int twoway_merge(const struct cache_entry * const *src,
else
return merged_entry(newtree, current, 
o);
}
-   return o-gently ? -1 : reject_merge(current, o);
+   return reject_merge(current, o);
} else if ((!oldtree  !newtree) || /* 4 and 5 */
 (!oldtree  newtree 
  same(current, newtree)) || /* 6 and 7 */
@@ -1788,7 +1789,7 @@ int twoway_merge(const struct cache_entry * const *src,
/* 20 or 21 */
return merged_entry(newtree, current, o);
} else
-   return o-gently ? -1 : reject_merge(current, o);
+   return reject_merge(current, o);
}
else if (newtree) {
if (oldtree  !o-initial_checkout) {
-- 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] checkout -m: attempt merge when deletion of path was staged

2014-08-12 Thread Junio C Hamano
On Tue, Aug 12, 2014 at 5:03 PM, Jonathan Nieder jrnie...@gmail.com wrote:
 twoway_merge() is missing an o-gently check in the case where a file
 that needs to be modified is missing from the index but present in the
 old and new trees.  As a result, in this case 'git checkout -m' errors
 out instead of trying to perform a merge.

 Fix it by checking o-gently.  While at it, inline the o-gently check
 into reject_merge to prevent future call sites from making the same
 mistake.

 Noticed by code inspection.  The motivating case hasn't been tested.

That sounds sloppy X-.  I may comment more after figuring out
what _other_ reject_merge() caller that does not appear in the
patch would change its behaviour with this patch.

  side note: of course, if this were two patches, one that adds the
  same o-gently ? -1 : reject thing to places where they forget to
  do so, and the other that moves the gently thing to reject helper,
  then we can read all the necessary information to judge the change
  in the patch ;-)

Thanks.


 Signed-off-by: Jonathan Nieder jrnie...@gmail.com
 ---
 This is the most iffy of the three patches, mostly because I was too
 lazy to write a test.  I believe it's safe as-is nonetheless.

 Thanks for reading.

  unpack-trees.c | 11 ++-
  1 file changed, 6 insertions(+), 5 deletions(-)

 diff --git a/unpack-trees.c b/unpack-trees.c
 index 187b15b..6c45af7 100644
 --- a/unpack-trees.c
 +++ b/unpack-trees.c
 @@ -1178,7 +1178,8 @@ return_failed:
  static int reject_merge(const struct cache_entry *ce,
 struct unpack_trees_options *o)
  {
 -   return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce-name);
 +   return o-gently ? -1 :
 +   add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce-name);
  }

  static int same(const struct cache_entry *a, const struct cache_entry *b)
 @@ -1633,7 +1634,7 @@ int threeway_merge(const struct cache_entry * const 
 *stages,
 /* #14, #14ALT, #2ALT */
 if (remote  !df_conflict_head  head_match  !remote_match) {
 if (index  !same(index, remote)  !same(index, head))
 -   return o-gently ? -1 : reject_merge(index, o);
 +   return reject_merge(index, o);
 return merged_entry(remote, index, o);
 }
 /*
 @@ -1641,7 +1642,7 @@ int threeway_merge(const struct cache_entry * const 
 *stages,
  * make sure that it matches head.
  */
 if (index  !same(index, head))
 -   return o-gently ? -1 : reject_merge(index, o);
 +   return reject_merge(index, o);

 if (head) {
 /* #5ALT, #15 */
 @@ -1770,7 +1771,7 @@ int twoway_merge(const struct cache_entry * const *src,
 else
 return merged_entry(newtree, current, 
 o);
 }
 -   return o-gently ? -1 : reject_merge(current, o);
 +   return reject_merge(current, o);
 } else if ((!oldtree  !newtree) || /* 4 and 5 */
  (!oldtree  newtree 
   same(current, newtree)) || /* 6 and 7 */
 @@ -1788,7 +1789,7 @@ int twoway_merge(const struct cache_entry * const *src,
 /* 20 or 21 */
 return merged_entry(newtree, current, o);
 } else
 -   return o-gently ? -1 : reject_merge(current, o);
 +   return reject_merge(current, o);
 }
 else if (newtree) {
 if (oldtree  !o-initial_checkout) {
 --
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html