Skip to content

Commit 1e3e674

Browse files
committed
Merge branch 'sparse-index-stuff'
This is random stuff that probably all got upstream in the meantime.
2 parents 0a7fb9a + 4a1c14f commit 1e3e674

15 files changed

+231
-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: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
4747
int err;
4848

4949
if (!include_sparse &&
50+
!core_virtualfilesystem &&
5051
(ce_skip_worktree(ce) ||
5152
!path_in_sparse_checkout(ce->name, &the_index)))
5253
continue;
@@ -97,7 +98,8 @@ static void update_callback(struct diff_queue_struct *q,
9798
struct diff_filepair *p = q->queue[i];
9899
const char *path = p->one->path;
99100

100-
if (!include_sparse && !path_in_sparse_checkout(path, &the_index))
101+
if (!include_sparse && !core_virtualfilesystem &&
102+
!path_in_sparse_checkout(path, &the_index))
101103
continue;
102104

103105
switch (fix_unmerged_status(p, data)) {
@@ -215,8 +217,9 @@ static int refresh(int verbose, const struct pathspec *pathspec)
215217
if (!seen[i]) {
216218
const char *path = pathspec->items[i].original;
217219

218-
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
219-
!path_in_sparse_checkout(path, &the_index)) {
220+
if (!core_virtualfilesystem &&
221+
(matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
222+
!path_in_sparse_checkout(path, &the_index))) {
220223
string_list_append(&only_match_skip_worktree,
221224
pathspec->items[i].original);
222225
} else {
@@ -226,7 +229,11 @@ static int refresh(int verbose, const struct pathspec *pathspec)
226229
}
227230
}
228231

229-
if (only_match_skip_worktree.nr) {
232+
/*
233+
* When using a virtual filesystem, we might re-add a path
234+
* that is currently virtual and we want that to succeed.
235+
*/
236+
if (!core_virtualfilesystem && only_match_skip_worktree.nr) {
230237
advise_on_updating_sparse_paths(&only_match_skip_worktree);
231238
ret = 1;
232239
}
@@ -644,7 +651,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
644651
if (seen[i])
645652
continue;
646653

647-
if (!include_sparse &&
654+
/*
655+
* When using a virtual filesystem, we might re-add a path
656+
* that is currently virtual and we want that to succeed.
657+
*/
658+
if (!include_sparse && !core_virtualfilesystem &&
648659
matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
649660
string_list_append(&only_match_skip_worktree,
650661
pathspec.items[i].original);
@@ -668,7 +679,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
668679
}
669680
}
670681

671-
672682
if (only_match_skip_worktree.nr) {
673683
advise_on_updating_sparse_paths(&only_match_skip_worktree);
674684
exit_status = 1;

builtin/gc.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,8 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
12851285
char *lock_path = xstrfmt("%s/maintenance", r->objects->odb->path);
12861286

12871287
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
1288+
struct stat st;
1289+
struct strbuf lock_dot_lock = STRBUF_INIT;
12881290
/*
12891291
* Another maintenance command is running.
12901292
*
@@ -1295,6 +1297,25 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
12951297
if (!opts->auto_flag && !opts->quiet)
12961298
warning(_("lock file '%s' exists, skipping maintenance"),
12971299
lock_path);
1300+
1301+
/*
1302+
* Check timestamp on .lock file to see if we should
1303+
* delete it to recover from a fail state.
1304+
*/
1305+
strbuf_addstr(&lock_dot_lock, lock_path);
1306+
strbuf_addstr(&lock_dot_lock, ".lock");
1307+
if (lstat(lock_dot_lock.buf, &st))
1308+
warning_errno(_("unable to stat '%s'"), lock_dot_lock.buf);
1309+
else {
1310+
if (st.st_mtime < time(NULL) - (6 * 60 * 60)) {
1311+
if (unlink(lock_dot_lock.buf))
1312+
warning_errno(_("unable to delete stale lock file"));
1313+
else
1314+
warning(_("deleted stale lock file"));
1315+
}
1316+
}
1317+
1318+
strbuf_release(&lock_dot_lock);
12981319
free(lock_path);
12991320
return 0;
13001321
}

builtin/reset.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "dir.h"
2929
#include "strbuf.h"
3030
#include "quote.h"
31+
#include "dir.h"
32+
#include "entry.h"
3133

3234
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
3335

@@ -141,9 +143,47 @@ static void update_index_from_diff(struct diff_queue_struct *q,
141143

142144
for (i = 0; i < q->nr; i++) {
143145
int pos;
146+
int respect_skip_worktree = 1;
144147
struct diff_filespec *one = q->queue[i]->one;
148+
struct diff_filespec *two = q->queue[i]->two;
145149
int is_in_reset_tree = one->mode && !is_null_oid(&one->oid);
150+
int is_missing = !(one->mode && !is_null_oid(&one->oid));
151+
int was_missing = !two->mode && is_null_oid(&two->oid);
146152
struct cache_entry *ce;
153+
struct cache_entry *ceBefore;
154+
struct checkout state = CHECKOUT_INIT;
155+
156+
/*
157+
* When using the virtual filesystem feature, the cache entries that are
158+
* added here will not have the skip-worktree bit set.
159+
*
160+
* Without this code there is data that is lost because the files that
161+
* would normally be in the working directory are not there and show as
162+
* deleted for the next status or in the case of added files just disappear.
163+
* We need to create the previous version of the files in the working
164+
* directory so that they will have the right content and the next
165+
* status call will show modified or untracked files correctly.
166+
*/
167+
if (core_virtualfilesystem && !file_exists(two->path))
168+
{
169+
pos = cache_name_pos(two->path, strlen(two->path));
170+
if ((pos >= 0 && ce_skip_worktree(active_cache[pos])) &&
171+
(is_missing || !was_missing))
172+
{
173+
state.force = 1;
174+
state.refresh_cache = 1;
175+
state.istate = &the_index;
176+
ceBefore = make_cache_entry(&the_index, two->mode,
177+
&two->oid, two->path,
178+
0, 0);
179+
if (!ceBefore)
180+
die(_("make_cache_entry failed for path '%s'"),
181+
two->path);
182+
183+
checkout_entry(ceBefore, &state, NULL, NULL);
184+
respect_skip_worktree = 0;
185+
}
186+
}
147187

148188
if (!is_in_reset_tree && !intent_to_add) {
149189
remove_file_from_cache(one->path);
@@ -162,8 +202,14 @@ static void update_index_from_diff(struct diff_queue_struct *q,
162202
* to properly construct the reset sparse directory.
163203
*/
164204
pos = cache_name_pos(one->path, strlen(one->path));
165-
if ((pos >= 0 && ce_skip_worktree(active_cache[pos])) ||
166-
(pos < 0 && !path_in_sparse_checkout(one->path, &the_index)))
205+
206+
/*
207+
* Do not add the SKIP_WORKTREE bit back if we populated the
208+
* file on purpose in a virtual filesystem scenario.
209+
*/
210+
if (respect_skip_worktree &&
211+
((pos >= 0 && ce_skip_worktree(active_cache[pos])) ||
212+
(pos < 0 && !path_in_sparse_checkout(one->path, &the_index))))
167213
ce->ce_flags |= CE_SKIP_WORKTREE;
168214

169215
if (!ce)

builtin/rm.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
304304
for (i = 0; i < active_nr; i++) {
305305
const struct cache_entry *ce = active_cache[i];
306306

307-
if (!include_sparse &&
307+
if (!include_sparse && !core_virtualfilesystem &&
308308
(ce_skip_worktree(ce) ||
309309
!path_in_sparse_checkout(ce->name, &the_index)))
310310
continue;
@@ -341,7 +341,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
341341
*original ? original : ".");
342342
}
343343

344-
if (only_match_skip_worktree.nr) {
344+
/*
345+
* When using a virtual filesystem, we might re-add a path
346+
* that is currently virtual and we want that to succeed.
347+
*/
348+
if (!core_virtualfilesystem && only_match_skip_worktree.nr) {
345349
advise_on_updating_sparse_paths(&only_match_skip_worktree);
346350
ret = 1;
347351
}

builtin/sparse-checkout.c

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

107107
static void clean_tracked_sparse_directories(struct repository *r)
108108
{
109-
int i, was_full = 0;
109+
int i, value, was_full = 0;
110110
struct strbuf path = STRBUF_INIT;
111111
size_t pathlen;
112112
struct string_list_item *item;
@@ -122,6 +122,13 @@ static void clean_tracked_sparse_directories(struct repository *r)
122122
!r->index->sparse_checkout_patterns->use_cone_patterns)
123123
return;
124124

125+
/*
126+
* Users can disable this behavior.
127+
*/
128+
if (!repo_config_get_bool(r, "index.deletesparsedirectories", &value) &&
129+
!value)
130+
return;
131+
125132
/*
126133
* Use the sparse index as a data structure to assist finding
127134
* 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
@@ -3922,6 +3922,13 @@ static int reuse_worktree_file(struct index_state *istate,
39223922
if (!FAST_WORKING_DIRECTORY && !want_file && has_object_pack(oid))
39233923
return 0;
39243924

3925+
/*
3926+
* If this path does not match our sparse-checkout definition,
3927+
* then the file will not be in the working directory.
3928+
*/
3929+
if (!path_in_sparse_checkout(name, istate))
3930+
return 0;
3931+
39253932
/*
39263933
* Similarly, if we'd have to convert the file contents anyway, that
39273934
* makes the optimization not worthwhile.

dir.c

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

1518+
/*
1519+
* When using a virtual filesystem, there aren't really patterns
1520+
* to follow, but be extra careful to skip this check.
1521+
*/
1522+
if (core_virtualfilesystem)
1523+
return 1;
1524+
15181525
/*
15191526
* We default to accepting a path if the path is empty, there are no
15201527
* patterns, or the patterns are of the wrong type.

repo-settings.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void prepare_repo_settings(struct repository *r)
8484
/* Boolean config or default, does not cascade (simple) */
8585
repo_cfg_bool(r, "pack.usesparse", &r->settings.pack_use_sparse, 1);
8686
repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1);
87-
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0);
87+
repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 1);
8888

8989
/*
9090
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that

sequencer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ static int do_recursive_merge(struct repository *r,
683683
o.branch2 = next ? next_label : "(empty tree)";
684684
if (is_rebase_i(opts))
685685
o.buffer_output = 2;
686-
o.show_rename_progress = 1;
686+
o.show_rename_progress = isatty(2);
687687

688688
head_tree = parse_tree_indirect(head);
689689
next_tree = next ? get_commit_tree(next) : empty_tree(r);

0 commit comments

Comments
 (0)