mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-26 09:28:24 +02:00
eeshow/: make "related" work also for repositories (WIP)
For now, we only support the case where the file doesn't exists in any other repo, which is a common situation with sub-sheets.
This commit is contained in:
parent
ade54c6029
commit
a21bc66e55
@ -10,6 +10,7 @@
|
|||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -28,28 +29,42 @@ bool file_cat(const struct file *file, void *user, const char *line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *file_graft_relative(const char *base, const char *name)
|
||||||
|
{
|
||||||
|
const char *slash;
|
||||||
|
char *res;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
if (*name == '/')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
slash = strrchr(base, '/');
|
||||||
|
if (!slash)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
len = slash + 1 - base;
|
||||||
|
res = alloc_size(len + strlen(name) + 1);
|
||||||
|
memcpy(res, base, len);
|
||||||
|
strcpy(res + len, name);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool try_related(struct file *file)
|
static bool try_related(struct file *file)
|
||||||
{
|
{
|
||||||
const char *related;
|
|
||||||
const char *slash;
|
|
||||||
char *tmp;
|
char *tmp;
|
||||||
unsigned len;
|
|
||||||
|
|
||||||
if (!file->related)
|
if (!file->related)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
tmp = file_graft_relative(file->related->name, file->name);
|
||||||
|
if (!tmp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (*file->name == '/')
|
if (*file->name == '/')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
related = file->related->name;
|
|
||||||
slash = strrchr(related, '/');
|
|
||||||
if (!slash)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
len = slash + 1 - related;
|
|
||||||
tmp = alloc_size(len + strlen(file->name) + 1);
|
|
||||||
memcpy(tmp, related, len);
|
|
||||||
strcpy(tmp + len, file->name);
|
|
||||||
|
|
||||||
file->file = fopen(tmp, "r");
|
file->file = fopen(tmp, "r");
|
||||||
if (!file->file) {
|
if (!file->file) {
|
||||||
free(tmp);
|
free(tmp);
|
||||||
@ -90,15 +105,52 @@ static bool try_related(struct file *file)
|
|||||||
* @@@ explicit revision should always win over related.
|
* @@@ explicit revision should always win over related.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void *open_vcs(struct file *file)
|
||||||
|
{
|
||||||
|
char *colon;
|
||||||
|
|
||||||
|
colon = strchr(file->name, ':');
|
||||||
|
if (colon) {
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
tmp = stralloc(file->name);
|
||||||
|
tmp[colon - file->name] = 0;
|
||||||
|
file->vcs = vcs_git_open(tmp, colon + 1,
|
||||||
|
file->related ? file->related->vcs : NULL);
|
||||||
|
if (file->vcs) {
|
||||||
|
free(tmp);
|
||||||
|
return file->vcs;
|
||||||
|
}
|
||||||
|
if (verbose > 1)
|
||||||
|
fprintf(stderr, "could not open %s:%s\n",
|
||||||
|
tmp, colon + 1);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
file->vcs = vcs_git_open(NULL, file->name,
|
||||||
|
file->related ? file->related->vcs : NULL);
|
||||||
|
if (file->vcs)
|
||||||
|
return file->vcs;
|
||||||
|
if (verbose > 1)
|
||||||
|
fprintf(stderr, "could not open %s\n", file->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void file_open(struct file *file, const char *name, const struct file *related)
|
void file_open(struct file *file, const char *name, const struct file *related)
|
||||||
{
|
{
|
||||||
char *colon, *tmp;
|
|
||||||
|
|
||||||
file->name = stralloc(name);
|
file->name = stralloc(name);
|
||||||
file->lineno = 0;
|
file->lineno = 0;
|
||||||
file->related = related;
|
file->related = related;
|
||||||
|
file->file = NULL;
|
||||||
file->vcs = NULL;
|
file->vcs = NULL;
|
||||||
|
|
||||||
|
if (related && related->vcs) {
|
||||||
|
file->vcs = open_vcs(file);
|
||||||
|
if (file->vcs)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
file->file = fopen(name, "r");
|
file->file = fopen(name, "r");
|
||||||
if (file->file) {
|
if (file->file) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@ -112,21 +164,17 @@ void file_open(struct file *file, const char *name, const struct file *related)
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
perror(name);
|
perror(name);
|
||||||
|
|
||||||
colon = strchr(name, ':');
|
if (!strchr(name, ':')) {
|
||||||
if (!colon) {
|
|
||||||
if (!verbose)
|
if (!verbose)
|
||||||
perror(name);
|
perror(name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = stralloc(name);
|
file->vcs = open_vcs(file);
|
||||||
tmp[colon - name] = 0;
|
|
||||||
file->vcs = vcs_git_open(tmp, colon + 1);
|
|
||||||
if (!file->vcs) {
|
if (!file->vcs) {
|
||||||
fprintf(stderr, "could not open %s:%s\n", tmp, colon + 1);
|
fprintf(stderr, "could not open %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
free(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ struct file {
|
|||||||
|
|
||||||
bool file_cat(const struct file *file, void *user, const char *line);
|
bool file_cat(const struct file *file, void *user, const char *line);
|
||||||
|
|
||||||
|
char *file_graft_relative(const char *base, const char *name);
|
||||||
|
|
||||||
void file_open(struct file *file, const char *name,
|
void file_open(struct file *file, const char *name,
|
||||||
const struct file *related);
|
const struct file *related);
|
||||||
void file_read(struct file *file,
|
void file_read(struct file *file,
|
||||||
|
@ -27,6 +27,13 @@
|
|||||||
|
|
||||||
|
|
||||||
struct vcs_git {
|
struct vcs_git {
|
||||||
|
const char *name;
|
||||||
|
const char *revision;
|
||||||
|
const struct vcs_git *related;
|
||||||
|
|
||||||
|
git_repository *repo;
|
||||||
|
git_tree *tree;
|
||||||
|
|
||||||
const void *data;
|
const void *data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
};
|
};
|
||||||
@ -305,6 +312,18 @@ static const void *get_data(git_repository *repo, git_tree_entry *entry,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verbose > 2) {
|
||||||
|
git_buf buf = { 0 } ;
|
||||||
|
|
||||||
|
if (git_object_short_id(&buf, obj)) {
|
||||||
|
const git_error *e = giterr_last();
|
||||||
|
|
||||||
|
fprintf(stderr, "%s\n", e->message);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "object %s\n", buf.ptr);
|
||||||
|
git_buf_free(&buf);
|
||||||
|
}
|
||||||
blob = (git_blob *) obj;
|
blob = (git_blob *) obj;
|
||||||
*size = git_blob_rawsize(blob);
|
*size = git_blob_rawsize(blob);
|
||||||
return git_blob_rawcontent(blob);
|
return git_blob_rawcontent(blob);
|
||||||
@ -326,12 +345,78 @@ static bool send_line(const char *s, unsigned len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct vcs_git *vcs_git_open(const char *revision, const char *name)
|
static bool related_same_repo(struct vcs_git *vcs_git)
|
||||||
|
{
|
||||||
|
/* @@@ use same revision */
|
||||||
|
fprintf(stderr, "related_same_repo is no yet implemented\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool related_other_repo(struct vcs_git *vcs_git)
|
||||||
|
{
|
||||||
|
/* @@@ find revision <= date of revision in related */
|
||||||
|
fprintf(stderr, "related_other_repo is no yet implemented\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool related_only_repo(struct vcs_git *vcs_git)
|
||||||
|
{
|
||||||
|
const struct vcs_git *related = vcs_git->related;
|
||||||
|
char *tmp;
|
||||||
|
git_tree_entry *entry;
|
||||||
|
|
||||||
|
if (verbose > 1)
|
||||||
|
fprintf(stderr, "trying graft \"%s\" \"%s\"\n",
|
||||||
|
related->name, vcs_git->name);
|
||||||
|
tmp = file_graft_relative(related->name, vcs_git->name);
|
||||||
|
if (!tmp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vcs_git->repo = related->repo;
|
||||||
|
vcs_git->tree = related->tree;
|
||||||
|
|
||||||
|
/* @@@ code below also exists in vcs_git_open */
|
||||||
|
|
||||||
|
entry = find_file(vcs_git->repo, vcs_git->tree, tmp);
|
||||||
|
if (verbose)
|
||||||
|
fprintf(stderr, "reading %s\n", tmp);
|
||||||
|
|
||||||
|
vcs_git->data = get_data(vcs_git->repo, entry, &vcs_git->size);
|
||||||
|
|
||||||
|
free((char *) vcs_git->name);
|
||||||
|
vcs_git->name = tmp;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool try_related(struct vcs_git *vcs_git)
|
||||||
|
{
|
||||||
|
if (!vcs_git->related)
|
||||||
|
return 0;
|
||||||
|
if (vcs_git->revision)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
vcs_git->repo = select_repo(vcs_git->name);
|
||||||
|
if (vcs_git->repo) {
|
||||||
|
if (!strcmp(git_repository_path(vcs_git->related->repo),
|
||||||
|
git_repository_path(vcs_git->repo)))
|
||||||
|
return related_same_repo(vcs_git);
|
||||||
|
else
|
||||||
|
return related_other_repo(vcs_git);
|
||||||
|
}
|
||||||
|
|
||||||
|
return related_only_repo(vcs_git);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct vcs_git *vcs_git_open(const char *revision, const char *name,
|
||||||
|
const struct vcs_git *related)
|
||||||
{
|
{
|
||||||
static bool initialized = 0;
|
static bool initialized = 0;
|
||||||
struct vcs_git *vcs_git = alloc_type(struct vcs_git);
|
struct vcs_git *vcs_git = alloc_type(struct vcs_git);
|
||||||
git_repository *repo;
|
|
||||||
git_tree *tree;
|
|
||||||
git_tree_entry *entry;
|
git_tree_entry *entry;
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
@ -339,21 +424,30 @@ struct vcs_git *vcs_git_open(const char *revision, const char *name)
|
|||||||
initialized = 1;
|
initialized = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
repo = select_repo(name);
|
vcs_git->name = stralloc(name);
|
||||||
if (!repo) {
|
vcs_git->revision = revision ? stralloc(revision) : NULL;
|
||||||
fprintf(stderr, "%s:%s not found\n", revision, name);
|
vcs_git->related = related;
|
||||||
|
|
||||||
|
if (try_related(vcs_git))
|
||||||
|
return vcs_git;
|
||||||
|
|
||||||
|
vcs_git->repo = select_repo(name);
|
||||||
|
if (!vcs_git->repo) {
|
||||||
|
fprintf(stderr, "%s: not found\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (verbose > 1)
|
if (verbose > 1)
|
||||||
fprintf(stderr, "using repository %s\n",
|
fprintf(stderr, "using repository %s\n",
|
||||||
git_repository_path(repo));
|
git_repository_path(vcs_git->repo));
|
||||||
|
|
||||||
tree = pick_revision(repo, revision);
|
if (!revision)
|
||||||
entry = find_file(repo, tree, name);
|
revision = "HEAD";
|
||||||
|
vcs_git->tree = pick_revision(vcs_git->repo, revision);
|
||||||
|
entry = find_file(vcs_git->repo, vcs_git->tree, name);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "reading %s:%s\n", revision, name);
|
fprintf(stderr, "reading %s:%s\n", revision, name);
|
||||||
|
|
||||||
vcs_git->data = get_data(repo, entry, &vcs_git->size);
|
vcs_git->data = get_data(vcs_git->repo, entry, &vcs_git->size);
|
||||||
|
|
||||||
return vcs_git;
|
return vcs_git;
|
||||||
}
|
}
|
||||||
@ -384,5 +478,9 @@ void vcs_git_read(void *ctx, struct file *file,
|
|||||||
|
|
||||||
void vcs_git_close(void *ctx)
|
void vcs_git_close(void *ctx)
|
||||||
{
|
{
|
||||||
free(ctx);
|
struct vcs_git *vcs_git = ctx;
|
||||||
|
|
||||||
|
free((char *) vcs_git->name);
|
||||||
|
free((char *) vcs_git->revision);
|
||||||
|
free(vcs_git);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,8 @@
|
|||||||
struct vcs_git;
|
struct vcs_git;
|
||||||
struct file;
|
struct file;
|
||||||
|
|
||||||
struct vcs_git *vcs_git_open(const char *revision, const char *name);
|
struct vcs_git *vcs_git_open(const char *revision, const char *name,
|
||||||
|
const struct vcs_git *related);
|
||||||
void vcs_git_read(void *ctx, struct file *file,
|
void vcs_git_read(void *ctx, struct file *file,
|
||||||
bool (*parse)(const struct file *file, void *user, const char *line),
|
bool (*parse)(const struct file *file, void *user, const char *line),
|
||||||
void *user);
|
void *user);
|
||||||
|
Loading…
Reference in New Issue
Block a user