diff --git a/Makefile b/Makefile index 13293d33fd..48facad01a 100644 --- a/Makefile +++ b/Makefile @@ -645,6 +645,7 @@ LIB_H += pack-refs.h LIB_H += pack-revindex.h LIB_H += parse-options.h LIB_H += patch-ids.h +LIB_H += pathspec.h LIB_H += pkt-line.h LIB_H += progress.h LIB_H += prompt.h @@ -758,6 +759,7 @@ LIB_OBJS += parse-options-cb.o LIB_OBJS += patch-delta.o LIB_OBJS += patch-ids.o LIB_OBJS += path.o +LIB_OBJS += pathspec.o LIB_OBJS += pkt-line.o LIB_OBJS += preload-index.o LIB_OBJS += pretty.o diff --git a/builtin/add.c b/builtin/add.c index 1f62ba3d2e..e51ba441ca 100644 --- a/builtin/add.c +++ b/builtin/add.c @@ -6,6 +6,7 @@ #include "cache.h" #include "builtin.h" #include "dir.h" +#include "pathspec.h" #include "exec_cmd.h" #include "cache-tree.h" #include "run-command.h" @@ -97,39 +98,6 @@ int add_files_to_cache(const char *prefix, const char **pathspec, int flags) return !!data.add_errors; } -static void fill_pathspec_matches(const char **pathspec, char *seen, int specs) -{ - int num_unmatched = 0, i; - - /* - * Since we are walking the index as if we were walking the directory, - * we have to mark the matched pathspec as seen; otherwise we will - * mistakenly think that the user gave a pathspec that did not match - * anything. - */ - for (i = 0; i < specs; i++) - if (!seen[i]) - num_unmatched++; - if (!num_unmatched) - return; - for (i = 0; i < active_nr; i++) { - struct cache_entry *ce = active_cache[i]; - match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen); - } -} - -static char *find_used_pathspec(const char **pathspec) -{ - char *seen; - int i; - - for (i = 0; pathspec[i]; i++) - ; /* just counting */ - seen = xcalloc(i, 1); - fill_pathspec_matches(pathspec, seen, i); - return seen; -} - static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) { char *seen; diff --git a/pathspec.c b/pathspec.c new file mode 100644 index 0000000000..1472af89ce --- /dev/null +++ b/pathspec.c @@ -0,0 +1,57 @@ +#include "cache.h" +#include "dir.h" +#include "pathspec.h" + +/* + * Finds which of the given pathspecs match items in the index. + * + * For each pathspec, sets the corresponding entry in the seen[] array + * (which should be specs items long, i.e. the same size as pathspec) + * to the nature of the "closest" (i.e. most specific) match found for + * that pathspec in the index, if it was a closer type of match than + * the existing entry. As an optimization, matching is skipped + * altogether if seen[] already only contains non-zero entries. + * + * If seen[] has not already been written to, it may make sense + * to use find_used_pathspec() instead. + */ +void fill_pathspec_matches(const char **pathspec, char *seen, int specs) +{ + int num_unmatched = 0, i; + + /* + * Since we are walking the index as if we were walking the directory, + * we have to mark the matched pathspec as seen; otherwise we will + * mistakenly think that the user gave a pathspec that did not match + * anything. + */ + for (i = 0; i < specs; i++) + if (!seen[i]) + num_unmatched++; + if (!num_unmatched) + return; + for (i = 0; i < active_nr; i++) { + struct cache_entry *ce = active_cache[i]; + match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen); + } +} + +/* + * Finds which of the given pathspecs match items in the index. + * + * This is a one-shot wrapper around fill_pathspec_matches() which + * allocates, populates, and returns a seen[] array indicating the + * nature of the "closest" (i.e. most specific) matches which each of + * the given pathspecs achieves against all items in the index. + */ +char *find_used_pathspec(const char **pathspec) +{ + char *seen; + int i; + + for (i = 0; pathspec[i]; i++) + ; /* just counting */ + seen = xcalloc(i, 1); + fill_pathspec_matches(pathspec, seen, i); + return seen; +} diff --git a/pathspec.h b/pathspec.h new file mode 100644 index 0000000000..1cb1909e4c --- /dev/null +++ b/pathspec.h @@ -0,0 +1,7 @@ +#ifndef PATHSPEC_H +#define PATHSPEC_H + +extern char *find_used_pathspec(const char **pathspec); +extern void fill_pathspec_matches(const char **pathspec, char *seen, int specs); + +#endif /* PATHSPEC_H */