rev-list.c 3.09 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
static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts);

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

	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);
31
		buf[GIT_OID_HEXSZ] = '\0';
32 33 34 35
		printf("%s\n", buf);
	}

	return 0;
Greg Price committed
36 37
}

Ben Straub committed
38
static int push_commit(git_revwalk *walk, const git_oid *oid, int hide)
Greg Price committed
39 40
{
	if (hide)
41
		return git_revwalk_hide(walk, oid);
Greg Price committed
42
	else
43
		return git_revwalk_push(walk, oid);
Greg Price committed
44 45 46 47 48
}

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

Ben Straub committed
51
	if ((error = git_revparse_single(&obj, repo, spec)) < 0)
Greg Price committed
52
		return error;
Vicent Marti committed
53

54 55 56
	error = push_commit(walk, git_object_id(obj), hide);
	git_object_free(obj);
	return error;
Greg Price committed
57 58 59 60
}

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

Vicent Marti committed
64
	if ((error = git_revparse(&revspec, repo, range)))
Greg Price committed
65
		return error;
Vicent Marti committed
66 67

	if (revspec.flags & GIT_REVPARSE_MERGE_BASE) {
Greg Price committed
68 69 70 71
		/* TODO: support "<commit>...<commit>" */
		return GIT_EINVALIDSPEC;
	}

Vicent Marti committed
72
	if ((error = push_commit(walk, git_object_id(revspec.from), !hide)))
Greg Price committed
73 74
		goto out;

Vicent Marti committed
75 76 77 78 79
	error = push_commit(walk, git_object_id(revspec.to), hide);

out:
	git_object_free(revspec.from);
	git_object_free(revspec.to);
Greg Price committed
80 81 82
	return error;
}

83
static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts)
Greg Price committed
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
{
	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;
}