| 1 | #ifndef DIR_H |
| 2 | #define DIR_H |
| 3 | |
| 4 | #include "hash.h" |
| 5 | #include "hashmap.h" |
| 6 | #include "pathspec.h" |
| 7 | #include "statinfo.h" |
| 8 | #include "strbuf.h" |
| 9 | |
| 10 | struct repository; |
| 11 | |
| 12 | /** |
| 13 | * The directory listing API is used to enumerate paths in the work tree, |
| 14 | * optionally taking `.git/info/exclude` and `.gitignore` files per directory |
| 15 | * into account. |
| 16 | */ |
| 17 | |
| 18 | /** |
| 19 | * Calling sequence |
| 20 | * ---------------- |
| 21 | * |
| 22 | * Note: The index may be checked for .gitignore files that are |
| 23 | * CE_SKIP_WORKTREE marked. If you want to exclude files, make sure you have |
| 24 | * loaded the index first. |
| 25 | * |
| 26 | * - Prepare `struct dir_struct dir` using `dir_init()` function. |
| 27 | * |
| 28 | * - To add single exclude pattern, call `add_pattern_list()` and then |
| 29 | * `add_pattern()`. |
| 30 | * |
| 31 | * - To add patterns from a file (e.g. `.git/info/exclude`), call |
| 32 | * `add_patterns_from_file()` , and/or set `dir.exclude_per_dir`. |
| 33 | * |
| 34 | * - A short-hand function `setup_standard_excludes()` can be used to set |
| 35 | * up the standard set of exclude settings, instead of manually calling |
| 36 | * the add_pattern*() family of functions. |
| 37 | * |
| 38 | * - Call `fill_directory()`. |
| 39 | * |
| 40 | * - Use `dir.entries[]` and `dir.ignored[]`. |
| 41 | * |
| 42 | * - Call `dir_clear()` when the contained elements are no longer in use. |
| 43 | * |
| 44 | */ |
| 45 | |
| 46 | |
| 47 | struct dir_entry { |
| 48 | unsigned int len; |
| 49 | char name[FLEX_ARRAY]; /* more */ |
| 50 | }; |
| 51 | |
| 52 | #define PATTERN_FLAG_NODIR 1 |
| 53 | #define PATTERN_FLAG_ENDSWITH 4 |
| 54 | #define PATTERN_FLAG_MUSTBEDIR 8 |
| 55 | #define PATTERN_FLAG_NEGATIVE 16 |
| 56 | |
| 57 | struct path_pattern { |
| 58 | /* |
| 59 | * This allows callers of last_matching_pattern() etc. |
| 60 | * to determine the origin of the matching pattern. |
| 61 | */ |
| 62 | struct pattern_list *pl; |
| 63 | |
| 64 | int patternlen; |
| 65 | int nowildcardlen; |
| 66 | const char *base; |
| 67 | int baselen; |
| 68 | unsigned flags; /* PATTERN_FLAG_* */ |
| 69 | |
| 70 | /* |
| 71 | * Counting starts from 1 for line numbers in ignore files, |
| 72 | * and from -1 decrementing for patterns from CLI args. |
| 73 | */ |
| 74 | int srcpos; |
| 75 | |
| 76 | char pattern[FLEX_ARRAY]; |
| 77 | }; |
| 78 | |
| 79 | /* used for hashmaps for cone patterns */ |
| 80 | struct pattern_entry { |
| 81 | struct hashmap_entry ent; |
| 82 | char *pattern; |
| 83 | size_t patternlen; |
| 84 | }; |
| 85 | |
| 86 | /* |
| 87 | * Each excludes file will be parsed into a fresh exclude_list which |
| 88 | * is appended to the relevant exclude_list_group (either EXC_DIRS or |
| 89 | * EXC_FILE). An exclude_list within the EXC_CMDL exclude_list_group |
| 90 | * can also be used to represent the list of --exclude values passed |
| 91 | * via CLI args. |
| 92 | */ |
| 93 | struct pattern_list { |
| 94 | int nr; |
| 95 | int alloc; |
| 96 | |
| 97 | /* origin of list, e.g. path to filename, or descriptive string */ |
| 98 | const char *src; |
| 99 | |
| 100 | struct path_pattern **patterns; |
| 101 | |
| 102 | /* |
| 103 | * While scanning the excludes, we attempt to match the patterns |
| 104 | * with a more restricted set that allows us to use hashsets for |
| 105 | * matching logic, which is faster than the linear lookup in the |
| 106 | * excludes array above. If non-zero, that check succeeded. |
| 107 | */ |
| 108 | unsigned use_cone_patterns; |
| 109 | unsigned full_cone; |
| 110 | |
| 111 | /* |
| 112 | * Stores paths where everything starting with those paths |
| 113 | * is included. |
| 114 | */ |
| 115 | struct hashmap recursive_hashmap; |
| 116 | |
| 117 | /* |
| 118 | * Used to check single-level parents of blobs. |
| 119 | */ |
| 120 | struct hashmap parent_hashmap; |
| 121 | }; |
| 122 | |
| 123 | /* |
| 124 | * The contents of the per-directory exclude files are lazily read on |
| 125 | * demand and then cached in memory, one per exclude_stack struct, in |
| 126 | * order to avoid opening and parsing each one every time that |
| 127 | * directory is traversed. |
| 128 | */ |
| 129 | struct exclude_stack { |
| 130 | struct exclude_stack *prev; /* the struct exclude_stack for the parent directory */ |
| 131 | int baselen; |
| 132 | int exclude_ix; /* index of exclude_list within EXC_DIRS exclude_list_group */ |
| 133 | struct untracked_cache_dir *ucd; |
| 134 | }; |
| 135 | |
| 136 | struct exclude_list_group { |
| 137 | int nr, alloc; |
| 138 | struct pattern_list *pl; |
| 139 | }; |
| 140 | |
| 141 | struct oid_stat { |
| 142 | struct stat_data stat; |
| 143 | struct object_id oid; |
| 144 | int valid; |
| 145 | }; |
| 146 | |
| 147 | /* |
| 148 | * Untracked cache |
| 149 | * |
| 150 | * The following inputs are sufficient to determine what files in a |
| 151 | * directory are excluded: |
| 152 | * |
| 153 | * - The list of files and directories of the directory in question |
| 154 | * - The $GIT_DIR/index |
| 155 | * - dir_struct flags |
| 156 | * - The content of $GIT_COMMON_DIR/info/exclude |
| 157 | * - The content of core.excludesfile |
| 158 | * - The content (or the lack) of .gitignore of all parent directories |
| 159 | * from $GIT_WORK_TREE |
| 160 | * - The check_only flag in read_directory_recursive (for |
| 161 | * DIR_HIDE_EMPTY_DIRECTORIES) |
| 162 | * |
| 163 | * The first input can be checked using directory mtime. In many |
| 164 | * filesystems, directory mtime (stat_data field) is updated when its |
| 165 | * files or direct subdirs are added or removed. |
| 166 | * |
| 167 | * The second one can be hooked from cache_tree_invalidate_path(). |
| 168 | * Whenever a file (or a submodule) is added or removed from a |
| 169 | * directory, we invalidate that directory. |
| 170 | * |
| 171 | * The remaining inputs are easy, their SHA-1 could be used to verify |
| 172 | * their contents (exclude_sha1[], info_exclude_sha1[] and |
| 173 | * excludes_file_sha1[]) |
| 174 | */ |
| 175 | struct untracked_cache_dir { |
| 176 | struct untracked_cache_dir **dirs; |
| 177 | char **untracked; |
| 178 | struct stat_data stat_data; |
| 179 | unsigned int untracked_alloc, dirs_nr, dirs_alloc; |
| 180 | unsigned int untracked_nr; |
| 181 | unsigned int check_only : 1; |
| 182 | /* all data except 'dirs' in this struct are good */ |
| 183 | unsigned int valid : 1; |
| 184 | unsigned int recurse : 1; |
| 185 | /* null object ID means this directory does not have .gitignore */ |
| 186 | struct object_id exclude_oid; |
| 187 | char name[FLEX_ARRAY]; |
| 188 | }; |
| 189 | |
| 190 | struct untracked_cache { |
| 191 | struct oid_stat ss_info_exclude; |
| 192 | struct oid_stat ss_excludes_file; |
| 193 | const char *exclude_per_dir; |
| 194 | char *exclude_per_dir_to_free; |
| 195 | struct strbuf ident; |
| 196 | /* |
| 197 | * dir_struct#flags must match dir_flags or the untracked |
| 198 | * cache is ignored. |
| 199 | */ |
| 200 | unsigned dir_flags; |
| 201 | struct untracked_cache_dir *root; |
| 202 | /* Statistics */ |
| 203 | int dir_created; |
| 204 | int gitignore_invalidated; |
| 205 | int dir_invalidated; |
| 206 | int dir_opened; |
| 207 | /* fsmonitor invalidation data */ |
| 208 | unsigned int use_fsmonitor : 1; |
| 209 | }; |
| 210 | |
| 211 | /** |
| 212 | * structure is used to pass directory traversal options to the library and to |
| 213 | * record the paths discovered. A single `struct dir_struct` is used regardless |
| 214 | * of whether or not the traversal recursively descends into subdirectories. |
| 215 | */ |
| 216 | struct dir_struct { |
| 217 | |
| 218 | /* bit-field of options */ |
| 219 | enum { |
| 220 | |
| 221 | /** |
| 222 | * Return just ignored files in `entries[]`, not untracked files. |
| 223 | * This flag is mutually exclusive with `DIR_SHOW_IGNORED_TOO`. |
| 224 | */ |
| 225 | DIR_SHOW_IGNORED = 1<<0, |
| 226 | |
| 227 | /* Include a directory that is not tracked. */ |
| 228 | DIR_SHOW_OTHER_DIRECTORIES = 1<<1, |
| 229 | |
| 230 | /* Do not include a directory that is not tracked and is empty. */ |
| 231 | DIR_HIDE_EMPTY_DIRECTORIES = 1<<2, |
| 232 | |
| 233 | /** |
| 234 | * If set, recurse into a directory that looks like a Git directory. |
| 235 | * Otherwise it is shown as a directory. |
| 236 | */ |
| 237 | DIR_NO_GITLINKS = 1<<3, |
| 238 | |
| 239 | /** |
| 240 | * Special mode for git-add. Return ignored files in `ignored[]` and |
| 241 | * untracked files in `entries[]`. Only returns ignored files that match |
| 242 | * pathspec exactly (no wildcards). Does not recurse into ignored |
| 243 | * directories. |
| 244 | */ |
| 245 | DIR_COLLECT_IGNORED = 1<<4, |
| 246 | |
| 247 | /** |
| 248 | * Similar to `DIR_SHOW_IGNORED`, but return ignored files in |
| 249 | * `ignored[]` in addition to untracked files in `entries[]`. |
| 250 | * This flag is mutually exclusive with `DIR_SHOW_IGNORED`. |
| 251 | */ |
| 252 | DIR_SHOW_IGNORED_TOO = 1<<5, |
| 253 | |
| 254 | DIR_COLLECT_KILLED_ONLY = 1<<6, |
| 255 | |
| 256 | /** |
| 257 | * Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is |
| 258 | * set, the untracked contents of untracked directories are also |
| 259 | * returned in `entries[]`. |
| 260 | */ |
| 261 | DIR_KEEP_UNTRACKED_CONTENTS = 1<<7, |
| 262 | |
| 263 | /** |
| 264 | * Only has meaning if `DIR_SHOW_IGNORED_TOO` is also set; if this is |
| 265 | * set, returns ignored files and directories that match an exclude |
| 266 | * pattern. If a directory matches an exclude pattern, then the |
| 267 | * directory is returned and the contained paths are not. A directory |
| 268 | * that does not match an exclude pattern will not be returned even if |
| 269 | * all of its contents are ignored. In this case, the contents are |
| 270 | * returned as individual entries. |
| 271 | * |
| 272 | * If this is set, files and directories that explicitly match an ignore |
| 273 | * pattern are reported. Implicitly ignored directories (directories that |
| 274 | * do not match an ignore pattern, but whose contents are all ignored) |
| 275 | * are not reported, instead all of the contents are reported. |
| 276 | */ |
| 277 | DIR_SHOW_IGNORED_TOO_MODE_MATCHING = 1<<8, |
| 278 | |
| 279 | DIR_SKIP_NESTED_GIT = 1<<9 |
| 280 | } flags; |
| 281 | |
| 282 | /* The number of members in `entries[]` array. */ |
| 283 | int nr; /* output only */ |
| 284 | |
| 285 | /* The number of members in `ignored[]` array. */ |
| 286 | int ignored_nr; /* output only */ |
| 287 | |
| 288 | /* An array of `struct dir_entry`, each element of which describes a path. */ |
| 289 | struct dir_entry **entries; /* output only */ |
| 290 | |
| 291 | /** |
| 292 | * used for ignored paths with the `DIR_SHOW_IGNORED_TOO` and |
| 293 | * `DIR_COLLECT_IGNORED` flags. |
| 294 | */ |
| 295 | struct dir_entry **ignored; /* output only */ |
| 296 | |
| 297 | /* Enable/update untracked file cache if set */ |
| 298 | struct untracked_cache *untracked; |
| 299 | |
| 300 | /** |
| 301 | * Deprecated: ls-files is the only allowed caller; all other callers |
| 302 | * should leave this as NULL; it pre-dated the |
| 303 | * setup_standard_excludes() mechanism that replaces this. |
| 304 | * |
| 305 | * This field tracks the name of the file to be read in each directory |
| 306 | * for excluded files (typically `.gitignore`). |
| 307 | */ |
| 308 | const char *exclude_per_dir; |
| 309 | |
| 310 | struct dir_struct_internal { |
| 311 | /* Keeps track of allocation of `entries[]` array.*/ |
| 312 | int alloc; |
| 313 | |
| 314 | /* Keeps track of allocation of `ignored[]` array. */ |
| 315 | int ignored_alloc; |
| 316 | |
| 317 | /* |
| 318 | * We maintain three groups of exclude pattern lists: |
| 319 | * |
| 320 | * EXC_CMDL lists patterns explicitly given on the command line. |
| 321 | * EXC_DIRS lists patterns obtained from per-directory ignore |
| 322 | * files. |
| 323 | * EXC_FILE lists patterns from fallback ignore files, e.g. |
| 324 | * - .git/info/exclude |
| 325 | * - core.excludesfile |
| 326 | * |
| 327 | * Each group contains multiple exclude lists, a single list |
| 328 | * per source. |
| 329 | */ |
| 330 | #define EXC_CMDL 0 |
| 331 | #define EXC_DIRS 1 |
| 332 | #define EXC_FILE 2 |
| 333 | struct exclude_list_group exclude_list_group[3]; |
| 334 | |
| 335 | /* |
| 336 | * Temporary variables which are used during loading of the |
| 337 | * per-directory exclude lists. |
| 338 | * |
| 339 | * exclude_stack points to the top of the exclude_stack, and |
| 340 | * basebuf contains the full path to the current |
| 341 | * (sub)directory in the traversal. Exclude points to the |
| 342 | * matching exclude struct if the directory is excluded. |
| 343 | */ |
| 344 | struct exclude_stack *exclude_stack; |
| 345 | struct path_pattern *pattern; |
| 346 | struct strbuf basebuf; |
| 347 | |
| 348 | /* Additional metadata related to 'untracked' */ |
| 349 | struct oid_stat ss_info_exclude; |
| 350 | struct oid_stat ss_excludes_file; |
| 351 | unsigned unmanaged_exclude_files; |
| 352 | |
| 353 | /* Stats about the traversal */ |
| 354 | unsigned visited_paths; |
| 355 | unsigned visited_directories; |
| 356 | } internal; |
| 357 | }; |
| 358 | |
| 359 | #define DIR_INIT { 0 } |
| 360 | |
| 361 | struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp); |
| 362 | |
| 363 | /* |
| 364 | * Get the d_type of a dirent. If the d_type is unknown, derive it from |
| 365 | * stat.st_mode using the path to the dirent's containing directory (path) and |
| 366 | * the name of the dirent itself. |
| 367 | * |
| 368 | * If 'follow_symlink' is 1, this function will attempt to follow DT_LNK types |
| 369 | * using 'stat'. Links are *not* followed recursively, so a symlink pointing |
| 370 | * to another symlink will still resolve to 'DT_LNK'. |
| 371 | * |
| 372 | * Note that 'path' is assumed to have a trailing slash. It is also modified |
| 373 | * in-place during the execution of the function, but is then reverted to its |
| 374 | * original value before returning. |
| 375 | */ |
| 376 | unsigned char get_dtype(struct dirent *e, struct strbuf *path, |
| 377 | int follow_symlink); |
| 378 | |
| 379 | /*Count the number of slashes for string s*/ |
| 380 | int count_slashes(const char *s); |
| 381 | |
| 382 | /* |
| 383 | * The ordering of these constants is significant, with |
| 384 | * higher-numbered match types signifying "closer" (i.e. more |
| 385 | * specific) matches which will override lower-numbered match types |
| 386 | * when populating the seen[] array. |
| 387 | */ |
| 388 | #define MATCHED_RECURSIVELY 1 |
| 389 | #define MATCHED_RECURSIVELY_LEADING_PATHSPEC 2 |
| 390 | #define MATCHED_FNMATCH 3 |
| 391 | #define MATCHED_EXACTLY 4 |
| 392 | int simple_length(const char *match); |
| 393 | int no_wildcard(const char *string); |
| 394 | char *common_prefix(const struct pathspec *pathspec); |
| 395 | int report_path_error(const char *ps_matched, const struct pathspec *pathspec); |
| 396 | int within_depth(const char *name, int namelen, int depth, int max_depth); |
| 397 | |
| 398 | int fill_directory(struct dir_struct *dir, |
| 399 | struct index_state *istate, |
| 400 | const struct pathspec *pathspec); |
| 401 | int read_directory(struct dir_struct *, struct index_state *istate, |
| 402 | const char *path, int len, |
| 403 | const struct pathspec *pathspec); |
| 404 | |
| 405 | enum pattern_match_result { |
| 406 | UNDECIDED = -1, |
| 407 | NOT_MATCHED = 0, |
| 408 | MATCHED = 1, |
| 409 | MATCHED_RECURSIVE = 2, |
| 410 | }; |
| 411 | |
| 412 | /* |
| 413 | * Scan the list of patterns to determine if the ordered list |
| 414 | * of patterns matches on 'pathname'. |
| 415 | * |
| 416 | * Return 1 for a match, 0 for not matched and -1 for undecided. |
| 417 | */ |
| 418 | enum pattern_match_result path_matches_pattern_list(const char *pathname, |
| 419 | int pathlen, |
| 420 | const char *basename, int *dtype, |
| 421 | struct pattern_list *pl, |
| 422 | struct index_state *istate); |
| 423 | |
| 424 | int init_sparse_checkout_patterns(struct index_state *state); |
| 425 | |
| 426 | int path_in_sparse_checkout(const char *path, |
| 427 | struct index_state *istate); |
| 428 | int path_in_cone_mode_sparse_checkout(const char *path, |
| 429 | struct index_state *istate); |
| 430 | |
| 431 | struct dir_entry *dir_add_ignored(struct dir_struct *dir, |
| 432 | struct index_state *istate, |
| 433 | const char *pathname, int len); |
| 434 | |
| 435 | /* |
| 436 | * these implement the matching logic for dir.c:excluded_from_list and |
| 437 | * attr.c:path_matches() |
| 438 | */ |
| 439 | int match_basename(const char *, int, |
| 440 | const char *, int, int, unsigned); |
| 441 | int match_pathname(const char *, int, |
| 442 | const char *, int, |
| 443 | const char *, int, int); |
| 444 | |
| 445 | struct path_pattern *last_matching_pattern(struct dir_struct *dir, |
| 446 | struct index_state *istate, |
| 447 | const char *name, int *dtype); |
| 448 | |
| 449 | int is_excluded(struct dir_struct *dir, |
| 450 | struct index_state *istate, |
| 451 | const char *name, int *dtype); |
| 452 | |
| 453 | int pl_hashmap_cmp(const void *unused_cmp_data, |
| 454 | const struct hashmap_entry *a, |
| 455 | const struct hashmap_entry *b, |
| 456 | const void *key); |
| 457 | int hashmap_contains_parent(struct hashmap *map, |
| 458 | const char *path, |
| 459 | struct strbuf *buffer); |
| 460 | struct pattern_list *add_pattern_list(struct dir_struct *dir, |
| 461 | int group_type, const char *src); |
| 462 | int add_patterns_from_file_to_list(const char *fname, const char *base, int baselen, |
| 463 | struct pattern_list *pl, struct index_state *istate, |
| 464 | unsigned flags); |
| 465 | void add_patterns_from_file(struct dir_struct *, const char *fname); |
| 466 | int add_patterns_from_blob_to_list(struct object_id *oid, |
| 467 | const char *base, int baselen, |
| 468 | struct pattern_list *pl); |
| 469 | int add_patterns_from_buffer(char *buf, size_t size, |
| 470 | const char *base, int baselen, |
| 471 | struct pattern_list *pl); |
| 472 | void parse_path_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen); |
| 473 | void add_pattern(const char *string, const char *base, |
| 474 | int baselen, struct pattern_list *pl, int srcpos); |
| 475 | void clear_pattern_list(struct pattern_list *pl); |
| 476 | void dir_clear(struct dir_struct *dir); |
| 477 | |
| 478 | int repo_file_exists(struct repository *repo, const char *path); |
| 479 | int file_exists(const char *); |
| 480 | |
| 481 | int is_inside_dir(const char *dir); |
| 482 | int dir_inside_of(const char *subdir, const char *dir); |
| 483 | |
| 484 | static inline int is_dot_or_dotdot(const char *name) |
| 485 | { |
| 486 | return (name[0] == '.' && |
| 487 | (name[1] == '\0' || |
| 488 | (name[1] == '.' && name[2] == '\0'))); |
| 489 | } |
| 490 | |
| 491 | int is_empty_dir(const char *dir); |
| 492 | |
| 493 | /* |
| 494 | * Retrieve the "humanish" basename of the given Git URL. |
| 495 | * |
| 496 | * For example: |
| 497 | * /path/to/repo.git => "repo" |
| 498 | * host.xz:foo/.git => "foo" |
| 499 | * http://example.com/user/bar.baz => "bar.baz" |
| 500 | */ |
| 501 | char *git_url_basename(const char *repo, int is_bundle, int is_bare); |
| 502 | void strip_dir_trailing_slashes(char *dir); |
| 503 | |
| 504 | void setup_standard_excludes(struct dir_struct *dir); |
| 505 | |
| 506 | char *get_sparse_checkout_filename(void); |
| 507 | int get_sparse_checkout_patterns(struct pattern_list *pl); |
| 508 | |
| 509 | /* Constants for remove_dir_recursively: */ |
| 510 | |
| 511 | /* |
| 512 | * If a non-directory is found within path, stop and return an error. |
| 513 | * (In this case some empty directories might already have been |
| 514 | * removed.) |
| 515 | */ |
| 516 | #define REMOVE_DIR_EMPTY_ONLY 01 |
| 517 | |
| 518 | /* |
| 519 | * If any Git work trees are found within path, skip them without |
| 520 | * considering it an error. |
| 521 | */ |
| 522 | #define REMOVE_DIR_KEEP_NESTED_GIT 02 |
| 523 | |
| 524 | /* Remove the contents of path, but leave path itself. */ |
| 525 | #define REMOVE_DIR_KEEP_TOPLEVEL 04 |
| 526 | |
| 527 | /* Remove the_original_cwd too */ |
| 528 | #define REMOVE_DIR_PURGE_ORIGINAL_CWD 0x08 |
| 529 | |
| 530 | /* |
| 531 | * Remove path and its contents, recursively. flags is a combination |
| 532 | * of the above REMOVE_DIR_* constants. Return 0 on success. |
| 533 | * |
| 534 | * This function uses path as temporary scratch space, but restores it |
| 535 | * before returning. |
| 536 | */ |
| 537 | int remove_dir_recursively(struct strbuf *path, int flag); |
| 538 | |
| 539 | /* |
| 540 | * This function pointer type is called on each file discovered in |
| 541 | * for_each_file_in_dir. The iteration stops if this method returns |
| 542 | * non-zero. |
| 543 | */ |
| 544 | typedef int (*file_iterator)(const char *path, const void *data); |
| 545 | |
| 546 | struct strbuf; |
| 547 | /* |
| 548 | * Given a directory path, recursively visit each file within, including |
| 549 | * within subdirectories. |
| 550 | */ |
| 551 | int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data); |
| 552 | |
| 553 | /* |
| 554 | * Tries to remove the path, along with leading empty directories so long as |
| 555 | * those empty directories are not startup_info->original_cwd. Ignores |
| 556 | * ENOENT. |
| 557 | */ |
| 558 | int remove_path(const char *path); |
| 559 | |
| 560 | int git_fspathcmp(const char *a, const char *b); |
| 561 | int fspatheq(const char *a, const char *b); |
| 562 | int git_fspathncmp(const char *a, const char *b, size_t count); |
| 563 | unsigned int fspathhash(const char *str); |
| 564 | |
| 565 | /* |
| 566 | * Reports whether paths collide. This may be because the paths differ only in |
| 567 | * case on a case-sensitive filesystem, or that one path refers to a symlink |
| 568 | * that collides with one of the parent directories of the other. |
| 569 | */ |
| 570 | int paths_collide(const char *a, const char *b); |
| 571 | |
| 572 | /* |
| 573 | * The prefix part of pattern must not contains wildcards. |
| 574 | */ |
| 575 | struct pathspec_item; |
| 576 | int git_fnmatch(const struct pathspec_item *item, |
| 577 | const char *pattern, const char *string, |
| 578 | int prefix); |
| 579 | |
| 580 | int submodule_path_match(struct index_state *istate, |
| 581 | const struct pathspec *ps, |
| 582 | const char *submodule_name, |
| 583 | char *seen); |
| 584 | |
| 585 | static inline int dir_path_match(struct index_state *istate, |
| 586 | const struct dir_entry *ent, |
| 587 | const struct pathspec *pathspec, |
| 588 | int prefix, char *seen) |
| 589 | { |
| 590 | int has_trailing_dir = ent->len && ent->name[ent->len - 1] == '/'; |
| 591 | int len = has_trailing_dir ? ent->len - 1 : ent->len; |
| 592 | return match_pathspec(istate, pathspec, ent->name, len, prefix, seen, |
| 593 | has_trailing_dir); |
| 594 | } |
| 595 | |
| 596 | int cmp_dir_entry(const void *p1, const void *p2); |
| 597 | int check_dir_entry_contains(const struct dir_entry *out, const struct dir_entry *in); |
| 598 | |
| 599 | void untracked_cache_invalidate_path(struct index_state *, const char *, int safe_path); |
| 600 | /* |
| 601 | * Invalidate the untracked-cache for this path, but first strip |
| 602 | * off a trailing slash, if present. |
| 603 | */ |
| 604 | void untracked_cache_invalidate_trimmed_path(struct index_state *, |
| 605 | const char *path, |
| 606 | int safe_path); |
| 607 | void untracked_cache_remove_from_index(struct index_state *, const char *); |
| 608 | void untracked_cache_add_to_index(struct index_state *, const char *); |
| 609 | |
| 610 | void free_untracked_cache(struct untracked_cache *); |
| 611 | struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz); |
| 612 | void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked); |
| 613 | void add_untracked_cache(struct index_state *istate); |
| 614 | void remove_untracked_cache(struct index_state *istate); |
| 615 | |
| 616 | /* |
| 617 | * Connect a worktree to a git directory by creating (or overwriting) a |
| 618 | * '.git' file containing the location of the git directory. In the git |
| 619 | * directory set the core.worktree setting to indicate where the worktree is. |
| 620 | * When `recurse_into_nested` is set, recurse into any nested submodules, |
| 621 | * connecting them as well. |
| 622 | */ |
| 623 | void connect_work_tree_and_git_dir(const char *work_tree, |
| 624 | const char *git_dir, |
| 625 | int recurse_into_nested); |
| 626 | void relocate_gitdir(const char *path, |
| 627 | const char *old_git_dir, |
| 628 | const char *new_git_dir); |
| 629 | |
| 630 | /** |
| 631 | * The "enum path_matches_kind" determines how path_match_flags() will |
| 632 | * behave. The flags come in sets, and one (and only one) must be |
| 633 | * provided out of each "set": |
| 634 | * |
| 635 | * PATH_MATCH_NATIVE: |
| 636 | * Path separator is is_dir_sep() |
| 637 | * PATH_MATCH_XPLATFORM: |
| 638 | * Path separator is is_xplatform_dir_sep() |
| 639 | * |
| 640 | * Do we use is_dir_sep() to check for a directory separator |
| 641 | * (*_NATIVE), or do we always check for '/' or '\' (*_XPLATFORM). The |
| 642 | * "*_NATIVE" version on Windows is the same as "*_XPLATFORM", |
| 643 | * everywhere else "*_NATIVE" means "only /". |
| 644 | * |
| 645 | * PATH_MATCH_STARTS_WITH_DOT_SLASH: |
| 646 | * Match a path starting with "./" |
| 647 | * PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH: |
| 648 | * Match a path starting with "../" |
| 649 | * |
| 650 | * The "/" in the above is adjusted based on the "*_NATIVE" and |
| 651 | * "*_XPLATFORM" flags. |
| 652 | */ |
| 653 | enum path_match_flags { |
| 654 | PATH_MATCH_NATIVE = 1 << 0, |
| 655 | PATH_MATCH_XPLATFORM = 1 << 1, |
| 656 | PATH_MATCH_STARTS_WITH_DOT_SLASH = 1 << 2, |
| 657 | PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH = 1 << 3, |
| 658 | }; |
| 659 | #define PATH_MATCH_KINDS_MASK (PATH_MATCH_STARTS_WITH_DOT_SLASH | \ |
| 660 | PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH) |
| 661 | #define PATH_MATCH_PLATFORM_MASK (PATH_MATCH_NATIVE | PATH_MATCH_XPLATFORM) |
| 662 | |
| 663 | /** |
| 664 | * path_match_flags() checks if a given "path" matches a given "enum |
| 665 | * path_match_flags" criteria. |
| 666 | */ |
| 667 | int path_match_flags(const char *const path, const enum path_match_flags f); |
| 668 | |
| 669 | /** |
| 670 | * starts_with_dot_slash_native(): convenience wrapper for |
| 671 | * path_match_flags() with PATH_MATCH_STARTS_WITH_DOT_SLASH and |
| 672 | * PATH_MATCH_NATIVE. |
| 673 | */ |
| 674 | static inline int starts_with_dot_slash_native(const char *const path) |
| 675 | { |
| 676 | const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_SLASH; |
| 677 | |
| 678 | return path_match_flags(path, what | PATH_MATCH_NATIVE); |
| 679 | } |
| 680 | |
| 681 | /** |
| 682 | * starts_with_dot_slash_native(): convenience wrapper for |
| 683 | * path_match_flags() with PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH and |
| 684 | * PATH_MATCH_NATIVE. |
| 685 | */ |
| 686 | static inline int starts_with_dot_dot_slash_native(const char *const path) |
| 687 | { |
| 688 | const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH; |
| 689 | |
| 690 | return path_match_flags(path, what | PATH_MATCH_NATIVE); |
| 691 | } |
| 692 | |
| 693 | /** |
| 694 | * starts_with_dot_slash: convenience wrapper for |
| 695 | * patch_match_flags() with PATH_MATCH_STARTS_WITH_DOT_SLASH and |
| 696 | * PATH_MATCH_XPLATFORM. |
| 697 | */ |
| 698 | static inline int starts_with_dot_slash(const char *const path) |
| 699 | { |
| 700 | const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_SLASH; |
| 701 | |
| 702 | return path_match_flags(path, what | PATH_MATCH_XPLATFORM); |
| 703 | } |
| 704 | |
| 705 | /** |
| 706 | * starts_with_dot_dot_slash: convenience wrapper for |
| 707 | * patch_match_flags() with PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH and |
| 708 | * PATH_MATCH_XPLATFORM. |
| 709 | */ |
| 710 | static inline int starts_with_dot_dot_slash(const char *const path) |
| 711 | { |
| 712 | const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH; |
| 713 | |
| 714 | return path_match_flags(path, what | PATH_MATCH_XPLATFORM); |
| 715 | } |
| 716 | #endif |