Introduction
Introduction Statistics Contact Development Disclaimer Help
sort branches and tags by time (descending) and add tags.xml for releases - sta…
git clone git://git.codemadness.org/stagit-gopher
Log
Files
Refs
README
LICENSE
---
commit 4dded587b089f4c2fda9694a908157a549c6cc1a
parent de86bac090f236501ee9f211d2bd55aa39c38ac7
Author: Hiltjo Posthuma <[email protected]>
Date: Sun, 19 Jul 2020 18:56:10 +0200
sort branches and tags by time (descending) and add tags.xml for releases
Similar to the recent changes to stagit (HTML version).
Diffstat:
M stagit-gopher.1 | 6 ++++--
M stagit-gopher.c | 294 ++++++++++++++++++++---------…
2 files changed, 192 insertions(+), 108 deletions(-)
---
diff --git a/stagit-gopher.1 b/stagit-gopher.1
@@ -1,4 +1,4 @@
-.Dd February 6, 2019
+.Dd July 19, 2020
.Dt STAGIT-GOPHER 1
.Os
.Sh NAME
@@ -46,7 +46,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.gph
List of files in the latest tree, linking to the file.
.It log.gph
diff --git a/stagit-gopher.c b/stagit-gopher.c
@@ -50,6 +50,12 @@ struct commitinfo {
size_t ndeltas;
};
+/* reference and associated data for sorting */
+struct referenceinfo {
+ struct git_reference *ref;
+ struct commitinfo *ci;
+};
+
static git_repository *repo;
static const char *relpath = "";
@@ -288,6 +294,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)
{
@@ -760,7 +864,7 @@ err:
}
void
-printcommitatom(FILE *fp, struct commitinfo *ci)
+printcommitatom(FILE *fp, struct commitinfo *ci, const char *tag)
{
fputs("<entry>\n", fp);
@@ -777,6 +881,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);
}
@@ -812,8 +921,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;
@@ -826,17 +937,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);
@@ -1012,115 +1140,63 @@ writefiles(FILE *fp, const git_oid *id)
}
int
-refs_cmp(const void *v1, const void *v2)
-{
- git_reference *r1 = (*(git_reference **)v1);
- git_reference *r2 = (*(git_reference **)v2);
- int r;
-
- if ((r = git_reference_is_branch(r1) - git_reference_is_branch(r2)))
- return r;
-
- return strcmp(git_reference_shorthand(r1),
- git_reference_shorthand(r2));
-}
-
-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;
- git_reference **refs = NULL;
size_t count, i, j, refcount;
const char *titles[] = { "Branches", "Tags" };
- const char *name;
+ const char *ids[] = { "branches", "tags" };
+ const char *s;
char buf[256];
- if (git_reference_iterator_new(&it, repo))
+ if (getrefs(&ris, &refcount) == -1)
return -1;
- for (refcount = 0; !git_reference_next(&ref, it); refcount++) {
- if (!(refs = reallocarray(refs, refcount + 1, sizeof(git_refer…
- err(1, "realloc");
- refs[refcount] = ref;
- }
- git_reference_iterator_free(it);
-
- /* sort by type then shorthand name */
- qsort(refs, refcount, sizeof(git_reference *), refs_cmp);
-
- for (j = 0; j < 2; j++) {
- for (i = 0, count = 0; i < refcount; i++) {
- if (!(git_reference_is_branch(refs[i]) && j == 0) &&
- !(git_reference_is_tag(refs[i]) && j == 1))
- continue;
-
- switch (git_reference_type(refs[i])) {
- case GIT_REF_SYMBOLIC:
- if (git_reference_resolve(&dref, refs[i]))
- goto err;
- r = dref;
- break;
- case GIT_REF_OID:
- r = refs[i];
- 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;
-
- /* print header if it has an entry (first). */
- if (++count == 1) {
- fprintf(fp, "%s\n", titles[j]);
- fprintf(fp, " %-32.32s", "Name");
- fprintf(fp, " %-16.16s", "Last commit date");
- fprintf(fp, " %s\n", "Author");
- }
+ for (i = 0, j = 0, count = 0; i < refcount; i++) {
+ if (j == 0 && git_reference_is_tag(ris[i].ref)) {
+ /* table footer */
+ if (count)
+ fputs("\n", fp);
+ count = 0;
+ j = 1;
+ }
- name = git_reference_shorthand(r);
+ /* print header if it has an entry (first). */
+ if (++count == 1) {
+ fprintf(fp, "%s\n", titles[j]);
+ fprintf(fp, " %-32.32s", "Name");
+ fprintf(fp, " %-16.16s", "Last commit date");
+ fprintf(fp, " %s\n", "Author");
+ }
- fputs(" ", fp);
- utf8pad(buf, sizeof(buf), name, 32, ' ');
+ ci = ris[i].ci;
+ s = git_reference_shorthand(ris[i].ref);
+
+ fputs(" ", fp);
+ utf8pad(buf, sizeof(buf), s, 32, ' ');
+ gphlink(fp, buf, strlen(buf));
+ fputs(" ", fp);
+ if (ci->author)
+ printtimeshort(fp, &(ci->author->when));
+ else
+ fputs(" ", fp);
+ fputs(" ", fp);
+ if (ci->author) {
+ utf8pad(buf, sizeof(buf), ci->author->name, 25, '\0');
gphlink(fp, buf, strlen(buf));
- fputs(" ", fp);
- if (ci->author)
- printtimeshort(fp, &(ci->author->when));
- else
- fputs(" ", fp);
- fputs(" ", fp);
- if (ci->author) {
- utf8pad(buf, sizeof(buf), ci->author->name, 25…
- gphlink(fp, buf, strlen(buf));
- }
- fputs("\n", fp);
-
- commitinfo_free(ci);
- git_object_free(obj);
- obj = NULL;
- git_reference_free(dref);
- dref = NULL;
}
- /* table footer */
- if (count)
- fputs("\n", fp);
+ fputs("\n", fp);
}
+ /* table footer */
+ if (count)
+ fputs("\n", fp);
-err:
- git_object_free(obj);
- git_reference_free(dref);
-
- for (i = 0; i < refcount; i++)
- git_reference_free(refs[i]);
- free(refs);
+ for (i = 0; i < refcount; i++) {
+ commitinfo_free(ris[i].ci);
+ git_reference_free(ris[i].ref);
+ }
+ free(ris);
return 0;
}
@@ -1311,6 +1387,7 @@ main(int argc, char *argv[])
writelog(fp, head);
}
fprintf(fp, "\n[0|Atom feed|%s/atom.xml|server|port]\n", relpath);
+ fprintf(fp, "\n[0|Atom feed (tags)|%s/tags.xml|server|port]\n", relpat…
writefooter(fp);
fclose(fp);
@@ -1331,7 +1408,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 */
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.