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