diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commit_list.c | 10 | ||||
-rw-r--r-- | src/graph.c | 93 | ||||
-rw-r--r-- | src/merge.c | 9 | ||||
-rw-r--r-- | src/revwalk.c | 5 | ||||
-rw-r--r-- | src/revwalk.h | 2 |
5 files changed, 108 insertions, 11 deletions
diff --git a/src/commit_list.c b/src/commit_list.c index c1a7b223f..d79934a2f 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -127,7 +127,7 @@ static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, g if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; - commit->parents[i] = commit_lookup(walk, &oid); + commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; @@ -181,9 +181,13 @@ int git_commit_list_parse(git_revwalk *walk, git_commit_list_node *commit) if ((error = git_odb_read(&obj, walk->odb, &commit->oid)) < 0) return error; - assert(obj->raw.type == GIT_OBJ_COMMIT); - error = commit_quick_parse(walk, commit, &obj->raw); + if (obj->raw.type != GIT_OBJ_COMMIT) { + giterr_set(GITERR_INVALID, "Object is no commit object"); + error = -1; + } else + error = commit_quick_parse(walk, commit, &obj->raw); + git_odb_object_free(obj); return error; } diff --git a/src/graph.c b/src/graph.c new file mode 100644 index 000000000..28026d4b4 --- /dev/null +++ b/src/graph.c @@ -0,0 +1,93 @@ + +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "revwalk.h" +#include "merge.h" +#include "git2/graph.h" + +static int ahead_behind(git_commit_list_node *one, git_commit_list_node *two, + size_t *ahead, size_t *behind) +{ + git_commit_list_node *commit; + git_pqueue pq; + int i; + *ahead = 0; + *behind = 0; + + if (git_pqueue_init(&pq, 2, git_commit_list_time_cmp) < 0) + return -1; + if (git_pqueue_insert(&pq, one) < 0) + return -1; + if (git_pqueue_insert(&pq, two) < 0) + return -1; + + while ((commit = git_pqueue_pop(&pq)) != NULL) { + if (commit->flags & RESULT || + (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) + continue; + else if (commit->flags & PARENT1) + (*behind)++; + else if (commit->flags & PARENT2) + (*ahead)++; + + for (i = 0; i < commit->out_degree; i++) { + git_commit_list_node *p = commit->parents[i]; + if (git_pqueue_insert(&pq, p) < 0) + return -1; + } + commit->flags |= RESULT; + } + + return 0; +} + +int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, + const git_oid *one, const git_oid *two) +{ + git_revwalk *walk; + git_vector list; + struct git_commit_list *result = NULL; + git_commit_list_node *commit1, *commit2; + void *contents[1]; + + if (git_revwalk_new(&walk, repo) < 0) + return -1; + + commit2 = git_revwalk__commit_lookup(walk, two); + if (commit2 == NULL) + goto on_error; + + /* This is just one value, so we can do it on the stack */ + memset(&list, 0x0, sizeof(git_vector)); + contents[0] = commit2; + list.length = 1; + list.contents = contents; + + commit1 = git_revwalk__commit_lookup(walk, one); + if (commit1 == NULL) + goto on_error; + + if (git_merge__bases_many(&result, walk, commit1, &list) < 0) + goto on_error; + if (ahead_behind(commit1, commit2, ahead, behind) < 0) + goto on_error; + + if (!result) { + git_revwalk_free(walk); + return GIT_ENOTFOUND; + } + + git_commit_list_free(&result); + git_revwalk_free(walk); + + return 0; + +on_error: + git_revwalk_free(walk); + return -1; +} diff --git a/src/merge.c b/src/merge.c index c795b808b..1386d0908 100644 --- a/src/merge.c +++ b/src/merge.c @@ -71,14 +71,14 @@ int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_ goto cleanup; for (i = 1; i < length; i++) { - commit = commit_lookup(walk, &input_array[i]); + commit = git_revwalk__commit_lookup(walk, &input_array[i]); if (commit == NULL) goto cleanup; git_vector_insert(&list, commit); } - commit = commit_lookup(walk, &input_array[0]); + commit = git_revwalk__commit_lookup(walk, &input_array[0]); if (commit == NULL) goto cleanup; @@ -112,7 +112,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const if (git_revwalk_new(&walk, repo) < 0) return -1; - commit = commit_lookup(walk, two); + commit = git_revwalk__commit_lookup(walk, two); if (commit == NULL) goto on_error; @@ -122,7 +122,7 @@ int git_merge_base(git_oid *out, git_repository *repo, const git_oid *one, const list.length = 1; list.contents = contents; - commit = commit_lookup(walk, one); + commit = git_revwalk__commit_lookup(walk, one); if (commit == NULL) goto on_error; @@ -241,4 +241,3 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l *out = result; return 0; } - diff --git a/src/revwalk.c b/src/revwalk.c index bdbbdbd17..cad2f09bd 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -15,7 +15,8 @@ #include <regex.h> -git_commit_list_node *commit_lookup(git_revwalk *walk, const git_oid *oid) +git_commit_list_node *git_revwalk__commit_lookup( + git_revwalk *walk, const git_oid *oid) { git_commit_list_node *commit; khiter_t pos; @@ -101,7 +102,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting) return -1; } - commit = commit_lookup(walk, oid); + commit = git_revwalk__commit_lookup(walk, oid); if (commit == NULL) return -1; /* error already reported by failed lookup */ diff --git a/src/revwalk.h b/src/revwalk.h index 2d482cfcc..6146eaf25 100644 --- a/src/revwalk.h +++ b/src/revwalk.h @@ -39,6 +39,6 @@ struct git_revwalk { git_vector twos; }; -git_commit_list_node *commit_lookup(git_revwalk *walk, const git_oid *oid); +git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid); #endif |