Skip to content

Commit 48254d4

Browse files
committed
Merge branch 'sparse-index-stuff'
This is random stuff that probably all got upstream in the meantime.
2 parents 53d8dbf + e66f547 commit 48254d4

16 files changed

+232
-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
#define USE_THE_INDEX_VARIABLE
77
#include "builtin.h"
8+
#include "environment.h"
89
#include "advice.h"
910
#include "config.h"
1011
#include "lockfile.h"
@@ -48,6 +49,7 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
4849
int err;
4950

5051
if (!include_sparse &&
52+
!core_virtualfilesystem &&
5153
(ce_skip_worktree(ce) ||
5254
!path_in_sparse_checkout(ce->name, &the_index)))
5355
continue;
@@ -128,8 +130,9 @@ static int refresh(int verbose, const struct pathspec *pathspec)
128130
if (!seen[i]) {
129131
const char *path = pathspec->items[i].original;
130132

131-
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
132-
!path_in_sparse_checkout(path, &the_index)) {
133+
if (!core_virtualfilesystem &&
134+
(matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
135+
!path_in_sparse_checkout(path, &the_index))) {
133136
string_list_append(&only_match_skip_worktree,
134137
pathspec->items[i].original);
135138
} else {
@@ -139,7 +142,11 @@ static int refresh(int verbose, const struct pathspec *pathspec)
139142
}
140143
}
141144

