зеркало из https://github.com/microsoft/git.git
Merge 'sparse-checkout-fixes' into HEAD
This commit is contained in:
Коммит
49e748e582
18
apply.c
18
apply.c
|
@ -3343,6 +3343,24 @@ static int checkout_target(struct index_state *istate,
|
|||
{
|
||||
struct checkout costate = CHECKOUT_INIT;
|
||||
|
||||
/*
|
||||
* Do not checkout the entry if the skipworktree bit is set
|
||||
*
|
||||
* Both callers of this method (check_preimage and load_current)
|
||||
* check for the existance of the file before calling this
|
||||
* method so we know that the file doesn't exist at this point
|
||||
* and we don't need to perform that check again here.
|
||||
* We just need to check the skip-worktree and return.
|
||||
*
|
||||
* This is to prevent git from creating a file in the
|
||||
* working directory that has the skip-worktree bit on,
|
||||
* then updating the index from the patch and not keeping
|
||||
* the working directory version up to date with what it
|
||||
* changed the index version to be.
|
||||
*/
|
||||
if (ce_skip_worktree(ce))
|
||||
return 0;
|
||||
|
||||
costate.refresh_cache = 1;
|
||||
costate.istate = istate;
|
||||
if (checkout_entry(ce, &costate, NULL, NULL) ||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "submodule-config.h"
|
||||
#include "strbuf.h"
|
||||
#include "quote.h"
|
||||
#include "dir.h"
|
||||
|
||||
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
|
||||
|
||||
|
@ -128,12 +129,45 @@ static void update_index_from_diff(struct diff_queue_struct *q,
|
|||
struct diff_options *opt, void *data)
|
||||
{
|
||||
int i;
|
||||
int pos;
|
||||
int intent_to_add = *(int *)data;
|
||||
|
||||
for (i = 0; i < q->nr; i++) {
|
||||
struct diff_filespec *one = q->queue[i]->one;
|
||||
struct diff_filespec *two = q->queue[i]->two;
|
||||
int is_missing = !(one->mode && !is_null_oid(&one->oid));
|
||||
int was_missing = !two->mode && is_null_oid(&two->oid);
|
||||
struct cache_entry *ce;
|
||||
struct cache_entry *ceBefore;
|
||||
struct checkout state = CHECKOUT_INIT;
|
||||
|
||||
/*
|
||||
* When using the sparse-checkout feature the cache entries that are
|
||||
* added here will not have the skip-worktree bit set.
|
||||
* Without this code there is data that is lost because the files that
|
||||
* would normally be in the working directory are not there and show as
|
||||
* deleted for the next status or in the case of added files just disappear.
|
||||
* We need to create the previous version of the files in the working
|
||||
* directory so that they will have the right content and the next
|
||||
* status call will show modified or untracked files correctly.
|
||||
*/
|
||||
if (core_apply_sparse_checkout && !file_exists(two->path))
|
||||
{
|
||||
pos = cache_name_pos(two->path, strlen(two->path));
|
||||
if ((pos >= 0 && ce_skip_worktree(active_cache[pos])) && (is_missing || !was_missing))
|
||||
{
|
||||
state.force = 1;
|
||||
state.refresh_cache = 1;
|
||||
state.istate = &the_index;
|
||||
ceBefore = make_cache_entry(&the_index, two->mode, &two->oid, two->path,
|
||||
0, 0);
|
||||
if (!ceBefore)
|
||||
die(_("make_cache_entry failed for path '%s'"),
|
||||
two->path);
|
||||
|
||||
checkout_entry(ceBefore, &state, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_missing && !intent_to_add) {
|
||||
remove_file_from_cache(one->path);
|
||||
|
|
|
@ -1485,7 +1485,7 @@ static int handle_change_delete(struct merge_options *opt,
|
|||
* path. We could call update_file_flags() with update_cache=0
|
||||
* and update_wd=0, but that's a no-op.
|
||||
*/
|
||||
if (change_branch != opt->branch1 || alt_path)
|
||||
if (change_branch != opt->branch1 || alt_path || !file_exists(update_path))
|
||||
ret = update_file(opt, 0, changed, update_path);
|
||||
}
|
||||
free(alt_path);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='reset when using a sparse-checkout'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
# reset using a sparse-checkout file
|
||||
|
||||
test_expect_success 'setup' '
|
||||
test_tick &&
|
||||
echo "checkout file" >c &&
|
||||
echo "modify file" >m &&
|
||||
echo "delete file" >d &&
|
||||
git add . &&
|
||||
git commit -m "initial commit" &&
|
||||
echo "added file" >a &&
|
||||
echo "modification of a file" >m &&
|
||||
git rm d &&
|
||||
git add . &&
|
||||
git commit -m "second commit" &&
|
||||
git checkout -b endCommit
|
||||
'
|
||||
|
||||
test_expect_success 'reset when there is a sparse-checkout' '
|
||||
echo "/c" >.git/info/sparse-checkout &&
|
||||
test_config core.sparsecheckout true &&
|
||||
git checkout -b resetBranch &&
|
||||
test_path_is_missing m &&
|
||||
test_path_is_missing a &&
|
||||
test_path_is_missing d &&
|
||||
git reset HEAD~1 &&
|
||||
test "checkout file" = "$(cat c)" &&
|
||||
test "modification of a file" = "$(cat m)" &&
|
||||
test "added file" = "$(cat a)" &&
|
||||
test_path_is_missing d
|
||||
'
|
||||
|
||||
test_expect_success 'reset after deleting file without skip-worktree bit' '
|
||||
git checkout -f endCommit &&
|
||||
git clean -xdf &&
|
||||
echo "/c
|
||||
/m" >.git/info/sparse-checkout &&
|
||||
test_config core.sparsecheckout true &&
|
||||
git checkout -b resetAfterDelete &&
|
||||
test_path_is_file m &&
|
||||
test_path_is_missing a &&
|
||||
test_path_is_missing d &&
|
||||
rm -f m &&
|
||||
git reset HEAD~1 &&
|
||||
test "checkout file" = "$(cat c)" &&
|
||||
test "added file" = "$(cat a)" &&
|
||||
test_path_is_missing m &&
|
||||
test_path_is_missing d
|
||||
'
|
||||
|
||||
|
||||
|
||||
test_done
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='merge can handle sparse-checkout'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
# merges with conflicts
|
||||
|
||||
test_expect_success 'setup' '
|
||||
test_commit a &&
|
||||
test_commit file &&
|
||||
git checkout -b delete-file &&
|
||||
git rm file.t &&
|
||||
test_tick &&
|
||||
git commit -m "remove file" &&
|
||||
git checkout master &&
|
||||
test_commit modify file.t changed
|
||||
'
|
||||
|
||||
test_expect_success 'merge conflict deleted file and modified' '
|
||||
echo "/a.t" >.git/info/sparse-checkout &&
|
||||
test_config core.sparsecheckout true &&
|
||||
git checkout -f &&
|
||||
test_path_is_missing file.t &&
|
||||
test_must_fail git merge delete-file &&
|
||||
test_path_is_file file.t &&
|
||||
test "changed" = "$(cat file.t)"
|
||||
'
|
||||
|
||||
test_done
|
|
@ -506,7 +506,9 @@ static int apply_sparse_checkout(struct index_state *istate,
|
|||
*/
|
||||
if (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))
|
||||
return -1;
|
||||
ce->ce_flags |= CE_WT_REMOVE;
|
||||
if (!gvfs_config_is_set(GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT))
|
||||
ce->ce_flags |= CE_WT_REMOVE;
|
||||
|
||||
ce->ce_flags &= ~CE_UPDATE;
|
||||
}
|
||||
if (was_skip_worktree && !ce_skip_worktree(ce)) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче