All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] D/F conflicts fixes.
@ 2005-06-23 23:20 Junio C Hamano
  2005-06-23 23:25 ` [PATCH 1/2] Add more tests for read-tree --emu23 Junio C Hamano
  2005-06-24 23:40 ` [PATCH 2/2] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
  0 siblings, 2 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-23 23:20 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

I'll be sending these two patches.

    [PATCH 1/2] Add more tests for read-tree --emu23.
    [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/2] Add more tests for read-tree --emu23.
  2005-06-23 23:20 [PATCH 0/2] D/F conflicts fixes Junio C Hamano
@ 2005-06-23 23:25 ` Junio C Hamano
  2005-06-24 23:40 ` [PATCH 2/2] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
  1 sibling, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-23 23:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

This adds more tests for --emu23.  One is to show how it can
carry forward more local changes than the straightforward
two-way fast forward, and another is to show the recent
overeager optimization of directory/file conflict check broke
things, which will be fixed in the next commit.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 t/t1001-read-tree-m-2way.sh       |   70 +++++++++++++++++++++++++---
 t/t1005-read-tree-m-2way-emu23.sh |   94 ++++++++++++++++++++++++++++++++++---
 2 files changed, 150 insertions(+), 14 deletions(-)

diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -29,7 +29,6 @@ read_tree_twoway () {
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 compare_change () {
-    	cat current
 	sed -n >current \
 	    -e '/^--- /d; /^+++ /d; /^@@ /d;' \
 	    -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
@@ -51,11 +50,22 @@ check_cache_at () {
 	esac
 }
 
+cat >bozbar-old <<\EOF
+This is a sample file used in two-way fast forward merge
+tests.  Its second line ends with a magic word bozbar
+which will be modified by the merged head to gnusto.
+It has some extra lines so that external tools can
+successfully merge independent changes made to later
+lines (such as this one), avoiding line conflicts.
+EOF
+
+sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
+
 test_expect_success \
     setup \
     'echo frotz >frotz &&
      echo nitfol >nitfol &&
-     echo bozbar >bozbar &&
+     cat bozbar-old >bozbar &&
      echo rezrov >rezrov &&
      echo yomin >yomin &&
      git-update-cache --add nitfol bozbar rezrov &&
@@ -63,7 +73,7 @@ test_expect_success \
      echo treeH $treeH &&
      git-ls-tree $treeH &&
 
-     echo gnusto >bozbar &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add frotz bozbar --force-remove rezrov &&
      git-ls-files --stage >M.out &&
      treeM=`git-write-tree` &&
@@ -86,6 +96,8 @@ echo '+100644 X 0	yomin' >expected
 test_expect_success \
     '4 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add yomin &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >4.out || exit
@@ -96,6 +108,8 @@ test_expect_success \
 test_expect_success \
     '5 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo yomin >yomin &&
      git-update-cache --add yomin &&
      echo yomin yomin >yomin &&
@@ -108,6 +122,8 @@ test_expect_success \
 test_expect_success \
     '6 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add frotz &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >6.out &&
@@ -117,6 +133,8 @@ test_expect_success \
 test_expect_success \
     '7 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz frotz >frotz &&
@@ -128,6 +146,8 @@ test_expect_success \
 test_expect_success \
     '8 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -135,6 +155,8 @@ test_expect_success \
 test_expect_success \
     '9 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz >frotz &&
@@ -143,6 +165,8 @@ test_expect_success \
 test_expect_success \
     '10 - path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      read_tree_twoway $treeH $treeM &&
@@ -152,6 +176,8 @@ test_expect_success \
 test_expect_success \
     '11 - dirty path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov rezrov >rezrov &&
@@ -160,6 +186,8 @@ test_expect_success \
 test_expect_success \
     '12 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -167,6 +195,8 @@ test_expect_success \
 test_expect_success \
     '13 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov >rezrov &&
@@ -180,6 +210,8 @@ EOF
 test_expect_success \
     '14 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      read_tree_twoway $treeH $treeM &&
@@ -191,6 +223,8 @@ test_expect_success \
 test_expect_success \
     '15 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      echo nitfol nitfol nitfol >nitfol &&
@@ -203,6 +237,8 @@ test_expect_success \
 test_expect_success \
     '16 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -210,6 +246,8 @@ test_expect_success \
 test_expect_success \
     '17 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      echo bozbar bozbar bozbar >bozbar &&
@@ -218,7 +256,9 @@ test_expect_success \
 test_expect_success \
     '18 - local change already having a good result.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >18.out &&
@@ -228,7 +268,9 @@ test_expect_success \
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      read_tree_twoway $treeH $treeM &&
@@ -239,7 +281,9 @@ test_expect_success \
 test_expect_success \
     '20 - no local change, use new tree.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >20.out &&
@@ -249,11 +293,23 @@ test_expect_success \
 test_expect_success \
     '21 - no local change, dirty cache.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
 
+# This fails with straight two-way fast forward.
+test_expect_success \
+    '22 - local change cache updated.' \
+    'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
+     git-update-cache --add bozbar &&
+     if read_tree_twoway $treeH $treeM; then false; else :; fi'
+
 # Also make sure we did not break DF vs DF/DF case.
 test_expect_success \
     'DF vs DF/DF case setup.' \
diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh
--- a/t/t1005-read-tree-m-2way-emu23.sh
+++ b/t/t1005-read-tree-m-2way-emu23.sh
@@ -32,7 +32,6 @@ read_tree_twoway () {
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 compare_change () {
-    	cat current
 	sed -n >current \
 	    -e '/^--- /d; /^+++ /d; /^@@ /d;' \
 	    -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
@@ -60,11 +59,22 @@ check_stages () {
     diff -u expected_stages current_stages
 }
 
+cat >bozbar-old <<\EOF
+This is a sample file used in two-way fast forward merge
+tests.  Its second line ends with a magic word bozbar
+which will be modified by the merged head to gnusto.
+It has some extra lines so that external tools can
+successfully merge independent changes made to later
+lines (such as this one), avoiding line conflicts.
+EOF
+
+sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
+
 test_expect_success \
     setup \
     'echo frotz >frotz &&
      echo nitfol >nitfol &&
-     echo bozbar >bozbar &&
+     cat bozbar-old >bozbar &&
      echo rezrov >rezrov &&
      echo yomin >yomin &&
      git-update-cache --add nitfol bozbar rezrov &&
@@ -72,7 +82,7 @@ test_expect_success \
      echo treeH $treeH &&
      git-ls-tree $treeH &&
 
-     echo gnusto >bozbar &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add frotz bozbar --force-remove rezrov &&
      git-ls-files --stage >M.out &&
      treeM=`git-write-tree` &&
@@ -106,6 +116,8 @@ echo '+100644 X 0	yomin' >expected
 test_expect_success \
     '4 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add yomin &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >4.out || exit
@@ -118,6 +130,8 @@ test_expect_success \
 test_expect_success \
     '5 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo yomin >yomin &&
      git-update-cache --add yomin &&
      echo yomin yomin >yomin &&
@@ -132,6 +146,8 @@ test_expect_success \
 test_expect_success \
     '6 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add frotz &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >6.out &&
@@ -143,6 +159,8 @@ test_expect_success \
 test_expect_success \
     '7 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz frotz >frotz &&
@@ -154,6 +172,8 @@ test_expect_success \
 test_expect_success \
     '8 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -161,6 +181,8 @@ test_expect_success \
 test_expect_success \
     '9 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz >frotz &&
@@ -169,6 +191,8 @@ test_expect_success \
 test_expect_success \
     '10 - path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      read_tree_twoway $treeH $treeM &&
@@ -178,6 +202,8 @@ test_expect_success \
 test_expect_success \
     '11 - dirty path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov rezrov >rezrov &&
@@ -186,6 +212,8 @@ test_expect_success \
 test_expect_success \
     '12 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -193,6 +221,8 @@ test_expect_success \
 test_expect_success \
     '13 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov >rezrov &&
@@ -206,6 +236,8 @@ EOF
 test_expect_success \
     '14 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      read_tree_twoway $treeH $treeM &&
@@ -217,6 +249,8 @@ test_expect_success \
 test_expect_success \
     '15 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      echo nitfol nitfol nitfol >nitfol &&
@@ -233,6 +267,8 @@ test_expect_success \
 test_expect_success \
     '16 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      git-read-tree --emu23 $treeH $treeM &&
@@ -249,6 +285,8 @@ EOF
 test_expect_success \
     '17 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      echo bozbar bozbar bozbar >bozbar &&
@@ -257,7 +295,9 @@ test_expect_success \
 test_expect_success \
     '18 - local change already having a good result.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >18.out &&
@@ -267,7 +307,9 @@ test_expect_success \
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      read_tree_twoway $treeH $treeM &&
@@ -278,7 +320,9 @@ test_expect_success \
 test_expect_success \
     '20 - no local change, use new tree.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >20.out &&
@@ -288,11 +332,31 @@ test_expect_success \
 test_expect_success \
     '21 - no local change, dirty cache.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
 
+echo '-100644 X 0	bozbar
++100644 X 0	bozbar' >expected
+
+# This fails with straight two-way fast forward, but emu23
+# can merge them.
+test_expect_success \
+    '22 - local change cache updated.' \
+    'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
+     git-update-cache --add bozbar &&
+     read_tree_twoway $treeH $treeM &&
+     git-ls-files --stage >22.out || exit
+     diff -u M.out 22.out >22diff.out
+     compare_change 22diff.out &&
+     check_cache_at bozbar clean'
+
 # Also make sure we did not break DF vs DF/DF case.
 test_expect_success \
     'DF vs DF/DF case setup.' \
@@ -324,4 +388,20 @@ test_expect_success \
      check_cache_at DF/DF clean && # different from pure 2-way
      :'
 
+# Emu23 can grok I having more than H.  Make sure we did not
+# botch the conflict tests (Linus code botches this test).
+test_expect_success \
+    'DF vs DF/DF case test (#2).' \
+    'rm -f .git/index &&
+     rm -fr DF &&
+     mkdir DF &&
+     echo DF/DF >DF/DF &&
+     git-update-cache --add DF/DF &&
+     # This should fail because I and H have a conflict
+     # at DF.
+     if git-read-tree --emu23 $treeDF $treeDFDF
+     then true  ;# should be false
+     else false ;# should be true
+     fi'
+
 test_done
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
  2005-06-23 23:20 [PATCH 0/2] D/F conflicts fixes Junio C Hamano
  2005-06-23 23:25 ` [PATCH 1/2] Add more tests for read-tree --emu23 Junio C Hamano
@ 2005-06-24 23:40 ` Junio C Hamano
  2005-06-25  0:57   ` Linus Torvalds
  1 sibling, 1 reply; 19+ messages in thread
From: Junio C Hamano @ 2005-06-24 23:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

An earlier change to optimize directory-file conflict check
broke what "read-tree --emu23" expects.  Introduce an explicit
flag to tell add_cache_entry() not to check for conflicts and
use it when reading an existing tree into an empty stage ---
by definition this case can never introduce such conflicts.

Resurrect the unoptimized directory-file conflict check code for
now as well.  The new one did not handle higher stages properly.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 cache.h                           |    1 
 read-cache.c                      |  177 +++++++++++++++++++------------------
 t/t1005-read-tree-m-2way-emu23.sh |    6 +
 tree.c                            |    2 
 4 files changed, 95 insertions(+), 91 deletions(-)

cb13405368b0132ec3b3edcda22d32d89e9c1f85
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -130,6 +130,7 @@ extern int write_cache(int newfd, struct
 extern int cache_name_pos(const char *name, int namelen);
 #define ADD_CACHE_OK_TO_ADD 1		/* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2	/* Ok to replace file/directory */
+#define ADD_CACHE_SKIP_DF_CHECK 4	/* Ok to skip directory/file conflict checks */
 extern int add_cache_entry(struct cache_entry *ce, int option);
 extern int remove_cache_entry_at(int pos);
 extern int remove_file_from_cache(char *path);
diff --git a/read-cache.c b/read-cache.c
--- a/read-cache.c
+++ b/read-cache.c
@@ -171,83 +171,6 @@ int ce_same_name(struct cache_entry *a, 
 	return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
 }
 
-/*
- * Do we have another file that has the beginning components being a
- * proper superset of the name we're trying to add?
- */
-static int has_file_name(const struct cache_entry *ce, int pos, int ok_to_replace)
-{
-	int retval = 0;
-	int len = ce_namelen(ce);
-	const char *name = ce->name;
-
-	while (pos < active_nr) {
-		struct cache_entry *p = active_cache[pos++];
-
-		if (len >= ce_namelen(p))
-			break;
-		if (memcmp(name, p->name, len))
-			break;
-		if (p->name[len] != '/')
-			continue;
-		retval = -1;
-		if (!ok_to_replace)
-			break;
-		remove_cache_entry_at(--pos);
-	}
-	return retval;
-}
-
-/*
- * Do we have another file with a pathname that is a proper
- * subset of the name we're trying to add?
- */
-static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace)
-{
-	int retval = 0;
-	const char *name = ce->name;
-	const char *slash = name + ce_namelen(ce);
-
-	for (;;) {
-		int len;
-
-		for (;;) {
-			if (*--slash == '/')
-				break;
-			if (slash <= ce->name)
-				return retval;
-		}
-		len = slash - name;
-
-		pos = cache_name_pos(name, len);
-		if (pos >= 0) {
-			retval = -1;
-			if (ok_to_replace)
-				break;
-			remove_cache_entry_at(pos);
-			continue;
-		}
-
-		/*
-		 * Trivial optimization: if we find an entry that
-		 * already matches the sub-directory, then we know
-		 * we're ok, and we can exit
-		 */
-		pos = -pos-1;
-		if (pos < active_nr) {
-			struct cache_entry *p = active_cache[pos];
-			if (ce_namelen(p) <= len)
-				continue;
-			if (p->name[len] != '/')
-				continue;
-			if (memcmp(p->name, name, len))
-				continue;
-			break;
-		}
-	}
-	return retval;
-}
-
 /* We may be in a situation where we already have path/file and path
  * is being added, or we already have path and path/file is being
  * added.  Either one would result in a nonsense tree that has path
@@ -257,19 +180,98 @@ static int has_dir_name(const struct cac
  * from the cache so the caller should recompute the insert position.
  * When this happens, we return non-zero.
  */
-static int check_file_directory_conflict(const struct cache_entry *ce, int pos, int ok_to_replace)
+static int check_file_directory_conflict(const struct cache_entry *ce,
+					 int ok_to_replace)
 {
+	int pos, replaced = 0;
+	const char *path = ce->name;
+	int namelen = strlen(path);
+	int stage = ce_stage(ce);
+	char *pathbuf = xmalloc(namelen + 1);
+	char *cp;
+
+	memcpy(pathbuf, path, namelen + 1);
+
 	/*
-	 * We check if the path is a sub-path of a subsequent pathname
-	 * first, since removing those will not change the position
-	 * in the array
+	 * We are inserting path/file.  Do they have path registered at
+	 * the same stage?  We need to do this for all the levels of our
+	 * subpath.
 	 */
-	int retval = has_file_name(ce, pos, ok_to_replace);
-	/*
-	 * Then check if the path might have a clashing sub-directory
-	 * before it.
+	cp = pathbuf;
+	while (1) {
+		char *ep = strchr(cp, '/');
+		int len;
+		if (!ep)
+			break;
+		*ep = 0;    /* first cut it at slash */
+		len = ep - pathbuf;
+		pos = cache_name_pos(pathbuf,
+				     ntohs(create_ce_flags(len, stage)));
+		if (0 <= pos) {
+			/* Our leading path component is registered as a file,
+			 * and we are trying to make it a directory.  This is
+			 * bad.
+			 */
+			if (!ok_to_replace) {
+				free(pathbuf);
+				return -1;
+			}
+			fprintf(stderr, "removing file '%s' to replace it with a directory to create '%s'.\n", pathbuf, path);
+			remove_cache_entry_at(pos);
+			replaced = 1;
+		}
+		*ep = '/';  /* then restore it and go downwards */
+		cp = ep + 1;
+	}
+	free(pathbuf);
+
+	/* Do we have an entry in the cache that makes our path a prefix
+	 * of it?  That is, are we creating a file where they already expect
+	 * a directory there?
+	 */
+	pos = cache_name_pos(path,
+			     ntohs(create_ce_flags(namelen, stage)));
+
+	/* (0 <= pos) cannot happen because add_cache_entry()
+	 * should have taken care of that case.
+	 */
+	pos = -pos-1;
+
+	/* pos would point at an existing entry that would come immediately
+	 * after our path.  It could be the same as our path in higher stage,
+	 * or different path but in a lower stage.
+	 *
+	 * E.g. when we are inserting path at stage 2,
+	 *
+	 *        1 path
+	 * pos->  3 path
+	 *        2 path/file1
+	 *        3 path/file1
+	 *        2 path/file2
+	 *        2 patho
+	 *
+	 * We need to examine pos, ignore it because it is at different
+	 * stage, examine next to find the path/file at stage 2, and
+	 * complain.  We need to do this until we are not the leading
+	 * path of an existing entry anymore.
 	 */
-	return retval + has_dir_name(ce, pos, ok_to_replace);
+
+	while (pos < active_nr) {
+		struct cache_entry *other = active_cache[pos];
+		if (strncmp(other->name, path, namelen))
+			break; /* it is not our "subdirectory" anymore */
+		if ((ce_stage(other) == stage) &&
+		    other->name[namelen] == '/') {
+			if (!ok_to_replace)
+				return -1;
+			fprintf(stderr, "removing file '%s' under '%s' to be replaced with a file\n", other->name, path);
+			remove_cache_entry_at(pos);
+			replaced = 1;
+			continue; /* cycle without updating pos */
+		}
+		pos++;
+	}
+	return replaced;
 }
 
 int add_cache_entry(struct cache_entry *ce, int option)
@@ -277,6 +279,7 @@ int add_cache_entry(struct cache_entry *
 	int pos;
 	int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
 	int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
+	int skip_df_check = option & ADD_CACHE_SKIP_DF_CHECK;
 	pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
 
 	/* existing match? Just replace it */
@@ -302,7 +305,7 @@ int add_cache_entry(struct cache_entry *
 	if (!ok_to_add)
 		return -1;
 
-	if (!ce_stage(ce) && check_file_directory_conflict(ce, pos, ok_to_replace)) {
+	if (!skip_df_check && check_file_directory_conflict(ce, ok_to_replace)) {
 		if (!ok_to_replace)
 			return -1;
 		pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh
--- a/t/t1005-read-tree-m-2way-emu23.sh
+++ b/t/t1005-read-tree-m-2way-emu23.sh
@@ -389,7 +389,7 @@ test_expect_success \
      :'
 
 # Emu23 can grok I having more than H.  Make sure we did not
-# botch the conflict tests (Linus code botches this test).
+# botch the conflict tests (fixed).
 test_expect_success \
     'DF vs DF/DF case test (#2).' \
     'rm -f .git/index &&
@@ -400,8 +400,8 @@ test_expect_success \
      # This should fail because I and H have a conflict
      # at DF.
      if git-read-tree --emu23 $treeDF $treeDFDF
-     then true  ;# should be false
-     else false ;# should be true
+     then false
+     else true
      fi'
 
 test_done
diff --git a/tree.c b/tree.c
--- a/tree.c
+++ b/tree.c
@@ -18,7 +18,7 @@ static int read_one_entry(unsigned char 
 	memcpy(ce->name, base, baselen);
 	memcpy(ce->name + baselen, pathname, len+1);
 	memcpy(ce->sha1, sha1, 20);
-	return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
+	return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DF_CHECK);
 }
 
 static int read_tree_recursive(void *buffer, unsigned long size,
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
  2005-06-24 23:40 ` [PATCH 2/2] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
@ 2005-06-25  0:57   ` Linus Torvalds
  2005-06-25  2:40     ` Junio C Hamano
  0 siblings, 1 reply; 19+ messages in thread
From: Linus Torvalds @ 2005-06-25  0:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git



On Fri, 24 Jun 2005, Junio C Hamano wrote:
> 
> Resurrect the unoptimized directory-file conflict check code for
> now as well.  The new one did not handle higher stages properly.

I really don't want to do this. 

Can you fix the "optimized" one instead? Currently the only "optimization"  
is really to just not call it for any non-stage0 thing, the real advantage
is that the old code was totally unreadable and did everything in one big 
thing. 

I'm ok with dropping the optimization, but I don't want to lose the 
cleanup of splitting that horrible old function into two.

		Linus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 2/2] Fix oversimplified optimization for add_cache_entry().
  2005-06-25  0:57   ` Linus Torvalds
@ 2005-06-25  2:40     ` Junio C Hamano
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
  0 siblings, 1 reply; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  2:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> I really don't want to do this. 
LT> Can you fix the "optimized" one instead?

Will do.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 0/9] Fix oversimplified optimization for add_cache_entry().
  2005-06-25  2:40     ` Junio C Hamano
@ 2005-06-25  9:16       ` Junio C Hamano
  2005-06-25  9:21         ` [PATCH 1/9] fix date parsing for GIT raw commit timestamp format Junio C Hamano
                           ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:16 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

>>>>> "JCH" == Junio C Hamano <junkio@cox.net> writes:

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:
LT> I really don't want to do this. 
LT> Can you fix the "optimized" one instead?

JCH> Will do.

I have this list which logically consists of three sets.  I am
using the new "git rebase" to maintain it and your not taking my
patch stream gave me a good opportunity to test it ;-).

  [PATCH 1/9] [RFC] fix date parsing for GIT raw commit timestamp format.
  [PATCH 2/9] git-commit-script: get commit message from an existing one.
  [PATCH 3/9] git-cherry: find commits not merged upstream.
  [PATCH 4/9] git-rebase-script: rebase local commits to new upstream head.

These four are updated "git rebase" I've written while on-road
without knowing about your git-patch-id; the updated one uses
git-patch-id to identify which are merged and which are not.

To carry earlier commit datetime forward, date.c needs to be
fixed (PATCH 1/9, which I sent you separately Friday), and
enhancing git-commit-script to be able to specify an existing
commit to slurp the commit message (and author & date
information) was necessary (well, not strictly necessary, but
that is the way I am used to, which is stolen from JIT), which
is PATCH 2/9.  PATCH 3/9 and PATCH 4/9 use git-patch-id to
implement the cherrypick/rebase.

  [PATCH 5/9] Add more tests for read-tree --emu23.
  [PATCH 6/9] git-merge-one-file-script: do not misinterpret rm failure
  [PATCH 7/9] Fix oversimplified optimization for add_cache_entry().

These three are reworked D/F conflict fix.  PATCH 5/9 is the
same demonstration of what is broken in the current code.  The
problem fixed by PATCH 6/9 was discovered while I was trying out
the fixes.  PATCH 7/9 teaches your "optimized" has_file/has_dir
implementation to honor stages while they operate.

  [PATCH 8/9] http-pull: documentation updates.
  [PATCH 9/9] Add a bit of developer documentation to pull.h

These are resend.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/9] fix date parsing for GIT raw commit timestamp format.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
@ 2005-06-25  9:21         ` Junio C Hamano
  2005-06-25  9:22         ` [PATCH 2/9] git-commit-script: get commit message from an existing one Junio C Hamano
                           ` (8 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:21 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Usually all of the match_xxx routines in date.c fill tm
structure assuming that the parsed string talks about local
time, and parse_date routine compensates for it by adjusting the
value with tz offset parsed out separately.  However, this logic
does not work well when we feed GIT raw commit timestamp to it,
because what match_digits gets is already in GMT.

A good testcase is:

    $ make test-date
    $ ./test-date 'Fri Jun 24 16:55:27 2005 -0700' '1119657327 -0700'

These two timestamps represent the same time, but the second one
without the fix this commit introduces gives you 7 hours off.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 date.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

dff2db477c3d450350a0dfdce4fa3f9543206b86
diff --git a/date.c b/date.c
--- a/date.c
+++ b/date.c
@@ -270,7 +270,7 @@ static int match_multi_number(unsigned l
 /*
  * We've seen a digit. Time? Year? Date? 
  */
-static int match_digit(char *date, struct tm *tm, int *offset)
+static int match_digit(char *date, struct tm *tm, int *offset, int *tm_gmt)
 {
 	int n;
 	char *end;
@@ -283,8 +283,10 @@ static int match_digit(char *date, struc
 	 */
 	if (num > 946684800) {
 		time_t time = num;
-		if (gmtime_r(&time, tm))
+		if (gmtime_r(&time, tm)) {
+			*tm_gmt = 1;
 			return end - date;
+		}
 	}
 
 	/*
@@ -389,7 +391,7 @@ static int match_tz(char *date, int *off
 void parse_date(char *date, char *result, int maxlen)
 {
 	struct tm tm;
-	int offset, sign;
+	int offset, sign, tm_gmt;
 	time_t then;
 
 	memset(&tm, 0, sizeof(tm));
@@ -398,6 +400,7 @@ void parse_date(char *date, char *result
 	tm.tm_mday = -1;
 	tm.tm_isdst = -1;
 	offset = -1;
+	tm_gmt = 0;
 
 	for (;;) {
 		int match = 0;
@@ -410,7 +413,7 @@ void parse_date(char *date, char *result
 		if (isalpha(c))
 			match = match_alpha(date, &tm, &offset);
 		else if (isdigit(c))
-			match = match_digit(date, &tm, &offset);
+			match = match_digit(date, &tm, &offset, &tm_gmt);
 		else if ((c == '-' || c == '+') && isdigit(date[1]))
 			match = match_tz(date, &offset);
 
@@ -430,7 +433,8 @@ void parse_date(char *date, char *result
 	if (then == -1)
 		return;
 
-	then -= offset * 60;
+	if (!tm_gmt)
+		then -= offset * 60;
 
 	sign = '+';
 	if (offset < 0) {
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 2/9] git-commit-script: get commit message from an existing one.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
  2005-06-25  9:21         ` [PATCH 1/9] fix date parsing for GIT raw commit timestamp format Junio C Hamano
@ 2005-06-25  9:22         ` Junio C Hamano
  2005-06-25  9:22         ` [PATCH 3/9] git-cherry: find commits not merged upstream Junio C Hamano
                           ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:22 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

With -m flag specified, git-commit-script takes the commit
message along with author information from an existing commit.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 git-commit-script |   75 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 67 insertions(+), 8 deletions(-)

da2ff8148a94b982c7ee369d5a37c4d20e8dd2a4
diff --git a/git-commit-script b/git-commit-script
--- a/git-commit-script
+++ b/git-commit-script
@@ -1,12 +1,37 @@
 #!/bin/sh
+#
+# Copyright (c) 2005 Linus Torvalds
+#
+
+usage () {
+    echo 'git commit [-m existing-commit] [<path>...]'
+    exit 1
+}
+
 : ${GIT_DIR=.git}
-if [ ! -d $GIT_DIR ]; then
+if [ ! -d "$GIT_DIR" ]; then
 	echo Not a git directory 1>&2
 	exit 1
 fi
+while case "$#" in 0) break ;; esac
+do
+    case "$1" in
+    -m) shift
+        case "$#" in
+	0) usage ;;
+	*) use_commit=`git-rev-parse "$1"` ||
+	   exit ;;
+	esac
+	;;
+    *)  break
+        ;;
+    esac
+    shift
+done
+
 git-update-cache -q --refresh -- "$@" || exit 1
 PARENTS="-p HEAD"
-if [ ! -r $GIT_DIR/HEAD ]; then
+if [ ! -r "$GIT_DIR/HEAD" ]; then
 	if [ -z "$(git-ls-files)" ]; then
 		echo Nothing to commit 1>&2
 		exit 1
@@ -20,7 +45,7 @@ if [ ! -r $GIT_DIR/HEAD ]; then
 	) > .editmsg
 	PARENTS=""
 else
-	if [ -f $GIT_DIR/MERGE_HEAD ]; then
+	if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
 		echo "#"
 		echo "# It looks like your may be committing a MERGE."
 		echo "# If this is not correct, please remove the file"
@@ -28,8 +53,38 @@ else
 		echo "# and try again"
 		echo "#"
 		PARENTS="-p HEAD -p MERGE_HEAD"
-	fi > .editmsg
-	git-status-script >> .editmsg
+	elif test "$use_commit" != ""
+	then
+		pick_author_script='
+		/^author /{
+			h
+			s/^author \([^<]*\) <[^>]*> .*$/\1/
+			s/'\''/'\''\'\'\''/g
+			s/.*/GIT_AUTHOR_NAME='\''&'\''/p
+
+			g
+			s/^author [^<]* <\([^>]*\)> .*$/\1/
+			s/'\''/'\''\'\'\''/g
+			s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
+
+			g
+			s/^author [^<]* <[^>]*> \(.*\)$/\1/
+			s/'\''/'\''\'\'\''/g
+			s/.*/GIT_AUTHOR_DATE='\''&'\''/p
+
+			q
+		}
+		'
+		set_author_env=`git-cat-file commit "$use_commit" |
+		sed -ne "$pick_author_script"`
+		eval "$set_author_env"
+		export GIT_AUTHOR_NAME
+		export GIT_AUTHOR_EMAIL
+		export GIT_AUTHOR_DATE
+		git-cat-file commit "$use_commit" |
+		sed -e '1,/^$/d'
+	fi >.editmsg
+	git-status-script >>.editmsg
 fi
 if [ "$?" != "0" ]
 then
@@ -37,13 +92,17 @@ then
 	rm .editmsg
 	exit 1
 fi
-${VISUAL:-${EDITOR:-vi}} .editmsg
+case "$use_commit" in
+'')
+	${VISUAL:-${EDITOR:-vi}} .editmsg
+	;;
+esac
 grep -v '^#' < .editmsg | git-stripspace > .cmitmsg
 [ -s .cmitmsg ] && 
 	tree=$(git-write-tree) &&
 	commit=$(cat .cmitmsg | git-commit-tree $tree $PARENTS) &&
-	echo $commit > $GIT_DIR/HEAD &&
-	rm -f -- $GIT_DIR/MERGE_HEAD
+	echo $commit > "$GIT_DIR/HEAD" &&
+	rm -f -- "$GIT_DIR/MERGE_HEAD"
 ret="$?"
 rm -f .cmitmsg .editmsg
 exit "$ret"
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 3/9] git-cherry: find commits not merged upstream.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
  2005-06-25  9:21         ` [PATCH 1/9] fix date parsing for GIT raw commit timestamp format Junio C Hamano
  2005-06-25  9:22         ` [PATCH 2/9] git-commit-script: get commit message from an existing one Junio C Hamano
@ 2005-06-25  9:22         ` Junio C Hamano
  2005-06-25  9:23         ` [PATCH 4/9] git-rebase-script: rebase local commits to new upstream head Junio C Hamano
                           ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:22 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

The git-cherry command helps the git-rebase script by finding
commits that have not been merged upstream.  Commits already
included in upstream are prefixed with '-' (meaning "drop from
my local pull"), while commits missing from upstream are
prefixed with '+' (meaning "add to the updated upstream").

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 Makefile   |    2 +
 git-cherry |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+), 1 deletions(-)
 create mode 100755 git-cherry

350e3957925c9b4404977bbd6f65bf68ba28d26f
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ SCRIPTS=git git-apply-patch-script git-m
 	git-deltafy-script git-fetch-script git-status-script git-commit-script \
 	git-log-script git-shortlog git-cvsimport-script git-diff-script \
 	git-reset-script git-add-script git-checkout-script git-clone-script \
-	gitk
+	gitk git-cherry
 
 PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
 	git-read-tree git-commit-tree git-cat-file git-fsck-cache \
diff --git a/git-cherry b/git-cherry
new file mode 100755
--- /dev/null
+++ b/git-cherry
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano.
+#
+
+usage="usage: $0 "'<upstream> [<head>]
+
+             __*__*__*__*__> <upstream>
+            /
+  fork-point
+            \__+__+__+__+__+__+__+__> <head>
+
+Each commit between the fork-point and <head> is examined, and
+compared against the change each commit between the fork-point and
+<upstream> introduces.  If the change does not seem to be in the
+upstream, it is shown on the standard output.
+
+The output is intended to be used as:
+
+    OLD_HEAD=$(git-rev-parse HEAD)
+    git-rev-parse linus >${GIT_DIR-.}/HEAD
+    git-cherry linus OLD_HEAD |
+    while read commit
+    do
+        GIT_EXTERNAL_DIFF=git-apply-patch-script git-diff-tree -p "$commit" &&
+	git-commit-script -m "$commit"
+    done
+'
+
+case "$#" in
+1) linus=`git-rev-parse "$1"` &&
+   junio=`git-rev-parse HEAD` || exit
+   ;;
+2) linus=`git-rev-parse "$1"` &&
+   junio=`git-rev-parse "$2"` || exit
+   ;;
+*) echo >&2 "$usage"; exit 1 ;;
+esac
+
+# Note that these list commits in reverse order;
+# not that the order in inup matters...
+inup=`git-rev-list ^$junio $linus` &&
+ours=`git-rev-list $junio ^$linus` || exit
+
+tmp=.cherry-tmp$$
+patch=$tmp-patch
+mkdir $patch
+trap "rm -rf $tmp-*" 0 1 2 3 15
+
+_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+
+for c in $inup
+do
+	git-diff-tree -p $c
+done | git-patch-id |
+while read id name
+do
+	echo $name >>$patch/$id
+done
+
+LF='
+'
+
+O=
+for c in $ours
+do
+	set x `git-diff-tree -p $c | git-patch-id`
+	if test "$2" != ""
+	then
+		if test -f "$patch/$2"
+		then
+			sign=-
+		else
+			sign=+
+		fi
+		case "$O" in
+		'')	O="$sign $c" ;;
+		*)	O="$sign $c$LF$O" ;;
+		esac
+	fi
+done
+case "$O" in
+'') ;;
+*)  echo "$O" ;;
+esac
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 4/9] git-rebase-script: rebase local commits to new upstream head.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (2 preceding siblings ...)
  2005-06-25  9:22         ` [PATCH 3/9] git-cherry: find commits not merged upstream Junio C Hamano
@ 2005-06-25  9:23         ` Junio C Hamano
  2005-06-25  9:24         ` [PATCH 5/9] Add more tests for read-tree --emu23 Junio C Hamano
                           ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:23 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Using git-cherry, forward port local commits missing from the
new upstream head.  This also depends on "-m" flag support in
git-commit-script.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 Makefile          |    2 +-
 git-rebase-script |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+), 1 deletions(-)
 create mode 100755 git-rebase-script

39830aca0319e04ed6c45203614543418974f877
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ SCRIPTS=git git-apply-patch-script git-m
 	git-deltafy-script git-fetch-script git-status-script git-commit-script \
 	git-log-script git-shortlog git-cvsimport-script git-diff-script \
 	git-reset-script git-add-script git-checkout-script git-clone-script \
-	gitk git-cherry
+	gitk git-cherry git-rebase-script
 
 PROG=   git-update-cache git-diff-files git-init-db git-write-tree \
 	git-read-tree git-commit-tree git-cat-file git-fsck-cache \
diff --git a/git-rebase-script b/git-rebase-script
new file mode 100755
--- /dev/null
+++ b/git-rebase-script
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano.
+#
+
+usage="usage: $0 "'<upstream> [<head>]
+
+Uses output from git-cherry to rebase local commits to the new head of
+upstream tree.'
+
+: ${GIT_DIR=.git}
+
+case "$#" in
+1) linus=`git-rev-parse "$1"` &&
+   junio=`git-rev-parse HEAD` || exit
+   ;;
+2) linus=`git-rev-parse "$1"` &&
+   junio=`git-rev-parse "$2"` || exit
+   ;;
+*) echo >&2 "$usage"; exit 1 ;;
+esac
+
+git-read-tree -m -u $junio $linus &&
+echo "$linus" >"$GIT_DIR/HEAD" || exit
+
+tmp=.rebase-tmp$$
+fail=$tmp-fail
+trap "rm -rf $tmp-*" 0 1 2 3 15
+
+>$fail
+
+git-cherry $linus $junio |
+while read sign commit
+do
+	case "$sign" in
+	-) continue ;;
+	esac
+	S=`cat "$GIT_DIR/HEAD"` &&
+        GIT_EXTERNAL_DIFF=git-apply-patch-script git-diff-tree -p $commit &&
+	git-commit-script -m "$commit" || {
+		echo $commit >>$fail
+		git-read-tree --reset -u $S
+	}
+done
+if test -s $fail
+then
+	echo Some commits could not be rebased, check by hand:
+	cat $fail
+fi
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 5/9] Add more tests for read-tree --emu23.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (3 preceding siblings ...)
  2005-06-25  9:23         ` [PATCH 4/9] git-rebase-script: rebase local commits to new upstream head Junio C Hamano
@ 2005-06-25  9:24         ` Junio C Hamano
  2005-06-25  9:24         ` [PATCH 6/9] git-merge-one-file-script: do not misinterpret rm failure Junio C Hamano
                           ` (4 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:24 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

This adds more tests for --emu23.  One is to show how it can
carry forward more local changes than the straightforward
two-way fast forward, and another is to show the recent
overeager optimization of directory/file conflict check broke
things, which will be fixed in the next commit.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 t/t1001-read-tree-m-2way.sh       |   70 +++++++++++++++++++++++++---
 t/t1005-read-tree-m-2way-emu23.sh |   94 ++++++++++++++++++++++++++++++++++---
 2 files changed, 150 insertions(+), 14 deletions(-)

633115eb1338884fd9488fe57ef4ea2fb91559d5
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -29,7 +29,6 @@ read_tree_twoway () {
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 compare_change () {
-    	cat current
 	sed -n >current \
 	    -e '/^--- /d; /^+++ /d; /^@@ /d;' \
 	    -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
@@ -51,11 +50,22 @@ check_cache_at () {
 	esac
 }
 
+cat >bozbar-old <<\EOF
+This is a sample file used in two-way fast forward merge
+tests.  Its second line ends with a magic word bozbar
+which will be modified by the merged head to gnusto.
+It has some extra lines so that external tools can
+successfully merge independent changes made to later
+lines (such as this one), avoiding line conflicts.
+EOF
+
+sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
+
 test_expect_success \
     setup \
     'echo frotz >frotz &&
      echo nitfol >nitfol &&
-     echo bozbar >bozbar &&
+     cat bozbar-old >bozbar &&
      echo rezrov >rezrov &&
      echo yomin >yomin &&
      git-update-cache --add nitfol bozbar rezrov &&
@@ -63,7 +73,7 @@ test_expect_success \
      echo treeH $treeH &&
      git-ls-tree $treeH &&
 
-     echo gnusto >bozbar &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add frotz bozbar --force-remove rezrov &&
      git-ls-files --stage >M.out &&
      treeM=`git-write-tree` &&
@@ -86,6 +96,8 @@ echo '+100644 X 0	yomin' >expected
 test_expect_success \
     '4 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add yomin &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >4.out || exit
@@ -96,6 +108,8 @@ test_expect_success \
 test_expect_success \
     '5 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo yomin >yomin &&
      git-update-cache --add yomin &&
      echo yomin yomin >yomin &&
@@ -108,6 +122,8 @@ test_expect_success \
 test_expect_success \
     '6 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add frotz &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >6.out &&
@@ -117,6 +133,8 @@ test_expect_success \
 test_expect_success \
     '7 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz frotz >frotz &&
@@ -128,6 +146,8 @@ test_expect_success \
 test_expect_success \
     '8 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -135,6 +155,8 @@ test_expect_success \
 test_expect_success \
     '9 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz >frotz &&
@@ -143,6 +165,8 @@ test_expect_success \
 test_expect_success \
     '10 - path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      read_tree_twoway $treeH $treeM &&
@@ -152,6 +176,8 @@ test_expect_success \
 test_expect_success \
     '11 - dirty path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov rezrov >rezrov &&
@@ -160,6 +186,8 @@ test_expect_success \
 test_expect_success \
     '12 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -167,6 +195,8 @@ test_expect_success \
 test_expect_success \
     '13 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov >rezrov &&
@@ -180,6 +210,8 @@ EOF
 test_expect_success \
     '14 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      read_tree_twoway $treeH $treeM &&
@@ -191,6 +223,8 @@ test_expect_success \
 test_expect_success \
     '15 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      echo nitfol nitfol nitfol >nitfol &&
@@ -203,6 +237,8 @@ test_expect_success \
 test_expect_success \
     '16 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -210,6 +246,8 @@ test_expect_success \
 test_expect_success \
     '17 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      echo bozbar bozbar bozbar >bozbar &&
@@ -218,7 +256,9 @@ test_expect_success \
 test_expect_success \
     '18 - local change already having a good result.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >18.out &&
@@ -228,7 +268,9 @@ test_expect_success \
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      read_tree_twoway $treeH $treeM &&
@@ -239,7 +281,9 @@ test_expect_success \
 test_expect_success \
     '20 - no local change, use new tree.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >20.out &&
@@ -249,11 +293,23 @@ test_expect_success \
 test_expect_success \
     '21 - no local change, dirty cache.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
 
+# This fails with straight two-way fast forward.
+test_expect_success \
+    '22 - local change cache updated.' \
+    'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
+     git-update-cache --add bozbar &&
+     if read_tree_twoway $treeH $treeM; then false; else :; fi'
+
 # Also make sure we did not break DF vs DF/DF case.
 test_expect_success \
     'DF vs DF/DF case setup.' \
diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh
--- a/t/t1005-read-tree-m-2way-emu23.sh
+++ b/t/t1005-read-tree-m-2way-emu23.sh
@@ -32,7 +32,6 @@ read_tree_twoway () {
 _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 compare_change () {
-    	cat current
 	sed -n >current \
 	    -e '/^--- /d; /^+++ /d; /^@@ /d;' \
 	    -e 's/^\([-+][0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /p' \
@@ -60,11 +59,22 @@ check_stages () {
     diff -u expected_stages current_stages
 }
 
+cat >bozbar-old <<\EOF
+This is a sample file used in two-way fast forward merge
+tests.  Its second line ends with a magic word bozbar
+which will be modified by the merged head to gnusto.
+It has some extra lines so that external tools can
+successfully merge independent changes made to later
+lines (such as this one), avoiding line conflicts.
+EOF
+
+sed -e 's/bozbar/gnusto (earlier bozbar)/' bozbar-old >bozbar-new
+
 test_expect_success \
     setup \
     'echo frotz >frotz &&
      echo nitfol >nitfol &&
-     echo bozbar >bozbar &&
+     cat bozbar-old >bozbar &&
      echo rezrov >rezrov &&
      echo yomin >yomin &&
      git-update-cache --add nitfol bozbar rezrov &&
@@ -72,7 +82,7 @@ test_expect_success \
      echo treeH $treeH &&
      git-ls-tree $treeH &&
 
-     echo gnusto >bozbar &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add frotz bozbar --force-remove rezrov &&
      git-ls-files --stage >M.out &&
      treeM=`git-write-tree` &&
@@ -106,6 +116,8 @@ echo '+100644 X 0	yomin' >expected
 test_expect_success \
     '4 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add yomin &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >4.out || exit
@@ -118,6 +130,8 @@ test_expect_success \
 test_expect_success \
     '5 - carry forward local addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo yomin >yomin &&
      git-update-cache --add yomin &&
      echo yomin yomin >yomin &&
@@ -132,6 +146,8 @@ test_expect_success \
 test_expect_success \
     '6 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      git-update-cache --add frotz &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >6.out &&
@@ -143,6 +159,8 @@ test_expect_success \
 test_expect_success \
     '7 - local addition already has the same.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz frotz >frotz &&
@@ -154,6 +172,8 @@ test_expect_success \
 test_expect_success \
     '8 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -161,6 +181,8 @@ test_expect_success \
 test_expect_success \
     '9 - conflicting addition.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo frotz frotz >frotz &&
      git-update-cache --add frotz &&
      echo frotz >frotz &&
@@ -169,6 +191,8 @@ test_expect_success \
 test_expect_success \
     '10 - path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      read_tree_twoway $treeH $treeM &&
@@ -178,6 +202,8 @@ test_expect_success \
 test_expect_success \
     '11 - dirty path removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov rezrov >rezrov &&
@@ -186,6 +212,8 @@ test_expect_success \
 test_expect_success \
     '12 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
@@ -193,6 +221,8 @@ test_expect_success \
 test_expect_success \
     '13 - unmatching local changes being removed.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo rezrov rezrov >rezrov &&
      git-update-cache --add rezrov &&
      echo rezrov >rezrov &&
@@ -206,6 +236,8 @@ EOF
 test_expect_success \
     '14 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      read_tree_twoway $treeH $treeM &&
@@ -217,6 +249,8 @@ test_expect_success \
 test_expect_success \
     '15 - unchanged in two heads.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo nitfol nitfol >nitfol &&
      git-update-cache --add nitfol &&
      echo nitfol nitfol nitfol >nitfol &&
@@ -233,6 +267,8 @@ test_expect_success \
 test_expect_success \
     '16 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      git-read-tree --emu23 $treeH $treeM &&
@@ -249,6 +285,8 @@ EOF
 test_expect_success \
     '17 - conflicting local change.' \
     'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
      echo bozbar bozbar >bozbar &&
      git-update-cache --add bozbar &&
      echo bozbar bozbar bozbar >bozbar &&
@@ -257,7 +295,9 @@ test_expect_success \
 test_expect_success \
     '18 - local change already having a good result.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >18.out &&
@@ -267,7 +307,9 @@ test_expect_success \
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
     'rm -f .git/index &&
-     echo gnusto >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-new >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      read_tree_twoway $treeH $treeM &&
@@ -278,7 +320,9 @@ test_expect_success \
 test_expect_success \
     '20 - no local change, use new tree.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      read_tree_twoway $treeH $treeM &&
      git-ls-files --stage >20.out &&
@@ -288,11 +332,31 @@ test_expect_success \
 test_expect_success \
     '21 - no local change, dirty cache.' \
     'rm -f .git/index &&
-     echo bozbar >bozbar &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     cat bozbar-old >bozbar &&
      git-update-cache --add bozbar &&
      echo gnusto gnusto >bozbar &&
      if read_tree_twoway $treeH $treeM; then false; else :; fi'
 
+echo '-100644 X 0	bozbar
++100644 X 0	bozbar' >expected
+
+# This fails with straight two-way fast forward, but emu23
+# can merge them.
+test_expect_success \
+    '22 - local change cache updated.' \
+    'rm -f .git/index &&
+     git-read-tree $treeH &&
+     git-checkout-cache -u -f -q -a &&
+     sed -e "s/such as/SUCH AS/" bozbar-old >bozbar &&
+     git-update-cache --add bozbar &&
+     read_tree_twoway $treeH $treeM &&
+     git-ls-files --stage >22.out || exit
+     diff -u M.out 22.out >22diff.out
+     compare_change 22diff.out &&
+     check_cache_at bozbar clean'
+
 # Also make sure we did not break DF vs DF/DF case.
 test_expect_success \
     'DF vs DF/DF case setup.' \
@@ -324,4 +388,20 @@ test_expect_success \
      check_cache_at DF/DF clean && # different from pure 2-way
      :'
 
+# Emu23 can grok I having more than H.  Make sure we did not
+# botch the conflict tests (Linus code botches this test).
+test_expect_success \
+    'DF vs DF/DF case test (#2).' \
+    'rm -f .git/index &&
+     rm -fr DF &&
+     mkdir DF &&
+     echo DF/DF >DF/DF &&
+     git-update-cache --add DF/DF &&
+     # This should fail because I and H have a conflict
+     # at DF.
+     if git-read-tree --emu23 $treeDF $treeDFDF
+     then true  ;# should be false
+     else false ;# should be true
+     fi'
+
 test_done
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 6/9] git-merge-one-file-script: do not misinterpret rm failure.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (4 preceding siblings ...)
  2005-06-25  9:24         ` [PATCH 5/9] Add more tests for read-tree --emu23 Junio C Hamano
