diff options
Diffstat (limited to 'examples/rev-list.c')
-rw-r--r-- | examples/rev-list.c | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/examples/rev-list.c b/examples/rev-list.c new file mode 100644 index 000000000..d9ec15f76 --- /dev/null +++ b/examples/rev-list.c @@ -0,0 +1,120 @@ +#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); +} + +static int push_commit(git_revwalk *walk, const git_oid *oid, int hide) +{ + if (hide) + return git_revwalk_hide(walk, oid); + else + return git_revwalk_push(walk, oid); +} + +static int push_spec(git_repository *repo, git_revwalk *walk, const char *spec, int hide) +{ + int error; + git_object *obj; + + if ((error = git_revparse_single(&obj, repo, spec)) < 0) + return error; + + error = push_commit(walk, git_object_id(obj), hide); + git_object_free(obj); + return error; +} + +static int push_range(git_repository *repo, git_revwalk *walk, const char *range, int hide) +{ + git_revspec revspec; + int error = 0; + + if ((error = git_revparse(&revspec, repo, range))) + return error; + + if (revspec.flags & GIT_REVPARSE_MERGE_BASE) { + /* TODO: support "<commit>...<commit>" */ + return GIT_EINVALIDSPEC; + } + + if ((error = push_commit(walk, git_object_id(revspec.from), !hide))) + goto out; + + error = push_commit(walk, git_object_id(revspec.to), hide); + +out: + git_object_free(revspec.from); + git_object_free(revspec.to); + return error; +} + +static int revwalk_parseopts(git_repository *repo, git_revwalk *walk, int nopts, char **opts) +{ + 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; +} + |