1#include"cache.h" 2#include"dir.h" 3#include"pathspec.h" 4 5/* 6 * Finds which of the given pathspecs match items in the index. 7 * 8 * For each pathspec, sets the corresponding entry in the seen[] array 9 * (which should be specs items long, i.e. the same size as pathspec) 10 * to the nature of the "closest" (i.e. most specific) match found for 11 * that pathspec in the index, if it was a closer type of match than 12 * the existing entry. As an optimization, matching is skipped 13 * altogether if seen[] already only contains non-zero entries. 14 * 15 * If seen[] has not already been written to, it may make sense 16 * to use find_pathspecs_matching_against_index() instead. 17 */ 18voidadd_pathspec_matches_against_index(const char**pathspec, 19char*seen,int specs) 20{ 21int num_unmatched =0, i; 22 23/* 24 * Since we are walking the index as if we were walking the directory, 25 * we have to mark the matched pathspec as seen; otherwise we will 26 * mistakenly think that the user gave a pathspec that did not match 27 * anything. 28 */ 29for(i =0; i < specs; i++) 30if(!seen[i]) 31 num_unmatched++; 32if(!num_unmatched) 33return; 34for(i =0; i < active_nr; i++) { 35struct cache_entry *ce = active_cache[i]; 36match_pathspec(pathspec, ce->name,ce_namelen(ce),0, seen); 37} 38} 39 40/* 41 * Finds which of the given pathspecs match items in the index. 42 * 43 * This is a one-shot wrapper around add_pathspec_matches_against_index() 44 * which allocates, populates, and returns a seen[] array indicating the 45 * nature of the "closest" (i.e. most specific) matches which each of the 46 * given pathspecs achieves against all items in the index. 47 */ 48char*find_pathspecs_matching_against_index(const char**pathspec) 49{ 50char*seen; 51int i; 52 53for(i =0; pathspec[i]; i++) 54;/* just counting */ 55 seen =xcalloc(i,1); 56add_pathspec_matches_against_index(pathspec, seen, i); 57return seen; 58} 59 60/* 61 * Check the index to see whether path refers to a submodule, or 62 * something inside a submodule. If the former, returns the path with 63 * any trailing slash stripped. If the latter, dies with an error 64 * message. 65 */ 66const char*check_path_for_gitlink(const char*path) 67{ 68int i, path_len =strlen(path); 69for(i =0; i < active_nr; i++) { 70struct cache_entry *ce = active_cache[i]; 71if(S_ISGITLINK(ce->ce_mode)) { 72int ce_len =ce_namelen(ce); 73if(path_len <= ce_len || path[ce_len] !='/'|| 74memcmp(ce->name, path, ce_len)) 75/* path does not refer to this 76 * submodule or anything inside it */ 77continue; 78if(path_len == ce_len +1) { 79/* path refers to submodule; 80 * strip trailing slash */ 81returnxstrndup(ce->name, ce_len); 82}else{ 83die(_("Path '%s' is in submodule '%.*s'"), 84 path, ce_len, ce->name); 85} 86} 87} 88return path; 89} 90 91/* 92 * Dies if the given path refers to a file inside a symlinked 93 * directory in the index. 94 */ 95voiddie_if_path_beyond_symlink(const char*path,const char*prefix) 96{ 97if(has_symlink_leading_path(path,strlen(path))) { 98int len = prefix ?strlen(prefix) :0; 99die(_("'%s' is beyond a symbolic link"), path + len); 100} 101} 102 103/* 104 * Magic pathspec 105 * 106 * Possible future magic semantics include stuff like: 107 * 108 * { PATHSPEC_NOGLOB, '!', "noglob" }, 109 * { PATHSPEC_ICASE, '\0', "icase" }, 110 * { PATHSPEC_RECURSIVE, '*', "recursive" }, 111 * { PATHSPEC_REGEXP, '\0', "regexp" }, 112 * 113 */ 114 115static struct pathspec_magic { 116unsigned bit; 117char mnemonic;/* this cannot be ':'! */ 118const char*name; 119} pathspec_magic[] = { 120{ PATHSPEC_FROMTOP,'/',"top"}, 121}; 122 123/* 124 * Take an element of a pathspec and check for magic signatures. 125 * Append the result to the prefix. Return the magic bitmap. 126 * 127 * For now, we only parse the syntax and throw out anything other than 128 * "top" magic. 129 * 130 * NEEDSWORK: This needs to be rewritten when we start migrating 131 * get_pathspec() users to use the "struct pathspec" interface. For 132 * example, a pathspec element may be marked as case-insensitive, but 133 * the prefix part must always match literally, and a single stupid 134 * string cannot express such a case. 135 */ 136static unsignedprefix_pathspec(struct pathspec_item *item, 137unsigned*p_short_magic, 138const char**raw,unsigned flags, 139const char*prefix,int prefixlen, 140const char*elt) 141{ 142unsigned magic =0, short_magic =0; 143const char*copyfrom = elt; 144char*match; 145int i; 146 147if(elt[0] !=':') { 148;/* nothing to do */ 149}else if(elt[1] =='(') { 150/* longhand */ 151const char*nextat; 152for(copyfrom = elt +2; 153*copyfrom && *copyfrom !=')'; 154 copyfrom = nextat) { 155size_t len =strcspn(copyfrom,",)"); 156if(copyfrom[len] ==',') 157 nextat = copyfrom + len +1; 158else 159/* handle ')' and '\0' */ 160 nextat = copyfrom + len; 161if(!len) 162continue; 163for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 164if(strlen(pathspec_magic[i].name) == len && 165!strncmp(pathspec_magic[i].name, copyfrom, len)) { 166 magic |= pathspec_magic[i].bit; 167break; 168} 169if(ARRAY_SIZE(pathspec_magic) <= i) 170die(_("Invalid pathspec magic '%.*s' in '%s'"), 171(int) len, copyfrom, elt); 172} 173if(*copyfrom !=')') 174die(_("Missing ')' at the end of pathspec magic in '%s'"), elt); 175 copyfrom++; 176}else{ 177/* shorthand */ 178for(copyfrom = elt +1; 179*copyfrom && *copyfrom !=':'; 180 copyfrom++) { 181char ch = *copyfrom; 182 183if(!is_pathspec_magic(ch)) 184break; 185for(i =0; i <ARRAY_SIZE(pathspec_magic); i++) 186if(pathspec_magic[i].mnemonic == ch) { 187 short_magic |= pathspec_magic[i].bit; 188break; 189} 190if(ARRAY_SIZE(pathspec_magic) <= i) 191die(_("Unimplemented pathspec magic '%c' in '%s'"), 192 ch, elt); 193} 194if(*copyfrom ==':') 195 copyfrom++; 196} 197 198 magic |= short_magic; 199*p_short_magic = short_magic; 200 201if(magic & PATHSPEC_FROMTOP) 202 match =xstrdup(copyfrom); 203else 204 match =prefix_path(prefix, prefixlen, copyfrom); 205*raw = item->match = match; 206 item->original = elt; 207 item->len =strlen(item->match); 208if(limit_pathspec_to_literal()) 209 item->nowildcard_len = item->len; 210else 211 item->nowildcard_len =simple_length(item->match); 212 item->flags =0; 213if(item->nowildcard_len < item->len && 214 item->match[item->nowildcard_len] =='*'&& 215no_wildcard(item->match + item->nowildcard_len +1)) 216 item->flags |= PATHSPEC_ONESTAR; 217return magic; 218} 219 220static intpathspec_item_cmp(const void*a_,const void*b_) 221{ 222struct pathspec_item *a, *b; 223 224 a = (struct pathspec_item *)a_; 225 b = (struct pathspec_item *)b_; 226returnstrcmp(a->match, b->match); 227} 228 229static void NORETURN unsupported_magic(const char*pattern, 230unsigned magic, 231unsigned short_magic) 232{ 233struct strbuf sb = STRBUF_INIT; 234int i, n; 235for(n = i =0; i <ARRAY_SIZE(pathspec_magic); i++) { 236const struct pathspec_magic *m = pathspec_magic + i; 237if(!(magic & m->bit)) 238continue; 239if(sb.len) 240strbuf_addstr(&sb," "); 241if(short_magic & m->bit) 242strbuf_addf(&sb,"'%c'", m->mnemonic); 243else 244strbuf_addf(&sb,"'%s'", m->name); 245 n++; 246} 247/* 248 * We may want to substitute "this command" with a command 249 * name. E.g. when add--interactive dies when running 250 * "checkout -p" 251 */ 252die(_("%s: pathspec magic not supported by this command:%s"), 253 pattern, sb.buf); 254} 255 256/* 257 * Given command line arguments and a prefix, convert the input to 258 * pathspec. die() if any magic in magic_mask is used. 259 */ 260voidparse_pathspec(struct pathspec *pathspec, 261unsigned magic_mask,unsigned flags, 262const char*prefix,const char**argv) 263{ 264struct pathspec_item *item; 265const char*entry = argv ? *argv : NULL; 266int i, n, prefixlen; 267 268memset(pathspec,0,sizeof(*pathspec)); 269 270/* No arguments, no prefix -> no pathspec */ 271if(!entry && !prefix) 272return; 273 274if((flags & PATHSPEC_PREFER_CWD) && 275(flags & PATHSPEC_PREFER_FULL)) 276die("BUG: PATHSPEC_PREFER_CWD and PATHSPEC_PREFER_FULL are incompatible"); 277 278/* No arguments with prefix -> prefix pathspec */ 279if(!entry) { 280static const char*raw[2]; 281 282if(flags & PATHSPEC_PREFER_FULL) 283return; 284 285if(!(flags & PATHSPEC_PREFER_CWD)) 286die("BUG: PATHSPEC_PREFER_CWD requires arguments"); 287 288 pathspec->items = item =xmalloc(sizeof(*item)); 289memset(item,0,sizeof(*item)); 290 item->match = prefix; 291 item->original = prefix; 292 item->nowildcard_len = item->len =strlen(prefix); 293 raw[0] = prefix; 294 raw[1] = NULL; 295 pathspec->nr =1; 296 pathspec->raw = raw; 297return; 298} 299 300 n =0; 301while(argv[n]) 302 n++; 303 304 pathspec->nr = n; 305 pathspec->items = item =xmalloc(sizeof(*item) * n); 306 pathspec->raw = argv; 307 prefixlen = prefix ?strlen(prefix) :0; 308 309for(i =0; i < n; i++) { 310unsigned short_magic; 311 entry = argv[i]; 312 313 item[i].magic =prefix_pathspec(item + i, &short_magic, 314 argv + i, flags, 315 prefix, prefixlen, entry); 316if(item[i].magic & magic_mask) 317unsupported_magic(entry, 318 item[i].magic & magic_mask, 319 short_magic); 320if(item[i].nowildcard_len < item[i].len) 321 pathspec->has_wildcard =1; 322 pathspec->magic |= item[i].magic; 323} 324 325qsort(pathspec->items, pathspec->nr, 326sizeof(struct pathspec_item), pathspec_item_cmp); 327} 328 329/* 330 * N.B. get_pathspec() is deprecated in favor of the "struct pathspec" 331 * based interface - see pathspec.c:parse_pathspec(). 332 * 333 * Arguments: 334 * - prefix - a path relative to the root of the working tree 335 * - pathspec - a list of paths underneath the prefix path 336 * 337 * Iterates over pathspec, prepending each path with prefix, 338 * and return the resulting list. 339 * 340 * If pathspec is empty, return a singleton list containing prefix. 341 * 342 * If pathspec and prefix are both empty, return an empty list. 343 * 344 * This is typically used by built-in commands such as add.c, in order 345 * to normalize argv arguments provided to the built-in into a list of 346 * paths to process, all relative to the root of the working tree. 347 */ 348const char**get_pathspec(const char*prefix,const char**pathspec) 349{ 350struct pathspec ps; 351parse_pathspec(&ps, 352 PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP, 353 PATHSPEC_PREFER_CWD, 354 prefix, pathspec); 355return ps.raw; 356} 357 358voidcopy_pathspec(struct pathspec *dst,const struct pathspec *src) 359{ 360*dst = *src; 361 dst->items =xmalloc(sizeof(struct pathspec_item) * dst->nr); 362memcpy(dst->items, src->items, 363sizeof(struct pathspec_item) * dst->nr); 364}