From 4c3fe82ef17a6636c742b95cd292b83b02876e08 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Sun, 20 Sep 2020 04:22:22 -0700 Subject: diff-lib: accept option flags in run_diff_index() In a future commit, we will teach run_diff_index() to accept more options via flag bits. For now, change `cached` into a flag in the `option` bitfield. The behaviour should remain exactly the same. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- diff-lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'diff-lib.c') diff --git a/diff-lib.c b/diff-lib.c index 5d5d3dafab..ed720853ed 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -512,9 +512,10 @@ static int diff_cache(struct rev_info *revs, return unpack_trees(1, &t, &opts); } -int run_diff_index(struct rev_info *revs, int cached) +int run_diff_index(struct rev_info *revs, unsigned int option) { struct object_array_entry *ent; + int cached = !!(option & DIFF_INDEX_CACHED); if (revs->pending.nr != 1) BUG("run_diff_index must be passed exactly one tree"); -- cgit v1.2.3 From 177a8302683da62a62b5b03e8192fcfa897db750 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Sun, 20 Sep 2020 04:22:23 -0700 Subject: diff-lib: define diff_get_merge_base() In a future commit, we will be using this function to implement --merge-base functionality in various diff commands. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- diff-lib.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'diff-lib.c') diff --git a/diff-lib.c b/diff-lib.c index ed720853ed..468e3fe854 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -13,6 +13,7 @@ #include "submodule.h" #include "dir.h" #include "fsmonitor.h" +#include "commit-reach.h" /* * diff-files @@ -512,6 +513,50 @@ static int diff_cache(struct rev_info *revs, return unpack_trees(1, &t, &opts); } +void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb) +{ + int i; + struct commit *mb_child[2] = {0}; + struct commit_list *merge_bases; + + for (i = 0; i < revs->pending.nr; i++) { + struct object *obj = revs->pending.objects[i].item; + if (obj->flags) + die(_("--merge-base does not work with ranges")); + if (obj->type != OBJ_COMMIT) + die(_("--merge-base only works with commits")); + } + + /* + * This check must go after the for loop above because A...B + * ranges produce three pending commits, resulting in a + * misleading error message. + */ + if (revs->pending.nr < 1 || revs->pending.nr > 2) + BUG("unexpected revs->pending.nr: %d", revs->pending.nr); + + for (i = 0; i < revs->pending.nr; i++) + mb_child[i] = lookup_commit_reference(the_repository, &revs->pending.objects[i].item->oid); + if (revs->pending.nr == 1) { + struct object_id oid; + + if (get_oid("HEAD", &oid)) + die(_("unable to get HEAD")); + + mb_child[1] = lookup_commit_reference(the_repository, &oid); + } + + merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]); + if (!merge_bases) + die(_("no merge base found")); + if (merge_bases->next) + die(_("multiple merge bases found")); + + oidcpy(mb, &merge_bases->item->object.oid); + + free_commit_list(merge_bases); +} + int run_diff_index(struct rev_info *revs, unsigned int option) { struct object_array_entry *ent; -- cgit v1.2.3 From 0f5a1d449b9538c2765de9d6683abbb83a7fb4e2 Mon Sep 17 00:00:00 2001 From: Denton Liu Date: Sun, 20 Sep 2020 04:22:25 -0700 Subject: builtin/diff-index: learn --merge-base There is currently no easy way to take the diff between the working tree or index and the merge base between an arbitrary commit and HEAD. Even diff's `...` notation doesn't allow this because it only works between commits. However, the ability to do this would be desirable to a user who would like to see all the changes they've made on a branch plus uncommitted changes without taking into account changes made in the upstream branch. Teach diff-index and diff (with one commit) the --merge-base option which allows a user to use the merge base of a commit and HEAD as the "before" side. Signed-off-by: Denton Liu Signed-off-by: Junio C Hamano --- diff-lib.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'diff-lib.c') diff --git a/diff-lib.c b/diff-lib.c index 468e3fe854..c578560997 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -561,13 +561,26 @@ int run_diff_index(struct rev_info *revs, unsigned int option) { struct object_array_entry *ent; int cached = !!(option & DIFF_INDEX_CACHED); + int merge_base = !!(option & DIFF_INDEX_MERGE_BASE); + struct object_id oid; + const char *name; + char merge_base_hex[GIT_MAX_HEXSZ + 1]; if (revs->pending.nr != 1) BUG("run_diff_index must be passed exactly one tree"); trace_performance_enter(); ent = revs->pending.objects; - if (diff_cache(revs, &ent->item->oid, ent->name, cached)) + + if (merge_base) { + diff_get_merge_base(revs, &oid); + name = oid_to_hex_r(merge_base_hex, &oid); + } else { + oidcpy(&oid, &ent->item->oid); + name = ent->name; + } + + if (diff_cache(revs, &oid, name, cached)) exit(128); diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/"); -- cgit v1.2.3