Skip to content

Commit c24d3f7

Browse files
committed
Merge branch 'sparse-index-stuff'
This is random stuff that probably all got upstream in the meantime.
2 parents c5ffb86 + e1285e2 commit c24d3f7

14 files changed

+197
-17
lines changed

Documentation/config/index.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
index.deleteSparseDirectories::
2+
When enabled, the cone mode sparse-checkout feature will delete
3+
directories that are outside of the sparse-checkout cone, unless
4+
such a directory contains an untracked, non-ignored file. Defaults
5+
to true.
6+
17
index.recordEndOfIndexEntries::
28
Specifies whether the index file should include an "End Of Index
39
Entry" section. This reduces index load time on multiprocessor

builtin/add.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include "builtin.h"
8+
#include "environment.h"
89
#include "advice.h"
910
#include "config.h"
1011
#include "lockfile.h"
@@ -45,6 +46,7 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
4546
int err;
4647

4748
if (!include_sparse &&
49+
!core_virtualfilesystem &&
4850
(ce_skip_worktree(ce) ||
4951
!path_in_sparse_checkout(ce->name, the_repository->index)))
5052
continue;
@@ -125,8 +127,9 @@ static int refresh(int verbose, const struct pathspec *pathspec)
125127
if (!seen[i]) {
126128
const char *path = pathspec->items[i].original;
127129

128-
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
129-
!path_in_sparse_checkout(path, the_repository->index)) {
130+
if (!core_virtualfilesystem &&
131+
(matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
132+
!path_in_sparse_checkout(path, the_repository->index))) {
130133
string_list_append(&only_match_skip_worktree,
131134
pathspec->items[i].original);
132135
} else {
@@ -136,7 +139,11 @@ static int refresh(int verbose, const struct pathspec *pathspec)
136139
}
137140
}
138141