@ 2005-06-25  9:24         ` Junio C Hamano
  2005-06-25  9:25         ` [PATCH 7/9] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
                           ` (3 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:24 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

When a merge adds a file DF and removes a directory there by
deleting a path DF/DF, git-merge-one-file-script can be called
for the removal of DF/DF when the path DF is already created by
"git-read-tree -m -u".  When this happens, we get confused by a
failure return from 'rm -f -- "$4"' (where $4 is DF/DF); finding
file DF there the "rm -f" command complains that DF is not a
directory.

What we want to ensure is that there is no file DF/DF in this
case. Avoid getting ourselves confused by first checking if
there is a file, and only then try to remove it (and check for
failure from the "rm" command).

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 git-merge-one-file-script |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

7edbb24f69809eb41de865701bc4f17774348043
diff --git a/git-merge-one-file-script b/git-merge-one-file-script
--- a/git-merge-one-file-script
+++ b/git-merge-one-file-script
@@ -22,8 +22,11 @@ case "${1:-.}${2:-.}${3:-.}" in
 #
 "$1.." | "$1.$1" | "$1$1.")
 	echo "Removing $4"
-	rm -f -- "$4" &&
-		exec git-update-cache --remove -- "$4"
+	if test -f "$4"
+	then
+		rm -f -- "$4"
+	fi &&
+	exec git-update-cache --remove -- "$4"
 	;;
 
 #
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 7/9] Fix oversimplified optimization for add_cache_entry().
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (5 preceding siblings ...)
  2005-06-25  9:24         ` [PATCH 6/9] git-merge-one-file-script: do not misinterpret rm failure Junio C Hamano
@ 2005-06-25  9:25         ` Junio C Hamano
  2005-06-25  9:25         ` [PATCH 8/9] http-pull: documentation updates Junio C Hamano
                           ` (2 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

An earlier change to optimize directory-file conflict check
broke what "read-tree --emu23" expects.  This is fixed by this
commit.

(1) Introduces an explicit flag to tell add_cache_entry() not to
    check for conflicts and use it when reading an existing tree
    into an empty stage --- by definition this case can never
    introduce such conflicts.

(2) Makes read-cache.c:has_file_name() and read-cache.c:has_dir_name()
    aware of the cache stages, and flag conflict only with paths
    in the same stage.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 cache.h                           |    1 +
 read-cache.c                      |   32 +++++++++++++++++++++-----------
 t/t1005-read-tree-m-2way-emu23.sh |   25 ++++++++++++++++++++-----
 tree.c                            |    2 +-
 4 files changed, 43 insertions(+), 17 deletions(-)

904dbb145f2f42227ea5b94752146ef8d4c2b153
diff --git a/cache.h b/cache.h
--- a/cache.h
+++ b/cache.h
@@ -130,6 +130,7 @@ extern int write_cache(int newfd, struct
 extern int cache_name_pos(const char *name, int namelen);
 #define ADD_CACHE_OK_TO_ADD 1		/* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2	/* Ok to replace file/directory */
+#define ADD_CACHE_SKIP_DFCHECK 4	/* Ok to skip DF conflict checks */
 extern int add_cache_entry(struct cache_entry *ce, int option);
 extern int remove_cache_entry_at(int pos);
 extern int remove_file_from_cache(char *path);
diff --git a/read-cache.c b/read-cache.c
--- a/read-cache.c
+++ b/read-cache.c
@@ -179,6 +179,7 @@ static int has_file_name(const struct ca
 {
 	int retval = 0;
 	int len = ce_namelen(ce);
+	int stage = ce_stage(ce);
 	const char *name = ce->name;
 
 	while (pos < active_nr) {
@@ -188,6 +189,8 @@ static int has_file_name(const struct ca
 			break;
 		if (memcmp(name, p->name, len))
 			break;
+		if (ce_stage(p) != stage)
+			continue;
 		if (p->name[len] != '/')
 			continue;
 		retval = -1;
@@ -205,6 +208,7 @@ static int has_file_name(const struct ca
 static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace)
 {
 	int retval = 0;
+	int stage = ce_stage(ce);
 	const char *name = ce->name;
 	const char *slash = name + ce_namelen(ce);
 
@@ -219,7 +223,7 @@ static int has_dir_name(const struct cac
 		}
 		len = slash - name;
 
-		pos = cache_name_pos(name, len);
+		pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage)));
 		if (pos >= 0) {
 			retval = -1;
 			if (ok_to_replace)
@@ -231,18 +235,23 @@ static int has_dir_name(const struct cac
 		/*
 		 * Trivial optimization: if we find an entry that
 		 * already matches the sub-directory, then we know
-		 * we're ok, and we can exit
+		 * we're ok, and we can exit.
 		 */
 		pos = -pos-1;
-		if (pos < active_nr) {
+		while (pos < active_nr) {
 			struct cache_entry *p = active_cache[pos];
-			if (ce_namelen(p) <= len)
-				continue;
-			if (p->name[len] != '/')
-				continue;
-			if (memcmp(p->name, name, len))
-				continue;
-			break;
+			if ((ce_namelen(p) <= len) ||
+			    (p->name[len] != '/') ||
+			    memcmp(p->name, name, len))
+				break; /* not our subdirectory */
+			if (ce_stage(p) == stage)
+				/* p is at the same stage as our entry, and
+				 * is a subdirectory of what we are looking
+				 * at, so we cannot have conflicts at our
+				 * level or anything shorter.
+				 */
+				return retval;
+			pos++;
 		}
 	}
 	return retval;
@@ -277,6 +286,7 @@ int add_cache_entry(struct cache_entry *
 	int pos;
 	int ok_to_add = option & ADD_CACHE_OK_TO_ADD;
 	int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
+	int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
 	pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
 
 	/* existing match? Just replace it */
@@ -302,7 +312,7 @@ int add_cache_entry(struct cache_entry *
 	if (!ok_to_add)
 		return -1;
 
-	if (!ce_stage(ce) && check_file_directory_conflict(ce, pos, ok_to_replace)) {
+	if (!skip_df_check && check_file_directory_conflict(ce, pos, ok_to_replace)) {
 		if (!ok_to_replace)
 			return -1;
 		pos = cache_name_pos(ce->name, ntohs(ce->ce_flags));
diff --git a/t/t1005-read-tree-m-2way-emu23.sh b/t/t1005-read-tree-m-2way-emu23.sh
--- a/t/t1005-read-tree-m-2way-emu23.sh
+++ b/t/t1005-read-tree-m-2way-emu23.sh
@@ -366,6 +366,7 @@ test_expect_success \
      treeDF=`git-write-tree` &&
      echo treeDF $treeDF &&
      git-ls-tree $treeDF &&
+     git-ls-files --stage >DF.out
 
      rm -f DF &&
      mkdir DF &&
@@ -377,7 +378,7 @@ test_expect_success \
      git-ls-files --stage >DFDF.out'
 
 test_expect_success \
-    'DF vs DF/DF case test.' \
+    'DF vs DF/DF case test (#1)' \
     'rm -f .git/index &&
      rm -fr DF &&
      echo DF >DF &&
@@ -388,10 +389,24 @@ test_expect_success \
      check_cache_at DF/DF clean && # different from pure 2-way
      :'
 
+# The other way around
+test_expect_success \
+    'DF vs DF/DF case test (#2)' \
+    'rm -f .git/index &&
+     rm -fr DF &&
+     mkdir DF &&
+     echo DF/DF >DF/DF &&
+     git-update-cache --add DF/DF &&
+     read_tree_twoway $treeDFDF $treeDF &&
+     git-ls-files --stage >DFDFcheck.out &&
+     diff -u DF.out DFDFcheck.out &&
+     check_cache_at DF clean && # different from pure 2-way
+     :'
+
 # Emu23 can grok I having more than H.  Make sure we did not
-# botch the conflict tests (Linus code botches this test).
+# botch the conflict tests (fixed).
 test_expect_success \
-    'DF vs DF/DF case test (#2).' \
+    'DF vs DF/DF case test (#3).' \
     'rm -f .git/index &&
      rm -fr DF &&
      mkdir DF &&
@@ -400,8 +415,8 @@ test_expect_success \
      # This should fail because I and H have a conflict
      # at DF.
      if git-read-tree --emu23 $treeDF $treeDFDF
-     then true  ;# should be false
-     else false ;# should be true
+     then false
+     else true
      fi'
 
 test_done
diff --git a/tree.c b/tree.c
--- a/tree.c
+++ b/tree.c
@@ -18,7 +18,7 @@ static int read_one_entry(unsigned char 
 	memcpy(ce->name, base, baselen);
 	memcpy(ce->name + baselen, pathname, len+1);
 	memcpy(ce->sha1, sha1, 20);
-	return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
+	return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
 }
 
 static int read_tree_recursive(void *buffer, unsigned long size,
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 8/9] http-pull: documentation updates.
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (6 preceding siblings ...)
  2005-06-25  9:25         ` [PATCH 7/9] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
