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>
This commit is contained in:
Derrick Stolee 2018-07-20 16:33:06 +00:00 коммит произвёл Junio C Hamano
Родитель 6404355657
Коммит 1d614d41e5
5 изменённых файлов: 57 добавлений и 51 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#include "refspec.h"
#include "object-store.h"
#include "argv-array.h"
#include "commit-reach.h"
static const char * const builtin_remote_usage[] = {
N_("git remote [-v | --verbose]"),

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -39,4 +39,6 @@ struct commit_list *reduce_heads(struct commit_list *heads);
*/
void reduce_heads_replace(struct commit_list **heads);
int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid);
#endif

Просмотреть файл

@ -1784,55 +1784,6 @@ int resolve_remote_symref(struct ref *ref, struct ref *list)
return 1;
}
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;
}
/*
* Lookup the upstream branch for the given branch and if present, optionally
* compute the commit ahead/behind values for the pair.

Просмотреть файл

@ -149,7 +149,6 @@ extern struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
const struct string_list *server_options);
int resolve_remote_symref(struct ref *ref, struct ref *list);
int ref_newer(const struct object_id *new_oid, const struct object_id *old_oid);
/*
* Remove and free all but the first of any entries in the input list