Skip to content

Commit b29ad38

Browse files
ffyuandagitster
authored andcommitted
pathspec.h: move pathspec_needs_expanded_index() from reset.c to here
Method pathspec_needs_expanded_index() in reset.c from 4d1cfc1 (reset: make --mixed sparse-aware, 2021-11-29) is reusable when we need to verify if the index needs to be expanded when the command is utilizing a pathspec rather than a literal path. Move it to pathspec.h for reusability. Add a few items to the function so it can better serve its purpose as a standalone public function: * Add a check in front so if the index is not sparse, return early since no expansion is needed. * It now takes an arbitrary 'struct index_state' pointer instead of using `the_index` and `active_cache`. * Add documentation to the function. Helped-by: Victoria Dye <[email protected]> Helped-by: Derrick Stolee <[email protected]> Signed-off-by: Shaoxuan Yuan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ba80825 commit b29ad38

File tree

3 files changed

+102
-83
lines changed

3 files changed

+102
-83
lines changed

builtin/reset.c

Lines changed: 1 addition & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -174,88 +174,6 @@ static void update_index_from_diff(struct diff_queue_struct *q,
174174
}
175175
}
176176

177-
static int pathspec_needs_expanded_index(const struct pathspec *pathspec)
178-
{
179-
unsigned int i, pos;
180-
int res = 0;
181-
char *skip_worktree_seen = NULL;
182-
183-
/*
184-
* When using a magic pathspec, assume for the sake of simplicity that
185-
* the index needs to be expanded to match all matchable files.
186-
*/
187-
if (pathspec->magic)
188-
return 1;
189-
190-
for (i = 0; i < pathspec->nr; i++) {
191-
struct pathspec_item item = pathspec->items[i];
192-
193-
/*
194-
* If the pathspec item has a wildcard, the index should be expanded
195-
* if the pathspec has the possibility of matching a subset of entries inside
196-
* of a sparse directory (but not the entire directory).
197-
*
198-
* If the pathspec item is a literal path, the index only needs to be expanded
199-
* if a) the pathspec isn't in the sparse checkout cone (to make sure we don't
200-
* expand for in-cone files) and b) it doesn't match any sparse directories
201-
* (since we can reset whole sparse directories without expanding them).
202-
*/
203-
if (item.nowildcard_len < item.len) {
204-
/*
205-
* Special case: if the pattern is a path inside the cone
206-
* followed by only wildcards, the pattern cannot match
207-
* partial sparse directories, so we know we don't need to
208-
* expand the index.
209-
*
210-
* Examples:
211-
* - in-cone/foo***: doesn't need expanded index
212-
* - not-in-cone/bar*: may need expanded index
213-
* - **.c: may need expanded index
214-
*/
215-
if (strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len &&
216-
path_in_cone_mode_sparse_checkout(item.original, &the_index))
217-
continue;
218-
219-
for (pos = 0; pos < active_nr; pos++) {
220-
struct cache_entry *ce = active_cache[pos];
221-
222-
if (!S_ISSPARSEDIR(ce->ce_mode))
223-
continue;
224-
225-
/*
226-
* If the pre-wildcard length is longer than the sparse
227-
* directory name and the sparse directory is the first
228-
* component of the pathspec, need to expand the index.
229-
*/
230-
if (item.nowildcard_len > ce_namelen(ce) &&
231-
!strncmp(item.original, ce->name, ce_namelen(ce))) {
232-
res = 1;
233-
break;
234-
}
235-
236-
/*
237-
* If the pre-wildcard length is shorter than the sparse
238-
* directory and the pathspec does not match the whole
239-
* directory, need to expand the index.
240-
*/
241-
if (!strncmp(item.original, ce->name, item.nowildcard_len) &&
242-
wildmatch(item.original, ce->name, 0)) {
243-
res = 1;
244-
break;
245-
}
246-
}
247-
} else if (!path_in_cone_mode_sparse_checkout(item.original, &the_index) &&
248-
!matches_skip_worktree(pathspec, i, &skip_worktree_seen))
249-
res = 1;
250-
251-
if (res > 0)
252-
break;
253-
}
254-
255-
free(skip_worktree_seen);
256-
return res;
257-
}
258-
259177
static int read_from_tree(const struct pathspec *pathspec,
260178
struct object_id *tree_oid,
261179
int intent_to_add)
@@ -273,7 +191,7 @@ static int read_from_tree(const struct pathspec *pathspec,
273191
opt.change = diff_change;
274192
opt.add_remove = diff_addremove;
275193

276-
if (pathspec->nr && the_index.sparse_index && pathspec_needs_expanded_index(pathspec))
194+
if (pathspec->nr && pathspec_needs_expanded_index(&the_index, pathspec))
277195
ensure_full_index(&the_index);
278196

279197
if (do_diff_cache(tree_oid, &opt))

pathspec.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,92 @@ int match_pathspec_attrs(struct index_state *istate,
759759

760760
return 1;
761761
}
762+
763+
int pathspec_needs_expanded_index(struct index_state *istate,
764+
const struct pathspec *pathspec)
765+
{
766+
unsigned int i, pos;
767+
int res = 0;
768+
char *skip_worktree_seen = NULL;
769+
770+
/*
771+
* If index is not sparse, no index expansion is needed.
772+
*/
773+
if (!istate->sparse_index)
774+
return 0;
775+
776+
/*
777+
* When using a magic pathspec, assume for the sake of simplicity that
778+
* the index needs to be expanded to match all matchable files.
779+
*/
780+
if (pathspec->magic)
781+
return 1;
782+
783+
for (i = 0; i < pathspec->nr; i++) {
784+
struct pathspec_item item = pathspec->items[i];
785+
786+
/*
787+
* If the pathspec item has a wildcard, the index should be expanded
788+
* if the pathspec has the possibility of matching a subset of entries inside
789+
* of a sparse directory (but not the entire directory).
790+
*
791+
* If the pathspec item is a literal path, the index only needs to be expanded
792+
* if a) the pathspec isn't in the sparse checkout cone (to make sure we don't
793+
* expand for in-cone files) and b) it doesn't match any sparse directories
794+
* (since we can reset whole sparse directories without expanding them).
795+
*/
796+
if (item.nowildcard_len < item.len) {
797+
/*
798+
* Special case: if the pattern is a path inside the cone
799+
* followed by only wildcards, the pattern cannot match
800+
* partial sparse directories, so we know we don't need to
801+
* expand the index.
802+
*
803+
* Examples:
804+
* - in-cone/foo***: doesn't need expanded index
805+
* - not-in-cone/bar*: may need expanded index
806+
* - **.c: may need expanded index
807+
*/
808+
if (strspn(item.original + item.nowildcard_len, "*") == item.len - item.nowildcard_len &&
809+
path_in_cone_mode_sparse_checkout(item.original, istate))
810+
continue;
811+
812+
for (pos = 0; pos < istate->cache_nr; pos++) {
813+
struct cache_entry *ce = istate->cache[pos];
814+
815+
if (!S_ISSPARSEDIR(ce->ce_mode))
816+
continue;
817+
818+
/*
819+
* If the pre-wildcard length is longer than the sparse
820+
* directory name and the sparse directory is the first
821+
* component of the pathspec, need to expand the index.
822+
*/
823+
if (item.nowildcard_len > ce_namelen(ce) &&
824+
!strncmp(item.original, ce->name, ce_namelen(ce))) {
825+
res = 1;
826+
break;
827+
}
828+
829+
/*
830+
* If the pre-wildcard length is shorter than the sparse
831+
* directory and the pathspec does not match the whole
832+
* directory, need to expand the index.
833+
*/
834+
if (!strncmp(item.original, ce->name, item.nowildcard_len) &&
835+
wildmatch(item.original, ce->name, 0)) {
836+
res = 1;
837+
break;
838+
}
839+
}
840+
} else if (!path_in_cone_mode_sparse_checkout(item.original, istate) &&
841+
!matches_skip_worktree(pathspec, i, &skip_worktree_seen))
842+
res = 1;
843+
844+
if (res > 0)
845+
break;
846+
}
847+
848+
free(skip_worktree_seen);
849+
return res;
850+
}

pathspec.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,16 @@ int match_pathspec_attrs(struct index_state *istate,
171171
const char *name, int namelen,
172172
const struct pathspec_item *item);
173173

174+
/*
175+
* Determine whether a pathspec will match only entire index entries (non-sparse
176+
* files and/or entire sparse directories). If the pathspec has the potential to
177+
* match partial contents of a sparse directory, return 1 to indicate the index
178+
* should be expanded to match the appropriate index entries.
179+
*
180+
* For the sake of simplicity, always return 1 if using a more complex "magic"
181+
* pathspec.
182+
*/
183+
int pathspec_needs_expanded_index(struct index_state *istate,
184+
const struct pathspec *pathspec);
185+
174186
#endif /* PATHSPEC_H */

0 commit comments

Comments
 (0)