]> git.proxmox.com Git - libgit2.git/blame - src/graph.c
Merge pull request #1091 from carlosmn/stream-object
[libgit2.git] / src / graph.c
CommitLineData
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
13static 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
49on_error:
50 git_pqueue_free(&pq);
51 return -1;
0984c876
SG
52}
53
54int 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
95on_error:
96 git_revwalk_free(walk);
97 return -1;
98}