Commit 1db12b00532d747fa7a805a8fa8d293c58ec16d9

Russell Belfer 2012-03-25T23:04:26

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.

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);