Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Sparse Index] Integrate with git status #374

Merged
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2a4a725
sparse-index: skip indexes with unmerged entries
derrickstolee Apr 29, 2021
f5bae86
sparse-index: include EXTENDED flag when expanding
derrickstolee May 4, 2021
d965669
t1092: replace incorrect 'echo' with 'cat'
derrickstolee May 26, 2021
44a9402
t1092: expand repository data shape
derrickstolee May 14, 2021
701ac0e
t1092: add tests for status/add and sparse files
derrickstolee Apr 12, 2021
587333f
unpack-trees: preserve cache_bottom
derrickstolee Apr 21, 2021
6fc898a
unpack-trees: compare sparse directories correctly
derrickstolee Apr 21, 2021
b676ef4
unpack-trees: unpack sparse directory entries
derrickstolee May 27, 2021
d693f00
dir.c: accept a directory as part of cone-mode patterns
derrickstolee Jan 11, 2021
ed11cfc
diff-lib: handle index diffs with sparse dirs
derrickstolee Jun 1, 2021
48fd25a
status: skip sparse-checkout percentage with sparse-index
derrickstolee Jan 15, 2021
3499105
status: use sparse-index throughout
derrickstolee Jan 8, 2021
60a6706
wt-status: expand added sparse directory entries
derrickstolee May 4, 2021
76bd8ec
fsmonitor: integrate with sparse index
derrickstolee Jan 15, 2021
a1a570a
Merge sparse-aware 'git status' into vfs-2.32.0
derrickstolee Jun 15, 2021
093a832
t1092: cleanups
derrickstolee Jun 17, 2021
722e7cd
fixup! unpack-trees: unpack sparse directory entries
derrickstolee Jun 17, 2021
9edbebf
fixup! unpack-trees: unpack sparse directory entries
derrickstolee Jun 17, 2021
0fda21d
fixup! t1092: expand repository data shape
derrickstolee Jun 17, 2021
610518c
fixup! unpack-trees: unpack sparse directory entries
derrickstolee Jun 17, 2021
320586f
fixup! dir.c: accept a directory as part of cone-mode patterns
derrickstolee Jun 17, 2021
ddaebb7
fixup! wt-status: expand added sparse directory entries
derrickstolee Jun 17, 2021
44bfb50
fixup! sparse-index: implement ensure_full_index()
derrickstolee Jun 17, 2021
0c20b94
fixup! fsmonitor: integrate with sparse index
derrickstolee Jun 17, 2021
f462956
fixup! fixup! t1092: expand repository data shape
derrickstolee Jun 18, 2021
87a3a29
fixup! wt-status: expand added sparse directory entries
derrickstolee Jun 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 96 additions & 14 deletions unpack-trees.c
Original file line number Diff line number Diff line change
Expand Up @@ -1051,13 +1051,15 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
const struct name_entry *n,
int stage,
struct index_state *istate,
int is_transient)
int is_transient,
int is_sparse_directory)
{
size_t len = traverse_path_len(info, tree_entry_len(n));
size_t alloc_len = is_sparse_directory ? len + 1 : len;
struct cache_entry *ce =
is_transient ?
make_empty_transient_cache_entry(len, NULL) :
make_empty_cache_entry(istate, len);
make_empty_transient_cache_entry(alloc_len, NULL) :
make_empty_cache_entry(istate, alloc_len);

ce->ce_mode = create_ce_mode(n->mode);
ce->ce_flags = create_ce_flags(stage);
Expand All @@ -1066,6 +1068,13 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
/* len+1 because the cache_entry allocates space for NUL */
derrickstolee marked this conversation as resolved.
Show resolved Hide resolved
make_traverse_path(ce->name, len + 1, info, n->path, n->pathlen);

if (is_sparse_directory) {
ce->name[len] = '/';
ce->name[len + 1] = '\0';
ce->ce_namelen++;
ce->ce_flags |= CE_SKIP_WORKTREE;
}

return ce;
}