139-
if (only_match_skip_worktree.nr) {
142+
/*
143+
* When using a virtual filesystem, we might re-add a path
144+
* that is currently virtual and we want that to succeed.
145+
*/
146+
if (!core_virtualfilesystem && only_match_skip_worktree.nr) {
140147
advise_on_updating_sparse_paths(&only_match_skip_worktree);
141148
ret = 1;
142149
}
@@ -512,7 +519,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
512519
if (seen[i])
513520
continue;
514521

515-
if (!include_sparse &&
522+
/*
523+
* When using a virtual filesystem, we might re-add a path
524+
* that is currently virtual and we want that to succeed.
525+
*/
526+
if (!include_sparse && !core_virtualfilesystem &&
516527
matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
517528
string_list_append(&only_match_skip_worktree,
518529
pathspec.items[i].original);
@@ -536,7 +547,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
536547
}
537548
}
538549

539-
540550
if (only_match_skip_worktree.nr) {
541551
advise_on_updating_sparse_paths(&only_match_skip_worktree);
542552
exit_status = 1;

builtin/reset.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#include "add-interactive.h"
3838
#include "strbuf.h"
3939
#include "quote.h"
40+
#include "dir.h"
41+
#include "entry.h"
4042

4143
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
4244

@@ -157,9 +159,48 @@ static void update_index_from_diff(struct diff_queue_struct *q,
157159

158160
for (i = 0; i < q->nr; i++) {
159161
int pos;
162+
int respect_skip_worktree = 1;
160163
struct diff_filespec *one = q->queue[i]->one;
164+
struct diff_filespec *two = q->queue[i]->two;
161165
int is_in_reset_tree = one->mode && !is_null_oid(&one->oid);
166+
int is_missing = !(one->mode && !is_null_oid(&one->oid));
167+
int was_missing = !two->mode && is_null_oid(&two->oid);
162168
struct cache_entry *ce;
169+
struct cache_entry *ceBefore;
170+
struct checkout state = CHECKOUT_INIT;
171+
172+
/*
173+
* When using the virtual filesystem feature, the cache entries that are
174+
* added here will not have the skip-worktree bit set.
175+
*
176+
* Without this code there is data that is lost because the files that
177+
* would normally be in the working directory are not there and show as
178+
* deleted for the next status or in the case of added files just disappear.
179+
* We need to create the previous version of the files in the working
180+
* directory so that they will have the right content and the next
181+
* status call will show modified or untracked files correctly.
182+
*/
183+
if (core_virtualfilesystem && !file_exists(two->path))
184+
{
185+
respect_skip_worktree = 0;
186+
pos = index_name_pos(the_repository->index, two->path, strlen(two->path));
187+
188+
if ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) &&
189+
(is_missing || !was_missing))
190+
{
191+
state.force = 1;
192+
state.refresh_cache = 1;
193+
state.istate = the_repository->index;
194+
ceBefore = make_cache_entry(the_repository->index, two->mode,
195+
&two->oid, two->path,
196+
0, 0);
197+
if (!ceBefore)
198+
die(_("make_cache_entry failed for path '%s'"),
199+
two->path);
200+
201+
checkout_entry(ceBefore, &state, NULL, NULL);
202+
}
203+
}
163204

164205
if (!is_in_reset_tree && !intent_to_add) {
165206
remove_file_from_index(the_repository->index, one->path);
@@ -178,8 +219,14 @@ static void update_index_from_diff(struct diff_queue_struct *q,
178219
* to properly construct the reset sparse directory.
179220
*/
180221
pos = index_name_pos(the_repository->index, one->path, strlen(one->path));
181-
if ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) ||
182-
(pos < 0 && !path_in_sparse_checkout(one->path, the_repository->index)))
222+
223+
/*
224+
* Do not add the SKIP_WORKTREE bit back if we populated the
225+
* file on purpose in a virtual filesystem scenario.
226+
*/
227+
if (respect_skip_worktree &&
228+
((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) ||
229+
(pos < 0 && !path_in_sparse_checkout(one->path, the_repository->index))))
183230
ce->ce_flags |= CE_SKIP_WORKTREE;
184231

185232
if (!ce)

builtin/rm.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#include "builtin.h"
8+
#include "environment.h"
89
#include "advice.h"
910
#include "config.h"
1011
#include "lockfile.h"
@@ -311,7 +312,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
311312
for (i = 0; i < the_repository->index->cache_nr; i++) {
312313
const struct cache_entry *ce = the_repository->index->cache[i];
313314

314-
if (!include_sparse &&
315+
if (!include_sparse && !core_virtualfilesystem &&
315316
(ce_skip_worktree(ce) ||
316317
!path_in_sparse_checkout(ce->name, the_repository->index)))
317318
continue;
@@ -348,7 +349,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
348349
*original ? original : ".");
349350
}
350351

351-
if (only_match_skip_worktree.nr) {
352+
/*
353+
* When using a virtual filesystem, we might re-add a path
354+
* that is currently virtual and we want that to succeed.
355+
*/
356+
if (!core_virtualfilesystem && only_match_skip_worktree.nr) {
352357
advise_on_updating_sparse_paths(&only_match_skip_worktree);
353358
ret = 1;
354359
}

builtin/sparse-checkout.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static int sparse_checkout_list(int argc, const char **argv, const char *prefix)
108108

109109
static void clean_tracked_sparse_directories(struct repository *r)
110110
{
111-
int i, was_full = 0;
111+
int i, value, was_full = 0;
112112
struct strbuf path = STRBUF_INIT;
113113
size_t pathlen;
114114
struct string_list_item *item;
@@ -124,6 +124,13 @@ static void clean_tracked_sparse_directories(struct repository *r)
124124
!r->index->sparse_checkout_patterns->use_cone_patterns)
125125
return;
126126

127+
/*
128+
* Users can disable this behavior.
129+
*/
130+
if (!repo_config_get_bool(r, "index.deletesparsedirectories", &value) &&
131+
!value)
132+
return;
133+
127134
/*
128135
* Use the sparse index as a data structure to assist finding
129136
* directories that are safe to delete. This conversion to a

diff.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4042,6 +4042,13 @@ static int reuse_worktree_file(struct index_state *istate,
40424042
if (!FAST_WORKING_DIRECTORY && !want_file && has_object_pack(oid))
40434043
return 0;
40444044

4045+
/*
4046+
* If this path does not match our sparse-checkout definition,
4047+
* then the file will not be in the working directory.
4048+
*/
4049+
if (!path_in_sparse_checkout(name, istate))
4050+
return 0;
4051+
40454052
/*
40464053
* Similarly, if we'd have to convert the file contents anyway, that
40474054
* makes the optimization not worthwhile.

dir.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,13 @@ static int path_in_sparse_checkout_1(const char *path,
15811581
enum pattern_match_result match = UNDECIDED;
15821582
const char *end, *slash;
15831583

1584+
/*
1585+
* When using a virtual filesystem, there aren't really patterns
1586+
* to follow, but be extra careful to skip this check.
1587+
*/
1588+
if (core_virtualfilesystem)
1589+
return 1;
1590+
15841591
/*
15851592
* We default to accepting a path if the path is empty, there are no
15861593
* patterns, or the patterns are of the wrong type.

read-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3997,7 +3997,7 @@ static void update_callback(struct diff_queue_struct *q,
39973997
struct diff_filepair *p = q->queue[i];
39983998
const char *path = p->one->path;
39993999

4000-
if (!data->include_sparse &&
4000+
if (!data->include_sparse && !core_virtualfilesystem &&
40014001
!path_in_sparse_checkout(path, data->index))
40024002
continue;
40034003

repo-settings.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ void prepare_repo_settings(struct repository *r)
9292
/* Boolean config or default, does not cascade (simple) */
9393
repo_cfg_bool(r, "pack.usesparse", &r->settings.pack_use_sparse, 1);
9494
repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1);
95-
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0);
95+
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 1);
9696
repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash);
9797
repo_cfg_bool(r, "pack.readreverseindex", &r->settings.pack_read_reverse_index, 1);
9898
repo_cfg_bool(r, "pack.usebitmapboundarytraversal",

sequencer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ static int do_recursive_merge(struct repository *r,
768768
o.branch2 = next ? next_label : "(empty tree)";
769769
if (is_rebase_i(opts))
770770
o.buffer_output = 2;
771-
o.show_rename_progress = 1;
771+
o.show_rename_progress = isatty(2);
772772

773773
head_tree = parse_tree_indirect(head);
774774
if (!head_tree)

t/perf/p2000-sparse-operations.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ test_expect_success 'setup repo and indexes' '
5656
git -c core.sparseCheckoutCone=true clone --branch=wide --sparse . full-v3 &&
5757
(
5858
cd full-v3 &&
59-
git sparse-checkout init --cone &&
59+
git sparse-checkout init --cone --no-sparse-index &&
6060
git sparse-checkout set $SPARSE_CONE &&
6161
git config index.version 3 &&
6262
git update-index --index-version=3 &&
@@ -65,7 +65,7 @@ test_expect_success 'setup repo and indexes' '
6565
git -c core.sparseCheckoutCone=true clone --branch=wide --sparse . full-v4 &&
6666
(
6767
cd full-v4 &&
68-
git sparse-checkout init --cone &&
68+
git sparse-checkout init --cone --no-sparse-index &&
6969
git sparse-checkout set $SPARSE_CONE &&
7070
git config index.version 4 &&
7171
git update-index --index-version=4 &&

t/t1091-sparse-checkout-builtin.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,10 @@ test_expect_success 'cone mode clears ignored subdirectories' '
784784
git -C repo status --porcelain=v2 >out &&
785785
test_must_be_empty out &&
786786
787+
git -C repo -c index.deleteSparseDirectories=false sparse-checkout reapply &&
788+
test_path_is_dir repo/folder1 &&
789+
test_path_is_dir repo/deep/deeper2 &&
790+
787791
git -C repo sparse-checkout reapply &&
788792
test_path_is_missing repo/folder1 &&
789793
test_path_is_missing repo/deep/deeper2 &&

0 commit comments

Comments
 (0)