Skip to content

Commit

Permalink
sparse-checkout: create helper methods
Browse files Browse the repository at this point in the history
As we integrate the sparse index into more builtins, we occasionally
need to check the sparse-checkout patterns to see if a path is within
the sparse-checkout cone. Create some helper methods that help
initialize the patterns and check for pattern matching to make this
easier.

The existing callers of commands like get_sparse_checkout_patterns() use
a custom 'struct pattern_list' that is not necessarily the one in the
'struct index_state', so there are not many previous uses that could
adopt these helpers. There are just two in builtin/add.c and
sparse-index.c that can use path_in_sparse_checkout().

We add a path_in_cone_mode_sparse_checkout() as well that will only
return false if the path is outside of the sparse-checkout definition
_and_ the sparse-checkout patterns are in cone mode.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
  • Loading branch information
derrickstolee committed Aug 24, 2021
1 parent e7cdaa0 commit 347410c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 15 deletions.
7 changes: 1 addition & 6 deletions builtin/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,21 +190,16 @@ static int refresh(int verbose, const struct pathspec *pathspec)
struct string_list only_match_skip_worktree = STRING_LIST_INIT_NODUP;
int flags = REFRESH_IGNORE_SKIP_WORKTREE |
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
struct pattern_list pl = { 0 };
int sparse_checkout_enabled = !get_sparse_checkout_patterns(&pl);

seen = xcalloc(pathspec->nr, 1);
refresh_index(&the_index, flags, pathspec, seen,
_("Unstaged changes after refreshing the index:"));
for (i = 0; i < pathspec->nr; i++) {
if (!seen[i]) {
const char *path = pathspec->items[i].original;
int dtype = DT_REG;

if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
(sparse_checkout_enabled &&
!path_matches_pattern_list(path, strlen(path), NULL,
&dtype, &pl, &the_index))) {
!path_in_sparse_checkout(path, &the_index)) {
string_list_append(&only_match_skip_worktree,
pathspec->items[i].original);
} else {
Expand Down
54 changes: 54 additions & 0 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,60 @@ enum pattern_match_result path_matches_pattern_list(
return result;
}

int init_sparse_checkout_patterns(struct index_state *istate)
{
if (!core_apply_sparse_checkout ||
istate->sparse_checkout_patterns)
return 0;

CALLOC_ARRAY(istate->sparse_checkout_patterns, 1);

if (get_sparse_checkout_patterns(istate->sparse_checkout_patterns) < 0) {
FREE_AND_NULL(istate->sparse_checkout_patterns);
return -1;
}

return 0;
}

static int path_in_sparse_checkout_1(const char *path,
struct index_state *istate,
int require_cone_mode)
{
const char *base;
int dtype = DT_REG;
init_sparse_checkout_patterns(istate);

/*
* We default to accepting a path if there are no patterns or
* they are of the wrong type.
*/
if (!istate->sparse_checkout_patterns ||
(require_cone_mode &&
!istate->sparse_checkout_patterns->use_cone_patterns))
return 1;



base = strrchr(path, '/');
return path_matches_pattern_list(path, strlen(path), base ? base + 1 : path,
&dtype,
istate->sparse_checkout_patterns,
istate) > 0;
}

int path_in_sparse_checkout(const char *path,
struct index_state *istate)
{
return path_in_sparse_checkout_1(path, istate, 0);
}

int path_in_cone_modesparse_checkout(const char *path,
struct index_state *istate)
{
return path_in_sparse_checkout_1(path, istate, 1);
}

static struct path_pattern *last_matching_pattern_from_lists(
struct dir_struct *dir, struct index_state *istate,
const char *pathname, int pathlen,
Expand Down
8 changes: 8 additions & 0 deletions dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,14 @@ enum pattern_match_result path_matches_pattern_list(const char *pathname,
const char *basename, int *dtype,
struct pattern_list *pl,
struct index_state *istate);

int init_sparse_checkout_patterns(struct index_state *state);

int path_in_sparse_checkout(const char *path,
struct index_state *istate);
int path_in_cone_modesparse_checkout(const char *path,
struct index_state *istate);

struct dir_entry *dir_add_ignored(struct dir_struct *dir,
struct index_state *istate,
const char *pathname, int len);
Expand Down
12 changes: 3 additions & 9 deletions sparse-index.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,14 @@ static int convert_to_sparse_rec(struct index_state *istate,
int i, can_convert = 1;
int start_converted = num_converted;
enum pattern_match_result match;
int dtype = DT_UNKNOWN;
struct strbuf child_path = STRBUF_INIT;
struct pattern_list *pl = istate->sparse_checkout_patterns;

/*
* Is the current path outside of the sparse cone?
* Then check if the region can be replaced by a sparse
* directory entry (everything is sparse and merged).
*/
match = path_matches_pattern_list(ct_path, ct_pathlen,
NULL, &dtype, pl, istate);
match = path_in_sparse_checkout(ct_path, istate);
if (match != NOT_MATCHED)
can_convert = 0;

Expand Down Expand Up @@ -153,11 +150,8 @@ int convert_to_sparse(struct index_state *istate)
if (!istate->repo->settings.sparse_index)
return 0;

if (!istate->sparse_checkout_patterns) {
istate->sparse_checkout_patterns = xcalloc(1, sizeof(struct pattern_list));
if (get_sparse_checkout_patterns(istate->sparse_checkout_patterns) < 0)
return 0;
}
if (init_sparse_checkout_patterns(istate) < 0)
return 0;

/*
* We need cone-mode patterns to use sparse-index. If a user edits
Expand Down

0 comments on commit 347410c

Please sign in to comment.