Expand All @@ -1074,20 +1083,28 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
* without actually calling it. If you change the logic here you may need to
* check and change there as well.
*/
static int unpack_nondirectories(int n, unsigned long mask,
unsigned long dirmask,
struct cache_entry **src,
const struct name_entry *names,
const struct traverse_info *info)
static int unpack_single_entry(int n, unsigned long mask,
unsigned long dirmask,
struct cache_entry **src,
const struct name_entry *names,
const struct traverse_info *info,
int sparse_directory)
derrickstolee marked this conversation as resolved.
Show resolved Hide resolved
{
int i;
struct unpack_trees_options *o = info->data;
unsigned long conflicts = info->df_conflicts | dirmask;

/* Do we have *only* directories? Nothing to do */
if (mask == dirmask && !src[0])
return 0;

/* defer work if our cache entry doesn't match the expectations. */
if (sparse_directory) {
if (src[0] && !S_ISSPARSEDIR(src[0]->ce_mode))
BUG("expected sparse directory entry");
} else if (src[0] && S_ISSPARSEDIR(src[0]->ce_mode)) {
return 0;
}

derrickstolee marked this conversation as resolved.
Show resolved Hide resolved
/*
* Ok, we've filled in up to any potential index entry in src[0],
* now do the rest.
Expand Down Expand Up @@ -1117,7 +1134,9 @@ static int unpack_nondirectories(int n, unsigned long mask,
* not stored in the index. otherwise construct the
* cache entry from the index aware logic.
*/
src[i + o->merge] = create_ce_entry(info, names + i, stage, &o->result, o->merge);
src[i + o->merge] = create_ce_entry(info, names + i, stage,
&o->result, o->merge,
sparse_directory);
}

if (o->merge) {
Expand Down Expand Up @@ -1221,16 +1240,59 @@ static int find_cache_pos(struct traverse_info *info,
return -1;
}

/*
* Given a sparse directory entry 'ce', compare ce->name to
* info->name + '/' + p->path + '/' if info->name is non-empty.
* Compare ce->name to p->path + '/' otherwise. Note that
* ce->name must end in a trailing '/' because it is a sparse
* directory entry.
*/
static int sparse_dir_matches_path(const struct cache_entry *ce,
struct traverse_info *info,
const struct name_entry *p)
{
assert(S_ISSPARSEDIR(ce->ce_mode));
assert(ce->name[ce->ce_namelen - 1] == '/');
derrickstolee marked this conversation as resolved.
Show resolved Hide resolved

if (info->namelen)
return ce->ce_namelen == info->namelen + p->pathlen + 2 &&
ce->name[info->namelen] == '/' &&
!strncmp(ce->name, info->name, info->namelen) &&
derrickstolee marked this conversation as resolved.
Show resolved Hide resolved
!strncmp(ce->name + info->namelen + 1, p->path, p->pathlen);
return ce->ce_namelen == p->pathlen + 1 &&
!strncmp(ce->name, p->path, p->pathlen);
}

static struct cache_entry *find_cache_entry(struct traverse_info *info,
const struct name_entry *p)
{
struct cache_entry *ce;
int pos = find_cache_pos(info, p->path, p->pathlen);
struct unpack_trees_options *o = info->data;

if (0 <= pos)
return o->src_index->cache[pos];
else

/*
* Check for a sparse-directory entry named "path/".
* Due to the input p->path not having a trailing
* slash, the negative 'pos' value overshoots the
* expected position by one, hence "-2" here.
*/
derrickstolee marked this conversation as resolved.
Show resolved Hide resolved
pos = -pos - 2;

if (pos < 0 || pos >= o->src_index->cache_nr)
return NULL;

ce = o->src_index->cache[pos];

if (!S_ISSPARSEDIR(ce->ce_mode))
return NULL;

if (sparse_dir_matches_path(ce, info, p))
return ce;

return NULL;
}

static void debug_path(struct traverse_info *info)
Expand Down Expand Up @@ -1265,6 +1327,21 @@ static void debug_unpack_callback(int n,
debug_name_entry(i, names + i);
}

/*
* Returns true if and only if the given cache_entry is a
* sparse-directory entry that matches the given name_entry
* from the tree walk at the given traverse_info.
*/
static int is_sparse_directory_entry(struct cache_entry *ce,
struct name_entry *name,
struct traverse_info *info)
{
if (!ce || !name || !S_ISSPARSEDIR(ce->ce_mode))
return 0;

return sparse_dir_matches_path(ce, info, name);
}

/*
* Note that traverse_by_cache_tree() duplicates some logic in this function
* without actually calling it. If you change the logic here you may need to
Expand Down Expand Up @@ -1321,7 +1398,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
}
}

if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0)
if (unpack_single_entry(n, mask, dirmask, src, names, info, 0) < 0)
return -1;

if (o->merge && src[0]) {
Expand Down Expand Up @@ -1351,9 +1428,14 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
}
}

if (traverse_trees_recursive(n, dirmask, mask & ~dirmask,
names, info) < 0)
if (is_sparse_directory_entry(src[0], names, info)) {
if (unpack_single_entry(n, dirmask, mask & ~dirmask, src, names, info, 1) < 0)
return -1;
} else if (traverse_trees_recursive(n, dirmask, mask & ~dirmask,
names, info) < 0) {
return -1;
}

return mask;
}

Expand Down