Blame examples/log.c

Packit Service 20376f
/*
Packit Service 20376f
 * libgit2 "log" example - shows how to walk history and get commit info
Packit Service 20376f
 *
Packit Service 20376f
 * Written by the libgit2 contributors
Packit Service 20376f
 *
Packit Service 20376f
 * To the extent possible under law, the author(s) have dedicated all copyright
Packit Service 20376f
 * and related and neighboring rights to this software to the public domain
Packit Service 20376f
 * worldwide. This software is distributed without any warranty.
Packit Service 20376f
 *
Packit Service 20376f
 * You should have received a copy of the CC0 Public Domain Dedication along
Packit Service 20376f
 * with this software. If not, see
Packit Service 20376f
 * <http://creativecommons.org/publicdomain/zero/1.0/>.
Packit Service 20376f
 */
Packit Service 20376f
Packit Service 20376f
#include "common.h"
Packit Service 20376f
Packit Service 20376f
/**
Packit Service 20376f
 * This example demonstrates the libgit2 rev walker APIs to roughly
Packit Service 20376f
 * simulate the output of `git log` and a few of command line arguments.
Packit Service 20376f
 * `git log` has many many options and this only shows a few of them.
Packit Service 20376f
 *
Packit Service 20376f
 * This does not have:
Packit Service 20376f
 *
Packit Service 20376f
 * - Robust error handling
Packit Service 20376f
 * - Colorized or paginated output formatting
Packit Service 20376f
 * - Most of the `git log` options
Packit Service 20376f
 *
Packit Service 20376f
 * This does have:
Packit Service 20376f
 *
Packit Service 20376f
 * - Examples of translating command line arguments to equivalent libgit2
Packit Service 20376f
 *   revwalker configuration calls
Packit Service 20376f
 * - Simplified options to apply pathspec limits and to show basic diffs
Packit Service 20376f
 */
Packit Service 20376f
Packit Service 20376f
/** log_state represents walker being configured while handling options */
Packit Service 20376f
struct log_state {
Packit Service 20376f
	git_repository *repo;
Packit Service 20376f
	const char *repodir;
Packit Service 20376f
	git_revwalk *walker;
Packit Service 20376f
	int hide;
Packit Service 20376f
	int sorting;
Packit Service 20376f
	int revisions;
Packit Service 20376f
};
Packit Service 20376f
Packit Service 20376f
/** utility functions that are called to configure the walker */
Packit Service 20376f
static void set_sorting(struct log_state *s, unsigned int sort_mode);
Packit Service 20376f
static void push_rev(struct log_state *s, git_object *obj, int hide);
Packit Service 20376f
static int add_revision(struct log_state *s, const char *revstr);
Packit Service 20376f
Packit Service 20376f
/** log_options holds other command line options that affect log output */
Packit Service 20376f
struct log_options {
Packit Service 20376f
	int show_diff;
Packit Service 20376f
	int skip, limit;
Packit Service 20376f
	int min_parents, max_parents;
Packit Service 20376f
	git_time_t before;
Packit Service 20376f
	git_time_t after;
Packit Service 20376f
	const char *author;
Packit Service 20376f
	const char *committer;
Packit Service 20376f
	const char *grep;
Packit Service 20376f
};
Packit Service 20376f
Packit Service 20376f
/** utility functions that parse options and help with log output */
Packit Service 20376f
static int parse_options(
Packit Service 20376f
	struct log_state *s, struct log_options *opt, int argc, char **argv);
