rev-list.c 2.87 KB
Newer Older
Greg Price committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <stdio.h>
#include <string.h>

#include <git2.h>

static void check_error(int error_code, const char *action)
{
	if (!error_code)
		return;

	const git_error *error = giterr_last();
	fprintf(stderr, "Error %d %s: %s\n", -error_code, action,
	        (error && error->message) ? error->message : "???");
	exit(1);
}

Ben Straub committed
17
static int push_commit(git_revwalk *walk, const git_oid *oid, int hide)
Greg Price committed
18 19
{
	if (hide)
20
		return git_revwalk_hide(walk, oid);
Greg Price committed
21
	else
22
		return git_revwalk_push(walk, oid);
Greg Price committed
23 24 25 26 27
}

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

Ben Straub committed
30
	if ((error = git_revparse_single(&obj, repo, spec)) < 0)
Greg Price committed
31
		return error;
Vicent Marti committed
32

33 34 35
	error = push_commit(walk, git_object_id(obj), hide);
	git_object_free(obj);
	return error;
Greg Price committed
36 37 38 39
}

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

Vicent Marti committed
43
	if ((error = git_revparse(&revspec, repo, range)))
Greg Price committed
44
		return error;
Vicent Marti committed
45 46

	if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
Greg Price committed
47 48 49 50
		/* TODO: support "<commit>...<commit>" */
		return GIT_EINVALIDSPEC;
	}

Vicent Marti committed
51
	if ((error = push_commit(walk, git_object_id(revspec.from), !hide)))
Greg Price committed
52 53
		goto out;

Vicent Marti committed
54 55 56 57 58
	error = push_commit(walk, git_object_id(revspec.to), hide);

out:
	git_object_free(revspec.from);
	git_object_free(revspec.to);
Greg Price committed
59 60 61
	return error;
}

62
static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts)
Greg Price committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 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
{
	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;
}

int main (int argc, char **argv)
{
	int error;
	git_repository *repo;
	git_revwalk *walk;
	git_oid oid;
	char buf[41];

	error = git_repository_open_ext(&repo, ".", 0, NULL);
	check_error(error, "opening repository");

	error = git_revwalk_new(&walk, repo);
	check_error(error, "allocating revwalk");
	error = revwalk_parseopts(repo, walk, argc-1, argv+1);
	check_error(error, "parsing options");

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

	return 0;
}