move struct pathspec and related functions to pathspec.[ch]

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed Jul 14, 2013 at 15:35 UTC 64acde94efd2906c3e20560c31c2957ac0b242c4
13 files changed +182 -169
archive.c
+1
@@ -5,6 +5,7 @@
5 #include "archive.h"
6 #include "parse-options.h"
7 #include "unpack-trees.h"
8 +#include "pathspec.h"
9
10 static char const * const archive_usage[] = {
11 N_("git archive [options] <tree-ish> [<path>...]"),
builtin/grep.c
+1
@@ -17,6 +17,7 @@
17 #include "grep.h"
18 #include "quote.h"
19 #include "dir.h"
20 +#include "pathspec.h"
21
22 static char const * const grep_usage[] = {
23 N_("git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"),
builtin/ls-files.c
+1
@@ -13,6 +13,7 @@
13 #include "parse-options.h"
14 #include "resolve-undo.h"
15 #include "string-list.h"
16 +#include "pathspec.h"
17
18 static int abbrev;
19 static int show_deleted;
builtin/ls-tree.c
+1
@@ -10,6 +10,7 @@
10 #include "quote.h"
11 #include "builtin.h"
12 #include "parse-options.h"
13 +#include "pathspec.h"
14
15 static int line_termination = '\n';
16 #define LS_RECURSIVE 1
builtin/update-index.c
+1
@@ -11,6 +11,7 @@
11 #include "refs.h"
12 #include "resolve-undo.h"
13 #include "parse-options.h"
14 +#include "pathspec.h"
15
16 /*
17 * Default to not allowing changes to the list of files. The
cache.h
+2 -20
@@ -189,6 +189,8 @@ struct cache_entry {
189 #error "CE_EXTENDED_FLAGS out of range"
190 #endif
191
192 +struct pathspec;
193 +
194 /*
195 * Copy the sha1 and stat state of a cache entry from one to
196 * another. But we never change the name, or the hash state!
@@ -489,28 +491,8 @@ extern void *read_blob_data_from_index(struct index_state *, const char *, unsig
491 extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
492 extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
493
492 -#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
493 -
494 -struct pathspec {
495 - const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
496 - int nr;
497 - unsigned int has_wildcard:1;
498 - unsigned int recursive:1;
499 - int max_depth;
500 - struct pathspec_item {
501 - const char *match;
502 - int len;
503 - int nowildcard_len;
504 - int flags;
505 - } *items;
506 -};
507 -
508 -extern int init_pathspec(struct pathspec *, const char **);
509 -extern void free_pathspec(struct pathspec *);
494 extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
495
512 -extern int limit_pathspec_to_literal(void);
513 -
496 #define HASH_WRITE_OBJECT 1
497 #define HASH_FORMAT_CHECK 2
498 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
diff.h
+1
@@ -5,6 +5,7 @@
5 #define DIFF_H
6
7 #include "tree-walk.h"
8 +#include "pathspec.h"
9
10 struct rev_info;
11 struct diff_options;
dir.c
+1
@@ -11,6 +11,7 @@
11 #include "dir.h"
12 #include "refs.h"
13 #include "wildmatch.h"
14 +#include "pathspec.h"
15
16 struct path_simplify {
17 int len;
pathspec.c
+150
@@ -99,3 +99,153 @@ void die_if_path_beyond_symlink(const char *path, const char *prefix)
99 die(_("'%s' is beyond a symbolic link"), path + len);
100 }
101 }
102 +
103 +/*
104 + * Magic pathspec
105 + *
106 + * NEEDSWORK: These need to be moved to dir.h or even to a new
107 + * pathspec.h when we restructure get_pathspec() users to use the
108 + * "struct pathspec" interface.
109 + *
110 + * Possible future magic semantics include stuff like:
111 + *
112 + * { PATHSPEC_NOGLOB, '!', "noglob" },
113 + * { PATHSPEC_ICASE, '\0', "icase" },
114 + * { PATHSPEC_RECURSIVE, '*', "recursive" },
115 + * { PATHSPEC_REGEXP, '\0', "regexp" },
116 + *
117 + */
118 +#define PATHSPEC_FROMTOP (1<<0)
119 +
120 +static struct pathspec_magic {
121 + unsigned bit;
122 + char mnemonic; /* this cannot be ':'! */
123 + const char *name;
124 +} pathspec_magic[] = {
125 + { PATHSPEC_FROMTOP, '/', "top" },
126 +};
127 +
128 +/*
129 + * Take an element of a pathspec and check for magic signatures.
130 + * Append the result to the prefix.
131 + *
132 + * For now, we only parse the syntax and throw out anything other than
133 + * "top" magic.
134 + *
135 + * NEEDSWORK: This needs to be rewritten when we start migrating
136 + * get_pathspec() users to use the "struct pathspec" interface. For
137 + * example, a pathspec element may be marked as case-insensitive, but
138 + * the prefix part must always match literally, and a single stupid
139 + * string cannot express such a case.
140 + */
141 +static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
142 +{
143 + unsigned magic = 0;
144 + const char *copyfrom = elt;
145 + int i;
146 +
147 + if (elt[0] != ':') {
148 + ; /* nothing to do */
149 + } else if (elt[1] == '(') {
150 + /* longhand */
151 + const char *nextat;
152 + for (copyfrom = elt + 2;
153 + *copyfrom && *copyfrom != ')';
154 + copyfrom = nextat) {
155 + size_t len = strcspn(copyfrom, ",)");
156 + if (copyfrom[len] == ',')
157 + nextat = copyfrom + len + 1;
158 + else
159 + /* handle ')' and '\0' */
160 + nextat = copyfrom + len;
161 + if (!len)
162 + continue;
163 + for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
164 + if (strlen(pathspec_magic[i].name) == len &&
165 + !strncmp(pathspec_magic[i].name, copyfrom, len)) {
166 + magic |= pathspec_magic[i].bit;
167 + break;
168 + }
169 + if (ARRAY_SIZE(pathspec_magic) <= i)
170 + die("Invalid pathspec magic '%.*s' in '%s'",
171 + (int) len, copyfrom, elt);
172 + }
173 + if (*copyfrom != ')')
174 + die("Missing ')' at the end of pathspec magic in '%s'", elt);
175 + copyfrom++;
176 + } else {
177 + /* shorthand */
178 + for (copyfrom = elt + 1;
179 + *copyfrom && *copyfrom != ':';
180 + copyfrom++) {
181 + char ch = *copyfrom;
182 +
183 + if (!is_pathspec_magic(ch))
184 + break;
185 + for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
186 + if (pathspec_magic[i].mnemonic == ch) {
187 + magic |= pathspec_magic[i].bit;
188 + break;
189 + }
190 + if (ARRAY_SIZE(pathspec_magic) <= i)
191 + die("Unimplemented pathspec magic '%c' in '%s'",
192 + ch, elt);
193 + }
194 + if (*copyfrom == ':')
195 + copyfrom++;
196 + }
197 +
198 + if (magic & PATHSPEC_FROMTOP)
199 + return xstrdup(copyfrom);
200 + else
201 + return prefix_path(prefix, prefixlen, copyfrom);
202 +}
203 +
204 +/*
205 + * N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
206 + * based interface - see pathspec_magic above.
207 + *
208 + * Arguments:
209 + * - prefix - a path relative to the root of the working tree
210 + * - pathspec - a list of paths underneath the prefix path
211 + *
212 + * Iterates over pathspec, prepending each path with prefix,
213 + * and return the resulting list.
214 + *
215 + * If pathspec is empty, return a singleton list containing prefix.
216 + *
217 + * If pathspec and prefix are both empty, return an empty list.
218 + *
219 + * This is typically used by built-in commands such as add.c, in order
220 + * to normalize argv arguments provided to the built-in into a list of
221 + * paths to process, all relative to the root of the working tree.
222 + */
223 +const char **get_pathspec(const char *prefix, const char **pathspec)
224 +{
225 + const char *entry = *pathspec;
226 + const char **src, **dst;
227 + int prefixlen;
228 +
229 + if (!prefix && !entry)
230 + return NULL;
231 +
232 + if (!entry) {
233 + static const char *spec[2];
234 + spec[0] = prefix;
235 + spec[1] = NULL;
236 + return spec;
237 + }
238 +
239 + /* Otherwise we have to re-write the entries.. */
240 + src = pathspec;
241 + dst = pathspec;
242 + prefixlen = prefix ? strlen(prefix) : 0;
243 + while (*src) {
244 + *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
245 + src++;
246 + }
247 + *dst = NULL;
248 + if (!*pathspec)
249 + return NULL;
250 + return pathspec;
251 +}
pathspec.h
+21
@@ -1,6 +1,27 @@
1 #ifndef PATHSPEC_H
2 #define PATHSPEC_H
3
4 +#define PATHSPEC_ONESTAR 1 /* the pathspec pattern sastisfies GFNM_ONESTAR */
5 +
6 +struct pathspec {
7 + const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
8 + int nr;
9 + unsigned int has_wildcard:1;
10 + unsigned int recursive:1;
11 + int max_depth;
12 + struct pathspec_item {
13 + const char *match;
14 + int len;
15 + int nowildcard_len;
16 + int flags;
17 + } *items;
18 +};
19 +
20 +extern int init_pathspec(struct pathspec *, const char **);
21 +extern void free_pathspec(struct pathspec *);
22 +
23 +extern int limit_pathspec_to_literal(void);
24 +
25 extern char *find_pathspecs_matching_against_index(const char **pathspec);
26 extern void add_pathspec_matches_against_index(const char **pathspec, char *seen, int specs);
27 extern const char *check_path_for_gitlink(const char *path);
preload-index.c
+1
@@ -2,6 +2,7 @@
2 * Copyright (C) 2008 Linus Torvalds
3 */
4 #include "cache.h"
5 +#include "pathspec.h"
6
7 #ifdef NO_PTHREADS
8 static void preload_index(struct index_state *index, const char **pathspec)
setup.c
-149
@@ -154,155 +154,6 @@ void verify_non_filename(const char *prefix, const char *arg)
154 "'git <command> [<revision>...] -- [<file>...]'", arg);
155 }
156
157 -/*
158 - * Magic pathspec
159 - *
160 - * NEEDSWORK: These need to be moved to dir.h or even to a new
161 - * pathspec.h when we restructure get_pathspec() users to use the
162 - * "struct pathspec" interface.
163 - *
164 - * Possible future magic semantics include stuff like:
165 - *
166 - * { PATHSPEC_NOGLOB, '!', "noglob" },
167 - * { PATHSPEC_ICASE, '\0', "icase" },
168 - * { PATHSPEC_RECURSIVE, '*', "recursive" },
169 - * { PATHSPEC_REGEXP, '\0', "regexp" },
170 - *
171 - */
172 -#define PATHSPEC_FROMTOP (1<<0)
173 -
174 -static struct pathspec_magic {
175 - unsigned bit;
176 - char mnemonic; /* this cannot be ':'! */
177 - const char *name;
178 -} pathspec_magic[] = {
179 - { PATHSPEC_FROMTOP, '/', "top" },
180 -};
181 -
182 -/*
183 - * Take an element of a pathspec and check for magic signatures.
184 - * Append the result to the prefix.
185 - *
186 - * For now, we only parse the syntax and throw out anything other than
187 - * "top" magic.
188 - *
189 - * NEEDSWORK: This needs to be rewritten when we start migrating
190 - * get_pathspec() users to use the "struct pathspec" interface. For
191 - * example, a pathspec element may be marked as case-insensitive, but
192 - * the prefix part must always match literally, and a single stupid
193 - * string cannot express such a case.
194 - */
195 -static const char *prefix_pathspec(const char *prefix, int prefixlen, const char *elt)
196 -{
197 - unsigned magic = 0;
198 - const char *copyfrom = elt;
199 - int i;
200 -
201 - if (elt[0] != ':') {
202 - ; /* nothing to do */
203 - } else if (elt[1] == '(') {
204 - /* longhand */
205 - const char *nextat;
206 - for (copyfrom = elt + 2;
207 - *copyfrom && *copyfrom != ')';
208 - copyfrom = nextat) {
209 - size_t len = strcspn(copyfrom, ",)");
210 - if (copyfrom[len] == ',')
211 - nextat = copyfrom + len + 1;
212 - else
213 - /* handle ')' and '\0' */
214 - nextat = copyfrom + len;
215 - if (!len)
216 - continue;
217 - for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
218 - if (strlen(pathspec_magic[i].name) == len &&
219 - !strncmp(pathspec_magic[i].name, copyfrom, len)) {
220 - magic |= pathspec_magic[i].bit;
221 - break;
222 - }
223 - if (ARRAY_SIZE(pathspec_magic) <= i)
224 - die("Invalid pathspec magic '%.*s' in '%s'",
225 - (int) len, copyfrom, elt);
226 - }
227 - if (*copyfrom != ')')
228 - die("Missing ')' at the end of pathspec magic in '%s'", elt);
229 - copyfrom++;
230 - } else {
231 - /* shorthand */
232 - for (copyfrom = elt + 1;
233 - *copyfrom && *copyfrom != ':';
234 - copyfrom++) {
235 - char ch = *copyfrom;
236 -
237 - if (!is_pathspec_magic(ch))
238 - break;
239 - for (i = 0; i < ARRAY_SIZE(pathspec_magic); i++)
240 - if (pathspec_magic[i].mnemonic == ch) {
241 - magic |= pathspec_magic[i].bit;
242 - break;
243 - }
244 - if (ARRAY_SIZE(pathspec_magic) <= i)
245 - die("Unimplemented pathspec magic '%c' in '%s'",
246 - ch, elt);
247 - }
248 - if (*copyfrom == ':')
249 - copyfrom++;
250 - }
251 -
252 - if (magic & PATHSPEC_FROMTOP)
253 - return xstrdup(copyfrom);
254 - else
255 - return prefix_path(prefix, prefixlen, copyfrom);
256 -}
257 -
258 -/*
259 - * N.B. get_pathspec() is deprecated in favor of the "struct pathspec"
260 - * based interface - see pathspec_magic above.
261 - *
262 - * Arguments:
263 - * - prefix - a path relative to the root of the working tree
264 - * - pathspec - a list of paths underneath the prefix path
265 - *
266 - * Iterates over pathspec, prepending each path with prefix,
267 - * and return the resulting list.
268 - *
269 - * If pathspec is empty, return a singleton list containing prefix.
270 - *
271 - * If pathspec and prefix are both empty, return an empty list.
272 - *
273 - * This is typically used by built-in commands such as add.c, in order
274 - * to normalize argv arguments provided to the built-in into a list of
275 - * paths to process, all relative to the root of the working tree.
276 - */
277 -const char **get_pathspec(const char *prefix, const char **pathspec)
278 -{
279 - const char *entry = *pathspec;
280 - const char **src, **dst;
281 - int prefixlen;
282 -
283 - if (!prefix && !entry)
284 - return NULL;
285 -
286 - if (!entry) {
287 - static const char *spec[2];
288 - spec[0] = prefix;
289 - spec[1] = NULL;
290 - return spec;
291 - }
292 -
293 - /* Otherwise we have to re-write the entries.. */
294 - src = pathspec;
295 - dst = pathspec;
296 - prefixlen = prefix ? strlen(prefix) : 0;
297 - while (*src) {
298 - *(dst++) = prefix_pathspec(prefix, prefixlen, *src);
299 - src++;
300 - }
301 - *dst = NULL;
302 - if (!*pathspec)
303 - return NULL;
304 - return pathspec;
305 -}
157
158 /*
159 * Test if it looks like we're at a git directory.
tree-walk.c
+1
@@ -3,6 +3,7 @@
3 #include "unpack-trees.h"
4 #include "dir.h"
5 #include "tree.h"
6 +#include "pathspec.h"
7
8 static const char *get_mode(const char *str, unsigned int *modep)
9 {