Merge branch 'jc/read-tree-safety'
authorJunio C Hamano <junkio@cox.net>
Sat, 20 May 2006 00:02:22 +0000 (17:02 -0700)
committerJunio C Hamano <junkio@cox.net>
Sat, 20 May 2006 00:02:22 +0000 (17:02 -0700)
* jc/read-tree-safety:
  read-tree -m -u: do not overwrite or remove untracked working tree files.

read-tree.c
t/t1002-read-tree-m-u-2way.sh
t/t3500-cherry.sh
t/t4002-diff-basic.sh
t/t6022-merge-rename.sh

index e16e91b..82e2a9a 100644 (file)
@@ -408,7 +408,7 @@ static void verify_uptodate(struct cache_entry *ce)
 {
        struct stat st;
 
-       if (index_only)
+       if (index_only || reset)
                return;
 
        if (!lstat(ce->name, &st)) {
@@ -426,6 +426,21 @@ static void verify_uptodate(struct cache_entry *ce)
        die("Entry '%s' not uptodate. Cannot merge.", ce->name);
 }
 
+/*
+ * We do not want to remove or overwrite a working tree file that
+ * is not tracked.
+ */
+static void verify_absent(const char *path, const char *action)
+{
+       struct stat st;
+
+       if (index_only || reset || !update)
+               return;
+       if (!lstat(path, &st))
+               die("Untracked working tree file '%s' "
+                   "would be %s by merge.", path, action);
+}
+
 static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
 {
        merge->ce_flags |= htons(CE_UPDATE);
@@ -443,6 +458,9 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
                        verify_uptodate(old);
                }
        }
+       else
+               verify_absent(merge->name, "overwritten");
+
        merge->ce_flags &= ~htons(CE_STAGEMASK);
        add_cache_entry(merge, ADD_CACHE_OK_TO_ADD);
        return 1;
@@ -452,6 +470,8 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old)
 {
        if (old)
                verify_uptodate(old);
+       else
+               verify_absent(ce->name, "removed");
        ce->ce_mode = 0;
        add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
        return 1;
@@ -487,6 +507,7 @@ static int threeway_merge(struct cache_entry **stages)
        int count;
        int head_match = 0;
        int remote_match = 0;
+       const char *path = NULL;
 
        int df_conflict_head = 0;
        int df_conflict_remote = 0;
@@ -498,8 +519,11 @@ static int threeway_merge(struct cache_entry **stages)
        for (i = 1; i < head_idx; i++) {
                if (!stages[i])
                        any_anc_missing = 1;
-               else
+               else {
+                       if (!path)
+                               path = stages[i]->name;
                        no_anc_exists = 0;
+               }
        }
 
        index = stages[0];
@@ -515,8 +539,15 @@ static int threeway_merge(struct cache_entry **stages)
                remote = NULL;
        }
 
+       if (!path && index)
+               path = index->name;
+       if (!path && head)
+               path = head->name;
+       if (!path && remote)
+               path = remote->name;
+
        /* First, if there's a #16 situation, note that to prevent #13
-        * and #14. 
+        * and #14.
         */
        if (!same(remote, head)) {
                for (i = 1; i < head_idx; i++) {
@@ -575,6 +606,8 @@ static int threeway_merge(struct cache_entry **stages)
                    (remote_deleted && head && head_match)) {
                        if (index)
                                return deleted_entry(index, index);
+                       else if (path)
+                               verify_absent(path, "removed");
                        return 0;
                }
                /*
@@ -592,6 +625,8 @@ static int threeway_merge(struct cache_entry **stages)
        if (index) {
                verify_uptodate(index);
        }
+       else if (path)
+               verify_absent(path, "overwritten");
 
        nontrivial_merge = 1;
 
@@ -689,7 +724,7 @@ static int oneway_merge(struct cache_entry **src)
                             merge_size);
 
        if (!a)
-               return deleted_entry(old, NULL);
+               return deleted_entry(old, old);
        if (old && same(old, a)) {
                if (reset) {
                        struct stat st;
@@ -699,7 +734,7 @@ static int oneway_merge(struct cache_entry **src)
                }
                return keep_entry(old);
        }
-       return merged_entry(a, NULL);
+       return merged_entry(a, old);
 }
 
 static int read_cache_unmerged(void)
index 4d175d8..8335a63 100755 (executable)
@@ -39,7 +39,6 @@ test_expect_success \
      echo nitfol >nitfol &&
      echo bozbar >bozbar &&
      echo rezrov >rezrov &&
-     echo yomin >yomin &&
      git-update-index --add nitfol bozbar rezrov &&
      treeH=`git-write-tree` &&
      echo treeH $treeH &&
@@ -56,7 +55,8 @@ test_expect_success \
 
 test_expect_success \
     '1, 2, 3 - no carry forward' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      git-read-tree -m -u $treeH $treeM &&
      git-ls-files --stage >1-3.out &&
      cmp M.out 1-3.out &&
@@ -66,11 +66,12 @@ test_expect_success \
      check_cache_at frotz clean &&
      check_cache_at nitfol clean'
 
-echo '+100644 X 0      yomin' >expected
-
 test_expect_success \
     '4 - carry forward local addition.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
+     echo "+100644 X 0 yomin" >expected &&
+     echo yomin >yomin &&
      git-update-index --add yomin &&
      git-read-tree -m -u $treeH $treeM &&
      git-ls-files --stage >4.out || return 1
@@ -85,7 +86,9 @@ test_expect_success \
 
 test_expect_success \
     '5 - carry forward local addition.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
+     git-read-tree -m -u $treeH &&
      echo yomin >yomin &&
      git-update-index --add yomin &&
      echo yomin yomin >yomin &&
@@ -103,7 +106,9 @@ test_expect_success \
 
 test_expect_success \
     '6 - local addition already has the same.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
+     echo frotz >frotz &&
      git-update-index --add frotz &&
      git-read-tree -m -u $treeH $treeM &&
      git-ls-files --stage >6.out &&
@@ -117,7 +122,8 @@ test_expect_success \
 
 test_expect_success \
     '7 - local addition already has the same.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo frotz >frotz &&
      git-update-index --add frotz &&
      echo frotz frotz >frotz &&
@@ -134,14 +140,16 @@ test_expect_success \
 
 test_expect_success \
     '8 - conflicting addition.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo frotz frotz >frotz &&
      git-update-index --add frotz &&
      if git-read-tree -m -u $treeH $treeM; then false; else :; fi'
 
 test_expect_success \
     '9 - conflicting addition.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo frotz frotz >frotz &&
      git-update-index --add frotz &&
      echo frotz >frotz &&
@@ -149,7 +157,8 @@ test_expect_success \
 
 test_expect_success \
     '10 - path removed.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo rezrov >rezrov &&
      git-update-index --add rezrov &&
      git-read-tree -m -u $treeH $treeM &&
@@ -160,7 +169,8 @@ test_expect_success \
 
 test_expect_success \
     '11 - dirty path removed.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo rezrov >rezrov &&
      git-update-index --add rezrov &&
      echo rezrov rezrov >rezrov &&
@@ -168,14 +178,16 @@ test_expect_success \
 
 test_expect_success \
     '12 - unmatching local changes being removed.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo rezrov rezrov >rezrov &&
      git-update-index --add rezrov &&
      if git-read-tree -m -u $treeH $treeM; then false; else :; fi'
 
 test_expect_success \
     '13 - unmatching local changes being removed.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo rezrov rezrov >rezrov &&
      git-update-index --add rezrov &&
      echo rezrov >rezrov &&
@@ -188,7 +200,8 @@ EOF
 
 test_expect_success \
     '14 - unchanged in two heads.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo nitfol nitfol >nitfol &&
      git-update-index --add nitfol &&
      git-read-tree -m -u $treeH $treeM &&
@@ -207,7 +220,8 @@ test_expect_success \
 
 test_expect_success \
     '15 - unchanged in two heads.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo nitfol nitfol >nitfol &&
      git-update-index --add nitfol &&
      echo nitfol nitfol nitfol >nitfol &&
@@ -227,14 +241,16 @@ test_expect_success \
 
 test_expect_success \
     '16 - conflicting local change.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo bozbar bozbar >bozbar &&
      git-update-index --add bozbar &&
      if git-read-tree -m -u $treeH $treeM; then false; else :; fi'
 
 test_expect_success \
     '17 - conflicting local change.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo bozbar bozbar >bozbar &&
      git-update-index --add bozbar &&
      echo bozbar bozbar bozbar >bozbar &&
@@ -242,7 +258,8 @@ test_expect_success \
 
 test_expect_success \
     '18 - local change already having a good result.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo gnusto >bozbar &&
      git-update-index --add bozbar &&
      git-read-tree -m -u $treeH $treeM &&
@@ -254,7 +271,8 @@ test_expect_success \
 
 test_expect_success \
     '19 - local change already having a good result, further modified.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo gnusto >bozbar &&
      git-update-index --add bozbar &&
      echo gnusto gnusto >bozbar &&
@@ -273,7 +291,8 @@ test_expect_success \
 
 test_expect_success \
     '20 - no local change, use new tree.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo bozbar >bozbar &&
      git-update-index --add bozbar &&
      git-read-tree -m -u $treeH $treeM &&
@@ -285,7 +304,8 @@ test_expect_success \
 
 test_expect_success \
     '21 - no local change, dirty cache.' \
-    'rm -f .git/index &&
+    'rm -f .git/index nitfol bozbar rezrov frotz &&
+     git-read-tree --reset -u $treeH &&
      echo bozbar >bozbar &&
      git-update-index --add bozbar &&
      echo gnusto gnusto >bozbar &&
@@ -294,7 +314,7 @@ test_expect_success \
 # Also make sure we did not break DF vs DF/DF case.
 test_expect_success \
     'DF vs DF/DF case setup.' \
-    'rm -f .git/index &&
+    'rm -f .git/index
      echo DF >DF &&
      git-update-index --add DF &&
      treeDF=`git-write-tree` &&
index b141f89..e83bbee 100755 (executable)
@@ -30,6 +30,7 @@ test_expect_success \
      git-commit -m "Add C." &&
 
      git-checkout -f master &&
+     rm -f B C &&
 
      echo Third >> A &&
      git-update-index A &&
index 769274a..56eda63 100755 (executable)
@@ -191,7 +191,7 @@ test_expect_success \
     'rm -fr Z [A-Z][A-Z] &&
      git-read-tree $tree_A &&
      git-checkout-index -f -a &&
-     git-read-tree -m $tree_O || return 1
+     git-read-tree --reset $tree_O || return 1
      git-update-index --refresh >/dev/null ;# this can exit non-zero
      git-diff-files >.test-a &&
      cmp_diff_files_output .test-a .test-recursive-OA'
@@ -201,7 +201,7 @@ test_expect_success \
     'rm -fr Z [A-Z][A-Z] &&
      git-read-tree $tree_B &&
      git-checkout-index -f -a &&
-     git-read-tree -m $tree_O || return 1
+     git-read-tree --reset $tree_O || return 1
      git-update-index --refresh >/dev/null ;# this can exit non-zero
      git-diff-files >.test-a &&
      cmp_diff_files_output .test-a .test-recursive-OB'
@@ -211,7 +211,7 @@ test_expect_success \
     'rm -fr Z [A-Z][A-Z] &&
      git-read-tree $tree_B &&
      git-checkout-index -f -a &&
-     git-read-tree -m $tree_A || return 1
+     git-read-tree --reset $tree_A || return 1
      git-update-index --refresh >/dev/null ;# this can exit non-zero
      git-diff-files >.test-a &&
      cmp_diff_files_output .test-a .test-recursive-AB'
index a2d24b5..5ac2564 100755 (executable)
@@ -111,6 +111,7 @@ test_expect_success 'pull renaming branch into unrenaming one' \
 
 test_expect_success 'pull renaming branch into another renaming one' \
 '
+       rm -f B
        git reset --hard
        git checkout red
        git pull . white && {