Commit d0628e2f by Russell Belfer Committed by Vicent Marti

More progress on log example

parent 0d44d3dc
......@@ -3,21 +3,15 @@
#include <stdlib.h>
#include <string.h>
static void check(int error, const char *message)
static void check(int error, const char *message, const char *arg)
{
if (error) {
if (!error)
return;
if (arg)
fprintf(stderr, "%s '%s' (%d)\n", message, arg, error);
else
fprintf(stderr, "%s (%d)\n", message, error);
exit(1);
}
}
static int check_str_param(const char *arg, const char *pat, const char **val)
{
size_t len = strlen(pat);
if (strncmp(arg, pat, len))
return 0;
*val = (const char *)(arg + len);
return 1;
exit(1);
}
static void usage(const char *message, const char *arg)
......@@ -30,75 +24,165 @@ static void usage(const char *message, const char *arg)
exit(1);
}
int main(int argc, char *argv[])
{
int i, j, last_nonoption, force_files = -1;
char *a;
const char *dir = ".";
struct log_state {
git_repository *repo;
const char *repodir;
git_revwalk *walker;
git_revspec revs;
int hide;
int sorting;
};
git_threads_init();
static void set_sorting(struct log_state *s, unsigned int sort_mode)
{
if (!s->repo) {
if (!s->repodir) s->repodir = ".";
check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL),
"Could not open repository", s->repodir);
}
for (i = 1, last_nonoption = 1; i < argc; ++i) {
a = argv[i];
if (!s->walker)
check(git_revwalk_new(&s->walker, s->repo),
"Could not create revision walker", NULL);
if (sort_mode == GIT_SORT_REVERSE)
s->sorting = s->sorting ^ GIT_SORT_REVERSE;
else
s->sorting = sort_mode | (s->sorting & GIT_SORT_REVERSE);
git_revwalk_sorting(s->walker, s->sorting);
}
static void push_rev(struct log_state *s, git_object *obj, int hide)
{
hide = s->hide ^ hide;
if (!s->walker)
check(git_revwalk_new(&s->walker, s->repo),
"Could not create revision walker", NULL);
if (!obj)
check(git_revwalk_push_head(s->walker),
"Could not find repository HEAD", NULL);
else if (hide)
check(git_revwalk_hide(s->walker, git_object_id(obj)),
"Reference does not refer to a commit", NULL);
else
check(git_revwalk_push(s->walker, git_object_id(obj)),
"Reference does not refer to a commit", NULL);
git_object_free(obj);
}
if (a[0] != '-' || force_files > 0) {
/* condense args not prefixed with '-' to start of argv */
if (last_nonoption != i)
argv[last_nonoption] = a;
last_nonoption++;
static int add_revision(struct log_state *s, const char *revstr)
{
git_revspec revs;
int hide = 0;
if (!s->repo) {
if (!s->repodir) s->repodir = ".";
check(git_repository_open_ext(&s->repo, s->repodir, 0, NULL),
"Could not open repository", s->repodir);
}
if (!revstr)
push_rev(s, NULL, hide);
else if (*revstr == '^') {
revs.flags = GIT_REVPARSE_SINGLE;
hide = !hide;
if (!git_revparse_single(&revs.from, s->repo, revstr + 1))
return -1;
} else
if (!git_revparse(&revs, s->repo, revstr))
return -1;
if ((revs.flags & GIT_REVPARSE_SINGLE) != 0)
push_rev(s, revs.from, hide);
else {
push_rev(s, revs.to, hide);
if ((revs.flags & GIT_REVPARSE_MERGE_BASE) != 0) {
git_oid base;
check(git_merge_base(&base, s->repo,
git_object_id(revs.from), git_object_id(revs.to)),
"Could not find merge base", revstr);
check(git_object_lookup(&revs.to, s->repo, &base, GIT_OBJ_COMMIT),
"Could not find merge base commit", NULL);
push_rev(s, revs.to, hide);
}
else if (!strcmp(a, "--"))
force_files = last_nonoption; /* copy all args as filenames */
else if (!check_str_param(a, "--git-dir=", &dir))
usage("Unknown argument", a);
push_rev(s, revs.from, !hide);
}
check(git_repository_open_ext(&repo, dir, 0, NULL),
"Could not open repository");
check(git_revwalk_new(&walker, repo),
"Could not create revision walker");
return 0;
}
struct log_options {
int show_diff;
int skip;
int min_parents, max_parents;
git_time_t before;
git_time_t after;
char *author;
char *committer;
if (force_files < 0)
force_files = last_nonoption;
};
for (i = 1; i < force_files; ) {
printf("option '%s'\n", argv[i]);
int main(int argc, char *argv[])
{
int i, count = 0;
char *a;
struct log_state s;
git_strarray paths;
git_oid oid;
git_commit *commit;
char buf[GIT_OID_HEXSZ + 1];
if (!git_revparse(&revs, repo, argv[i])) {
char str[GIT_OID_HEXSZ+1];
git_threads_init();
if (revs.from) {
git_oid_tostr(str, sizeof(str), git_object_id(revs.from));
printf("revwalk from %s\n", str);
}
if (revs.to) {
git_oid_tostr(str, sizeof(str), git_object_id(revs.to));
printf("revwalk to %s\n", str);
}
memset(&s, 0, sizeof(s));
/* push / hide / merge-base in revwalker */
for (i = 1; i < argc; ++i) {
a = argv[i];
if (a[0] != '-') {
if (!add_revision(&s, a))
++count;
else /* try failed revision parse as filename */
break;
} else if (!strcmp(a, "--")) {
++i;
} else {
/* shift array down */
for (a = argv[i], j = i + 1; j < force_files; ++j)
argv[j - 1] = argv[j];
argv[--force_files] = a;
break;
}
else if (!strcmp(a, "--date-order"))
set_sorting(&s, GIT_SORT_TIME);
else if (!strcmp(a, "--topo-order"))
set_sorting(&s, GIT_SORT_TOPOLOGICAL);
else if (!strcmp(a, "--reverse"))
set_sorting(&s, GIT_SORT_REVERSE);
else if (!strncmp(a, "--git-dir=", strlen("--git-dir=")))
s.repodir = a + strlen("--git-dir=");
else
usage("Unsupported argument", a);
}
if (i == 1) {
/* no revs pushed so push HEAD */
printf("revwalk HEAD\n");
}
if (!count)
add_revision(&s, NULL);
paths.strings = &argv[i];
paths.count = argc - i;
for (i = force_files; i < last_nonoption; ++i)
printf("file %s\n", argv[i]);
while (!git_revwalk_next(&oid, s.walker)) {
check(git_commit_lookup(&commit, s.repo, &oid),
"Failed to look up commit", NULL);
git_commit_free(commit);
git_oid_tostr(buf, sizeof(buf), &oid);
printf("%s\n", buf);
}
git_repository_free(repo);
git_revwalk_free(s.walker);
git_repository_free(s.repo);
git_threads_shutdown();
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment