diff --git a/stagit.c b/stagit.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <fcntl.h>
#include <git2.h>
#include "cmark.h"
@@ -486,16 +487,31 @@ void writeheader(FILE *fp, const char *title)
if (license)
fprintf(fp, "<li><a href=\"%sfile/%s.html\">LICENSE</a></li>\n",
relpath, license);
- fputs("</ul>\n", fp);
}
void writefooter(FILE *fp)
{
fputs("</main>\n", fp);
- fputs("<footer>Pablo © 2020</footer>\n", fp);
+ fputs("<footer>Pablo © 2021</footer>\n", fp);
fputs("</body>\n</html>\n", fp);
}
+/*
+ * Writes the raw contents of a blob in a file
+ */
+int writeblobraw(const git_blob *blob, const char *fpath)
+{
+ int fd = open(fpath, O_CREAT);
+ if (fd == -1) return 0;
+
+ int len = git_blob_rawsize(blob);
+ const void *s = git_blob_rawcontent(blob);
+ size_t size = write(fd, s, len);
+ close(fd);
+
+ return size;
+}
+
size_t writeblobhtml(FILE *fp, const git_blob *blob)
{
size_t n = 0, i, len, prev;
@@ -760,6 +776,7 @@ int writelog(FILE *fp, const git_oid *oid)
relpath = "../";
fpfile = efopen(path, "w");
writeheader(fpfile, ci->summary);
+ fputs("</ul>\n", fp);
fputs("<div class=\"codeblock\">\n", fpfile);
fputs("<pre>", fpfile);
printshowfile(fpfile, ci);
@@ -902,6 +919,8 @@ size_t writeblob(git_object *obj, const char *fpath, const char *filename, size_
fp = efopen(fpath, "w");
writeheader(fp, filename);
+ fprintf(fp, "<li><a href=\"%s/blob/%s\">raw file (blob)</a></li>", relpath, filename);
+ fputs("</ul>\n", fp);
fputs("<div class=\"titled-block\">\n<h1>", fp);
xmlencode(fp, filename, strlen(filename));
fprintf(fp, " (%zuB)", filesize);
@@ -914,6 +933,7 @@ size_t writeblob(git_object *obj, const char *fpath, const char *filename, size_
if (ferror(fp))
err(1, "fwrite");
}
+
fputs("</div>\n</div>\n", fp);
writefooter(fp);
fclose(fp);
@@ -968,7 +988,7 @@ int writefilestree(FILE *fp, git_tree *tree, const char *path)
const git_tree_entry *entry = NULL;
git_object *obj = NULL;
const char *entryname;
- char filepath[PATH_MAX], entrypath[PATH_MAX], oid[8];
+ char filepath[PATH_MAX], blobpath[PATH_MAX], entrypath[PATH_MAX], oid[8];
size_t count, i, lc, filesize;
int r, ret;
@@ -983,6 +1003,10 @@ int writefilestree(FILE *fp, git_tree *tree, const char *path)
entrypath);
if (r < 0 || (size_t)r >= sizeof(filepath))
errx(1, "path truncated: 'file/%s.html'", entrypath);
+ r = snprintf(blobpath, sizeof(filepath), "path/%s.html",
+ entrypath);
+ if (r < 0 || (size_t)r >= sizeof(filepath))
+ errx(1, "path truncated: 'file/%s.html'", entrypath);
if (!git_tree_entry_to_object(&obj, repo, entry)) {
switch (git_object_type(obj)) {
@@ -1003,6 +1027,7 @@ int writefilestree(FILE *fp, git_tree *tree, const char *path)
filesize = git_blob_rawsize((git_blob *)obj);
lc = writeblob(obj, filepath, entryname, filesize);
+ writeblobraw((git_blob *)obj, blobpath);
fputs("<tr><td>", fp);
fputs(filemode(git_tree_entry_filemode(entry)), fp);
@@ -1125,6 +1150,7 @@ void write_markdown_readme(FILE *fp, git_blob *readme)
char *html = cmark_markdown_to_html(markdown,
strlen(markdown), CMARK_OPT_SAFE);
writeheader(fp, "README");
+ fputs("</ul>\n", fp);
fprintf(fp, "<section id=\"readme\">\n");
fprintf(fp, "%s", html);
fprintf(fp, "</section>\n");
@@ -1286,6 +1312,7 @@ int main(int argc, char *argv[])
relpath = "";
mkdir("commit", S_IRWXU | S_IRWXG | S_IRWXO);
writeheader(fp, "Log");
+ fputs("</ul>\n", fp);
fputs("<div class=\"table-container\"><table id=\"log\"><thead>\n<tr><td><b>Date</b></td>"
"<td><b>Commit message</b></td>"
"<td><b>Author</b></td><td class=\"num\" align=\"right\"><b>Files</b></td>"
@@ -1337,6 +1364,7 @@ int main(int argc, char *argv[])
/* files for HEAD */
fp = efopen("files.html", "w");
writeheader(fp, "Files");
+ fputs("</ul>\n", fp);
if (head)
writefiles(fp, head);
writefooter(fp);
@@ -1345,6 +1373,7 @@ int main(int argc, char *argv[])
/* summary page with branches and tags */
fp = efopen("refs.html", "w");
writeheader(fp, "Refs");
+ fputs("</ul>\n", fp);
writerefs(fp);
writefooter(fp);
fclose(fp);