summaryrefslogtreecommitdiff
path: root/src/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/status.c')
-rw-r--r--src/status.c83
1 files changed, 35 insertions, 48 deletions
diff --git a/src/status.c b/src/status.c
index 2d022bfda..0bd170e6d 100644
--- a/src/status.c
+++ b/src/status.c
@@ -17,6 +17,7 @@
#include "git2/diff.h"
#include "diff.h"
+#include "diff_output.h"
static unsigned int index_delta2status(git_delta_t index_status)
{
@@ -76,21 +77,43 @@ static unsigned int workdir_delta2status(git_delta_t workdir_status)
return st;
}
+typedef struct {
+ int (*cb)(const char *, unsigned int, void *);
+ void *cbdata;
+} status_user_callback;
+
+static int status_invoke_cb(
+ void *cbref, git_diff_delta *i2h, git_diff_delta *w2i)
+{
+ status_user_callback *usercb = cbref;
+ const char *path = NULL;
+ unsigned int status = 0;
+
+ if (w2i) {
+ path = w2i->old_file.path;
+ status |= workdir_delta2status(w2i->status);
+ }
+ if (i2h) {
+ path = i2h->old_file.path;
+ status |= index_delta2status(i2h->status);
+ }
+
+ return usercb->cb(path, status, usercb->cbdata);
+}
+
int git_status_foreach_ext(
git_repository *repo,
const git_status_options *opts,
int (*cb)(const char *, unsigned int, void *),
void *cbdata)
{
- int err = 0, cmp;
+ int err = 0;
git_diff_options diffopt;
git_diff_list *idx2head = NULL, *wd2idx = NULL;
git_tree *head = NULL;
git_status_show_t show =
opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
- git_diff_delta *i2h, *w2i;
- size_t i, j, i_max, j_max;
- bool ignore_case = false;
+ status_user_callback usercb;
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
@@ -126,55 +149,19 @@ int git_status_foreach_ext(
(err = git_diff_workdir_to_index(repo, &diffopt, &wd2idx)) < 0)
goto cleanup;
+ usercb.cb = cb;
+ usercb.cbdata = cbdata;
+
if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
- for (i = 0; !err && i < idx2head->deltas.length; i++) {
- i2h = GIT_VECTOR_GET(&idx2head->deltas, i);
- if (cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata))
- err = GIT_EUSER;
- }
+ if ((err = git_diff__paired_foreach(
+ idx2head, NULL, status_invoke_cb, &usercb)) < 0)
+ goto cleanup;
+
git_diff_list_free(idx2head);
idx2head = NULL;
}
- i_max = idx2head ? idx2head->deltas.length : 0;
- j_max = wd2idx ? wd2idx->deltas.length : 0;
-
- if (idx2head && wd2idx &&
- (0 != (idx2head->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) ||
- 0 != (wd2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE)))
- {
- /* Then use the ignore-case sorter... */
- ignore_case = true;
-
- /* and assert that both are ignore-case sorted. If this function
- * ever needs to support merge joining result sets that are not sorted
- * by the same function, then it will need to be extended to do a spool
- * and sort on one of the results before merge joining */
- assert(0 != (idx2head->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) &&
- 0 != (wd2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE));
- }
-
- for (i = 0, j = 0; !err && (i < i_max || j < j_max); ) {
- i2h = idx2head ? GIT_VECTOR_GET(&idx2head->deltas,i) : NULL;
- w2i = wd2idx ? GIT_VECTOR_GET(&wd2idx->deltas,j) : NULL;
-
- cmp = !w2i ? -1 : !i2h ? 1 : STRCMP_CASESELECT(ignore_case, i2h->old_file.path, w2i->old_file.path);
-
- if (cmp < 0) {
- if (cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata))
- err = GIT_EUSER;
- i++;
- } else if (cmp > 0) {
- if (cb(w2i->old_file.path, workdir_delta2status(w2i->status), cbdata))
- err = GIT_EUSER;
- j++;
- } else {
- if (cb(i2h->old_file.path, index_delta2status(i2h->status) |
- workdir_delta2status(w2i->status), cbdata))
- err = GIT_EUSER;
- i++; j++;
- }
- }
+ err = git_diff__paired_foreach(idx2head, wd2idx, status_invoke_cb, &usercb);
cleanup:
git_tree_free(head);