commit-reach: move ref_newer from remote.c
[gitweb.git] / commit-reach.c
index 8ab6044414a127e358f0f4abb6977f2aba347882..a6bc4781a63d118d989599241057ec95fa39da5b 100644 (file)
@@ -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;
+}