mirror of
https://git.proxmox.com/git/libgit2
synced 2025-06-19 18:54:04 +00:00
More progress on log example
This commit is contained in:
parent
0d44d3dc84
commit
d0628e2fee
220
examples/log.c
220
examples/log.c
@ -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);
|
||||
}
|
||||
|
||||
struct log_state {
|
||||
git_repository *repo;
|
||||
const char *repodir;
|
||||
git_revwalk *walker;
|
||||
int hide;
|
||||
int sorting;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
push_rev(s, revs.from, !hide);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, j, last_nonoption, force_files = -1;
|
||||
int i, count = 0;
|
||||
char *a;
|
||||
const char *dir = ".";
|
||||
git_repository *repo;
|
||||
git_revwalk *walker;
|
||||
git_revspec revs;
|
||||
struct log_state s;
|
||||
git_strarray paths;
|
||||
git_oid oid;
|
||||
git_commit *commit;
|
||||
char buf[GIT_OID_HEXSZ + 1];
|
||||
|
||||
git_threads_init();
|
||||
|
||||
for (i = 1, last_nonoption = 1; i < argc; ++i) {
|
||||
memset(&s, 0, sizeof(s));
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
a = argv[i];
|
||||
|
||||
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++;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
check(git_repository_open_ext(&repo, dir, 0, NULL),
|
||||
"Could not open repository");
|
||||
check(git_revwalk_new(&walker, repo),
|
||||
"Could not create revision walker");
|
||||
|
||||
if (force_files < 0)
|
||||
force_files = last_nonoption;
|
||||
|
||||
for (i = 1; i < force_files; ) {
|
||||
printf("option '%s'\n", argv[i]);
|
||||
|
||||
if (!git_revparse(&revs, repo, argv[i])) {
|
||||
char str[GIT_OID_HEXSZ+1];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* push / hide / merge-base in revwalker */
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for (i = force_files; i < last_nonoption; ++i)
|
||||
printf("file %s\n", argv[i]);
|
||||
|
||||
git_repository_free(repo);
|
||||
git_revwalk_free(s.walker);
|
||||
git_repository_free(s.repo);
|
||||
git_threads_shutdown();
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user