mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-26 00:33:45 +02:00
eeshow/: option -H path_into_repo to list branched history of repository
This commit is contained in:
parent
9564707f83
commit
e18c146323
@ -13,7 +13,7 @@
|
||||
NAME = eeshow
|
||||
OBJS = main.o sch-parse.o sch-render.o lib-parse.o lib-render.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
|
||||
|
||||
CFLAGS = -g -Wall -Wextra -Wno-unused-parameter -Wshadow \
|
||||
|
196
eeshow/git-hist.c
Normal file
196
eeshow/git-hist.c
Normal 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
36
eeshow/git-hist.h
Normal 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 */
|
@ -27,6 +27,7 @@
|
||||
#include "file.h"
|
||||
#include "lib.h"
|
||||
#include "sch.h"
|
||||
#include "git-hist.h"
|
||||
#include "gui.h"
|
||||
#include "main.h"
|
||||
|
||||
@ -48,11 +49,13 @@ void usage(const char *name)
|
||||
"usage: %s [-r] [-v ...] [[rev:]file.lib ...] [rev:]file.sch\n"
|
||||
" %*s[-- driver_spec]\n"
|
||||
" %s [-v ...] -C [rev:]file\n"
|
||||
" %s [-v ...] -H path_into_repo\n"
|
||||
"\n"
|
||||
" rev git revision\n"
|
||||
" -r recurse into sub-sheets\n"
|
||||
" -v increase verbosity of diagnostic output\n"
|
||||
" -C 'cat' the file to standard output\n"
|
||||
" -H show history of repository on standard output\n"
|
||||
"\n"
|
||||
"FIG driver spec:\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"
|
||||
"\n"
|
||||
" see PNG\n"
|
||||
, name, (int) strlen(name) + 1, "", name);
|
||||
, name, (int) strlen(name) + 1, "", name, name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -87,6 +90,7 @@ int main(int argc, char **argv)
|
||||
struct file sch_file;
|
||||
bool recurse = 0;
|
||||
const char *cat = NULL;
|
||||
const char *history = NULL;
|
||||
char c;
|
||||
int arg, dashdash;
|
||||
bool have_dashdash = 0;
|
||||
@ -102,7 +106,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
while ((c = getopt(dashdash, argv, "rvC:")) != EOF)
|
||||
while ((c = getopt(dashdash, argv, "rvC:H:")) != EOF)
|
||||
switch (c) {
|
||||
case 'r':
|
||||
recurse = 1;
|
||||
@ -113,6 +117,9 @@ int main(int argc, char **argv)
|
||||
case 'C':
|
||||
cat = optarg;
|
||||
break;
|
||||
case 'H':
|
||||
history = optarg;
|
||||
break;
|
||||
default:
|
||||
usage(*argv);
|
||||
}
|
||||
@ -128,6 +135,14 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (history) {
|
||||
struct hist *h;
|
||||
|
||||
h = vcs_git_hist(history);
|
||||
dump_hist(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dashdash - optind < 1)
|
||||
usage(*argv);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user