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