Eliminate hairy COITERATE macro I decided that the COITERATE macro was, in the end causing more confusion that it would save and decided just to write out the loops that I needed for parallel diff list iteration. It is not that much code and this just feels less obfuscated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
diff --git a/src/diff.c b/src/diff.c
index d5a841c..e1016db 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -565,23 +565,39 @@ int git_diff_merge(
{
int error = 0;
git_vector onto_new;
- git_diff_delta *delta, *o;
- const git_diff_delta *f;
- unsigned int i;
+ git_diff_delta *delta;
+ unsigned int i, j;
+
+ assert(onto && from);
+
+ if (!from->deltas.length)
+ return 0;
if (git_vector_init(&onto_new, onto->deltas.length, diff_delta__cmp) < 0)
return -1;
- GIT_DIFF_COITERATE(
- onto, from, o, f,
- delta = diff_delta__dup(o),
- delta = diff_delta__dup(f),
- delta = diff_delta__merge_like_cgit(o, f),
+ for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
+ git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
+ const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
+ int cmp = !f ? -1 : !o ? 1 : strcmp(o->old.path, f->old.path);
+
+ if (cmp < 0) {
+ delta = diff_delta__dup(o);
+ i++;
+ } else if (cmp > 0) {
+ delta = diff_delta__dup(f);
+ j++;
+ } else {
+ delta = diff_delta__merge_like_cgit(o, f);
+ i++;
+ j++;
+ }
+
if ((error = !delta ? -1 : git_vector_insert(&onto_new, delta)) < 0)
break;
- );
+ }
- if (error == 0) {
+ if (!error) {
git_vector_swap(&onto->deltas, &onto_new);
onto->new_src = from->new_src;
}
diff --git a/src/diff.h b/src/diff.h
index 058a1f5..7d69199 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -21,19 +21,5 @@ struct git_diff_list {
git_iterator_type_t new_src;
};
-/* macro lets you iterate over two diff lists together */
-
-#define GIT_DIFF_COITERATE(A,B,AD,BD,LEFT,RIGHT,BOTH,AFTER) do { \
- unsigned int _i = 0, _j = 0; int _cmp; \
- while (((A) && _i < (A)->deltas.length) || ((B) && _j < (B)->deltas.length)) { \
- (AD) = (A) ? GIT_VECTOR_GET(&(A)->deltas,_i) : NULL; \
- (BD) = (B) ? GIT_VECTOR_GET(&(B)->deltas,_j) : NULL; \
- _cmp = !(BD) ? -1 : !(AD) ? 1 : strcmp((AD)->old.path,(BD)->old.path); \
- if (_cmp < 0) { LEFT; _i++; } \
- else if (_cmp > 0) { RIGHT; _j++; } \
- else { BOTH; _i++; _j++; } \
- AFTER; \
- } } while (0)
-
#endif
diff --git a/src/status.c b/src/status.c
index bec7529..88dd5e0 100644
--- a/src/status.c
+++ b/src/status.c
@@ -120,13 +120,14 @@ int git_status_foreach_ext(
int (*cb)(const char *, unsigned int, void *),
void *cbdata)
{
- int err = 0;
+ int err = 0, cmp;
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;
+ unsigned int i, j, i_max, j_max;
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
@@ -158,23 +159,35 @@ int git_status_foreach_ext(
goto cleanup;
if (show == GIT_STATUS_SHOW_INDEX_THEN_WORKDIR) {
- git_diff_list *empty = NULL;
- GIT_DIFF_COITERATE(
- idx2head, empty, i2h, w2i,
- err = cb(i2h->old.path, index_delta2status(i2h->status), cbdata),
- /* nothing */, /* nothing */, if (err < 0) break);
-
+ for (i = 0; !err && i < idx2head->deltas.length; i++) {
+ i2h = GIT_VECTOR_GET(&idx2head->deltas, i);
+ err = cb(i2h->old.path, index_delta2status(i2h->status), cbdata);
+ }
git_diff_list_free(idx2head);
idx2head = NULL;
}
- GIT_DIFF_COITERATE(
- idx2head, wd2idx, i2h, w2i,
- err = cb(i2h->old.path, index_delta2status(i2h->status), cbdata),
- err = cb(w2i->old.path, workdir_delta2status(w2i->status), cbdata),
- err = cb(i2h->old.path, index_delta2status(i2h->status) |
- workdir_delta2status(w2i->status), cbdata),
- if (err < 0) break);
+ i_max = idx2head ? idx2head->deltas.length : 0;
+ j_max = wd2idx ? wd2idx->deltas.length : 0;
+
+ 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(i2h->old.path, w2i->old.path);
+
+ if (cmp < 0) {
+ err = cb(i2h->old.path, index_delta2status(i2h->status), cbdata);
+ i++;
+ } else if (cmp > 0) {
+ err = cb(w2i->old.path, workdir_delta2status(w2i->status), cbdata);
+ j++;
+ } else {
+ err = cb(i2h->old.path, index_delta2status(i2h->status) |
+ workdir_delta2status(w2i->status), cbdata);
+ i++; j++;
+ }
+ }
cleanup:
git_tree_free(head);