source src/status.c
| Line | Flow | Count | Block(s) | Source |
|---|---|---|---|---|
| 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 | - | |||
| 8 | - | #include "status.h" | ||
| 9 | - | |||
| 10 | - | #include "git2.h" | ||
| 11 | - | #include "futils.h" | ||
| 12 | - | #include "hash.h" | ||
| 13 | - | #include "vector.h" | ||
| 14 | - | #include "tree.h" | ||
| 15 | - | #include "git2/status.h" | ||
| 16 | - | #include "repository.h" | ||
| 17 | - | #include "ignore.h" | ||
| 18 | - | #include "index.h" | ||
| 19 | - | #include "wildmatch.h" | ||
| 20 | - | |||
| 21 | - | #include "git2/diff.h" | ||
| 22 | - | #include "diff.h" | ||
| 23 | - | #include "diff_generate.h" | ||
| 24 | - | |||
| 25 | ![]() |
666 | 2 | static unsigned int index_delta2status(const git_diff_delta *head2idx) |
| 26 | - | { | ||
| 27 | 666 | 2 | git_status_t st = GIT_STATUS_CURRENT; | |
| 28 | - | |||
| 29 | 666 | 2 | switch (head2idx->status) { | |
| 30 | - | case GIT_DELTA_ADDED: | ||
| 31 | - | case GIT_DELTA_COPIED: | ||
| 32 | 253 | 3 | st = GIT_STATUS_INDEX_NEW; | |
| 33 | 253 | 3 | break; | |
| 34 | - | case GIT_DELTA_DELETED: | ||
| 35 | 58 | 4 | st = GIT_STATUS_INDEX_DELETED; | |
| 36 | 58 | 4 | break; | |
| 37 | - | case GIT_DELTA_MODIFIED: | ||
| 38 | 138 | 5 | st = GIT_STATUS_INDEX_MODIFIED; | |
| 39 | 138 | 5 | break; | |
| 40 | - | case GIT_DELTA_RENAMED: | ||
| 41 | 18 | 6 | st = GIT_STATUS_INDEX_RENAMED; | |
| 42 | - | |||
| 43 | 18 | 6,7 | if (!git_oid_equal(&head2idx->old_file.id, &head2idx->new_file.id)) | |
| 44 | 5 | 8 | st |= GIT_STATUS_INDEX_MODIFIED; | |
| 45 | 18 | 9 | break; | |
| 46 | - | case GIT_DELTA_TYPECHANGE: | ||
| 47 | ##### | 10 | st = GIT_STATUS_INDEX_TYPECHANGE; | |
| 48 | ##### | 10 | break; | |
| 49 | - | case GIT_DELTA_CONFLICTED: | ||
| 50 | 6 | 11 | st = GIT_STATUS_CONFLICTED; | |
| 51 | 6 | 11 | break; | |
| 52 | - | default: | ||
| 53 | 193 | 12 | break; | |
| 54 | - | } | ||
| 55 | - | |||
| 56 | 666 | 13 | return st; | |
| 57 | - | } | ||
| 58 | - | |||
| 59 | ![]() |
1031 | 2 | static unsigned int workdir_delta2status( |
| 60 | - | git_diff *diff, git_diff_delta *idx2wd) | ||
| 61 | - | { | ||
| 62 | 1031 | 2 | git_status_t st = GIT_STATUS_CURRENT; | |
| 63 | - | |||
| 64 | 1031 | 2 | switch (idx2wd->status) { | |
| 65 | - | case GIT_DELTA_ADDED: | ||
| 66 | - | case GIT_DELTA_COPIED: | ||
| 67 | - | case GIT_DELTA_UNTRACKED: | ||
| 68 | 332 | 3 | st = GIT_STATUS_WT_NEW; | |
| 69 | 332 | 3 | break; | |
| 70 | - | case GIT_DELTA_UNREADABLE: | ||
| 71 | 1 | 4 | st = GIT_STATUS_WT_UNREADABLE; | |
| 72 | 1 | 4 | break; | |
| 73 | - | case GIT_DELTA_DELETED: | ||
| 74 | 86 | 5 | st = GIT_STATUS_WT_DELETED; | |
| 75 | 86 | 5 | break; | |
| 76 | - | case GIT_DELTA_MODIFIED: | ||
| 77 | 268 | 6 | st = GIT_STATUS_WT_MODIFIED; | |
| 78 | 268 | 6 | break; | |
| 79 | - | case GIT_DELTA_IGNORED: | ||
| 80 | 109 | 7 | st = GIT_STATUS_IGNORED; | |
| 81 | 109 | 7 | break; | |
| 82 | - | case GIT_DELTA_RENAMED: | ||
| 83 | 19 | 8 | st = GIT_STATUS_WT_RENAMED; | |
| 84 | - | |||
| 85 | 19 | 8,9 | if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) { | |
| 86 | - | /* if OIDs don't match, we might need to calculate them now to | ||
| 87 | - | * discern between RENAMED vs RENAMED+MODIFED | ||
| 88 | - | */ | ||
| 89 | 19 | 10-12 | if (git_oid_is_zero(&idx2wd->old_file.id) && | |
| 90 | ##### | 12,14 | diff->old_src == GIT_ITERATOR_WORKDIR && | |
| 91 | ##### | 13,13 | !git_diff__oid_for_file( | |
| 92 | - | &idx2wd->old_file.id, diff, idx2wd->old_file.path, | ||
| 93 | ##### | 13 | idx2wd->old_file.mode, idx2wd->old_file.size)) | |
| 94 | ##### | 15 | idx2wd->old_file.flags |= GIT_DIFF_FLAG_VALID_ID; | |
| 95 | - | |||
| 96 | 19 | 16-18 | if (git_oid_is_zero(&idx2wd->new_file.id) && | |
| 97 | 19 | 18,20 | diff->new_src == GIT_ITERATOR_WORKDIR && | |
| 98 | 19 | 19,19 | !git_diff__oid_for_file( | |
| 99 | - | &idx2wd->new_file.id, diff, idx2wd->new_file.path, | ||
| 100 | 19 | 19 | idx2wd->new_file.mode, idx2wd->new_file.size)) | |
| 101 | 19 | 21 | idx2wd->new_file.flags |= GIT_DIFF_FLAG_VALID_ID; | |
| 102 | - | |||
| 103 | 19 | 22,23 | if (!git_oid_equal(&idx2wd->old_file.id, &idx2wd->new_file.id)) | |
| 104 | 6 | 24 | st |= GIT_STATUS_WT_MODIFIED; | |
| 105 | - | } | ||
| 106 | 19 | 25 | break; | |
| 107 | - | case GIT_DELTA_TYPECHANGE: | ||
| 108 | ##### | 26 | st = GIT_STATUS_WT_TYPECHANGE; | |
| 109 | ##### | 26 | break; | |
| 110 | - | case GIT_DELTA_CONFLICTED: | ||
| 111 | 6 | 27 | st = GIT_STATUS_CONFLICTED; | |
| 112 | 6 | 27 | break; | |
| 113 | - | default: | ||
| 114 | 210 | 28 | break; | |
| 115 | - | } | ||
| 116 | - | |||
| 117 | 1031 | 29 | return st; | |
| 118 | - | } | ||
| 119 | - | |||
| 120 | ![]() |
1278 | 2 | static bool status_is_included( |
| 121 | - | git_status_list *status, | ||
| 122 | - | git_diff_delta *head2idx, | ||
| 123 | - | git_diff_delta *idx2wd) | ||
| 124 | - | { | ||
| 125 | 1278 | 2 | if (!(status->opts.flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES)) | |
| 126 | 1052 | 3 | return 1; | |
| 127 | - | |||
| 128 | - | /* if excluding submodules and this is a submodule everywhere */ | ||
| 129 | 226 | 4 | if (head2idx) { | |
| 130 | 126 | 5,6 | if (head2idx->status != GIT_DELTA_ADDED && | |
| 131 | 54 | 6 | head2idx->old_file.mode != GIT_FILEMODE_COMMIT) | |
| 132 | 54 | 7 | return 1; | |
| 133 | 72 | 8,9 | if (head2idx->status != GIT_DELTA_DELETED && | |
| 134 | 72 | 9 | head2idx->new_file.mode != GIT_FILEMODE_COMMIT) | |
| 135 | 72 | 10 | return 1; | |
| 136 | - | } | ||
| 137 | 100 | 11 | if (idx2wd) { | |
| 138 | 100 | 12,13 | if (idx2wd->status != GIT_DELTA_ADDED && | |
| 139 | 100 | 13 | idx2wd->old_file.mode != GIT_FILEMODE_COMMIT) | |
| 140 | 100 | 14 | return 1; | |
| 141 | ##### | 15,16 | if (idx2wd->status != GIT_DELTA_DELETED && | |
| 142 | ##### | 16 | idx2wd->new_file.mode != GIT_FILEMODE_COMMIT) | |
| 143 | ##### | 17 | return 1; | |
| 144 | - | } | ||
| 145 | - | |||
| 146 | - | /* only get here if every valid mode is GIT_FILEMODE_COMMIT */ | ||
| 147 | ##### | 18 | return 0; | |
| 148 | - | } | ||
| 149 | - | |||
| 150 | 1278 | 2 | static git_status_t status_compute( | |
| 151 | - | git_status_list *status, | ||
| 152 | - | git_diff_delta *head2idx, | ||
| 153 | - | git_diff_delta *idx2wd) | ||
| 154 | - | { | ||
| 155 | 1278 | 2 | git_status_t st = GIT_STATUS_CURRENT; | |
| 156 | - | |||
| 157 | 1278 | 2 | if (head2idx) | |
| 158 | 666 | 3,4 | st |= index_delta2status(head2idx); | |
| 159 | - | |||
| 160 | 1278 | 5 | if (idx2wd) | |
| 161 | 1031 | 6,7 | st |= workdir_delta2status(status->idx2wd, idx2wd); | |
| 162 | - | |||
| 163 | 1278 | 8 | return st; | |
| 164 | - | } | ||
| 165 | - | |||
| 166 | 1278 | 2 | static int status_collect( | |
| 167 | - | git_diff_delta *head2idx, | ||
| 168 | - | git_diff_delta *idx2wd, | ||
| 169 | - | void *payload) | ||
| 170 | - | { | ||
| 171 | 1278 | 2 | git_status_list *status = payload; | |
| 172 | - | git_status_entry *status_entry; | ||
| 173 | - | |||
| 174 | 1278 | 2,3 | if (!status_is_included(status, head2idx, idx2wd)) | |
| 175 | ##### | 4 | return 0; | |
| 176 | - | |||
| 177 | 1278 | 5 | status_entry = git__malloc(sizeof(git_status_entry)); | |
| 178 | 1278 | 6,7 | GIT_ERROR_CHECK_ALLOC(status_entry); | |
| 179 | - | |||
| 180 | 1278 | 8 | status_entry->status = status_compute(status, head2idx, idx2wd); | |
| 181 | 1278 | 9 | status_entry->head_to_index = head2idx; | |
| 182 | 1278 | 9 | status_entry->index_to_workdir = idx2wd; | |
| 183 | - | |||
| 184 | 1278 | 9 | return git_vector_insert(&status->paired, status_entry); | |
| 185 | - | } | ||
| 186 | - | |||
| 187 | ![]() |
80 | 2 | GIT_INLINE(int) status_entry_cmp_base( |
| 188 | - | const void *a, | ||
| 189 | - | const void *b, | ||
| 190 | - | int (*strcomp)(const char *a, const char *b)) | ||
| 191 | - | { | ||
| 192 | 80 | 2 | const git_status_entry *entry_a = a; | |
| 193 | 80 | 2 | const git_status_entry *entry_b = b; | |
| 194 | - | const git_diff_delta *delta_a, *delta_b; | ||
| 195 | - | |||
| 196 | 80 | 2-4 | delta_a = entry_a->index_to_workdir ? entry_a->index_to_workdir : | |
| 197 | - | entry_a->head_to_index; | ||
| 198 | 80 | 5-7 | delta_b = entry_b->index_to_workdir ? entry_b->index_to_workdir : | |
| 199 | - | entry_b->head_to_index; | ||
| 200 | - | |||
| 201 | 80 | 8,9 | if (!delta_a && delta_b) | |
| 202 | ##### | 10 | return -1; | |
| 203 | 80 | 11,12 | if (delta_a && !delta_b) | |
| 204 | ##### | 13 | return 1; | |
| 205 | 80 | 14,15 | if (!delta_a && !delta_b) | |
| 206 | ##### | 16 | return 0; | |
| 207 | - | |||
| 208 | 80 | 17 | return strcomp(delta_a->new_file.path, delta_b->new_file.path); | |
| 209 | - | } | ||
| 210 | - | |||
| 211 | 35 | 2 | static int status_entry_icmp(const void *a, const void *b) | |
| 212 | - | { | ||
| 213 | 35 | 2 | return status_entry_cmp_base(a, b, git__strcasecmp); | |
| 214 | - | } | ||
| 215 | - | |||
| 216 | 45 | 2 | static int status_entry_cmp(const void *a, const void *b) | |
| 217 | - | { | ||
| 218 | 45 | 2 | return status_entry_cmp_base(a, b, git__strcmp); | |
| 219 | - | } | ||
| 220 | - | |||
| 221 | ![]() |
664 | 2 | static git_status_list *git_status_list_alloc(git_index *index) |
| 222 | - | { | ||
| 223 | 664 | 2 | git_status_list *status = NULL; | |
| 224 | - | int (*entrycmp)(const void *a, const void *b); | ||
| 225 | - | |||
| 226 | 664 | 2,3 | if (!(status = git__calloc(1, sizeof(git_status_list)))) | |
| 227 | ##### | 4 | return NULL; | |
| 228 | - | |||
| 229 | 664 | 5-7 | entrycmp = index->ignore_case ? status_entry_icmp : status_entry_cmp; | |
| 230 | - | |||
| 231 | 664 | 8,9 | if (git_vector_init(&status->paired, 0, entrycmp) < 0) { | |
| 232 | ##### | 10 | git__free(status); | |
| 233 | ##### | 11 | return NULL; | |
| 234 | - | } | ||
| 235 | - | |||
| 236 | 664 | 12 | return status; | |
| 237 | - | } | ||
| 238 | - | |||
| 239 | ![]() |
665 | 2 | static int status_validate_options(const git_status_options *opts) |
| 240 | - | { | ||
| 241 | 665 | 2 | if (!opts) | |
| 242 | 112 | 3 | return 0; | |
| 243 | - | |||
| 244 | 553 | 4-6 | GIT_ERROR_CHECK_VERSION(opts, GIT_STATUS_OPTIONS_VERSION, "git_status_options"); | |
| 245 | - | |||
| 246 | 553 | 7 | if (opts->show > GIT_STATUS_SHOW_WORKDIR_ONLY) { | |
| 247 | ##### | 8 | git_error_set(GIT_ERROR_INVALID, "unknown status 'show' option"); | |
| 248 | ##### | 9 | return -1; | |
| 249 | - | } | ||
| 250 | - | |||
| 251 | 553 | 10,11 | if ((opts->flags & GIT_STATUS_OPT_NO_REFRESH) != 0 && | |
| 252 | ##### | 11 | (opts->flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) { | |
| 253 | ##### | 12 | git_error_set(GIT_ERROR_INVALID, "updating index from status " | |
| 254 | - | "is not allowed when index refresh is disabled"); | ||
| 255 | ##### | 13 | return -1; | |
| 256 | - | } | ||
| 257 | - | |||
| 258 | 553 | 14 | return 0; | |
| 259 | - | } | ||
| 260 | - | |||
| 261 | ![]() |
665 | 2 | int git_status_list_new( |
| 262 | - | git_status_list **out, | ||
| 263 | - | git_repository *repo, | ||
| 264 | - | const git_status_options *opts) | ||
| 265 | - | { | ||
| 266 | 665 | 2 | git_index *index = NULL; | |
| 267 | 665 | 2 | git_status_list *status = NULL; | |
| 268 | 665 | 2 | git_diff_options diffopt = GIT_DIFF_OPTIONS_INIT; | |
| 269 | 665 | 2 | git_diff_find_options findopt = GIT_DIFF_FIND_OPTIONS_INIT; | |
| 270 | 665 | 2 | git_tree *head = NULL; | |
| 271 | 665 | 5 | git_status_show_t show = | |
| 272 | 665 | 2-4 | opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR; | |
| 273 | 665 | 5 | int error = 0; | |
| 274 | 665 | 5-7 | unsigned int flags = opts ? opts->flags : GIT_STATUS_OPT_DEFAULTS; | |
| 275 | - | |||
| 276 | 665 | 8 | *out = NULL; | |
| 277 | - | |||
| 278 | 665 | 8,9 | if (status_validate_options(opts) < 0) | |
| 279 | ##### | 10 | return -1; | |
| 280 | - | |||
| 281 | 665 | 11-14 | if ((error = git_repository__ensure_not_bare(repo, "status")) < 0 || | |
| 282 | - | (error = git_repository_index(&index, repo)) < 0) | ||
| 283 | 1 | 15 | return error; | |
| 284 | - | |||
| 285 | 664 | 16,17 | if (opts != NULL && opts->baseline != NULL) { | |
| 286 | 1 | 18 | head = opts->baseline; | |
| 287 | - | } else { | ||
| 288 | - | /* if there is no HEAD, that's okay - we'll make an empty iterator */ | ||
| 289 | 663 | 19,20 | if ((error = git_repository_head_tree(&head, repo)) < 0) { | |
| 290 | 95 | 21,22 | if (error != GIT_ENOTFOUND && error != GIT_EUNBORNBRANCH) | |
| 291 | ##### | 23 | goto done; | |
| 292 | 95 | 24 | git_error_clear(); | |
| 293 | - | } | ||
| 294 | - | } | ||
| 295 | - | |||
| 296 | - | /* refresh index from disk unless prevented */ | ||
| 297 | 664 | 25,27 | if ((flags & GIT_STATUS_OPT_NO_REFRESH) == 0 && | |
| 298 | 664 | 26 | git_index_read_safely(index) < 0) | |
| 299 | ##### | 28 | git_error_clear(); | |
| 300 | - | |||
| 301 | 664 | 29 | status = git_status_list_alloc(index); | |
| 302 | 664 | 30,31 | GIT_ERROR_CHECK_ALLOC(status); | |
| 303 | - | |||
| 304 | 664 | 32 | if (opts) { | |
| 305 | 552 | 33 | memcpy(&status->opts, opts, sizeof(git_status_options)); | |
| 306 | 552 | 33 | memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec)); | |
| 307 | - | } | ||
| 308 | - | |||
| 309 | 664 | 34 | diffopt.flags = GIT_DIFF_INCLUDE_TYPECHANGE; | |
| 310 | 664 | 34 | findopt.flags = GIT_DIFF_FIND_FOR_UNTRACKED; | |
| 311 | - | |||
| 312 | 664 | 34 | if ((flags & GIT_STATUS_OPT_INCLUDE_UNTRACKED) != 0) | |
| 313 | 636 | 35 | diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNTRACKED; | |
| 314 | 664 | 36 | if ((flags & GIT_STATUS_OPT_INCLUDE_IGNORED) != 0) | |
| 315 | 565 | 37 | diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_IGNORED; | |
| 316 | 664 | 38 | if ((flags & GIT_STATUS_OPT_INCLUDE_UNMODIFIED) != 0) | |
| 317 | 419 | 39 | diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNMODIFIED; | |
| 318 | 664 | 40 | if ((flags & GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS) != 0) | |
| 319 | 620 | 41 | diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_UNTRACKED_DIRS; | |
| 320 | 664 | 42 | if ((flags & GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH) != 0) | |
| 321 | 423 | 43 | diffopt.flags = diffopt.flags | GIT_DIFF_DISABLE_PATHSPEC_MATCH; | |
| 322 | 664 | 44 | if ((flags & GIT_STATUS_OPT_RECURSE_IGNORED_DIRS) != 0) | |
| 323 | 424 | 45 | diffopt.flags = diffopt.flags | GIT_DIFF_RECURSE_IGNORED_DIRS; | |
| 324 | 664 | 46 | if ((flags & GIT_STATUS_OPT_EXCLUDE_SUBMODULES) != 0) | |
| 325 | 69 | 47 | diffopt.flags = diffopt.flags | GIT_DIFF_IGNORE_SUBMODULES; | |
| 326 | 664 | 48 | if ((flags & GIT_STATUS_OPT_UPDATE_INDEX) != 0) | |
| 327 | 2 | 49 | diffopt.flags = diffopt.flags | GIT_DIFF_UPDATE_INDEX; | |
| 328 | 664 | 50 | if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE) != 0) | |
| 329 | 3 | 51 | diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE; | |
| 330 | 664 | 52 | if ((flags & GIT_STATUS_OPT_INCLUDE_UNREADABLE_AS_UNTRACKED) != 0) | |
| 331 | 2 | 53 | diffopt.flags = diffopt.flags | GIT_DIFF_INCLUDE_UNREADABLE_AS_UNTRACKED; | |
| 332 | - | |||
| 333 | 664 | 54 | if ((flags & GIT_STATUS_OPT_RENAMES_FROM_REWRITES) != 0) | |
| 334 | 6 | 55,55 | findopt.flags = findopt.flags | | |
| 335 | - | GIT_DIFF_FIND_AND_BREAK_REWRITES | | ||
| 336 | 6 | 55 | GIT_DIFF_FIND_RENAMES_FROM_REWRITES | | |
| 337 | - | GIT_DIFF_BREAK_REWRITES_FOR_RENAMES_ONLY; | ||
| 338 | - | |||
| 339 | 664 | 56 | if (show != GIT_STATUS_SHOW_WORKDIR_ONLY) { | |
| 340 | 658 | 57,58 | if ((error = git_diff_tree_to_index( | |
| 341 | - | &status->head2idx, repo, head, index, &diffopt)) < 0) | ||
| 342 | ##### | 59 | goto done; | |
| 343 | - | |||
| 344 | 658 | 60-62 | if ((flags & GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX) != 0 && | |
| 345 | 12 | 61 | (error = git_diff_find_similar(status->head2idx, &findopt)) < 0) | |
| 346 | ##### | 63 | goto done; | |
| 347 | - | } | ||
| 348 | - | |||
| 349 | 664 | 64 | if (show != GIT_STATUS_SHOW_INDEX_ONLY) { | |
| 350 | 662 | 65,66 | if ((error = git_diff_index_to_workdir( | |
| 351 | - | &status->idx2wd, repo, index, &diffopt)) < 0) { | ||
| 352 | ##### | 67 | goto done; | |
| 353 | - | } | ||
| 354 | - | |||
| 355 | 662 | 68-70 | if ((flags & GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR) != 0 && | |
| 356 | 11 | 69 | (error = git_diff_find_similar(status->idx2wd, &findopt)) < 0) | |
| 357 | ##### | 71 | goto done; | |
| 358 | - | } | ||
| 359 | - | |||
| 360 | 664 | 72 | error = git_diff__paired_foreach( | |
| 361 | - | status->head2idx, status->idx2wd, status_collect, status); | ||
| 362 | 664 | 73 | if (error < 0) | |
| 363 | ##### | 74 | goto done; | |
| 364 | - | |||
| 365 | 664 | 75 | if (flags & GIT_STATUS_OPT_SORT_CASE_SENSITIVELY) | |
| 366 | 1 | 76 | git_vector_set_cmp(&status->paired, status_entry_cmp); | |
| 367 | 664 | 77 | if (flags & GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY) | |
| 368 | 2 | 78 | git_vector_set_cmp(&status->paired, status_entry_icmp); | |
| 369 | - | |||
| 370 | 664 | 79 | if ((flags & | |
| 371 | - | (GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | | ||
| 372 | - | GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR | | ||
| 373 | - | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY | | ||
| 374 | - | GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY)) != 0) | ||
| 375 | 18 | 80 | git_vector_sort(&status->paired); | |
| 376 | - | |||
| 377 | - | done: | ||
| 378 | 664 | 81 | if (error < 0) { | |
| 379 | ##### | 82 | git_status_list_free(status); | |
| 380 | ##### | 83 | status = NULL; | |
| 381 | - | } | ||
| 382 | - | |||
| 383 | 664 | 84 | *out = status; | |
| 384 | - | |||
| 385 | 664 | 84,85 | if (opts == NULL || opts->baseline != head) | |
| 386 | 615 | 86 | git_tree_free(head); | |
| 387 | 664 | 87 | git_index_free(index); | |
| 388 | - | |||
| 389 | 664 | 88 | return error; | |
| 390 | - | } | ||
| 391 | - | |||
| 392 | 72 | 2 | size_t git_status_list_entrycount(git_status_list *status) | |
| 393 | - | { | ||
| 394 | 72 | 2,3 | assert(status); | |
| 395 | - | |||
| 396 | 72 | 4 | return status->paired.length; | |
| 397 | - | } | ||
| 398 | - | |||
| 399 | 120 | 2 | const git_status_entry *git_status_byindex(git_status_list *status, size_t i) | |
| 400 | - | { | ||
| 401 | 120 | 2,3 | assert(status); | |
| 402 | - | |||
| 403 | 120 | 4 | return git_vector_get(&status->paired, i); | |
| 404 | - | } | ||
| 405 | - | |||
| 406 | 664 | 2 | void git_status_list_free(git_status_list *status) | |
| 407 | - | { | ||
| 408 | 664 | 2 | if (status == NULL) | |
| 409 | 664 | 3,9 | return; | |
| 410 | - | |||
| 411 | 664 | 4 | git_diff_free(status->head2idx); | |
| 412 | 664 | 5 | git_diff_free(status->idx2wd); | |
| 413 | - | |||
| 414 | 664 | 6 | git_vector_free_deep(&status->paired); | |
| 415 | - | |||
| 416 | 664 | 7 | git__memzero(status, sizeof(*status)); | |
| 417 | 664 | 8 | git__free(status); | |
| 418 | - | } | ||
| 419 | - | |||
| 420 | ![]() |
611 | 2 | int git_status_foreach_ext( |
| 421 | - | git_repository *repo, | ||
| 422 | - | const git_status_options *opts, | ||
| 423 | - | git_status_cb cb, | ||
| 424 | - | void *payload) | ||
| 425 | - | { | ||
| 426 | - | git_status_list *status; | ||
| 427 | - | const git_status_entry *status_entry; | ||
| 428 | - | size_t i; | ||
| 429 | 611 | 2 | int error = 0; | |
| 430 | - | |||
| 431 | 611 | 2,3 | if ((error = git_status_list_new(&status, repo, opts)) < 0) { | |
| 432 | 1 | 4 | return error; | |
| 433 | - | } | ||
| 434 | - | |||
| 435 | 1513 | 5,12-14 | git_vector_foreach(&status->paired, i, status_entry) { | |
| 436 | 965 | 6,9 | const char *path = status_entry->head_to_index ? | |
| 437 | 965 | 6-8 | status_entry->head_to_index->old_file.path : | |
| 438 | 492 | 8 | status_entry->index_to_workdir->old_file.path; | |
| 439 | - | |||
| 440 | 965 | 9,10 | if ((error = cb(path, status_entry->status, payload)) != 0) { | |
| 441 | 62 | 11 | git_error_set_after_callback(error); | |
| 442 | 62 | 15 | break; | |
| 443 | - | } | ||
| 444 | - | } | ||
| 445 | - | |||
| 446 | 610 | 16 | git_status_list_free(status); | |
| 447 | - | |||
| 448 | 610 | 17 | return error; | |
| 449 | - | } | ||
| 450 | - | |||
| 451 | 88 | 2 | int git_status_foreach(git_repository *repo, git_status_cb cb, void *payload) | |
| 452 | - | { | ||
| 453 | 88 | 2 | return git_status_foreach_ext(repo, NULL, cb, payload); | |
| 454 | - | } | ||
| 455 | - | |||
| 456 | - | struct status_file_info { | ||
| 457 | - | char *expected; | ||
| 458 | - | unsigned int count; | ||
| 459 | - | unsigned int status; | ||
| 460 | - | int wildmatch_flags; | ||
| 461 | - | int ambiguous; | ||
| 462 | - | }; | ||
| 463 | - | |||
| 464 | ![]() |
339 | 2 | static int get_one_status(const char *path, unsigned int status, void *data) |
| 465 | - | { | ||
| 466 | 339 | 2 | struct status_file_info *sfi = data; | |
| 467 | - | int (*strcomp)(const char *a, const char *b); | ||
| 468 | - | |||
| 469 | 339 | 2 | sfi->count++; | |
| 470 | 339 | 2 | sfi->status = status; | |
| 471 | - | |||
| 472 | 339 | 2-4 | strcomp = (sfi->wildmatch_flags & WM_CASEFOLD) ? git__strcasecmp : git__strcmp; | |
| 473 | - | |||
| 474 | 339 | 5,7 | if (sfi->count > 1 || | |
| 475 | 339 | 6,9 | (strcomp(sfi->expected, path) != 0 && | |
| 476 | 1 | 8 | wildmatch(sfi->expected, path, sfi->wildmatch_flags) != 0)) | |
| 477 | - | { | ||
| 478 | 1 | 10 | sfi->ambiguous = true; | |
| 479 | 1 | 10 | return GIT_EAMBIGUOUS; /* git_error_set will be done by caller */ | |
| 480 | - | } | ||
| 481 | - | |||
| 482 | 338 | 11 | return 0; | |
| 483 | - | } | ||
| 484 | - | |||
| 485 | ![]() |
414 | 2 | int git_status_file( |
| 486 | - | unsigned int *status_flags, | ||
| 487 | - | git_repository *repo, | ||
| 488 | - | const char *path) | ||
| 489 | - | { | ||
| 490 | - | int error; | ||
| 491 | 414 | 2 | git_status_options opts = GIT_STATUS_OPTIONS_INIT; | |
| 492 | 414 | 2 | struct status_file_info sfi = {0}; | |
| 493 | - | git_index *index; | ||
| 494 | - | |||
| 495 | 414 | 2-5 | assert(status_flags && repo && path); | |
| 496 | - | |||
| 497 | 414 | 6,7 | if ((error = git_repository_index__weakptr(&index, repo)) < 0) | |
| 498 | ##### | 8 | return error; | |
| 499 | - | |||
| 500 | 414 | 9,10 | if ((sfi.expected = git__strdup(path)) == NULL) | |
| 501 | ##### | 11 | return -1; | |
| 502 | 414 | 12 | if (index->ignore_case) | |
| 503 | 3 | 13 | sfi.wildmatch_flags = WM_CASEFOLD; | |
| 504 | - | |||
| 505 | 414 | 14 | opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; | |
| 506 | 414 | 14 | opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED | | |
| 507 | - | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS | | ||
| 508 | - | GIT_STATUS_OPT_INCLUDE_UNTRACKED | | ||
| 509 | - | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | | ||
| 510 | - | GIT_STATUS_OPT_INCLUDE_UNMODIFIED | | ||
| 511 | - | GIT_STATUS_OPT_DISABLE_PATHSPEC_MATCH; | ||
| 512 | 414 | 14 | opts.pathspec.count = 1; | |
| 513 | 414 | 14 | opts.pathspec.strings = &sfi.expected; | |
| 514 | - | |||
| 515 | 414 | 14 | error = git_status_foreach_ext(repo, &opts, get_one_status, &sfi); | |
| 516 | - | |||
| 517 | 414 | 15,16 | if (error < 0 && sfi.ambiguous) { | |
| 518 | 1 | 17 | git_error_set(GIT_ERROR_INVALID, | |
| 519 | - | "ambiguous path '%s' given to git_status_file", sfi.expected); | ||
| 520 | 1 | 18 | error = GIT_EAMBIGUOUS; | |
| 521 | - | } | ||
| 522 | - | |||
| 523 | 414 | 19,20 | if (!error && !sfi.count) { | |
| 524 | 74 | 21 | git_error_set(GIT_ERROR_INVALID, | |
| 525 | - | "attempt to get status of nonexistent file '%s'", path); | ||
| 526 | 74 | 22 | error = GIT_ENOTFOUND; | |
| 527 | - | } | ||
| 528 | - | |||
| 529 | 414 | 23 | *status_flags = sfi.status; | |
| 530 | - | |||
| 531 | 414 | 23 | git__free(sfi.expected); | |
| 532 | - | |||
| 533 | 414 | 24 | return error; | |
| 534 | - | } | ||
| 535 | - | |||
| 536 | 165 | 2 | int git_status_should_ignore( | |
| 537 | - | int *ignored, | ||
| 538 | - | git_repository *repo, | ||
| 539 | - | const char *path) | ||
| 540 | - | { | ||
| 541 | 165 | 2 | return git_ignore_path_is_ignored(ignored, repo, path); | |
| 542 | - | } | ||
| 543 | - | |||
| 544 | ![]() |
1 | 2 | int git_status_options_init(git_status_options *opts, unsigned int version) |
| 545 | - | { | ||
| 546 | 1 | 2-4 | GIT_INIT_STRUCTURE_FROM_TEMPLATE( | |
| 547 | - | opts, version, git_status_options, GIT_STATUS_OPTIONS_INIT); | ||
| 548 | 1 | 5 | return 0; | |
| 549 | - | } | ||
| 550 | - | |||
| 551 | - | #ifndef GIT_DEPRECATE_HARD | ||
| 552 | ##### | 2 | int git_status_init_options(git_status_options *opts, unsigned int version) | |
| 553 | - | { | ||
| 554 | ##### | 2 | return git_status_options_init(opts, version); | |
| 555 | - | } | ||
| 556 | - | #endif | ||
| 557 | - | |||
| 558 | ![]() |
3 | 2 | int git_status_list_get_perfdata( |
| 559 | - | git_diff_perfdata *out, const git_status_list *status) | ||
| 560 | - | { | ||
| 561 | 3 | 2,3 | assert(out); | |
| 562 | 3 | 4-6 | GIT_ERROR_CHECK_VERSION(out, GIT_DIFF_PERFDATA_VERSION, "git_diff_perfdata"); | |
| 563 | - | |||
| 564 | 3 | 7 | out->stat_calls = 0; | |
| 565 | 3 | 7 | out->oid_calculations = 0; | |
| 566 | - | |||
| 567 | 3 | 7 | if (status->head2idx) { | |
| 568 | 3 | 8 | out->stat_calls += status->head2idx->perf.stat_calls; | |
| 569 | 3 | 8 | out->oid_calculations += status->head2idx->perf.oid_calculations; | |
| 570 | - | } | ||
| 571 | 3 | 9 | if (status->idx2wd) { | |
| 572 | 3 | 10 | out->stat_calls += status->idx2wd->perf.stat_calls; | |
| 573 | 3 | 10 | out->oid_calculations += status->idx2wd->perf.oid_calculations; | |
| 574 | - | } | ||
| 575 | - | |||
| 576 | 3 | 11 | return 0; | |
| 577 | - | } | ||
| 578 | - |