142-
if (only_match_skip_worktree.nr) {
145+
/*
146+
* When using a virtual filesystem, we might re-add a path
147+
* that is currently virtual and we want that to succeed.
148+
*/
149+
if (!core_virtualfilesystem && only_match_skip_worktree.nr) {
143150
advise_on_updating_sparse_paths(&only_match_skip_worktree);
144151
ret = 1;
145152
}
@@ -517,7 +524,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
517524
if (seen[i])
518525
continue;
519526

520-
if (!include_sparse &&
527+
/*
528+
* When using a virtual filesystem, we might re-add a path
529+
* that is currently virtual and we want that to succeed.
530+
*/
531+
if (!include_sparse && !core_virtualfilesystem &&
521532
matches_skip_worktree(&pathspec, i, &skip_worktree_seen)) {
522533
string_list_append(&only_match_skip_worktree,
523534
pathspec.items[i].original);
@@ -541,7 +552,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
541552
}
542553
}
543554

544-
545555
if (only_match_skip_worktree.nr) {
546556
advise_on_updating_sparse_paths(&only_match_skip_worktree);
547557
exit_status = 1;

builtin/gc.c

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

13111311
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
1312+
struct stat st;
1313+
struct strbuf lock_dot_lock = STRBUF_INIT;
13121314
/*
13131315
* Another maintenance command is running.
13141316
*
@@ -1319,6 +1321,25 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
13191321
if (!opts->auto_flag && !opts->quiet)
13201322
warning(_("lock file '%s' exists, skipping maintenance"),
13211323
lock_path);
1324+
1325+
/*
1326+
* Check timestamp on .lock file to see if we should
1327+
* delete it to recover from a fail state.
1328+
*/
1329+
strbuf_addstr(&lock_dot_lock, lock_path);
1330+
strbuf_addstr(&lock_dot_lock, ".lock");
1331+
if (lstat(lock_dot_lock.buf, &st))
1332+
warning_errno(_("unable to stat '%s'"), lock_dot_lock.buf);
1333+
else {
1334+
if (st.st_mtime < time(NULL) - (6 * 60 * 60)) {
1335+
if (unlink(lock_dot_lock.buf))
1336+
warning_errno(_("unable to delete stale lock file"));
1337+
else
1338+
warning(_("deleted stale lock file"));
1339+
}
1340+
}
1341+
1342+
strbuf_release(&lock_dot_lock);
13221343
free(lock_path);
13231344
return 0;
13241345
}

builtin/reset.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include "add-interactive.h"
4141
#include "strbuf.h"
4242
#include "quote.h"
43+
#include "dir.h"
44+
#include "entry.h"
4345

4446
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
4547

@@ -156,9 +158,47 @@ static void update_index_from_diff(struct diff_queue_struct *q,
156158

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

163203
if (!is_in_reset_tree && !intent_to_add) {
164204
remove_file_from_index(&the_index, one->path);
@@ -177,8 +217,14 @@ static void update_index_from_diff(struct diff_queue_struct *q,
177217
* to properly construct the reset sparse directory.
178218
*/
179219
pos = index_name_pos(&the_index, one->path, strlen(one->path));
180-
if ((pos >= 0 && ce_skip_worktree(the_index.cache[pos])) ||
181-
(pos < 0 && !path_in_sparse_checkout(one->path, &the_index)))
220+
221+
/*
222+
* Do not add the SKIP_WORKTREE bit back if we populated the
223+
* file on purpose in a virtual filesystem scenario.
224+
*/
225+
if (respect_skip_worktree &&
226+
((pos >= 0 && ce_skip_worktree(the_index.cache[pos])) ||
227+
(pos < 0 && !path_in_sparse_checkout(one->path, &the_index))))
182228
ce->ce_flags |= CE_SKIP_WORKTREE;
183229

184230
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
#define USE_THE_INDEX_VARIABLE
77
#include "builtin.h"
8+
#include "environment.h"
89
#include "advice.h"
910
#include "config.h"
1011
#include "lockfile.h"
@@ -312,7 +313,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
312313
for (i = 0; i < the_index.cache_nr; i++) {
313314
const struct cache_entry *ce = the_index.cache[i];
314315

315-
if (!include_sparse &&
316+
if (!include_sparse && !core_virtualfilesystem &&
316317
(ce_skip_worktree(ce) ||
317318
!path_in_sparse_checkout(ce->name, &the_index)))
318319
continue;
@@ -349,7 +350,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
349350
*original ? original : ".");
350351
}
351352

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

builtin/sparse-checkout.c

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

112112
static void clean_tracked_sparse_directories(struct repository *r)
113113
{
114-
int i, was_full = 0;
114+
int i, value, was_full = 0;
115115
struct strbuf path = STRBUF_INIT;
116116
size_t pathlen;
117117
struct string_list_item *item;
@@ -127,6 +127,13 @@ static void clean_tracked_sparse_directories(struct repository *r)
127127
!r->index->sparse_checkout_patterns->use_cone_patterns)
128128
return;
129129

130+
/*
131+
* Users can disable this behavior.
132+
*/
133+
if (!repo_config_get_bool(r, "index.deletesparsedirectories", &value) &&
134+
!value)
135+
return;
136+
130137
/*
131138
* Use the sparse index as a data structure to assist finding
132139
* 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
@@ -3994,6 +3994,13 @@ static int reuse_worktree_file(struct index_state *istate,
39943994
if (!FAST_WORKING_DIRECTORY && !want_file && has_object_pack(oid))
39953995
return 0;
39963996

3997+
/*
3998+
* If this path does not match our sparse-checkout definition,
3999+
* then the file will not be in the working directory.
4000+
*/
4001+
if (!path_in_sparse_checkout(name, istate))
4002+
return 0;
4003+
39974004
/*
39984005
* Similarly, if we'd have to convert the file contents anyway, that
39994006
* makes the optimization not worthwhile.

dir.c

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

1536+
/*
1537+
* When using a virtual filesystem, there aren't really patterns
1538+
* to follow, but be extra careful to skip this check.
1539+
*/
1540+
if (core_virtualfilesystem)
1541+
return 1;
1542+
15361543
/*
15371544
* We default to accepting a path if the path is empty, there are no
15381545
* 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
@@ -3943,7 +3943,7 @@ static void update_callback(struct diff_queue_struct *q,
39433943
struct diff_filepair *p = q->queue[i];
39443944
const char *path = p->one->path;
39453945

3946-
if (!data->include_sparse &&
3946+
if (!data->include_sparse && !core_virtualfilesystem &&
39473947
!path_in_sparse_checkout(path, data->index))
39483948
continue;
39493949

repo-settings.c

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

0 commit comments

Comments
 (0)