summaryrefslogtreecommitdiff
path: root/commit-reach.c
diff options
context:
space:
mode:
authorLibravatar Derrick Stolee <dstolee@microsoft.com>2018-07-20 16:33:06 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2018-07-20 15:38:54 -0700
commit1d614d41e5fc030bc2f2799a58791aa912f78378 (patch)
tree9f3c355e56968b1f3fcdbdfc318e8a65c8c0f100 /commit-reach.c
parentcommit.h: remove method declarations (diff)
downloadtgif-1d614d41e5fc030bc2f2799a58791aa912f78378.tar.xz
commit-reach: move ref_newer from remote.c
There are several commit walks in the codebase. Group them together into a new commit-reach.c file and corresponding header. After we group these walks into one place, we can reduce duplicate logic by calling equivalent methods. The ref_newer() method is used by 'git push -f' to check if a force-push is necessary. By making the method public, we make it possible to test the method directly without setting up an envieronment where a 'git push' call makes sense. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'commit-reach.c')
-rw-r--r--commit-reach.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/commit-reach.c b/commit-reach.c
index 8ab6044414..a6bc4781a6 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -1,6 +1,10 @@
#include "cache.h"
-#include "prio-queue.h"
#include "commit.h"
+#include "decorate.h"
+#include "prio-queue.h"
+#include "tree.h"
+#include "revision.h"
+#include "tag.h"
#include "commit-reach.h"
/* Remember to update object flag allocation in object.h */
@@ -358,3 +362,52 @@ void reduce_heads_replace(struct commit_list **heads)
free_commit_list(*heads);
*heads = result;
}
+
+static void unmark_and_free(struct commit_list *list, unsigned int mark)
+{
+ while (list) {
+ struct commit *commit = pop_commit(&list);
+ commit->object.flags &= ~mark;
+ }
+}
+
+int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid)
+{
+ struct object *o;
+ struct commit *old_commit, *new_commit;
+ struct commit_list *list, *used;
+ int found = 0;
+
+ /*
+ * Both new_commit and old_commit must be commit-ish and new_commit is descendant of
+ * old_commit. Otherwise we require --force.
+ */
+ o = deref_tag(the_repository, parse_object(the_repository, old_oid),
+ NULL, 0);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+ old_commit = (struct commit *) o;
+
+ o = deref_tag(the_repository, parse_object(the_repository, new_oid),
+ NULL, 0);
+ if (!o || o->type != OBJ_COMMIT)
+ return 0;
+ new_commit = (struct commit *) o;
+
+ if (parse_commit(new_commit) < 0)
+ return 0;
+
+ used = list = NULL;
+ commit_list_insert(new_commit, &list);
+ while (list) {
+ new_commit = pop_most_recent_commit(&list, TMP_MARK);
+ commit_list_insert(new_commit, &used);
+ if (new_commit == old_commit) {
+ found = 1;
+ break;
+ }
+ }
+ unmark_and_free(list, TMP_MARK);
+ unmark_and_free(used, TMP_MARK);
+ return found;
+}