Introduction
Introduction Statistics Contact Development Disclaimer Help
tMerge remote-tracking branch 'upstream/master' - stagit - [fork] customized bu…
git clone git://src.adamsgaard.dk/stagit
Log
Files
Refs
README
LICENSE
---
commit d1d85502bcdcab164b0e7b3d95939bef42b8a544
parent c413dc3336479c76292bf3225d58bb55c43da056
Author: Anders Damsgaard <[email protected]>
Date: Wed, 22 Jul 2020 07:51:29 +0200
Merge remote-tracking branch 'upstream/master'
Diffstat:
M stagit.1 | 6 ++++--
M stagit.c | 294 +++++++++++++++++++----------…
2 files changed, 190 insertions(+), 110 deletions(-)
---
diff --git a/stagit.1 b/stagit.1
t@@ -1,4 +1,4 @@
-.Dd February 6, 2019
+.Dd July 19, 2020
.Dt STAGIT 1
.Os
.Sh NAME
t@@ -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
t@@ -48,6 +48,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 = "";
t@@ -243,6 +249,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)
{
t@@ -356,6 +460,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 style=\"width:100%\"><tr><td>", fp);
fprintf(fp, "<a href=\"../%s\"><img src=\"%slogo.png\" alt=\"\" width=…
t@@ -677,7 +783,7 @@ err:
}
void
-printcommitatom(FILE *fp, struct commitinfo *ci)
+printcommitatom(FILE *fp, struct commitinfo *ci, const char *tag)
{
fputs("<entry>\n", fp);
t@@ -694,6 +800,11 @@ printcommitatom(FILE *fp, struct commitinfo *ci)
}
if (ci->summary) {
fputs("<title type=\"text\">", fp);
+ if (tag && tag[0]) {
+ fputs("[", fp);
+ xmlencode(fp, tag, strlen(tag));
+ fputs("] ", fp);
+ }
xmlencode(fp, ci->summary, strlen(ci->summary));
fputs("</title>\n", fp);
}
t@@ -729,8 +840,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;
t@@ -743,17 +856,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);
t@@ -939,115 +1069,58 @@ 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 *ids[] = { "branches", "tags" };
- const char *name;
+ 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); 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, "<h2>%s</h2><table id=\"%s\">"
- "<thead>\n<tr><td><b>Name</b></td>"
- "<td><b>Last commit date (UTC)</b></td…
- "<td><b>Author</b></td>\n</tr>\n"
- "</thead><tbody>\n",
- titles[j], ids[j]);
- }
-
- relpath = "";
- name = git_reference_shorthand(r);
-
- fputs("<tr><td>", fp);
- xmlencode(fp, name, strlen(name));
- fputs("</td><td>", fp);
- if (ci->author)
- printtimeshort(fp, &(ci->author->when));
- fputs("</td><td>", fp);
- if (ci->author)
- xmlencode(fp, ci->author->name, strlen(ci->aut…
- fputs("</td></tr>\n", fp);
-
- relpath = "../";
+ for (i = 0, j = 0, count = 0; i < refcount; i++) {
+ if (j == 0 && git_reference_is_tag(ris[i].ref)) {
+ if (count)
+ fputs("</tbody></table><br/>\n", fp);
+ count = 0;
+ j = 1;
+ }
- commitinfo_free(ci);
- git_object_free(obj);
- obj = NULL;
- git_reference_free(dref);
- dref = NULL;
+ /* print header if it has an entry (first). */
+ if (++count == 1) {
+ fprintf(fp, "<h2>%s</h2><table id=\"%s\">"
+ "<thead>\n<tr><td><b>Name</b></td>"
+ "<td><b>Last commit date</b></td>"
+ "<td><b>Author</b></td>\n</tr>\n"
+ "</thead><tbody>\n",
+ titles[j], ids[j]);
}
- /* table footer */
- if (count)
- fputs("</tbody></table><br/>", fp);
- }
-err:
- git_object_free(obj);
- git_reference_free(dref);
+ ci = ris[i].ci;
+ s = git_reference_shorthand(ris[i].ref);
+
+ fputs("<tr><td>", fp);
+ xmlencode(fp, s, strlen(s));
+ fputs("</td><td>", fp);
+ if (ci->author)
+ printtimeshort(fp, &(ci->author->when));
+ fputs("</td><td>", fp);
+ if (ci->author)
+ xmlencode(fp, ci->author->name, strlen(ci->author->nam…
+ fputs("</td></tr>\n", fp);
+ }
+ /* table footer */
+ if (count)
+ fputs("</tbody></table><br/>\n", fp);
- 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;
}
t@@ -1255,7 +1328,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 mx1.adamsgaard.dk. 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.