ctucx.git: stagit

ctucx' stagit fork

commit ecd0f6fb42cc6ca1ed4d9756a1e1cd4f04f8df0a
parent ea2f8521c49df0f10de5e6d8a97842c0df7c47b0
Author: Miquel Ortega <miquel.ortega9@gmail.com>
Date: Thu, 10 Sep 2020 15:37:50 +0100

Add separate listing page for every directory

Instead of listing all the files in files.html, add dir.html at
file/path/to/dir.html, which lists files in directory, for every
directory. This generates a possible conflict with a directory with path
path/to/dir.html.
1 file changed, 54 insertions(+), 28 deletions(-)
M
stagit.c
|
82
++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
diff --git a/stagit.c b/stagit.c
@@ -398,6 +398,20 @@ mkdirp(const char *path)
 	return 0;
 }
 
+int
+mkdirfile(const char *path)
+{
+	char *d;
+	char tmp[PATH_MAX];
+	if (strlcpy(tmp, path, sizeof(tmp)) >= sizeof(tmp))
+		errx(1, "path truncated: '%s'", path);
+	if (!(d = dirname(tmp)))
+		err(1, "dirname");
+	if (mkdirp(d))
+		return -1;
+	return 0;
+}
+
 void
 printtimez(FILE *fp, const git_time *intime)
 {

@@ -893,16 +907,15 @@ writeatom(FILE *fp, int all)
 void
 writeblobraw(const git_blob *blob, const char *fpath, const char *filename, git_off_t filesize)
 {
-	char tmp[PATH_MAX] = "", *d;
+	char tmp[PATH_MAX] = "";
 	const char *p;
 	int lc = 0;
 	FILE *fp;
 
+	mkdirfile(fpath);
+
 	if (strlcpy(tmp, fpath, sizeof(tmp)) >= sizeof(tmp))
 		errx(1, "path truncated: '%s'", fpath);
-	if (!(d = dirname(tmp)))
-		err(1, "dirname");
-	mkdirp(d);
 
 	for (p = fpath, tmp[0] = '\0'; *p; p++) {
 		if (*p == '/' && strlcat(tmp, "../", sizeof(tmp)) >= sizeof(tmp))

@@ -917,22 +930,22 @@ writeblobraw(const git_blob *blob, const char *fpath, const char *filename, git_
 int
 writeblob(git_object *obj, const char *fpath, const char *rpath, const char *filename, git_off_t filesize)
 {
-	char tmp[PATH_MAX] = "", *d;
-	const char *p;
+	char tmp[PATH_MAX] = "";
+	const char *p, *oldrelpath;
 	int lc = 0;
 	FILE *fp;
 
+	mkdirfile(fpath);
+
 	if (strlcpy(tmp, fpath, sizeof(tmp)) >= sizeof(tmp))
 		errx(1, "path truncated: '%s'", fpath);
-	if (!(d = dirname(tmp)))
-		err(1, "dirname");
-	if (mkdirp(d))
-		return -1;
 
 	for (p = fpath, tmp[0] = '\0'; *p; p++) {
 		if (*p == '/' && strlcat(tmp, "../", sizeof(tmp)) >= sizeof(tmp))
 			errx(1, "path truncated: '../%s'", tmp);
 	}
+
+	oldrelpath = relpath;
 	relpath = tmp;
 
 	fp = efopen(fpath, "w");

@@ -952,7 +965,7 @@ writeblob(git_object *obj, const char *fpath, const char *rpath, const char *fil
 	writefooter(fp);
 	fclose(fp);
 
-	relpath = "";
+	relpath = oldrelpath;
 
 	return lc;
 }

@@ -1005,11 +1018,17 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
 	const git_tree_entry *entry = NULL;
 	git_object *obj = NULL;
 	git_off_t filesize;
-	const char *entryname;
-	char filepath[PATH_MAX], rawpath[PATH_MAX], entrypath[PATH_MAX];
+	FILE *fp_subtree;
+	const char *entryname, *oldrelpath;
+	char filepath[PATH_MAX], rawpath[PATH_MAX], entrypath[PATH_MAX], tmp[PATH_MAX];
 	size_t count, i;
 	int lc, r, rf, ret;
 
+	fputs("<table id=\"files\"><thead>\n<tr>"
+			"<td><b>Mode</b></td><td><b>Name</b></td>"
+			"<td class=\"num\" align=\"right\"><b>Size</b></td>"
+			"</tr>\n</thead><tbody>\n", fp);
+
 	count = git_tree_entrycount(tree);
 	for (i = 0; i < count; i++) {
 		if (!(entry = git_tree_entry_byindex(tree, i)) ||

@@ -1029,34 +1048,47 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
 		if (!git_tree_entry_to_object(&obj, repo, entry)) {
 			switch (git_object_type(obj)) {
 			case GIT_OBJ_BLOB:
+				filesize = git_blob_rawsize((git_blob *)obj);
+				lc = writeblob(obj, filepath, rawpath, entryname, filesize);
+				writeblobraw((git_blob *)obj, rawpath, entryname, filesize);
 				break;
 			case GIT_OBJ_TREE:
+				mkdirfile(filepath);
+
+				if (strlcpy(tmp, relpath, sizeof(tmp)) >= sizeof(tmp))
+					errx(1, "path truncated: '%s'", relpath);
+				if (strlcat(tmp, "../", sizeof(tmp)) >= sizeof(tmp))
+					errx(1, "path truncated: '../%s'", tmp);
+
+				oldrelpath = relpath;
+				relpath = tmp;
+				fp_subtree = efopen(filepath, "w");
+				writeheader(fp_subtree, "Files");
 				/* NOTE: recurses */
-				ret = writefilestree(fp, (git_tree *)obj,
+				ret = writefilestree(fp_subtree, (git_tree *)obj,
 				                     entrypath);
+				writefooter(fp_subtree);
+				relpath = oldrelpath;
 				git_object_free(obj);
+				lc = -1;
 				if (ret)
 					return ret;
-				continue;
+				break;
 			default:
 				git_object_free(obj);
 				continue;
 			}
 
-			filesize = git_blob_rawsize((git_blob *)obj);
-			lc = writeblob(obj, filepath, rawpath, entryname, filesize);
-			writeblobraw((git_blob *)obj, rawpath, entryname, filesize);
-
 			fputs("<tr><td>", fp);
 			fputs(filemode(git_tree_entry_filemode(entry)), fp);
 			fprintf(fp, "</td><td><a href=\"%s", relpath);
 			xmlencode(fp, filepath, strlen(filepath));
 			fputs("\">", fp);
-			xmlencode(fp, entrypath, strlen(entrypath));
+			xmlencode(fp, entryname, strlen(entryname));
 			fputs("</a></td><td class=\"num\" align=\"right\">", fp);
 			if (lc > 0)
 				fprintf(fp, "%dL", lc);
-			else
+			else if (lc == 0)
 				fprintf(fp, "%juB", (uintmax_t)filesize);
 			fputs("</td></tr>\n", fp);
 			git_object_free(obj);

@@ -1074,6 +1106,7 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
 		}
 	}
 
+	fputs("</tbody></table>", fp);
 	return 0;
 }
 

@@ -1084,17 +1117,10 @@ writefiles(FILE *fp, const git_oid *id)
 	git_commit *commit = NULL;
 	int ret = -1;
 
-	fputs("<table id=\"files\"><thead>\n<tr>"
-	      "<td><b>Mode</b></td><td><b>Name</b></td>"
-	      "<td class=\"num\" align=\"right\"><b>Size</b></td>"
-	      "</tr>\n</thead><tbody>\n", fp);
-
 	if (!git_commit_lookup(&commit, repo, id) &&
 	    !git_commit_tree(&tree, commit))
 		ret = writefilestree(fp, tree, "");
 
-	fputs("</tbody></table>", fp);
-
 	git_commit_free(commit);
 	git_tree_free(tree);