]>
Commit | Line | Data |
---|---|---|
784b3abb | 1 | /* |
6cb831bd BS |
2 | * libgit2 "rev-list" example - shows how to transform a rev-spec into a list |
3 | * of commit ids | |
784b3abb | 4 | * |
6cb831bd BS |
5 | * Written by the libgit2 contributors |
6 | * | |
7 | * To the extent possible under law, the author(s) have dedicated all copyright | |
8 | * and related and neighboring rights to this software to the public domain | |
9 | * worldwide. This software is distributed without any warranty. | |
10 | * | |
11 | * You should have received a copy of the CC0 Public Domain Dedication along | |
12 | * with this software. If not, see | |
13 | * <http://creativecommons.org/publicdomain/zero/1.0/>. | |
784b3abb | 14 | */ |
8f7f5e55 | 15 | |
784b3abb | 16 | #include "common.h" |
8f7f5e55 | 17 | |
0c9c969a | 18 | #include <assert.h> |
784b3abb | 19 | |
0c9c969a UG |
20 | static int revwalk_parse_options(git_sort_t *sort, struct args_info *args); |
21 | static int revwalk_parse_revs(git_repository *repo, git_revwalk *walk, struct args_info *args); | |
22 | ||
23 | int lg2_rev_list(git_repository *repo, int argc, char **argv) | |
8f7f5e55 | 24 | { |
0c9c969a | 25 | struct args_info args = ARGS_INFO_INIT; |
784b3abb BS |
26 | git_revwalk *walk; |
27 | git_oid oid; | |
0c9c969a | 28 | git_sort_t sort; |
3b2cb2c9 | 29 | char buf[GIT_OID_HEXSZ+1]; |
784b3abb | 30 | |
0c9c969a | 31 | check_lg2(revwalk_parse_options(&sort, &args), "parsing options", NULL); |
8f7f5e55 | 32 | |
784b3abb | 33 | check_lg2(git_revwalk_new(&walk, repo), "allocating revwalk", NULL); |
0c9c969a UG |
34 | git_revwalk_sorting(walk, sort); |
35 | check_lg2(revwalk_parse_revs(repo, walk, &args), "parsing revs", NULL); | |
784b3abb BS |
36 | |
37 | while (!git_revwalk_next(&oid, walk)) { | |
38 | git_oid_fmt(buf, &oid); | |
3b2cb2c9 | 39 | buf[GIT_OID_HEXSZ] = '\0'; |
784b3abb BS |
40 | printf("%s\n", buf); |
41 | } | |
42 | ||
0c9c969a | 43 | git_revwalk_free(walk); |
784b3abb | 44 | return 0; |
8f7f5e55 GP |
45 | } |
46 | ||
5961d5ea | 47 | static int push_commit(git_revwalk *walk, const git_oid *oid, int hide) |
8f7f5e55 GP |
48 | { |
49 | if (hide) | |
1aa21fe3 | 50 | return git_revwalk_hide(walk, oid); |
8f7f5e55 | 51 | else |
1aa21fe3 | 52 | return git_revwalk_push(walk, oid); |
8f7f5e55 GP |
53 | } |
54 | ||
55 | static int push_spec(git_repository *repo, git_revwalk *walk, const char *spec, int hide) | |
56 | { | |
57 | int error; | |
299a224b | 58 | git_object *obj; |
8f7f5e55 | 59 | |
5961d5ea | 60 | if ((error = git_revparse_single(&obj, repo, spec)) < 0) |
8f7f5e55 | 61 | return error; |
32ef1d1c | 62 | |
299a224b BS |
63 | error = push_commit(walk, git_object_id(obj), hide); |
64 | git_object_free(obj); | |
65 | return error; | |
8f7f5e55 GP |
66 | } |
67 | ||
68 | static int push_range(git_repository *repo, git_revwalk *walk, const char *range, int hide) | |
69 | { | |
32ef1d1c | 70 | git_revspec revspec; |
8f7f5e55 GP |
71 | int error = 0; |
72 | ||
32ef1d1c | 73 | if ((error = git_revparse(&revspec, repo, range))) |
8f7f5e55 | 74 | return error; |
32ef1d1c VM |
75 | |
76 | if (revspec.flags & GIT_REVPARSE_MERGE_BASE) { | |
8f7f5e55 GP |
77 | /* TODO: support "<commit>...<commit>" */ |
78 | return GIT_EINVALIDSPEC; | |
79 | } | |
80 | ||
32ef1d1c | 81 | if ((error = push_commit(walk, git_object_id(revspec.from), !hide))) |
8f7f5e55 | 82 | goto out; |
8f7f5e55 | 83 | |
32ef1d1c VM |
84 | error = push_commit(walk, git_object_id(revspec.to), hide); |
85 | ||
86 | out: | |
87 | git_object_free(revspec.from); | |
88 | git_object_free(revspec.to); | |
8f7f5e55 GP |
89 | return error; |
90 | } | |
91 | ||
0c9c969a UG |
92 | static void print_usage(void) |
93 | { | |
94 | fprintf(stderr, "rev-list [--git-dir=dir] [--topo-order|--date-order] [--reverse] <revspec>\n"); | |
95 | exit(-1); | |
96 | } | |
97 | ||
98 | static int revwalk_parse_options(git_sort_t *sort, struct args_info *args) | |
99 | { | |
100 | assert(sort && args); | |
101 | *sort = GIT_SORT_NONE; | |
102 | ||
103 | if (args->argc < 1) | |
104 | print_usage(); | |
105 | ||
106 | for (args->pos = 1; args->pos < args->argc; ++args->pos) { | |
107 | const char *curr = args->argv[args->pos]; | |
108 | ||
109 | if (!strcmp(curr, "--topo-order")) { | |
110 | *sort |= GIT_SORT_TOPOLOGICAL; | |
111 | } else if (!strcmp(curr, "--date-order")) { | |
112 | *sort |= GIT_SORT_TIME; | |
113 | } else if (!strcmp(curr, "--reverse")) { | |
114 | *sort |= (*sort & ~GIT_SORT_REVERSE) ^ GIT_SORT_REVERSE; | |
115 | } else { | |
116 | break; | |
117 | } | |
118 | } | |
119 | return 0; | |
120 | } | |
121 | ||
122 | static int revwalk_parse_revs(git_repository *repo, git_revwalk *walk, struct args_info *args) | |
8f7f5e55 | 123 | { |
0c9c969a UG |
124 | int hide, error; |
125 | git_oid oid; | |
8f7f5e55 GP |
126 | |
127 | hide = 0; | |
0c9c969a UG |
128 | for (; args->pos < args->argc; ++args->pos) { |
129 | const char *curr = args->argv[args->pos]; | |
130 | ||
131 | if (!strcmp(curr, "--not")) { | |
8f7f5e55 | 132 | hide = !hide; |
0c9c969a UG |
133 | } else if (curr[0] == '^') { |
134 | if ((error = push_spec(repo, walk, curr + 1, !hide))) | |
8f7f5e55 | 135 | return error; |
0c9c969a UG |
136 | } else if (strstr(curr, "..")) { |
137 | if ((error = push_range(repo, walk, curr, hide))) | |
8f7f5e55 GP |
138 | return error; |
139 | } else { | |
0c9c969a UG |
140 | if (push_spec(repo, walk, curr, hide) == 0) |
141 | continue; | |
142 | ||
143 | if ((error = git_oid_fromstr(&oid, curr))) | |
144 | return error; | |
145 | if ((error = push_commit(walk, &oid, hide))) | |
8f7f5e55 GP |
146 | return error; |
147 | } | |
148 | } | |
149 | ||
150 | return 0; | |
151 | } | |
152 |