1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-29 14:17:30 +02:00

eeshow/: option -H path_into_repo to list branched history of repository

This commit is contained in:
Werner Almesberger 2016-08-04 16:12:40 -03:00
parent 9564707f83
commit e18c146323
4 changed files with 250 additions and 3 deletions

View File

@ -13,7 +13,7 @@
NAME = eeshow NAME = eeshow
OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \ OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.o \
gui.o gui-over.o gui-aoi.o \ gui.o gui-over.o gui-aoi.o \
file.o git-file.o \ file.o git-file.o git-hist.o \
style.o fig.o record.o cro.o diff.o gfx.o dwg.o text.o misc.o style.o fig.o record.o cro.o diff.o gfx.o dwg.o text.o misc.o
CFLAGS = -g -Wall -Wextra -Wno-unused-parameter -Wshadow \ CFLAGS = -g -Wall -Wextra -Wno-unused-parameter -Wshadow \

196
eeshow/git-hist.c Normal file
View File

@ -0,0 +1,196 @@
/*
* git-hist.c - Retrieve revision history from GIT repo
*
* Written 2016 by Werner Almesberger
* Copyright 2016 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <alloca.h>
#include "util.h"
#include "main.h"
#include "git-hist.h"
/*
* @@@ we assume to have a single head. That isn't necessarily true, since
* each open branch has its own head. Getting this right is for further study.
*/
static struct hist *new_commit(unsigned branch)
{
struct hist *h;
h = alloc_type(struct hist);
h->commit = NULL;
h->branch = branch;
h->newer = NULL;
h->n_newer = 0;
h->older = NULL;
h->n_older = 0;
return h;
}
static void uplink(struct hist *down, struct hist *up)
{
down->newer = realloc(down->newer,
sizeof(struct hist *) * (down->n_newer + 1));
if (!down->newer) {
perror("realloc");
exit(1);
}
down->newer[down->n_newer++] = up;
}
static struct hist *find_commit(struct hist *h, const git_commit *commit)
{
unsigned i;
struct hist *found;
/*
* @@@ should probably use
* git_oid_equal(git_object_id(a), git_object_id(b))
*/
if (h->commit == commit)
return h;
for (i = 0; i != h->n_older; i++) {
if (h->older[i]->newer[0] != h)
continue;
found = find_commit(h->older[i], commit);
if (found)
return found;
}
return NULL;
}
static void recurse(struct hist *h,
unsigned n_branches, struct hist **branches)
{
unsigned n, i, j;
struct hist **b;
const git_error *e;
n = git_commit_parentcount(h->commit);
if (verbose > 2)
fprintf(stderr, "commit %p: %u + %u\n",
h->commit, n_branches, n);
b = alloca(sizeof(struct hist) * (n_branches - 1 + n));
n_branches--;
memcpy(b, branches, sizeof(struct hist *) * n_branches);
h->older = alloc_size(sizeof(struct hist *) * n);
h->n_older = n;
for (i = 0; i != n; i++) {
git_commit *commit;
struct hist *found = NULL;
if (git_commit_parent(&commit, h->commit, i)) {
e = giterr_last();
fprintf(stderr, "git_commit_parent: %s\n", e->message);
exit(1);
}
for (j = 0; j != n_branches; j++) {
found = find_commit(b[j], commit);
if (found)
break;
}
if (found) {
uplink(found, h);
h->older[i] = found;
} else {
struct hist *new;
new = new_commit(n_branches);
new->commit = commit;
h->older[i] = new;
b[n_branches++] = new;
uplink(new, h);
recurse(new, n_branches, b);
}
}
}
struct hist *vcs_git_hist(const char *path)
{
struct hist *head;
git_repository *repo;
git_oid oid;
const git_error *e;
head = new_commit(0);
git_libgit2_init(); /* @@@ */
if (git_repository_open_ext(&repo, path,
GIT_REPOSITORY_OPEN_CROSS_FS, NULL)) {
e = giterr_last();
fprintf(stderr, "%s: %s\n", path, e->message);
exit(1);
}
if (git_reference_name_to_id(&oid, repo, "HEAD")) {
e = giterr_last();
fprintf(stderr, "%s: %s\n",
git_repository_path(repo), e->message);
exit(1);
}
if (git_commit_lookup(&head->commit, repo, &oid)) {
e = giterr_last();
fprintf(stderr, "%s: %s\n",
git_repository_path(repo), e->message);
exit(1);
}
recurse(head, 1, &head);
return head;
}
const char *vcs_git_summary(struct hist *h)
{
const char *summary;
const git_error *e;
summary = git_commit_summary(h->commit);
if (summary)
return summary;
e = giterr_last();
fprintf(stderr, "git_commit_summary: %s\n", e->message);
exit(1);
}
void dump_hist(struct hist *h)
{
git_buf buf = { 0 };
const git_error *e;
unsigned i;
if (git_object_short_id(&buf, (git_object *) h->commit)) {
e = giterr_last();
fprintf(stderr, "git_object_short_id: %s\n", e->message);
exit(1);
}
printf("%*s%s %s\n", 2 * h->branch, "", buf.ptr, vcs_git_summary(h));
git_buf_free(&buf);
for (i = 0; i != h->n_older; i++)
if (h->older[i]->newer[h->older[i]->n_newer - 1] == h)
dump_hist(h->older[i]);
}

