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.
This commit is contained in:
commit
22b49b7fb9
47
read-tree.c
47
read-tree.c
@ -411,7 +411,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)) {
|
||||
@ -435,6 +435,21 @@ static void invalidate_ce_path(struct cache_entry *ce)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
verify_absent(merge->name, "overwritten");
|
||||
invalidate_ce_path(merge);
|
||||
}
|
||||
|
||||
merge->ce_flags &= ~htons(CE_STAGEMASK);
|
||||
add_cache_entry(merge, ADD_CACHE_OK_TO_ADD);
|
||||
return 1;
|
||||
@ -464,6 +482,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);
|
||||
invalidate_ce_path(ce);
|
||||
@ -500,6 +520,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;
|
||||
@ -511,8 +532,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];
|
||||
@ -528,8 +552,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++) {
|
||||
@ -588,6 +619,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;
|
||||
}
|
||||
/*
|
||||
@ -605,6 +638,8 @@ static int threeway_merge(struct cache_entry **stages)
|
||||
if (index) {
|
||||
verify_uptodate(index);
|
||||
}
|
||||
else if (path)
|
||||
verify_absent(path, "overwritten");
|
||||
|
||||
nontrivial_merge = 1;
|
||||
|
||||
@ -725,7 +760,7 @@ static int oneway_merge(struct cache_entry **src)
|
||||
|
||||
if (!a) {
|
||||
invalidate_ce_path(old);
|
||||
return deleted_entry(old, NULL);
|
||||
return deleted_entry(old, old);
|
||||
}
|
||||
if (old && same(old, a)) {
|
||||
if (reset) {
|
||||
@ -736,7 +771,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)
|
||||
|
@ -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` &&
|
||||
|
@ -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 &&
|
||||
|
@ -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'
|
||||
|
@ -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 && {
|
||||
|
Loading…
Reference in New Issue
Block a user