Browse Source

Merge branch 'jc/read-tree-safety' into next

* jc/read-tree-safety:
  read-tree -m -u: do not overwrite or remove untracked working tree files.
maint
Junio C Hamano 19 years ago
parent
commit
22b49b7fb9
  1. 47
      read-tree.c
  2. 66
      t/t1002-read-tree-m-u-2way.sh
  3. 1
      t/t3500-cherry.sh
  4. 6
      t/t4002-diff-basic.sh
  5. 1
      t/t6022-merge-rename.sh

47
read-tree.c

@ -411,7 +411,7 @@ static void verify_uptodate(struct cache_entry *ce)
{ {
struct stat st; struct stat st;


if (index_only) if (index_only || reset)
return; return;


if (!lstat(ce->name, &st)) { if (!lstat(ce->name, &st)) {
@ -435,6 +435,21 @@ static void invalidate_ce_path(struct cache_entry *ce)
cache_tree_invalidate_path(active_cache_tree, ce->name); cache_tree_invalidate_path(active_cache_tree, 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) static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
{ {
merge->ce_flags |= htons(CE_UPDATE); merge->ce_flags |= htons(CE_UPDATE);
@ -453,8 +468,11 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old)
invalidate_ce_path(old); invalidate_ce_path(old);
} }
} }
else else {
verify_absent(merge->name, "overwritten");
invalidate_ce_path(merge); invalidate_ce_path(merge);
}

merge->ce_flags &= ~htons(CE_STAGEMASK); merge->ce_flags &= ~htons(CE_STAGEMASK);
add_cache_entry(merge, ADD_CACHE_OK_TO_ADD); add_cache_entry(merge, ADD_CACHE_OK_TO_ADD);
return 1; return 1;
@ -464,6 +482,8 @@ static int deleted_entry(struct cache_entry *ce, struct cache_entry *old)
{ {
if (old) if (old)
verify_uptodate(old); verify_uptodate(old);
else
verify_absent(ce->name, "removed");
ce->ce_mode = 0; ce->ce_mode = 0;
add_cache_entry(ce, ADD_CACHE_OK_TO_ADD); add_cache_entry(ce, ADD_CACHE_OK_TO_ADD);
invalidate_ce_path(ce); invalidate_ce_path(ce);
@ -500,6 +520,7 @@ static int threeway_merge(struct cache_entry **stages)
int count; int count;
int head_match = 0; int head_match = 0;
int remote_match = 0; int remote_match = 0;
const char *path = NULL;


int df_conflict_head = 0; int df_conflict_head = 0;
int df_conflict_remote = 0; int df_conflict_remote = 0;
@ -511,8 +532,11 @@ static int threeway_merge(struct cache_entry **stages)
for (i = 1; i < head_idx; i++) { for (i = 1; i < head_idx; i++) {
if (!stages[i]) if (!stages[i])
any_anc_missing = 1; any_anc_missing = 1;
else else {
if (!path)
path = stages[i]->name;
no_anc_exists = 0; no_anc_exists = 0;
}
} }


index = stages[0]; index = stages[0];
@ -528,8 +552,15 @@ static int threeway_merge(struct cache_entry **stages)
remote = NULL; 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 /* First, if there's a #16 situation, note that to prevent #13
* and #14. * and #14.
*/ */
if (!same(remote, head)) { if (!same(remote, head)) {
for (i = 1; i < head_idx; i++) { for (i = 1; i < head_idx; i++) {
@ -588,6 +619,8 @@ static int threeway_merge(struct cache_entry **stages)
(remote_deleted && head && head_match)) { (remote_deleted && head && head_match)) {
if (index) if (index)
return deleted_entry(index, index); return deleted_entry(index, index);
else if (path)
verify_absent(path, "removed");
return 0; return 0;
} }
/* /*
@ -605,6 +638,8 @@ static int threeway_merge(struct cache_entry **stages)
if (index) { if (index) {
verify_uptodate(index); verify_uptodate(index);
} }
else if (path)
verify_absent(path, "overwritten");


nontrivial_merge = 1; nontrivial_merge = 1;


@ -725,7 +760,7 @@ static int oneway_merge(struct cache_entry **src)


if (!a) { if (!a) {
invalidate_ce_path(old); invalidate_ce_path(old);
return deleted_entry(old, NULL); return deleted_entry(old, old);
} }
if (old && same(old, a)) { if (old && same(old, a)) {
if (reset) { if (reset) {
@ -736,7 +771,7 @@ static int oneway_merge(struct cache_entry **src)
} }
return keep_entry(old); return keep_entry(old);
} }
return merged_entry(a, NULL); return merged_entry(a, old);
} }


static int read_cache_unmerged(void) static int read_cache_unmerged(void)

66
t/t1002-read-tree-m-u-2way.sh

@ -39,7 +39,6 @@ test_expect_success \
echo nitfol >nitfol && echo nitfol >nitfol &&
echo bozbar >bozbar && echo bozbar >bozbar &&
echo rezrov >rezrov && echo rezrov >rezrov &&
echo yomin >yomin &&
git-update-index --add nitfol bozbar rezrov && git-update-index --add nitfol bozbar rezrov &&
treeH=`git-write-tree` && treeH=`git-write-tree` &&
echo treeH $treeH && echo treeH $treeH &&
@ -56,7 +55,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'1, 2, 3 - no carry forward' \ '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-read-tree -m -u $treeH $treeM &&
git-ls-files --stage >1-3.out && git-ls-files --stage >1-3.out &&
cmp M.out 1-3.out && cmp M.out 1-3.out &&
@ -66,11 +66,12 @@ test_expect_success \
check_cache_at frotz clean && check_cache_at frotz clean &&
check_cache_at nitfol clean' check_cache_at nitfol clean'


echo '+100644 X 0 yomin' >expected

test_expect_success \ test_expect_success \
'4 - carry forward local addition.' \ '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-update-index --add yomin &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
git-ls-files --stage >4.out || return 1 git-ls-files --stage >4.out || return 1
@ -85,7 +86,9 @@ test_expect_success \


test_expect_success \ test_expect_success \
'5 - carry forward local addition.' \ '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 && echo yomin >yomin &&
git-update-index --add yomin && git-update-index --add yomin &&
echo yomin yomin >yomin && echo yomin yomin >yomin &&
@ -103,7 +106,9 @@ test_expect_success \


test_expect_success \ test_expect_success \
'6 - local addition already has the same.' \ '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-update-index --add frotz &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
git-ls-files --stage >6.out && git-ls-files --stage >6.out &&
@ -117,7 +122,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'7 - local addition already has the same.' \ '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 && echo frotz >frotz &&
git-update-index --add frotz && git-update-index --add frotz &&
echo frotz frotz >frotz && echo frotz frotz >frotz &&
@ -134,14 +140,16 @@ test_expect_success \


test_expect_success \ test_expect_success \
'8 - conflicting addition.' \ '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 && echo frotz frotz >frotz &&
git-update-index --add frotz && git-update-index --add frotz &&
if git-read-tree -m -u $treeH $treeM; then false; else :; fi' if git-read-tree -m -u $treeH $treeM; then false; else :; fi'


test_expect_success \ test_expect_success \
'9 - conflicting addition.' \ '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 && echo frotz frotz >frotz &&
git-update-index --add frotz && git-update-index --add frotz &&
echo frotz >frotz && echo frotz >frotz &&
@ -149,7 +157,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'10 - path removed.' \ '10 - path removed.' \
'rm -f .git/index && 'rm -f .git/index nitfol bozbar rezrov frotz &&
git-read-tree --reset -u $treeH &&
echo rezrov >rezrov && echo rezrov >rezrov &&
git-update-index --add rezrov && git-update-index --add rezrov &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
@ -160,7 +169,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'11 - dirty path removed.' \ '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 && echo rezrov >rezrov &&
git-update-index --add rezrov && git-update-index --add rezrov &&
echo rezrov rezrov >rezrov && echo rezrov rezrov >rezrov &&
@ -168,14 +178,16 @@ test_expect_success \


test_expect_success \ test_expect_success \
'12 - unmatching local changes being removed.' \ '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 && echo rezrov rezrov >rezrov &&
git-update-index --add rezrov && git-update-index --add rezrov &&
if git-read-tree -m -u $treeH $treeM; then false; else :; fi' if git-read-tree -m -u $treeH $treeM; then false; else :; fi'


test_expect_success \ test_expect_success \
'13 - unmatching local changes being removed.' \ '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 && echo rezrov rezrov >rezrov &&
git-update-index --add rezrov && git-update-index --add rezrov &&
echo rezrov >rezrov && echo rezrov >rezrov &&
@ -188,7 +200,8 @@ EOF


test_expect_success \ test_expect_success \
'14 - unchanged in two heads.' \ '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 && echo nitfol nitfol >nitfol &&
git-update-index --add nitfol && git-update-index --add nitfol &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
@ -207,7 +220,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'15 - unchanged in two heads.' \ '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 && echo nitfol nitfol >nitfol &&
git-update-index --add nitfol && git-update-index --add nitfol &&
echo nitfol nitfol nitfol >nitfol && echo nitfol nitfol nitfol >nitfol &&
@ -227,14 +241,16 @@ test_expect_success \


test_expect_success \ test_expect_success \
'16 - conflicting local change.' \ '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 && echo bozbar bozbar >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
if git-read-tree -m -u $treeH $treeM; then false; else :; fi' if git-read-tree -m -u $treeH $treeM; then false; else :; fi'


test_expect_success \ test_expect_success \
'17 - conflicting local change.' \ '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 && echo bozbar bozbar >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
echo bozbar bozbar bozbar >bozbar && echo bozbar bozbar bozbar >bozbar &&
@ -242,7 +258,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'18 - local change already having a good result.' \ '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 && echo gnusto >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
@ -254,7 +271,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'19 - local change already having a good result, further modified.' \ '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 && echo gnusto >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
echo gnusto gnusto >bozbar && echo gnusto gnusto >bozbar &&
@ -273,7 +291,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'20 - no local change, use new tree.' \ '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 && echo bozbar >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
git-read-tree -m -u $treeH $treeM && git-read-tree -m -u $treeH $treeM &&
@ -285,7 +304,8 @@ test_expect_success \


test_expect_success \ test_expect_success \
'21 - no local change, dirty cache.' \ '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 && echo bozbar >bozbar &&
git-update-index --add bozbar && git-update-index --add bozbar &&
echo gnusto gnusto >bozbar && echo gnusto gnusto >bozbar &&
@ -294,7 +314,7 @@ test_expect_success \
# Also make sure we did not break DF vs DF/DF case. # Also make sure we did not break DF vs DF/DF case.
test_expect_success \ test_expect_success \
'DF vs DF/DF case setup.' \ 'DF vs DF/DF case setup.' \
'rm -f .git/index && 'rm -f .git/index
echo DF >DF && echo DF >DF &&
git-update-index --add DF && git-update-index --add DF &&
treeDF=`git-write-tree` && treeDF=`git-write-tree` &&

1
t/t3500-cherry.sh

@ -30,6 +30,7 @@ test_expect_success \
git-commit -m "Add C." && git-commit -m "Add C." &&


git-checkout -f master && git-checkout -f master &&
rm -f B C &&


echo Third >> A && echo Third >> A &&
git-update-index A && git-update-index A &&

6
t/t4002-diff-basic.sh

@ -191,7 +191,7 @@ test_expect_success \
'rm -fr Z [A-Z][A-Z] && 'rm -fr Z [A-Z][A-Z] &&
git-read-tree $tree_A && git-read-tree $tree_A &&
git-checkout-index -f -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-update-index --refresh >/dev/null ;# this can exit non-zero
git-diff-files >.test-a && git-diff-files >.test-a &&
cmp_diff_files_output .test-a .test-recursive-OA' cmp_diff_files_output .test-a .test-recursive-OA'
@ -201,7 +201,7 @@ test_expect_success \
'rm -fr Z [A-Z][A-Z] && 'rm -fr Z [A-Z][A-Z] &&
git-read-tree $tree_B && git-read-tree $tree_B &&
git-checkout-index -f -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-update-index --refresh >/dev/null ;# this can exit non-zero
git-diff-files >.test-a && git-diff-files >.test-a &&
cmp_diff_files_output .test-a .test-recursive-OB' cmp_diff_files_output .test-a .test-recursive-OB'
@ -211,7 +211,7 @@ test_expect_success \
'rm -fr Z [A-Z][A-Z] && 'rm -fr Z [A-Z][A-Z] &&
git-read-tree $tree_B && git-read-tree $tree_B &&
git-checkout-index -f -a && 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-update-index --refresh >/dev/null ;# this can exit non-zero
git-diff-files >.test-a && git-diff-files >.test-a &&
cmp_diff_files_output .test-a .test-recursive-AB' cmp_diff_files_output .test-a .test-recursive-AB'

1
t/t6022-merge-rename.sh

@ -111,6 +111,7 @@ test_expect_success 'pull renaming branch into unrenaming one' \


test_expect_success 'pull renaming branch into another renaming one' \ test_expect_success 'pull renaming branch into another renaming one' \
' '
rm -f B
git reset --hard git reset --hard
git checkout red git checkout red
git pull . white && { git pull . white && {

Loading…
Cancel
Save