Packit Service 20376f
static void print_time(const git_time *intime, const char *prefix);
Packit Service 20376f
static void print_commit(git_commit *commit);
Packit Service 20376f
static int match_with_parent(git_commit *commit, int i, git_diff_options *);
Packit Service 20376f
Packit Service 20376f
/** utility functions for filtering */
Packit Service 20376f
static int signature_matches(const git_signature *sig, const char *filter);
Packit Service 20376f
static int log_message_matches(const git_commit *commit, const char *filter);
Packit Service 20376f
Packit Service 20376f
int main(int argc, char *argv[])
Packit Service 20376f
{
Packit Service 20376f
	int i, count = 0, printed = 0, parents, last_arg;
Packit Service 20376f
	struct log_state s;
Packit Service 20376f
	struct log_options opt;
Packit Service 20376f
	git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
Packit Service 20376f
	git_oid oid;
Packit Service 20376f
	git_commit *commit = NULL;
Packit Service 20376f
	git_pathspec *ps = NULL;
Packit Service 20376f
Packit Service 20376f
	git_libgit2_init();
Packit Service 20376f
Packit Service 20376f
	/** Parse arguments and set up revwalker. */
Packit Service 20376f
Packit Service 20376f
	last_arg = parse_options(&s, &opt, argc, argv);
Packit Service 20376f
Packit Service 20376f
	diffopts.pathspec.strings = &argv[last_arg];
Packit Service 20376f
	diffopts.pathspec.count	  = argc - last_arg;
Packit Service 20376f
	if (diffopts.pathspec.count > 0)
Packit Service 20376f
		check_lg2(git_pathspec_new(&ps, &diffopts.pathspec),
Packit Service 20376f
			"Building pathspec", NULL);
Packit Service 20376f
Packit Service 20376f
	if (!s.revisions)
Packit Service 20376f
		add_revision(&s, NULL);
Packit Service 20376f
Packit Service 20376f
	/** Use the revwalker to traverse the history. */
Packit Service 20376f
Packit Service 20376f
	printed = count = 0;
Packit Service 20376f
Packit Service 20376f
	for (; !git_revwalk_next(&oid, s.walker); git_commit_free(commit)) {
Packit Service 20376f
		check_lg2(git_commit_lookup(&commit, s.repo, &oid),
Packit Service 20376f
			"Failed to look up commit", NULL);
Packit Service 20376f
Packit Service 20376f
		parents = (int)git_commit_parentcount(commit);
Packit Service 20376f
		if (parents < opt.min_parents)
Packit Service 20376f
			continue;
Packit Service 20376f
		if (opt.max_parents > 0 && parents > opt.max_parents)
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		if (diffopts.pathspec.count > 0) {
Packit Service 20376f
			int unmatched = parents;
Packit Service 20376f
Packit Service 20376f
			if (parents == 0) {
Packit Service 20376f
				git_tree *tree;
Packit Service 20376f
				check_lg2(git_commit_tree(&tree, commit), "Get tree", NULL);
Packit Service 20376f
				if (git_pathspec_match_tree(
Packit Service 20376f
						NULL, tree, GIT_PATHSPEC_NO_MATCH_ERROR, ps) != 0)
Packit Service 20376f
					unmatched = 1;
Packit Service 20376f
				git_tree_free(tree);
Packit Service 20376f
			} else if (parents == 1) {
Packit Service 20376f
				unmatched = match_with_parent(commit, 0, &diffopts) ? 0 : 1;
Packit Service 20376f
			} else {
Packit Service 20376f
				for (i = 0; i < parents; ++i) {
Packit Service 20376f
					if (match_with_parent(commit, i, &diffopts))
Packit Service 20376f
						unmatched--;
Packit Service 20376f
				}
Packit Service 20376f
			}
Packit Service 20376f
Packit Service 20376f
			if (unmatched > 0)
Packit Service 20376f
				continue;
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
		if (!signature_matches(git_commit_author(commit), opt.author))
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		if (!signature_matches(git_commit_committer(commit), opt.committer))
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		if (!log_message_matches(commit, opt.grep))
Packit Service 20376f
			continue;
Packit Service 20376f
Packit Service 20376f
		if (count++ < opt.skip)
Packit Service 20376f
			continue;
Packit Service 20376f
		if (opt.limit != -1 && printed++ >= opt.limit) {
Packit Service 20376f
			git_commit_free(commit);
Packit Service 20376f
			break;
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
		print_commit(commit);
Packit Service 20376f
Packit Service 20376f
		if (opt.show_diff) {
Packit Service 20376f
			git_tree *a = NULL, *b = NULL;
Packit Service 20376f
			git_diff *diff = NULL;
Packit Service 20376f
Packit Service 20376f
			if (parents > 1)
Packit Service 20376f
				continue;
Packit Service 20376f
			check_lg2(git_commit_tree(&b, commit), "Get tree", NULL);
Packit Service 20376f
			if (parents == 1) {
Packit Service 20376f
				git_commit *parent;
Packit Service 20376f
				check_lg2(git_commit_parent(&parent, commit, 0), "Get parent", NULL);
Packit Service 20376f
				check_lg2(git_commit_tree(&a, parent), "Tree for parent", NULL);
Packit Service 20376f
				git_commit_free(parent);
Packit Service 20376f
			}
Packit Service 20376f
Packit Service 20376f
			check_lg2(git_diff_tree_to_tree(
Packit Service 20376f
				&diff, git_commit_owner(commit), a, b, &diffopts),
Packit Service 20376f
				"Diff commit with parent", NULL);
Packit Service 20376f
			check_lg2(
Packit Service 20376f
                git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, diff_output, NULL),
Packit Service 20376f
				"Displaying diff", NULL);
Packit Service 20376f
Packit Service 20376f
			git_diff_free(diff);
Packit Service 20376f
			git_tree_free(a);
Packit Service 20376f
			git_tree_free(b);
Packit Service 20376f
		}
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	git_pathspec_free(ps);
Packit Service 20376f
	git_revwalk_free(s.walker);
Packit Service 20376f
	git_repository_free(s.repo);
Packit Service 20376f
	git_libgit2_shutdown();
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Determine if the given git_signature does not contain the filter text. */
Packit Service 20376f
static int signature_matches(const git_signature *sig, const char *filter) {
Packit Service 20376f
	if (filter == NULL)
Packit Service 20376f
		return 1;
Packit Service 20376f
Packit Service 20376f
	if (sig != NULL &&
Packit Service 20376f
		(strstr(sig->name, filter) != NULL ||
Packit Service 20376f
		strstr(sig->email, filter) != NULL))
Packit Service 20376f
		return 1;
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int log_message_matches(const git_commit *commit, const char *filter) {
Packit Service 20376f
	const char *message = NULL;
Packit Service 20376f
Packit Service 20376f
	if (filter == NULL)
Packit Service 20376f
		return 1;
Packit Service 20376f
Packit Service 20376f
	if ((message = git_commit_message(commit)) != NULL &&
Packit Service 20376f
		strstr(message, filter) != NULL)
Packit Service 20376f
		return 1;
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Push object (for hide or show) onto revwalker. */
Packit Service 20376f
static void push_rev(struct log_state *s, git_object *obj, int hide)
Packit Service 20376f
{
Packit Service 20376f
	hide = s->hide ^ hide;
Packit Service 20376f
Packit Service 20376f
	/** Create revwalker on demand if it doesn't already exist. */
Packit Service 20376f
	if (!s->walker) {
Packit Service 20376f
		check_lg2(git_revwalk_new(&s->walker, s->repo),
Packit Service 20376f
			"Could not create revision walker", NULL);
Packit Service 20376f
		git_revwalk_sorting(s->walker, s->sorting);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (!obj)
Packit Service 20376f
		check_lg2(git_revwalk_push_head(s->walker),
Packit Service 20376f
			"Could not find repository HEAD", NULL);
Packit Service 20376f
	else if (hide)
Packit Service 20376f
		check_lg2(git_revwalk_hide(s->walker, git_object_id(obj)),
Packit Service 20376f
			"Reference does not refer to a commit", NULL);
Packit Service 20376f
	else
Packit Service 20376f
		check_lg2(git_revwalk_push(s->walker, git_object_id(obj)),
Packit Service 20376f
			"Reference does not refer to a commit", NULL);
Packit Service 20376f
Packit Service 20376f
	git_object_free(obj);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Parse revision string and add revs to walker. */
Packit Service 20376f
static int add_revision(struct log_state *s, const char *revstr)
Packit Service 20376f
{
Packit Service 20376f
	git_revspec revs;
Packit Service 20376f
	int hide = 0;
Packit Service 20376f
Packit Service 20376f
	/** Open repo on demand if it isn't already open. */
Packit Service 20376f
	if (!s->repo) {
Packit Service 20376f
		if (!s->repodir) s->repodir = ".";
Packit Service 20376f
		check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL),
Packit Service 20376f
			"Could not open repository", s->repodir);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (!revstr) {
Packit Service 20376f
		push_rev(s, NULL, hide);
Packit Service 20376f
		return 0;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if (*revstr == '^') {
Packit Service 20376f
		revs.flags = GIT_REVPARSE_SINGLE;
Packit Service 20376f
		hide = !hide;
Packit Service 20376f
Packit Service 20376f
		if (git_revparse_single(&revs.from, s->repo, revstr + 1) < 0)
Packit Service 20376f
			return -1;
Packit Service 20376f
	} else if (git_revparse(&revs, s->repo, revstr) < 0)
Packit Service 20376f
		return -1;
Packit Service 20376f
Packit Service 20376f
	if ((revs.flags & GIT_REVPARSE_SINGLE) != 0)
Packit Service 20376f
		push_rev(s, revs.from, hide);
Packit Service 20376f
	else {
Packit Service 20376f
		push_rev(s, revs.to, hide);
Packit Service 20376f
Packit Service 20376f
		if ((revs.flags & GIT_REVPARSE_MERGE_BASE) != 0) {
Packit Service 20376f
			git_oid base;
Packit Service 20376f
			check_lg2(git_merge_base(&base, s->repo,
Packit Service 20376f
				git_object_id(revs.from), git_object_id(revs.to)),
Packit Service 20376f
				"Could not find merge base", revstr);
Packit Service 20376f
			check_lg2(
Packit Service 20376f
				git_object_lookup(&revs.to, s->repo, &base, GIT_OBJ_COMMIT),
Packit Service 20376f
				"Could not find merge base commit", NULL);
Packit Service 20376f
Packit Service 20376f
			push_rev(s, revs.to, hide);
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
		push_rev(s, revs.from, !hide);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Update revwalker with sorting mode. */
Packit Service 20376f
static void set_sorting(struct log_state *s, unsigned int sort_mode)
Packit Service 20376f
{
Packit Service 20376f
	/** Open repo on demand if it isn't already open. */
Packit Service 20376f
	if (!s->repo) {
Packit Service 20376f
		if (!s->repodir) s->repodir = ".";
Packit Service 20376f
		check_lg2(git_repository_open_ext(&s->repo, s->repodir, 0, NULL),
Packit Service 20376f
			"Could not open repository", s->repodir);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	/** Create revwalker on demand if it doesn't already exist. */
Packit Service 20376f
	if (!s->walker)
Packit Service 20376f
		check_lg2(git_revwalk_new(&s->walker, s->repo),
Packit Service 20376f
			"Could not create revision walker", NULL);
Packit Service 20376f
Packit Service 20376f
	if (sort_mode == GIT_SORT_REVERSE)
Packit Service 20376f
		s->sorting = s->sorting ^ GIT_SORT_REVERSE;
Packit Service 20376f
	else
Packit Service 20376f
		s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE);
Packit Service 20376f
Packit Service 20376f
	git_revwalk_sorting(s->walker, s->sorting);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Helper to format a git_time value like Git. */
Packit Service 20376f
static void print_time(const git_time *intime, const char *prefix)
Packit Service 20376f
{
Packit Service 20376f
	char sign, out[32];
Packit Service 20376f
	struct tm *intm;
Packit Service 20376f
	int offset, hours, minutes;
Packit Service 20376f
	time_t t;
Packit Service 20376f
Packit Service 20376f
	offset = intime->offset;
Packit Service 20376f
	if (offset < 0) {
Packit Service 20376f
		sign = '-';
Packit Service 20376f
		offset = -offset;
Packit Service 20376f
	} else {
Packit Service 20376f
		sign = '+';
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	hours   = offset / 60;
Packit Service 20376f
	minutes = offset % 60;
Packit Service 20376f
Packit Service 20376f
	t = (time_t)intime->time + (intime->offset * 60);
Packit Service 20376f
Packit Service 20376f
	intm = gmtime(&t);
Packit Service 20376f
	strftime(out, sizeof(out), "%a %b %e %T %Y", intm);
Packit Service 20376f
Packit Service 20376f
	printf("%s%s %c%02d%02d\n", prefix, out, sign, hours, minutes);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Helper to print a commit object. */
Packit Service 20376f
static void print_commit(git_commit *commit)
Packit Service 20376f
{
Packit Service 20376f
	char buf[GIT_OID_HEXSZ + 1];
Packit Service 20376f
	int i, count;
Packit Service 20376f
	const git_signature *sig;
Packit Service 20376f
	const char *scan, *eol;
Packit Service 20376f
Packit Service 20376f
	git_oid_tostr(buf, sizeof(buf), git_commit_id(commit));
Packit Service 20376f
	printf("commit %s\n", buf);
Packit Service 20376f
Packit Service 20376f
	if ((count = (int)git_commit_parentcount(commit)) > 1) {
Packit Service 20376f
		printf("Merge:");
Packit Service 20376f
		for (i = 0; i < count; ++i) {
Packit Service 20376f
			git_oid_tostr(buf, 8, git_commit_parent_id(commit, i));
Packit Service 20376f
			printf(" %s", buf);
Packit Service 20376f
		}
Packit Service 20376f
		printf("\n");
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	if ((sig = git_commit_author(commit)) != NULL) {
Packit Service 20376f
		printf("Author: %s <%s>\n", sig->name, sig->email);
Packit Service 20376f
		print_time(&sig->when, "Date:   ");
Packit Service 20376f
	}
Packit Service 20376f
	printf("\n");
Packit Service 20376f
Packit Service 20376f
	for (scan = git_commit_message(commit); scan && *scan; ) {
Packit Service 20376f
		for (eol = scan; *eol && *eol != '\n'; ++eol) /* find eol */;
Packit Service 20376f
Packit Service 20376f
		printf("    %.*s\n", (int)(eol - scan), scan);
Packit Service 20376f
		scan = *eol ? eol + 1 : NULL;
Packit Service 20376f
	}
Packit Service 20376f
	printf("\n");
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Helper to find how many files in a commit changed from its nth parent. */
Packit Service 20376f
static int match_with_parent(git_commit *commit, int i, git_diff_options *opts)
Packit Service 20376f
{
Packit Service 20376f
	git_commit *parent;
Packit Service 20376f
	git_tree *a, *b;
Packit Service 20376f
	git_diff *diff;
Packit Service 20376f
	int ndeltas;
Packit Service 20376f
Packit Service 20376f
	check_lg2(
Packit Service 20376f
		git_commit_parent(&parent, commit, (size_t)i), "Get parent", NULL);
Packit Service 20376f
	check_lg2(git_commit_tree(&a, parent), "Tree for parent", NULL);
Packit Service 20376f
	check_lg2(git_commit_tree(&b, commit), "Tree for commit", NULL);
Packit Service 20376f
	check_lg2(
Packit Service 20376f
		git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts),
Packit Service 20376f
		"Checking diff between parent and commit", NULL);
Packit Service 20376f
Packit Service 20376f
	ndeltas = (int)git_diff_num_deltas(diff);
Packit Service 20376f
Packit Service 20376f
	git_diff_free(diff);
Packit Service 20376f
	git_tree_free(a);
Packit Service 20376f
	git_tree_free(b);
Packit Service 20376f
	git_commit_free(parent);
Packit Service 20376f
Packit Service 20376f
	return ndeltas > 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Print a usage message for the program. */
Packit Service 20376f
static void usage(const char *message, const char *arg)
Packit Service 20376f
{
Packit Service 20376f
	if (message && arg)
Packit Service 20376f
		fprintf(stderr, "%s: %s\n", message, arg);
Packit Service 20376f
	else if (message)
Packit Service 20376f
		fprintf(stderr, "%s\n", message);
Packit Service 20376f
	fprintf(stderr, "usage: log [<options>]\n");
Packit Service 20376f
	exit(1);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/** Parse some log command line options. */
Packit Service 20376f
static int parse_options(
Packit Service 20376f
	struct log_state *s, struct log_options *opt, int argc, char **argv)
Packit Service 20376f
{
Packit Service 20376f
	struct args_info args = ARGS_INFO_INIT;
Packit Service 20376f
Packit Service 20376f
	memset(s, 0, sizeof(*s));
Packit Service 20376f
	s->sorting = GIT_SORT_TIME;
Packit Service 20376f
Packit Service 20376f
	memset(opt, 0, sizeof(*opt));
Packit Service 20376f
	opt->max_parents = -1;
Packit Service 20376f
	opt->limit = -1;
Packit Service 20376f
Packit Service 20376f
	for (args.pos = 1; args.pos < argc; ++args.pos) {
Packit Service 20376f
		const char *a = argv[args.pos];
Packit Service 20376f
Packit Service 20376f
		if (a[0] != '-') {
Packit Service 20376f
			if (!add_revision(s, a))
Packit Service 20376f
				s->revisions++;
Packit Service 20376f
			else
Packit Service 20376f
				/** Try failed revision parse as filename. */
Packit Service 20376f
				break;
Packit Service 20376f
		} else if (!strcmp(a, "--")) {
Packit Service 20376f
			++args.pos;
Packit Service 20376f
			break;
Packit Service 20376f
		}
Packit Service 20376f
		else if (!strcmp(a, "--date-order"))
Packit Service 20376f
			set_sorting(s, GIT_SORT_TIME);
Packit Service 20376f
		else if (!strcmp(a, "--topo-order"))
Packit Service 20376f
			set_sorting(s, GIT_SORT_TOPOLOGICAL);
Packit Service 20376f
		else if (!strcmp(a, "--reverse"))
Packit Service 20376f
			set_sorting(s, GIT_SORT_REVERSE);
Packit Service 20376f
		else if (match_str_arg(&opt->author, &args, "--author"))
Packit Service 20376f
			/** Found valid --author */;
Packit Service 20376f
		else if (match_str_arg(&opt->committer, &args, "--committer"))
Packit Service 20376f
			/** Found valid --committer */;
Packit Service 20376f
		else if (match_str_arg(&opt->grep, &args, "--grep"))
Packit Service 20376f
			/** Found valid --grep */;
Packit Service 20376f
		else if (match_str_arg(&s->repodir, &args, "--git-dir"))
Packit Service 20376f
			/** Found git-dir. */;
Packit Service 20376f
		else if (match_int_arg(&opt->skip, &args, "--skip", 0))
Packit Service 20376f
			/** Found valid --skip. */;
Packit Service 20376f
		else if (match_int_arg(&opt->limit, &args, "--max-count", 0))
Packit Service 20376f
			/** Found valid --max-count. */;
Packit Service 20376f
		else if (a[1] >= '0' && a[1] <= '9')
Packit Service 20376f
			is_integer(&opt->limit, a + 1, 0);
Packit Service 20376f
		else if (match_int_arg(&opt->limit, &args, "-n", 0))
Packit Service 20376f
			/** Found valid -n. */;
Packit Service 20376f
		else if (!strcmp(a, "--merges"))
Packit Service 20376f
			opt->min_parents = 2;
Packit Service 20376f
		else if (!strcmp(a, "--no-merges"))
Packit Service 20376f
			opt->max_parents = 1;
Packit Service 20376f
		else if (!strcmp(a, "--no-min-parents"))
Packit Service 20376f
			opt->min_parents = 0;
Packit Service 20376f
		else if (!strcmp(a, "--no-max-parents"))
Packit Service 20376f
			opt->max_parents = -1;
Packit Service 20376f
		else if (match_int_arg(&opt->max_parents, &args, "--max-parents=", 1))
Packit Service 20376f
			/** Found valid --max-parents. */;
Packit Service 20376f
		else if (match_int_arg(&opt->min_parents, &args, "--min-parents=", 0))
Packit Service 20376f
			/** Found valid --min_parents. */;
Packit Service 20376f
		else if (!strcmp(a, "-p") || !strcmp(a, "-u") || !strcmp(a, "--patch"))
Packit Service 20376f
			opt->show_diff = 1;
Packit Service 20376f
		else
Packit Service 20376f
			usage("Unsupported argument", a);
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
	return args.pos;
Packit Service 20376f
}
Packit Service 20376f