]>
Commit | Line | Data |
---|---|---|
0984c876 SG |
1 | |
2 | /* | |
3 | * Copyright (C) 2009-2012 the libgit2 contributors | |
4 | * | |
5 | * This file is part of libgit2, distributed under the GNU GPL v2 with | |
6 | * a Linking Exception. For full terms see the included COPYING file. | |
7 | */ | |
8 | ||
0984c876 | 9 | #include "revwalk.h" |
0984c876 | 10 | #include "merge.h" |
0984c876 SG |
11 | #include "git2/graph.h" |
12 | ||
13 | static int ahead_behind(git_commit_list_node *one, git_commit_list_node *two, | |
14 | size_t *ahead, size_t *behind) | |
15 | { | |
16 | git_commit_list_node *commit; | |
17 | git_pqueue pq; | |
18 | int i; | |
19 | *ahead = 0; | |
20 | *behind = 0; | |
21 | ||
22 | if (git_pqueue_init(&pq, 2, git_commit_list_time_cmp) < 0) | |
23 | return -1; | |
24 | if (git_pqueue_insert(&pq, one) < 0) | |
da820437 | 25 | goto on_error; |
0984c876 | 26 | if (git_pqueue_insert(&pq, two) < 0) |
da820437 | 27 | goto on_error; |
0984c876 SG |
28 | |
29 | while ((commit = git_pqueue_pop(&pq)) != NULL) { | |
30 | if (commit->flags & RESULT || | |
31 | (commit->flags & (PARENT1 | PARENT2)) == (PARENT1 | PARENT2)) | |
32 | continue; | |
33 | else if (commit->flags & PARENT1) | |
34 | (*behind)++; | |
35 | else if (commit->flags & PARENT2) | |
36 | (*ahead)++; | |
37 | ||
38 | for (i = 0; i < commit->out_degree; i++) { | |
39 | git_commit_list_node *p = commit->parents[i]; | |
40 | if (git_pqueue_insert(&pq, p) < 0) | |
41 | return -1; | |
42 | } | |
43 | commit->flags |= RESULT; | |
44 | } | |
45 | ||
da820437 | 46 | git_pqueue_free(&pq); |
0984c876 | 47 | return 0; |
da820437 CMN |
48 | |
49 | on_error: | |
50 | git_pqueue_free(&pq); | |
51 | return -1; | |
0984c876 SG |
52 | } |
53 | ||
54 | int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, | |
55 | const git_oid *one, const git_oid *two) | |
56 | { | |
57 | git_revwalk *walk; | |
58 | git_vector list; | |
59 | struct git_commit_list *result = NULL; | |
60 | git_commit_list_node *commit1, *commit2; | |
61 | void *contents[1]; | |
62 | ||
63 | if (git_revwalk_new(&walk, repo) < 0) | |
64 | return -1; | |
65 | ||
d5e44d84 | 66 | commit2 = git_revwalk__commit_lookup(walk, two); |
0984c876 SG |
67 | if (commit2 == NULL) |
68 | goto on_error; | |
69 | ||
70 | /* This is just one value, so we can do it on the stack */ | |
71 | memset(&list, 0x0, sizeof(git_vector)); | |
72 | contents[0] = commit2; | |
73 | list.length = 1; | |
74 | list.contents = contents; | |
75 | ||
d5e44d84 | 76 | commit1 = git_revwalk__commit_lookup(walk, one); |
0984c876 SG |
77 | if (commit1 == NULL) |
78 | goto on_error; | |
79 | ||
80 | if (git_merge__bases_many(&result, walk, commit1, &list) < 0) | |
81 | goto on_error; | |
82 | if (ahead_behind(commit1, commit2, ahead, behind) < 0) | |
83 | goto on_error; | |
84 | ||
85 | if (!result) { | |
86 | git_revwalk_free(walk); | |
87 | return GIT_ENOTFOUND; | |
88 | } | |
89 | ||
90 | git_commit_list_free(&result); | |
91 | git_revwalk_free(walk); | |
92 | ||
93 | return 0; | |
94 | ||
95 | on_error: | |
96 | git_revwalk_free(walk); | |
97 | return -1; | |
98 | } |