rev-list.c 3.22 KB
Newer Older
1
/*
2 3
 * libgit2 "rev-list" example - shows how to transform a rev-spec into a list
 * of commit ids
4
 *
5 6 7 8 9 10 11 12 13
 * Written by the libgit2 contributors
 *
 * To the extent possible under law, the author(s) have dedicated all copyright
 * and related and neighboring rights to this software to the public domain
 * worldwide. This software is distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along
 * with this software. If not, see
 * <http://creativecommons.org/publicdomain/zero/1.0/>.
14
 */
Greg Price committed
15

16
#include "common.h"
Greg Price committed
17

18 19 20
static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts);

int main (int argc, char **argv)
Greg Price committed
21
{
22 23 24
	git_repository *repo;
	git_revwalk *walk;
	git_oid oid;
25
	char buf[GIT_OID_HEXSZ+1];
26

27
	git_libgit2_init();
Greg Price committed
28

29 30 31 32 33 34
	check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "opening repository", NULL);
	check_lg2(git_revwalk_new(&walk, repo), "allocating revwalk", NULL);
	check_lg2(revwalk_parseopts(repo, walk, argc-1, argv+1), "parsing options", NULL);

	while (!git_revwalk_next(&oid, walk)) {
		git_oid_fmt(buf, &oid);
35
		buf[GIT_OID_HEXSZ] = '\0';
36 37 38
		printf("%s\n", buf);
	}

39
	git_libgit2_shutdown();
40
	return 0;
Greg Price committed
41 42
}

Ben Straub committed
43
static int push_commit(git_revwalk *walk, const git_oid *oid, int hide)
Greg Price committed
44 45
{
	if (hide)
46
		return git_revwalk_hide(walk, oid);
Greg Price committed
47
	else
48
		return git_revwalk_push(walk, oid);
Greg Price committed
49 50 51 52 53
}

static int push_spec(git_repository *repo, git_revwalk *walk, const char *spec, int hide)
{
	int error;
54
	git_object *obj;
Greg Price committed
55

Ben Straub committed
56
	if ((error = git_revparse_single(&obj, repo, spec)) < 0)
Greg Price committed
57
		return error;
Vicent Marti committed
58

59 60 61
	error = push_commit(walk, git_object_id(obj), hide);
	git_object_free(obj);
	return error;
Greg Price committed
62 63 64 65
}

static int push_range(git_repository *repo, git_revwalk *walk, const char *range, int hide)
{
Vicent Marti committed
66
	git_revspec revspec;
Greg Price committed
67 68
	int error = 0;

Vicent Marti committed
69
	if ((error = git_revparse(&revspec, repo, range)))
Greg Price committed
70
		return error;
Vicent Marti committed
71 72

	if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
Greg Price committed
73 74 75 76
		/* TODO: support "<commit>...<commit>" */
		return GIT_EINVALIDSPEC;
	}

Vicent Marti committed
77
	if ((error = push_commit(walk, git_object_id(revspec.from), !hide)))
Greg Price committed
78 79
		goto out;

Vicent Marti committed
80 81 82 83 84
	error = push_commit(walk, git_object_id(revspec.to), hide);

out:
	git_object_free(revspec.from);
	git_object_free(revspec.to);
Greg Price committed
85 86 87
	return error;
}

88
static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts)
Greg Price committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
{
	int hide, i, error;
	unsigned int sorting = GIT_SORT_NONE;

	hide = 0;
	for (i = 0; i < nopts; i++) {
		if (!strcmp(opts[i], "--topo-order")) {
			sorting = GIT_SORT_TOPOLOGICAL | (sorting & GIT_SORT_REVERSE);
			git_revwalk_sorting(walk, sorting);
		} else if (!strcmp(opts[i], "--date-order")) {
			sorting = GIT_SORT_TIME | (sorting & GIT_SORT_REVERSE);
			git_revwalk_sorting(walk, sorting);
		} else if (!strcmp(opts[i], "--reverse")) {
			sorting = (sorting & ~GIT_SORT_REVERSE)
			    | ((sorting & GIT_SORT_REVERSE) ? 0 : GIT_SORT_REVERSE);
			git_revwalk_sorting(walk, sorting);
		} else if (!strcmp(opts[i], "--not")) {
			hide = !hide;
		} else if (opts[i][0] == '^') {
			if ((error = push_spec(repo, walk, opts[i] + 1, !hide)))
				return error;
		} else if (strstr(opts[i], "..")) {
			if ((error = push_range(repo, walk, opts[i], hide)))
				return error;
		} else {
			if ((error = push_spec(repo, walk, opts[i], hide)))
				return error;
		}
	}

	return 0;
}