1 #ifndef PATHSPEC_H
2 #define PATHSPEC_H
3 
4 struct index_state;
5 
6 /* Pathspec magic */
7 #define PATHSPEC_FROMTOP	(1<<0)
8 #define PATHSPEC_MAXDEPTH	(1<<1)
9 #define PATHSPEC_LITERAL	(1<<2)
10 #define PATHSPEC_GLOB		(1<<3)
11 #define PATHSPEC_ICASE		(1<<4)
12 #define PATHSPEC_EXCLUDE	(1<<5)
13 #define PATHSPEC_ATTR		(1<<6)
14 #define PATHSPEC_ALL_MAGIC	  \
15 	(PATHSPEC_FROMTOP	| \
16 	 PATHSPEC_MAXDEPTH	| \
17 	 PATHSPEC_LITERAL	| \
18 	 PATHSPEC_GLOB		| \
19 	 PATHSPEC_ICASE		| \
20 	 PATHSPEC_EXCLUDE	| \
21 	 PATHSPEC_ATTR)
22 
23 #define PATHSPEC_ONESTAR 1	/* the pathspec pattern satisfies GFNM_ONESTAR */
24 
25 /**
26  * See glossary-context.txt for the syntax of pathspec.
27  * In memory, a pathspec set is represented by "struct pathspec" and is
28  * prepared by parse_pathspec().
29  */
30 struct pathspec {
31 	int nr;
32 	unsigned int has_wildcard:1;
33 	unsigned int recursive:1;
34 	unsigned int recurse_submodules:1;
35 	unsigned magic;
36 	int max_depth;
37 	struct pathspec_item {
38 		char *match;
39 		char *original;
40 		unsigned magic;
41 		int len, prefix;
42 		int nowildcard_len;
43 		int flags;
44 		int attr_match_nr;
45 		struct attr_match {
46 			char *value;
47 			enum attr_match_mode {
48 				MATCH_SET,
49 				MATCH_UNSET,
50 				MATCH_VALUE,
51 				MATCH_UNSPECIFIED
52 			} match_mode;
53 		} *attr_match;
54 		struct attr_check *attr_check;
55 	} *items;
56 };
57 
58 #define GUARD_PATHSPEC(ps, mask) \
59 	do { \
60 		if ((ps)->magic & ~(mask))	       \
61 			die("BUG:%s:%d: unsupported magic %x",	\
62 			    __FILE__, __LINE__, (ps)->magic & ~(mask)); \
63 	} while (0)
64 
65 /* parse_pathspec flags */
66 #define PATHSPEC_PREFER_CWD (1<<0) /* No args means match cwd */
67 #define PATHSPEC_PREFER_FULL (1<<1) /* No args means match everything */
68 #define PATHSPEC_MAXDEPTH_VALID (1<<2) /* max_depth field is valid */
69 /* die if a symlink is part of the given path's directory */
70 #define PATHSPEC_SYMLINK_LEADING_PATH (1<<3)
71 #define PATHSPEC_PREFIX_ORIGIN (1<<4)
72 #define PATHSPEC_KEEP_ORDER (1<<5)
73 /*
74  * For the callers that just need pure paths from somewhere else, not
75  * from command line. Global --*-pathspecs options are ignored. No
76  * magic is parsed in each pathspec either. If PATHSPEC_LITERAL is
77  * allowed, then it will automatically set for every pathspec.
78  */
79 #define PATHSPEC_LITERAL_PATH (1<<6)
80 
81 /**
82  * Given command line arguments and a prefix, convert the input to
83  * pathspec. die() if any magic in magic_mask is used.
84  *
85  * Any arguments used are copied. It is safe for the caller to modify
86  * or free 'prefix' and 'args' after calling this function.
87  *
88  * - magic_mask specifies what features that are NOT supported by the following
89  * code. If a user attempts to use such a feature, parse_pathspec() can reject
90  * it early.
91  *
92  * - flags specifies other things that the caller wants parse_pathspec to
93  * perform.
94  *
95  * - prefix and args come from cmd_* functions
96  *
97  * parse_pathspec() helps catch unsupported features and reject them politely.
98  * At a lower level, different pathspec-related functions may not support the
99  * same set of features. Such pathspec-sensitive functions are guarded with
100  * GUARD_PATHSPEC(), which will die in an unfriendly way when an unsupported
101  * feature is requested.
102  *
103  * The command designers are supposed to make sure that GUARD_PATHSPEC() never
104  * dies. They have to make sure all unsupported features are caught by
105  * parse_pathspec(), not by GUARD_PATHSPEC. grepping GUARD_PATHSPEC() should
106  * give the designers all pathspec-sensitive codepaths and what features they
107  * support.
108  *
109  * A similar process is applied when a new pathspec magic is added. The designer
110  * lifts the GUARD_PATHSPEC restriction in the functions that support the new
111  * magic. At the same time (s)he has to make sure this new feature will be
112  * caught at parse_pathspec() in commands that cannot handle the new magic in
113  * some cases. grepping parse_pathspec() should help.
114  */
115 void parse_pathspec(struct pathspec *pathspec,
116 		    unsigned magic_mask,
117 		    unsigned flags,
118 		    const char *prefix,
119 		    const char **args);
120 /*
121  * Same as parse_pathspec() but uses file as input.
122  * When 'file' is exactly "-" it uses 'stdin' instead.
123  */
124 void parse_pathspec_file(struct pathspec *pathspec,
125 			 unsigned magic_mask,
126 			 unsigned flags,
127 			 const char *prefix,
128 			 const char *file,
129 			 int nul_term_line);
130 
131 void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
132 void clear_pathspec(struct pathspec *);
133 
ps_strncmp(const struct pathspec_item * item,const char * s1,const char * s2,size_t n)134 static inline int ps_strncmp(const struct pathspec_item *item,
135 			     const char *s1, const char *s2, size_t n)
136 {
137 	if (item->magic & PATHSPEC_ICASE)
138 		return strncasecmp(s1, s2, n);
139 	else
140 		return strncmp(s1, s2, n);
141 }
142 
ps_strcmp(const struct pathspec_item * item,const char * s1,const char * s2)143 static inline int ps_strcmp(const struct pathspec_item *item,
144 			    const char *s1, const char *s2)
145 {
146 	if (item->magic & PATHSPEC_ICASE)
147 		return strcasecmp(s1, s2);
148 	else
149 		return strcmp(s1, s2);
150 }
151 
152 void add_pathspec_matches_against_index(const struct pathspec *pathspec,
153 					const struct index_state *istate,
154 					char *seen);
155 char *find_pathspecs_matching_against_index(const struct pathspec *pathspec,
156 					    const struct index_state *istate);
157 int match_pathspec_attrs(const struct index_state *istate,
158 			 const char *name, int namelen,
159 			 const struct pathspec_item *item);
160 
161 #endif /* PATHSPEC_H */
162