summaryrefslogtreecommitdiff
path: root/src/diff_output.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-11-08 16:56:34 -0800
committerRussell Belfer <rb@github.com>2012-11-09 13:52:07 -0800
commit55cbd05b18960e761a4d237ce5f1ff06455da98d (patch)
treeef602ca15261aa1d5ff6be6ea043d74d5fc45459 /src/diff_output.c
parent2e3d4b96c08f1b0e2ee9b248c53aec523d70fd25 (diff)
downloadlibgit2-55cbd05b18960e761a4d237ce5f1ff06455da98d.tar.gz
Some diff refactorings to help code reuse
There are some diff functions that are useful in a rewritten checkout and this lays some groundwork for that. This contains three main things: 1. Share the function diff uses to calculate the OID for a file in the working directory (now named `git_diff__oid_for_file` 2. Add a `git_diff__paired_foreach` function to iterator over two diff lists concurrently. Convert status to use it. 3. Move all the string/prefix/index entry comparisons into function pointers inside the `git_diff_list` object so they can be switched between case sensitive and insensitive versions. This makes them easier to reuse in various functions without replicating logic. As part of this, move a couple of index functions out of diff.c and into index.c.
Diffstat (limited to 'src/diff_output.c')
-rw-r--r--src/diff_output.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/diff_output.c b/src/diff_output.c
index e678ec857..2f61540ff 100644
--- a/src/diff_output.c
+++ b/src/diff_output.c
@@ -1573,3 +1573,58 @@ int git_diff_patch_to_str(
return error;
}
+
+int git_diff__paired_foreach(
+ git_diff_list *idx2head,
+ git_diff_list *wd2idx,
+ int (*cb)(void *cbref, git_diff_delta *i2h, git_diff_delta *w2i),
+ void *cbref)
+{
+ int cmp;
+ git_diff_delta *i2h, *w2i;
+ size_t i, j, i_max, j_max;
+ bool icase = false;
+
+ 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... */
+ icase = 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; 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(icase, i2h->old_file.path, w2i->old_file.path);
+
+ if (cmp < 0) {
+ if (cb(cbref, i2h, NULL))
+ return GIT_EUSER;
+ i++;
+ } else if (cmp > 0) {
+ if (cb(cbref, NULL, w2i))
+ return GIT_EUSER;
+ j++;
+ } else {
+ if (cb(cbref, i2h, w2i))
+ return GIT_EUSER;
+ i++; j++;
+ }
+ }
+
+ return 0;
+}
+