36
eeshow/git-hist.h Normal file
View File

@ -0,0 +1,36 @@
/*
* git-hist.h - Retrieve revision history from GIT repo
*
* Written 2016 by Werner Almesberger
* Copyright 2016 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef GIT_HIST_H
#define GIT_HIST_H
#include <git2.h>
struct hist {
struct git_commit *commit;
unsigned branch; /* branch index */
struct hist **newer;
unsigned n_newer;
struct hist **older;
unsigned n_older;
};
struct hist *vcs_git_hist(const char *path);
const char *vcs_git_summary(struct hist *hist);
void dump_hist(struct hist *h);
#endif /* !GIT_HIST_H */

View File

@ -27,6 +27,7 @@
#include "file.h" #include "file.h"
#include "lib.h" #include "lib.h"
#include "sch.h" #include "sch.h"
#include "git-hist.h"
#include "gui.h" #include "gui.h"
#include "main.h" #include "main.h"
@ -48,11 +49,13 @@ void usage(const char *name)
"usage: %s [-r] [-v ...] [[rev:]file.lib ...] [rev:]file.sch\n" "usage: %s [-r] [-v ...] [[rev:]file.lib ...] [rev:]file.sch\n"
" %*s[-- driver_spec]\n" " %*s[-- driver_spec]\n"
" %s [-v ...] -C [rev:]file\n" " %s [-v ...] -C [rev:]file\n"
" %s [-v ...] -H path_into_repo\n"
"\n" "\n"
" rev git revision\n" " rev git revision\n"
" -r recurse into sub-sheets\n" " -r recurse into sub-sheets\n"
" -v increase verbosity of diagnostic output\n" " -v increase verbosity of diagnostic output\n"
" -C 'cat' the file to standard output\n" " -C 'cat' the file to standard output\n"
" -H show history of repository on standard output\n"
"\n" "\n"
"FIG driver spec:\n" "FIG driver spec:\n"
" fig [-t template.fig] [var=value ...]\n" " fig [-t template.fig] [var=value ...]\n"
@ -75,7 +78,7 @@ void usage(const char *name)
" diff [-o output.pdf] [-s scale] [file.lib ...] file.sch\n" " diff [-o output.pdf] [-s scale] [file.lib ...] file.sch\n"
"\n" "\n"
" see PNG\n" " see PNG\n"
, name, (int) strlen(name) + 1, "", name); , name, (int) strlen(name) + 1, "", name, name);
exit(1); exit(1);
} }
@ -87,6 +90,7 @@ int main(int argc, char **argv)
struct file sch_file; struct file sch_file;
bool recurse = 0; bool recurse = 0;
const char *cat = NULL; const char *cat = NULL;
const char *history = NULL;
char c; char c;
int arg, dashdash; int arg, dashdash;
bool have_dashdash = 0; bool have_dashdash = 0;
@ -102,7 +106,7 @@ int main(int argc, char **argv)
break; break;
} }
while ((c = getopt(dashdash, argv, "rvC:")) != EOF) while ((c = getopt(dashdash, argv, "rvC:H:")) != EOF)
switch (c) { switch (c) {
case 'r': case 'r':
recurse = 1; recurse = 1;
@ -113,6 +117,9 @@ int main(int argc, char **argv)
case 'C': case 'C':
cat = optarg; cat = optarg;
break; break;
case 'H':
history = optarg;
break;
default: default:
usage(*argv); usage(*argv);
} }
@ -128,6 +135,14 @@ int main(int argc, char **argv)
return 0; return 0;
} }
if (history) {
struct hist *h;
h = vcs_git_hist(history);
dump_hist(h);
return 0;
}
if (dashdash - optind < 1) if (dashdash - optind < 1)
usage(*argv); usage(*argv);