@ 2005-06-25  9:25         ` Junio C Hamano
  2005-06-25  9:26         ` [PATCH 9/9] Add a bit of developer documentation to pull.h Junio C Hamano
  2005-06-26  1:02         ` [RFD] consider "git" wrapper semi-Porcelain Junio C Hamano
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Describe -w option.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 Documentation/git-http-pull.txt |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

bce3da4d8421812b0eb1d433b0af0fc3fc9bb54a
diff --git a/Documentation/git-http-pull.txt b/Documentation/git-http-pull.txt
--- a/Documentation/git-http-pull.txt
+++ b/Documentation/git-http-pull.txt
@@ -9,7 +9,7 @@ git-http-pull - Downloads a remote GIT r
 
 SYNOPSIS
 --------
-'git-http-pull' [-c] [-t] [-a] [-v] [-d] [--recover] commit-id url
+'git-http-pull' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] commit-id url
 
 DESCRIPTION
 -----------
@@ -30,7 +30,9 @@ Downloads a remote GIT repository via HT
 	usual, to recover after earlier pull that was interrupted.
 -v::
 	Report what is downloaded.
-
+-w::
+        Writes the commit-id into the filename under $GIT_DIR/refs/ on
+        the local end after the transfer is complete.
 
 Author
 ------
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 9/9] Add a bit of developer documentation to pull.h
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (7 preceding siblings ...)
  2005-06-25  9:25         ` [PATCH 8/9] http-pull: documentation updates Junio C Hamano
@ 2005-06-25  9:26         ` Junio C Hamano
  2005-06-26  1:02         ` [RFD] consider "git" wrapper semi-Porcelain Junio C Hamano
  9 siblings, 0 replies; 19+ messages in thread
From: Junio C Hamano @ 2005-06-25  9:26 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Describe what to implement in fetch() and fetch_ref() for
pull backend writers a bit better.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 pull.h |   21 +++++++++++++++------
 1 files changed, 15 insertions(+), 6 deletions(-)

190061e326b73dcf76d301d8b17ce96c783d7251
diff --git a/pull.h b/pull.h
--- a/pull.h
+++ b/pull.h
@@ -1,24 +1,33 @@
 #ifndef PULL_H
 #define PULL_H
 
-/** To be provided by the particular implementation. **/
+/*
+ * Fetch object given SHA1 from the remote, and store it locally under
+ * GIT_OBJECT_DIRECTORY.  Return 0 on success, -1 on failure.  To be
+ * provided by the particular implementation.
+ */
 extern int fetch(unsigned char *sha1);
 
+/*
+ * Fetch ref (relative to $GIT_DIR/refs) from the remote, and store
+ * the 20-byte SHA1 in sha1.  Return 0 on success, -1 on failure.  To
+ * be provided by the particular implementation.
+ */
 extern int fetch_ref(char *ref, unsigned char *sha1);
 
