Skip to content

Commit f9c6eae

Browse files
Kevin Willfordmjcheetham
authored andcommitted
gvfs: prevent files to be deleted outside the sparse checkout
Prevent the sparse checkout to delete files that were marked with skip-worktree bit and are not in the sparse-checkout file. This is because everything with the skip-worktree bit turned on is being virtualized and will be removed with the change of HEAD. There was only one failing test when running with these changes that was checking to make sure the worktree narrows on checkout which was expected since we would no longer be narrowing the worktree. Update 2022-04-05: temporarily set 'sparse.expectfilesoutsideofpatterns' in test (until we start disabling the "remove present-despite-SKIP_WORKTREE" behavior with 'core.virtualfilesystem' in a later commit). Signed-off-by: Kevin Willford <kewillf@microsoft.com>
1 parent 0c59b7c commit f9c6eae

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

Documentation/config/core.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,15 @@ core.gvfs::
756756
Bit value 4
757757
Normally git write-tree ensures that the objects referenced by the
758758
directory exist in the object database. This option disables this check.
759+
GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT::
760+
Bit value 8
761+
When marking entries to remove from the index and the working
762+
directory this option will take into account what the
763+
skip-worktree bit was set to so that if the entry has the
764+
skip-worktree bit set it will not be removed from the working
765+
directory. This will allow virtualized working directories to
766+
detect the change to HEAD and use the new commit tree to show
767+
the files that are in the working directory.
759768
--
760769

761770
core.sparseCheckout::

gvfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
#define GVFS_SKIP_SHA_ON_INDEX (1 << 0)
1515
#define GVFS_MISSING_OK (1 << 2)
16+
#define GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT (1 << 3)
1617

1718
void gvfs_load_config_value(const char *value);
1819
int gvfs_config_is_set(int mask);

t/t1090-sparse-checkout-scope.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,26 @@ test_expect_success 'in partial clone, sparse checkout only fetches needed blobs
107107
test_cmp expect actual
108108
'
109109

110+
test_expect_success 'checkout does not delete items outside the sparse checkout file' '
111+
# The "sparse.expectfilesoutsideofpatterns" config will prevent the
112+
# SKIP_WORKTREE flag from being dropped on files present on-disk.
113+
test_config sparse.expectfilesoutsideofpatterns true &&
114+
115+
test_config core.gvfs 8 &&
116+
git checkout -b outside &&
117+
echo "new file1" >d &&
118+
git add --sparse d &&
119+
git commit -m "branch initial" &&
120+
echo "new file1" >e &&
121+
git add --sparse e &&
122+
git commit -m "skipped worktree" &&
123+
git update-index --skip-worktree e &&
124+
echo "/d" >.git/info/sparse-checkout &&
125+
git checkout HEAD^ &&
126+
test_path_is_file d &&
127+
test_path_is_file e
128+
'
129+
110130
test_expect_success MINGW 'no unnecessary opendir() with fscache' '
111131
git clone . fscache-test &&
112132
(

unpack-trees.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "git-compat-util.h"
44
#include "advice.h"
5+
#include "gvfs.h"
56
#include "strvec.h"
67
#include "repository.h"
78
#include "parse.h"
@@ -2685,6 +2686,27 @@ static int deleted_entry(const struct cache_entry *ce,
26852686

26862687
if (!(old->ce_flags & CE_CONFLICTED) && verify_uptodate(old, o))
26872688
return -1;
2689+
2690+
/*
2691+
* When marking entries to remove from the index and the working
2692+
* directory this option will take into account what the
2693+
* skip-worktree bit was set to so that if the entry has the
2694+
* skip-worktree bit set it will not be removed from the working
2695+
* directory. This will allow virtualized working directories to
2696+
* detect the change to HEAD and use the new commit tree to show
2697+
* the files that are in the working directory.
2698+
*
2699+
* old is the cache_entry that will have the skip-worktree bit set
2700+
* which will need to be preserved when the CE_REMOVE entry is added
2701+
*/
2702+
if (gvfs_config_is_set(GVFS_NO_DELETE_OUTSIDE_SPARSECHECKOUT) &&
2703+
old &&
2704+
old->ce_flags & CE_SKIP_WORKTREE) {
2705+
add_entry(o, old, CE_REMOVE, 0);
2706+
invalidate_ce_path(old, o);
2707+
return 1;
2708+
}
2709+
26882710
add_entry(o, ce, CE_REMOVE, 0);
26892711
invalidate_ce_path(ce, o);
26902712
return 1;

0 commit comments

Comments
 (0)