1 /*
2  * libgit2 "rev-list" example - shows how to transform a rev-spec into a list
3  * of commit ids
4  *
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/>.
14  */
15 
16 #include "common.h"
17 
18 static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts);
19 
main(int argc,char ** argv)20 int main (int argc, char **argv)
21 {
22 	git_repository *repo;
23 	git_revwalk *walk;
24 	git_oid oid;
25 	char buf[GIT_OID_HEXSZ+1];
26 
27 	git_libgit2_init();
28 
29 	check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "opening repository", NULL);
30 	check_lg2(git_revwalk_new(&walk, repo), "allocating revwalk", NULL);
31 	check_lg2(revwalk_parseopts(repo, walk, argc-1, argv+1), "parsing options", NULL);
32 
33 	while (!git_revwalk_next(&oid, walk)) {
34 		git_oid_fmt(buf, &oid);
35 		buf[GIT_OID_HEXSZ] = '\0';
36 		printf("%s\n", buf);
37 	}
38 
39 	git_libgit2_shutdown();
40 	return 0;
41 }
42 
push_commit(git_revwalk * walk,const git_oid * oid,int hide)43 static int push_commit(git_revwalk *walk, const git_oid *oid, int hide)
44 {
45 	if (hide)
46 		return git_revwalk_hide(walk, oid);
47 	else
48 		return git_revwalk_push(walk, oid);
49 }
50 
push_spec(git_repository * repo,git_revwalk * walk,const char * spec,int hide)51 static int push_spec(git_repository *repo, git_revwalk *walk, const char *spec, int hide)
52 {
53 	int error;
54 	git_object *obj;
55 
56 	if ((error = git_revparse_single(&obj, repo, spec)) < 0)
57 		return error;
58 
59 	error = push_commit(walk, git_object_id(obj), hide);
60 	git_object_free(obj);
61 	return error;
62 }
63 
push_range(git_repository * repo,git_revwalk * walk,const char * range,int hide)64 static int push_range(git_repository *repo, git_revwalk *walk, const char *range, int hide)
65 {
66 	git_revspec revspec;
67 	int error = 0;
68 
69 	if ((error = git_revparse(&revspec, repo, range)))
70 		return error;
71 
72 	if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
73 		/* TODO: support "<commit>...<commit>" */
74 		return GIT_EINVALIDSPEC;
75 	}
76 
77 	if ((error = push_commit(walk, git_object_id(revspec.from), !hide)))
78 		goto out;
79 
80 	error = push_commit(walk, git_object_id(revspec.to), hide);
81 
82 out:
83 	git_object_free(revspec.from);
84 	git_object_free(revspec.to);
85 	return error;
86 }
87 
revwalk_parseopts(git_repository * repo,git_revwalk * walk,int nopts,char ** opts)88 static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts)
89 {
90 	int hide, i, error;
91 	unsigned int sorting = GIT_SORT_NONE;
92 
93 	hide = 0;
94 	for (i = 0; i < nopts; i++) {
95 		if (!strcmp(opts[i], "--topo-order")) {
96 			sorting = GIT_SORT_TOPOLOGICAL | (sorting & GIT_SORT_REVERSE);
97 			git_revwalk_sorting(walk, sorting);
98 		} else if (!strcmp(opts[i], "--date-order")) {
99 			sorting = GIT_SORT_TIME | (sorting & GIT_SORT_REVERSE);
100 			git_revwalk_sorting(walk, sorting);
101 		} else if (!strcmp(opts[i], "--reverse")) {
102 			sorting = (sorting & ~GIT_SORT_REVERSE)
103 			    | ((sorting & GIT_SORT_REVERSE) ? 0 : GIT_SORT_REVERSE);
104 			git_revwalk_sorting(walk, sorting);
105 		} else if (!strcmp(opts[i], "--not")) {
106 			hide = !hide;
107 		} else if (opts[i][0] == '^') {
108 			if ((error = push_spec(repo, walk, opts[i] + 1, !hide)))
109 				return error;
110 		} else if (strstr(opts[i], "..")) {
111 			if ((error = push_range(repo, walk, opts[i], hide)))
112 				return error;
113 		} else {
114 			if ((error = push_spec(repo, walk, opts[i], hide)))
115 				return error;
116 		}
117 	}
118 
119 	return 0;
120 }
121 
122