-/** If set, the ref filename to write the target value to. **/
+/* If set, the ref filename to write the target value to. */
 extern const char *write_ref;
 
-/** If set, the hash that the current value of write_ref must be. **/
+/* If set, the hash that the current value of write_ref must be. */
 extern const unsigned char *current_ref;
 
-/** Set to fetch the target tree. */
+/* Set to fetch the target tree. */
 extern int get_tree;
 
-/** Set to fetch the commit history. */
+/* Set to fetch the commit history. */
 extern int get_history;
 
-/** Set to fetch the trees in the commit history. **/
+/* Set to fetch the trees in the commit history. */
 extern int get_all;
 
 /* Set to zero to skip the check for delta object base;
------------


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [RFD] consider "git" wrapper semi-Porcelain
  2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
                           ` (8 preceding siblings ...)
  2005-06-25  9:26         ` [PATCH 9/9] Add a bit of developer documentation to pull.h Junio C Hamano
@ 2005-06-26  1:02         ` Junio C Hamano
  2005-06-26  1:21           ` Linus Torvalds
  9 siblings, 1 reply; 19+ messages in thread
From: Junio C Hamano @ 2005-06-26  1:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Currently "git" wrapper suggests both low-level git-* commands
and git-*-script commands as alternatives.  Earlier I stated
that git-*-script commands, like it or not, form a perfectly
good set of barebone Porcelain, as opposed to all the other
commands that do not end with "script" are low-level Plumbing.
After reviewing the current set of commands and scripts again, I
still think this view holds true [*1*, *2*].

I would propose the following, preferably before we go 1.0:

 (1) Do not suggest low-level Plumbing commands to "git" wrapper
     users, and do not call anything but git-*-script from "git"
     wrapper.  Once *-script Porcelain matures, hopefully
     everyday workflow would not require access to low-level
     Plumbing and can be done with git-*-script Porcelain.  When
     people know the GIT way, they can also work it around
     things that git-*-script Porcelain does not support well by
     writing their own git-*-script in terms of Plumbing-ish
     git-* commands, and if it is good enough for public
     consumption, propose it for inclusion upstream.

 (2) Make an alias git-whatchanged-script that just "exec"s
     git-whatchanged, to make things consistent.

 (3) Rename some git-*-script that are misnamed in the sense
     that they are not useful standalone scripts but more of
     Plumbing that happen to be written in shell [*3*].  I do
     not particularly like this proposal, because this breaks
     existing scripts.  However, if we go this route for
     consistency, I would further suggest renaming Porcelain-ish
     things git-*-cmd or something, call and suggest them from
     "git" wrapper, regardless of which language they are
     written in [*4*].


[Footnotes]

*1* One exception is git-whatchanged.

*2* That is the reason I did not name git-cherry
"git-cherry-script".  It is not useful standalone but meant to
be useful in scripting environment.

*3* git-apply-patch-script (my fault) and
git-merge-one-file-script fall into this category.

*4* Current naming and the proposal (1) above have a problem in
that they muddy the definition of what is "script": the name
"script" were originally used because they were written in
shell, and all of the Porcelain-ish things happen to be
"script".  Writing Porcelain-ish things in shell should not be a
requirement.


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFD] consider "git" wrapper semi-Porcelain
  2005-06-26  1:02         ` [RFD] consider "git" wrapper semi-Porcelain Junio C Hamano
@ 2005-06-26  1:21           ` Linus Torvalds
  2005-06-26 12:02             ` Junio C Hamano
  0 siblings, 1 reply; 19+ messages in thread
From: Linus Torvalds @ 2005-06-26  1:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git



On Sat, 25 Jun 2005, Junio C Hamano wrote:
> 
> I would propose the following, preferably before we go 1.0:

Agreed on all counts.

		Linus

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFD] consider "git" wrapper semi-Porcelain
  2005-06-26  1:21           ` Linus Torvalds
@ 2005-06-26 12:02             ` Junio C Hamano
  2005-06-26 12:36               ` Martijn Kuipers
  0 siblings, 1 reply; 19+ messages in thread
From: Junio C Hamano @ 2005-06-26 12:02 UTC (permalink / raw)
  To: git; +Cc: Linus Torvalds

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> On Sat, 25 Jun 2005, Junio C Hamano wrote:
>> 
>> I would propose the following, preferably before we go 1.0:

LT> Agreed on all counts.

With holy Penguin pee blessings, I would send in a "flag day"
patch sometime before July 4th weekend that:

 - renames most of the git-*-script to git-*-cmd;
 - renames git-whatchanged to git-whatchanged-cmd;
 - renames two misnamed git-*-script to git-*-helper

without any backward compatibility warts.

Unless people object and propose good transition plans, that
is.

This message is for people who uses bare GIT and who writes
Porcelain.  Please consider yourselves warned ;-).


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [RFD] consider "git" wrapper semi-Porcelain
  2005-06-26 12:02             ` Junio C Hamano
@ 2005-06-26 12:36               ` Martijn Kuipers
  0 siblings, 0 replies; 19+ messages in thread
From: Martijn Kuipers @ 2005-06-26 12:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Linus Torvalds

Hi,

Junio C Hamano wrote:

> - renames most of the git-*-script to git-*-cmd;

Wouldn't this ruin the nice tab-completion? git-plumbing and 
git-porcelain will only be distinctable from their last part.
Maybe I understood wrong, but if people are supposed to "just" use 
git-porcelain for every day use, then probably it would make more sense 
to rename to gitp-* for porcelain, as the tab-completion would work from 
the first word , which would be less confusing for us mere users (yes, 
any alternative first word would work).

Kind regards,
Martijn


^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2005-06-26 12:30 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-06-23 23:20 [PATCH 0/2] D/F conflicts fixes Junio C Hamano
2005-06-23 23:25 ` [PATCH 1/2] Add more tests for read-tree --emu23 Junio C Hamano
2005-06-24 23:40 ` [PATCH 2/2] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
2005-06-25  0:57   ` Linus Torvalds
2005-06-25  2:40     ` Junio C Hamano
2005-06-25  9:16       ` [PATCH 0/9] " Junio C Hamano
2005-06-25  9:21         ` [PATCH 1/9] fix date parsing for GIT raw commit timestamp format Junio C Hamano
2005-06-25  9:22         ` [PATCH 2/9] git-commit-script: get commit message from an existing one Junio C Hamano
2005-06-25  9:22         ` [PATCH 3/9] git-cherry: find commits not merged upstream Junio C Hamano
2005-06-25  9:23         ` [PATCH 4/9] git-rebase-script: rebase local commits to new upstream head Junio C Hamano
2005-06-25  9:24         ` [PATCH 5/9] Add more tests for read-tree --emu23 Junio C Hamano
2005-06-25  9:24         ` [PATCH 6/9] git-merge-one-file-script: do not misinterpret rm failure Junio C Hamano
2005-06-25  9:25         ` [PATCH 7/9] Fix oversimplified optimization for add_cache_entry() Junio C Hamano
2005-06-25  9:25         ` [PATCH 8/9] http-pull: documentation updates Junio C Hamano
2005-06-25  9:26         ` [PATCH 9/9] Add a bit of developer documentation to pull.h Junio C Hamano
2005-06-26  1:02         ` [RFD] consider "git" wrapper semi-Porcelain Junio C Hamano
2005-06-26  1:21           ` Linus Torvalds
2005-06-26 12:02             ` Junio C Hamano
2005-06-26 12:36               ` Martijn Kuipers

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.