diff --git a/stagit.1 b/stagit.1 index 360f716..f5adaf2 100644 --- 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 index b4f3b22..ff81b53 100644 --- 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, "\n\n", relpath); fprintf(fp, "\n", name, relpath); + fprintf(fp, "\n", + name, relpath); fprintf(fp, "\n", relpath); fputs("\n
\n