1 /* 2 * Copyright (C) the libgit2 contributors. All rights reserved. 3 * 4 * This file is part of libgit2, distributed under the GNU GPL v2 with 5 * a Linking Exception. For full terms see the included COPYING file. 6 */ 7 #ifndef INCLUDE_git_status_h__ 8 #define INCLUDE_git_status_h__ 9 10 #include "common.h" 11 #include "types.h" 12 #include "strarray.h" 13 #include "diff.h" 14 15 /** 16 * @file git2/status.h 17 * @brief Git file status routines 18 * @defgroup git_status Git file status routines 19 * @ingroup Git 20 * @{ 21 */ 22 GIT_BEGIN_DECL 23 24 /** 25 * Status flags for a single file. 26 * 27 * A combination of these values will be returned to indicate the status of 28 * a file. Status compares the working directory, the index, and the 29 * current HEAD of the repository. The `GIT_STATUS_INDEX` set of flags 30 * represents the status of file in the index relative to the HEAD, and the 31 * `GIT_STATUS_WT` set of flags represent the status of the file in the 32 * working directory relative to the index. 33 */ 34 typedef enum { 35 GIT_STATUS_CURRENT = 0, 36 37 GIT_STATUS_INDEX_NEW = (1u << 0), 38 GIT_STATUS_INDEX_MODIFIED = (1u << 1), 39 GIT_STATUS_INDEX_DELETED = (1u << 2), 40 GIT_STATUS_INDEX_RENAMED = (1u << 3), 41 GIT_STATUS_INDEX_TYPECHANGE = (1u << 4), 42 43 GIT_STATUS_WT_NEW = (1u << 7), 44 GIT_STATUS_WT_MODIFIED = (1u << 8), 45 GIT_STATUS_WT_DELETED = (1u << 9), 46 GIT_STATUS_WT_TYPECHANGE = (1u << 10), 47 GIT_STATUS_WT_RENAMED = (1u << 11), 48 GIT_STATUS_WT_UNREADABLE = (1u << 12), 49 50 GIT_STATUS_IGNORED = (1u << 14), 51 GIT_STATUS_CONFLICTED = (1u << 15), 52 } git_status_t; 53 54 /** 55 * Function pointer to receive status on individual files 56 * 57 * `path` is the relative path to the file from the root of the repository. 58 * 59 * `status_flags` is a combination of `git_status_t` values that apply. 60 * 61 * `payload` is the value you passed to the foreach function as payload. 62 */ 63 typedef int GIT_CALLBACK(git_status_cb)( 64 const char *path, unsigned int status_flags, void *payload); 65 66 /** 67 * Select the files on which to report status. 68 * 69 * With `git_status_foreach_ext`, this will control which changes get 70 * callbacks. With `git_status_list_new`, these will control which 71 * changes are included in the list. 72 */ 73 typedef enum { 74 /** 75 * The default. This roughly matches `git status --porcelain` regarding 76 * which files are included and in what order. 77 */ 78 GIT_STATUS_SHOW_INDEX_AND_WORKDIR = 0, 79 80 /** 81 * Only gives status based on HEAD to index comparison, not looking at 82 * working directory changes. 83 */ 84 GIT_STATUS_SHOW_INDEX_ONLY = 1, 85 86 /** 87 * Only gives status based on index to working directory comparison, 88 * not comparing the index to the HEAD. 89 */ 90 GIT_STATUS_SHOW_WORKDIR_ONLY = 2, 91 } git_status_show_t; 92 93 /** 94 * Flags to control status callbacks 95 * 96 * Calling `git_status_foreach()` is like calling the extended version 97 * with: GIT_STATUS_OPT_INCLUDE_IGNORED, GIT_STATUS_OPT_INCLUDE_UNTRACKED, 98 * and GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS. Those options are bundled 99 * together as `GIT_STATUS_OPT_DEFAULTS` if you want them as a baseline. 100 */ 101 typedef enum { 102 /** 103 * Says that callbacks should be made on untracked files. 104 * These will only be made if the workdir files are included in the status 105 * "show" option. 106 */ 107 GIT_STATUS_OPT_INCLUDE_UNTRACKED = (1u << 0), 108 109 /** 110 * Says that ignored files get callbacks. 111 * Again, these callbacks will only be made if the workdir files are 112 * included in the status "show" option. 113 */ 114 GIT_STATUS_OPT_INCLUDE_IGNORED = (1u << 1), 115 116 /** 117 * Indicates that callback should be made even on unmodified files. 118 */ 119 GIT_STATUS_OPT_INCLUDE_UNMODIFIED = (1u << 2), 120 121 /** 122 * Indicates that submodules should be skipped. 123 * This only applies if there are no pending typechanges to the submodule 124 * (either from or to another type). 125 */ 126 GIT_STATUS_OPT_EXCLUDE_SUBMODULES = (1u << 3), 127 128 /** 129 * Indicates that all files in untracked directories should be included. 130 * Normally if an entire directory is new, then just the top-level 131 * directory is included (with a trailing slash on the entry name). 132 * This flag says to include all of the individual files in the directory 133 * instead. 134 */ 135 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS = (1u << 4), 136 137 /** 138 * Indicates that the given path should be treated as a literal path, 139 * and not as a pathspec pattern. 140 */ 141 GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH = (1u << 5), 142 143 /** 144 * Indicates that the contents of ignored directories should be included 145 * in the status. This is like doing `git ls-files -o -i --exclude-standard` 146 * with core git. 147 */ 148 GIT_STATUS_OPT_RECURSE_IGNORED_DIRS = (1u << 6), 149 150 /** 151 * Indicates that rename detection should be processed between the head and 152 * the index and enables the GIT_STATUS_INDEX_RENAMED as a possible status 153 * flag. 154 */ 155 GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX = (1u << 7), 156 157 /** 158 * Indicates that rename detection should be run between the index and the 159 * working directory and enabled GIT_STATUS_WT_RENAMED as a possible status 160 * flag. 161 */ 162 GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR = (1u << 8), 163 164 /** 165 * Overrides the native case sensitivity for the file system and forces 166 * the output to be in case-sensitive order. 167 */ 168 GIT_STATUS_OPT_SORT_CASE_SENSITIVELY = (1u << 9), 169 170 /** 171 * Overrides the native case sensitivity for the file system and forces 172 * the output to be in case-insensitive order. 173 */ 174 GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY = (1u << 10), 175 176 /** 177 * Iindicates that rename detection should include rewritten files. 178 */ 179 GIT_STATUS_OPT_RENAMES_FROM_REWRITES = (1u << 11), 180 181 /** 182 * Bypasses the default status behavior of doing a "soft" index reload 183 * (i.e. reloading the index data if the file on disk has been modified 184 * outside libgit2). 185 */ 186 GIT_STATUS_OPT_NO_REFRESH = (1u << 12), 187 188 /** 189 * Tells libgit2 to refresh the stat cache in the index for files that are 190 * unchanged but have out of date stat einformation in the index. 191 * It will result in less work being done on subsequent calls to get status. 192 * This is mutually exclusive with the NO_REFRESH option. 193 */ 194 GIT_STATUS_OPT_UPDATE_INDEX = (1u << 13), 195 196 /** 197 * Normally files that cannot be opened or read are ignored as 198 * these are often transient files; this option will return 199 * unreadable files as `GIT_STATUS_WT_UNREADABLE`. 200 */ 201 GIT_STATUS_OPT_INCLUDE_UNREADABLE = (1u << 14), 202 203 /** 204 * Unreadable files will be detected and given the status 205 * untracked instead of unreadable. 206 */ 207 GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED = (1u << 15), 208 } git_status_opt_t; 209 210 #define GIT_STATUS_OPT_DEFAULTS \ 211 (GIT_STATUS_OPT_INCLUDE_IGNORED | \ 212 GIT_STATUS_OPT_INCLUDE_UNTRACKED | \ 213 GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS) 214 215 /** 216 * Options to control how `git_status_foreach_ext()` will issue callbacks. 217 * 218 * Initialize with `GIT_STATUS_OPTIONS_INIT`. Alternatively, you can 219 * use `git_status_options_init`. 220 * 221 */ 222 typedef struct { 223 /** 224 * The struct version; pass `GIT_STATUS_OPTIONS_VERSION`. 225 */ 226 unsigned int version; 227 228 /** 229 * The `show` value is one of the `git_status_show_t` constants that 230 * control which files to scan and in what order. 231 */ 232 git_status_show_t show; 233 234 /** 235 * The `flags` value is an OR'ed combination of the 236 * `git_status_opt_t` values above. 237 */ 238 unsigned int flags; 239 240 /** 241 * The `pathspec` is an array of path patterns to match (using 242 * fnmatch-style matching), or just an array of paths to match 243 * exactly if `GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH` is specified 244 * in the flags. 245 */ 246 git_strarray pathspec; 247 248 /** 249 * The `baseline` is the tree to be used for comparison to the 250 * working directory and index; defaults to HEAD. 251 */ 252 git_tree *baseline; 253 } git_status_options; 254 255 #define GIT_STATUS_OPTIONS_VERSION 1 256 #define GIT_STATUS_OPTIONS_INIT {GIT_STATUS_OPTIONS_VERSION} 257 258 /** 259 * Initialize git_status_options structure 260 * 261 * Initializes a `git_status_options` with default values. Equivalent to 262 * creating an instance with `GIT_STATUS_OPTIONS_INIT`. 263 * 264 * @param opts The `git_status_options` struct to initialize. 265 * @param version The struct version; pass `GIT_STATUS_OPTIONS_VERSION`. 266 * @return Zero on success; -1 on failure. 267 */ 268 GIT_EXTERN(int) git_status_options_init( 269 git_status_options *opts, 270 unsigned int version); 271 272 /** 273 * A status entry, providing the differences between the file as it exists 274 * in HEAD and the index, and providing the differences between the index 275 * and the working directory. 276 * 277 * The `status` value provides the status flags for this file. 278 * 279 * The `head_to_index` value provides detailed information about the 280 * differences between the file in HEAD and the file in the index. 281 * 282 * The `index_to_workdir` value provides detailed information about the 283 * differences between the file in the index and the file in the 284 * working directory. 285 */ 286 typedef struct { 287 git_status_t status; 288 git_diff_delta *head_to_index; 289 git_diff_delta *index_to_workdir; 290 } git_status_entry; 291 292 293 /** 294 * Gather file statuses and run a callback for each one. 295 * 296 * The callback is passed the path of the file, the status (a combination of 297 * the `git_status_t` values above) and the `payload` data pointer passed 298 * into this function. 299 * 300 * If the callback returns a non-zero value, this function will stop looping 301 * and return that value to caller. 302 * 303 * @param repo A repository object 304 * @param callback The function to call on each file 305 * @param payload Pointer to pass through to callback function 306 * @return 0 on success, non-zero callback return value, or error code 307 */ 308 GIT_EXTERN(int) git_status_foreach( 309 git_repository *repo, 310 git_status_cb callback, 311 void *payload); 312 313 /** 314 * Gather file status information and run callbacks as requested. 315 * 316 * This is an extended version of the `git_status_foreach()` API that 317 * allows for more granular control over which paths will be processed and 318 * in what order. See the `git_status_options` structure for details 319 * about the additional controls that this makes available. 320 * 321 * Note that if a `pathspec` is given in the `git_status_options` to filter 322 * the status, then the results from rename detection (if you enable it) may 323 * not be accurate. To do rename detection properly, this must be called 324 * with no `pathspec` so that all files can be considered. 325 * 326 * @param repo Repository object 327 * @param opts Status options structure 328 * @param callback The function to call on each file 329 * @param payload Pointer to pass through to callback function 330 * @return 0 on success, non-zero callback return value, or error code 331 */ 332 GIT_EXTERN(int) git_status_foreach_ext( 333 git_repository *repo, 334 const git_status_options *opts, 335 git_status_cb callback, 336 void *payload); 337 338 /** 339 * Get file status for a single file. 340 * 341 * This tries to get status for the filename that you give. If no files 342 * match that name (in either the HEAD, index, or working directory), this 343 * returns GIT_ENOTFOUND. 344 * 345 * If the name matches multiple files (for example, if the `path` names a 346 * directory or if running on a case- insensitive filesystem and yet the 347 * HEAD has two entries that both match the path), then this returns 348 * GIT_EAMBIGUOUS because it cannot give correct results. 349 * 350 * This does not do any sort of rename detection. Renames require a set of 351 * targets and because of the path filtering, there is not enough 352 * information to check renames correctly. To check file status with rename 353 * detection, there is no choice but to do a full `git_status_list_new` and 354 * scan through looking for the path that you are interested in. 355 * 356 * @param status_flags Output combination of git_status_t values for file 357 * @param repo A repository object 358 * @param path The exact path to retrieve status for relative to the 359 * repository working directory 360 * @return 0 on success, GIT_ENOTFOUND if the file is not found in the HEAD, 361 * index, and work tree, GIT_EAMBIGUOUS if `path` matches multiple files 362 * or if it refers to a folder, and -1 on other errors. 363 */ 364 GIT_EXTERN(int) git_status_file( 365 unsigned int *status_flags, 366 git_repository *repo, 367 const char *path); 368 369 /** 370 * Gather file status information and populate the `git_status_list`. 371 * 372 * Note that if a `pathspec` is given in the `git_status_options` to filter 373 * the status, then the results from rename detection (if you enable it) may 374 * not be accurate. To do rename detection properly, this must be called 375 * with no `pathspec` so that all files can be considered. 376 * 377 * @param out Pointer to store the status results in 378 * @param repo Repository object 379 * @param opts Status options structure 380 * @return 0 on success or error code 381 */ 382 GIT_EXTERN(int) git_status_list_new( 383 git_status_list **out, 384 git_repository *repo, 385 const git_status_options *opts); 386 387 /** 388 * Gets the count of status entries in this list. 389 * 390 * If there are no changes in status (at least according the options given 391 * when the status list was created), this can return 0. 392 * 393 * @param statuslist Existing status list object 394 * @return the number of status entries 395 */ 396 GIT_EXTERN(size_t) git_status_list_entrycount( 397 git_status_list *statuslist); 398 399 /** 400 * Get a pointer to one of the entries in the status list. 401 * 402 * The entry is not modifiable and should not be freed. 403 * 404 * @param statuslist Existing status list object 405 * @param idx Position of the entry 406 * @return Pointer to the entry; NULL if out of bounds 407 */ 408 GIT_EXTERN(const git_status_entry *) git_status_byindex( 409 git_status_list *statuslist, 410 size_t idx); 411 412 /** 413 * Free an existing status list 414 * 415 * @param statuslist Existing status list object 416 */ 417 GIT_EXTERN(void) git_status_list_free( 418 git_status_list *statuslist); 419 420 /** 421 * Test if the ignore rules apply to a given file. 422 * 423 * This function checks the ignore rules to see if they would apply to the 424 * given file. This indicates if the file would be ignored regardless of 425 * whether the file is already in the index or committed to the repository. 426 * 427 * One way to think of this is if you were to do "git add ." on the 428 * directory containing the file, would it be added or not? 429 * 430 * @param ignored Boolean returning 0 if the file is not ignored, 1 if it is 431 * @param repo A repository object 432 * @param path The file to check ignores for, rooted at the repo's workdir. 433 * @return 0 if ignore rules could be processed for the file (regardless 434 * of whether it exists or not), or an error < 0 if they could not. 435 */ 436 GIT_EXTERN(int) git_status_should_ignore( 437 int *ignored, 438 git_repository *repo, 439 const char *path); 440 441 /** @} */ 442 GIT_END_DECL 443 #endif 444