refactor get reference, add another feed for tags/releases - stagit - static gi… | |
git clone git://git.codemadness.org/stagit | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit d80a163acd47df2bd9ab145be6b249814aa9eceb | |
parent 693c06448972f049d74addbd4942365cd37d92e4 | |
Author: Hiltjo Posthuma <[email protected]> | |
Date: Sun, 19 Jul 2020 16:41:10 +0200 | |
refactor get reference, add another feed for tags/releases | |
A separate Atom feed is helpful to ports maintainers to monitor new | |
tags/releases. | |
Diffstat: | |
M stagit.1 | 6 ++++-- | |
M stagit.c | 226 +++++++++++++++++++----------… | |
2 files changed, 146 insertions(+), 86 deletions(-) | |
--- | |
diff --git a/stagit.1 b/stagit.1 | |
@@ -1,4 +1,4 @@ | |
-.Dd February 6, 2019 | |
+.Dd July 19, 2020 | |
.Dt STAGIT 1 | |
.Os | |
.Sh NAME | |
@@ -42,7 +42,9 @@ cannot be used at the same time. | |
The following files will be written: | |
.Bl -tag -width Ds | |
.It atom.xml | |
-Atom XML feed | |
+Atom XML feed of the last 100 commits. | |
+.It tags.xml | |
+Atom XML feed of the tags. | |
.It files.html | |
List of files in the latest tree, linking to the file. | |
.It log.html | |
diff --git a/stagit.c b/stagit.c | |
@@ -248,6 +248,104 @@ err: | |
return NULL; | |
} | |
+int | |
+refs_cmp(const void *v1, const void *v2) | |
+{ | |
+ struct referenceinfo *r1 = (struct referenceinfo *)v1; | |
+ struct referenceinfo *r2 = (struct referenceinfo *)v2; | |
+ time_t t1, t2; | |
+ int r; | |
+ | |
+ if ((r = git_reference_is_tag(r1->ref) - git_reference_is_tag(r2->ref)… | |
+ return r; | |
+ | |
+ t1 = r1->ci->author ? r1->ci->author->when.time : 0; | |
+ t2 = r2->ci->author ? r2->ci->author->when.time : 0; | |
+ if ((r = t1 > t2 ? -1 : (t1 == t2 ? 0 : 1))) | |
+ return r; | |
+ | |
+ return strcmp(git_reference_shorthand(r1->ref), | |
+ git_reference_shorthand(r2->ref)); | |
+} | |
+ | |
+int | |
+getrefs(struct referenceinfo **pris, size_t *prefcount) | |
+{ | |
+ struct referenceinfo *ris = NULL; | |
+ struct commitinfo *ci = NULL; | |
+ git_reference_iterator *it = NULL; | |
+ const git_oid *id = NULL; | |
+ git_object *obj = NULL; | |
+ git_reference *dref = NULL, *r, *ref = NULL; | |
+ size_t i, refcount; | |
+ | |
+ *pris = NULL; | |
+ *prefcount = 0; | |
+ | |
+ if (git_reference_iterator_new(&it, repo)) | |
+ return -1; | |
+ | |
+ for (refcount = 0; !git_reference_next(&ref, it); ) { | |
+ if (!git_reference_is_branch(ref) && !git_reference_is_tag(ref… | |
+ git_reference_free(ref); | |
+ ref = NULL; | |
+ continue; | |
+ } | |
+ | |
+ switch (git_reference_type(ref)) { | |
+ case GIT_REF_SYMBOLIC: | |
+ if (git_reference_resolve(&dref, ref)) | |
+ goto err; | |
+ r = dref; | |
+ break; | |
+ case GIT_REF_OID: | |
+ r = ref; | |
+ break; | |
+ default: | |
+ continue; | |
+ } | |
+ if (!git_reference_target(r) || | |
+ git_reference_peel(&obj, r, GIT_OBJ_ANY)) | |
+ goto err; | |
+ if (!(id = git_object_id(obj))) | |
+ goto err; | |
+ if (!(ci = commitinfo_getbyoid(id))) | |
+ break; | |
+ | |
+ if (!(ris = reallocarray(ris, refcount + 1, sizeof(*ris)))) | |
+ err(1, "realloc"); | |
+ ris[refcount].ci = ci; | |
+ ris[refcount].ref = r; | |
+ refcount++; | |
+ | |
+ git_object_free(obj); | |
+ obj = NULL; | |
+ git_reference_free(dref); | |
+ dref = NULL; | |
+ } | |
+ git_reference_iterator_free(it); | |
+ | |
+ /* sort by type, date then shorthand name */ | |
+ qsort(ris, refcount, sizeof(*ris), refs_cmp); | |
+ | |
+ *pris = ris; | |
+ *prefcount = refcount; | |
+ | |
+ return 0; | |
+ | |
+err: | |
+ git_object_free(obj); | |
+ git_reference_free(dref); | |
+ commitinfo_free(ci); | |
+ for (i = 0; i < refcount; i++) { | |
+ commitinfo_free(ris[i].ci); | |
+ git_reference_free(ris[i].ref); | |
+ } | |
+ free(ris); | |
+ | |
+ return -1; | |
+} | |
+ | |
FILE * | |
efopen(const char *name, const char *flags) | |
{ | |
@@ -361,6 +459,8 @@ writeheader(FILE *fp, const char *title) | |
fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" href=\"%s… | |
fprintf(fp, "<link rel=\"alternate\" type=\"application/atom+xml\" tit… | |
name, relpath); | |
+ fprintf(fp, "<link rel=\"alternate\" type=\"application/atom+xml\" tit… | |
+ name, relpath); | |
fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle… | |
fputs("</head>\n<body>\n<table><tr><td>", fp); | |
fprintf(fp, "<a href=\"../%s\"><img src=\"%slogo.png\" alt=\"\" width=… | |
@@ -680,7 +780,7 @@ err: | |
} | |
void | |
-printcommitatom(FILE *fp, struct commitinfo *ci) | |
+printcommitatom(FILE *fp, struct commitinfo *ci, const char *tag) | |
{ | |
fputs("<entry>\n", fp); | |
@@ -697,6 +797,11 @@ printcommitatom(FILE *fp, struct commitinfo *ci) | |
} | |
if (ci->summary) { | |
fputs("<title type=\"text\">", fp); | |
+ if (tag) { | |
+ fputs("[", fp); | |
+ xmlencode(fp, tag, strlen(tag)); | |
+ fputs("] ", fp); | |
+ } | |
xmlencode(fp, ci->summary, strlen(ci->summary)); | |
fputs("</title>\n", fp); | |
} | |
@@ -732,8 +837,10 @@ printcommitatom(FILE *fp, struct commitinfo *ci) | |
} | |
int | |
-writeatom(FILE *fp) | |
+writeatom(FILE *fp, int all) | |
{ | |
+ struct referenceinfo *ris = NULL; | |
+ size_t refcount = 0; | |
struct commitinfo *ci; | |
git_revwalk *w = NULL; | |
git_oid id; | |
@@ -746,17 +853,34 @@ writeatom(FILE *fp) | |
xmlencode(fp, description, strlen(description)); | |
fputs("</subtitle>\n", fp); | |
- git_revwalk_new(&w, repo); | |
- git_revwalk_push_head(w); | |
- git_revwalk_simplify_first_parent(w); | |
+ /* all commits or only tags? */ | |
+ if (all) { | |
+ git_revwalk_new(&w, repo); | |
+ git_revwalk_push_head(w); | |
+ git_revwalk_simplify_first_parent(w); | |
+ for (i = 0; i < m && !git_revwalk_next(&id, w); i++) { | |
+ if (!(ci = commitinfo_getbyoid(&id))) | |
+ break; | |
+ printcommitatom(fp, ci, ""); | |
+ commitinfo_free(ci); | |
+ } | |
+ git_revwalk_free(w); | |
+ } else { | |
+ /* references: tags */ | |
+ if (getrefs(&ris, &refcount) != -1) { | |
+ for (i = 0; i < refcount; i++) { | |
+ if (!git_reference_is_tag(ris[i].ref)) | |
+ continue; | |
- for (i = 0; i < m && !git_revwalk_next(&id, w); i++) { | |
- if (!(ci = commitinfo_getbyoid(&id))) | |
- break; | |
- printcommitatom(fp, ci); | |
- commitinfo_free(ci); | |
+ printcommitatom(fp, ris[i].ci, | |
+ git_reference_shorthand(ris[i]… | |
+ | |
+ commitinfo_free(ris[i].ci); | |
+ git_reference_free(ris[i].ref); | |
+ } | |
+ free(ris); | |
+ } | |
} | |
- git_revwalk_free(w); | |
fputs("</feed>\n", fp); | |
@@ -942,85 +1066,18 @@ writefiles(FILE *fp, const git_oid *id) | |
} | |
int | |
-refs_cmp(const void *v1, const void *v2) | |
-{ | |
- struct referenceinfo *r1 = (struct referenceinfo *)v1; | |
- struct referenceinfo *r2 = (struct referenceinfo *)v2; | |
- time_t t1, t2; | |
- int r; | |
- | |
- if ((r = git_reference_is_tag(r1->ref) - git_reference_is_tag(r2->ref)… | |
- return r; | |
- | |
- t1 = r1->ci->author ? r1->ci->author->when.time : 0; | |
- t2 = r2->ci->author ? r2->ci->author->when.time : 0; | |
- if ((r = t1 > t2 ? -1 : (t1 == t2 ? 0 : 1))) | |
- return r; | |
- | |
- return strcmp(git_reference_shorthand(r1->ref), | |
- git_reference_shorthand(r2->ref)); | |
-} | |
- | |
-int | |
writerefs(FILE *fp) | |
{ | |
struct referenceinfo *ris = NULL; | |
struct commitinfo *ci; | |
- const git_oid *id = NULL; | |
- git_object *obj = NULL; | |
- git_reference *dref = NULL, *r, *ref = NULL; | |
- git_reference_iterator *it = NULL; | |
size_t count, i, j, refcount; | |
const char *titles[] = { "Branches", "Tags" }; | |
const char *ids[] = { "branches", "tags" }; | |
const char *s; | |
- if (git_reference_iterator_new(&it, repo)) | |
+ if (getrefs(&ris, &refcount) == -1) | |
return -1; | |
- for (refcount = 0; !git_reference_next(&ref, it); ) { | |
- if (!git_reference_is_branch(ref) && !git_reference_is_tag(ref… | |
- git_reference_free(ref); | |
- ref = NULL; | |
- continue; | |
- } | |
- | |
- switch (git_reference_type(ref)) { | |
- case GIT_REF_SYMBOLIC: | |
- if (git_reference_resolve(&dref, ref)) | |
- goto err; | |
- r = dref; | |
- break; | |
- case GIT_REF_OID: | |
- r = ref; | |
- break; | |
- default: | |
- continue; | |
- } | |
- if (!git_reference_target(r) || | |
- git_reference_peel(&obj, r, GIT_OBJ_ANY)) | |
- goto err; | |
- if (!(id = git_object_id(obj))) | |
- goto err; | |
- if (!(ci = commitinfo_getbyoid(id))) | |
- break; | |
- | |
- if (!(ris = reallocarray(ris, refcount + 1, sizeof(*ris)))) | |
- err(1, "realloc"); | |
- ris[refcount].ci = ci; | |
- ris[refcount].ref = r; | |
- refcount++; | |
- | |
- git_object_free(obj); | |
- obj = NULL; | |
- git_reference_free(dref); | |
- dref = NULL; | |
- } | |
- git_reference_iterator_free(it); | |
- | |
- /* sort by type, date then shorthand name */ | |
- qsort(ris, refcount, sizeof(*ris), refs_cmp); | |
- | |
for (i = 0, j = 0, count = 0; i < refcount; i++) { | |
if (j == 0 && git_reference_is_tag(ris[i].ref)) { | |
if (count) | |
@@ -1056,10 +1113,6 @@ writerefs(FILE *fp) | |
if (count) | |
fputs("</tbody></table><br/>\n", fp); | |
-err: | |
- git_object_free(obj); | |
- git_reference_free(dref); | |
- | |
for (i = 0; i < refcount; i++) { | |
commitinfo_free(ris[i].ci); | |
git_reference_free(ris[i].ref); | |
@@ -1272,7 +1325,12 @@ main(int argc, char *argv[]) | |
/* Atom feed */ | |
fp = efopen("atom.xml", "w"); | |
- writeatom(fp); | |
+ writeatom(fp, 1); | |
+ fclose(fp); | |
+ | |
+ /* Atom feed for tags / releases */ | |
+ fp = efopen("tags.xml", "w"); | |
+ writeatom(fp, 0); | |
fclose(fp); | |
/* rename new cache file on success */ |