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