]> git.armaanb.net Git - stagit.git/blobdiff - urmoms.c
compat: add strlcpy, strlcat, for glibc
[stagit.git] / urmoms.c
index 41d4a56aeecf1653e200da14c2c5e1aa2ab25442..2c976bacdb26dae0ade5c528881eadddb3fd7abe 100644 (file)
--- a/urmoms.c
+++ b/urmoms.c
 #include <string.h>
 #include <unistd.h>
 
+#include <git2.h>
+
+#include "compat.h"
 #include "config.h"
-#include "git2.h"
 
 struct commitinfo {
        const git_oid *id;
@@ -61,6 +63,7 @@ struct commitinfo *
 commitinfo_getbyoid(const git_oid *id)
 {
        struct commitinfo *ci;
+       git_diff_options opts;
        int error;
 
        if (!(ci = calloc(1, sizeof(struct commitinfo))))
@@ -88,7 +91,9 @@ commitinfo_getbyoid(const git_oid *id)
                ci->parent_tree = NULL;
        }
 
-       if ((error = git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, NULL)))
+       git_diff_init_options(&opts, GIT_DIFF_OPTIONS_VERSION);
+       opts.flags |= GIT_DIFF_DISABLE_PATHSPEC_MATCH;
+       if ((error = git_diff_tree_to_tree(&(ci->diff), repo, ci->parent_tree, ci->commit_tree, &opts)))
                goto err;
        if (git_diff_get_stats(&(ci->stats), ci->diff))
                goto err;
@@ -108,39 +113,6 @@ err:
        return NULL;
 }
 
-int
-writeheader(FILE *fp)
-{
-       fputs("<!DOCTYPE HTML>"
-               "<html dir=\"ltr\" lang=\"en\">\n<head>\n"
-               "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
-               "<meta http-equiv=\"Content-Language\" content=\"en\" />\n", fp);
-       fprintf(fp, "<title>%s%s%s</title>\n", name, description[0] ? " - " : "", description);
-       fprintf(fp, "<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />\n", relpath);
-       fprintf(fp, "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"%s Atom Feed\" href=\"%satom.xml\" />\n",
-               name, relpath);
-       fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle.css\" />\n", relpath);
-       fputs("</head>\n<body>\n\n", fp);
-       fprintf(fp, "<table><tr><td><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></td>"
-               "<td><h1>%s</h1><span class=\"desc\">%s</span></td></tr><tr><td></td><td>\n",
-               relpath, name, description);
-       fprintf(fp, "<a href=\"%slog.html\">Log</a> | ", relpath);
-       fprintf(fp, "<a href=\"%sfiles.html\">Files</a>", relpath);
-       if (hasreadme)
-               fprintf(fp, " | <a href=\"%sfile/README.html\">README</a>", relpath);
-       if (haslicense)
-               fprintf(fp, " | <a href=\"%sfile/LICENSE.html\">LICENSE</a>", relpath);
-       fputs("</td></tr></table>\n<hr/><div id=\"content\">\n", fp);
-
-       return 0;
-}
-
-int
-writefooter(FILE *fp)
-{
-       return !fputs("</div></body>\n</html>", fp);
-}
-
 FILE *
 efopen(const char *name, const char *flags)
 {
@@ -241,6 +213,46 @@ printtimeshort(FILE *fp, const git_time *intime)
        printtimeformat(fp, intime, "%Y-%m-%d %H:%M");
 }
 
+int
+writeheader(FILE *fp)
+{
+       fputs("<!DOCTYPE HTML>"
+               "<html dir=\"ltr\" lang=\"en\">\n<head>\n"
+               "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
+               "<meta http-equiv=\"Content-Language\" content=\"en\" />\n<title>", fp);
+       xmlencode(fp, name, strlen(name));
+       if (description[0])
+               fputs(" - ", fp);
+       xmlencode(fp, description, strlen(description));
+       fprintf(fp, "</title>\n<link rel=\"icon\" type=\"image/png\" href=\"%sfavicon.png\" />\n", relpath);
+       fprintf(fp, "<link rel=\"alternate\" type=\"application/atom+xml\" title=\"%s Atom Feed\" href=\"%satom.xml\" />\n",
+               name, relpath);
+       fprintf(fp, "<link rel=\"stylesheet\" type=\"text/css\" href=\"%sstyle.css\" />\n", relpath);
+       fputs("</head>\n<body>\n<table><tr><td>", fp);
+       fprintf(fp, "<a href=\"../%s\"><img src=\"%slogo.png\" alt=\"\" width=\"32\" height=\"32\" /></a>",
+               relpath, relpath);
+       fputs("</td><td><h1>", fp);
+       xmlencode(fp, name, strlen(name));
+       fputs("</h1><span class=\"desc\">", fp);
+       xmlencode(fp, description, strlen(description));
+       fputs("</span></td></tr><tr><td></td><td>\n", fp);
+       fprintf(fp, "<a href=\"%slog.html\">Log</a> | ", relpath);
+       fprintf(fp, "<a href=\"%sfiles.html\">Files</a>", relpath);
+       if (hasreadme)
+               fprintf(fp, " | <a href=\"%sfile/README.html\">README</a>", relpath);
+       if (haslicense)
+               fprintf(fp, " | <a href=\"%sfile/LICENSE.html\">LICENSE</a>", relpath);
+       fputs("</td></tr></table>\n<hr/><div id=\"content\">\n", fp);
+
+       return 0;
+}
+
+int
+writefooter(FILE *fp)
+{
+       return !fputs("</div></body>\n</html>", fp);
+}
+
 void
 writeblobhtml(FILE *fp, const git_blob *blob)
 {
@@ -327,7 +339,7 @@ printshowfile(struct commitinfo *ci)
        if (!access(path, F_OK))
                return;
 
-       fp = efopen(path, "w+b");
+       fp = efopen(path, "w");
        writeheader(fp);
        fputs("<pre>\n", fp);
        printcommit(fp, ci);
@@ -399,14 +411,13 @@ printshowfile(struct commitinfo *ci)
        return;
 }
 
-int
+void
 writelog(FILE *fp)
 {
        struct commitinfo *ci;
        git_revwalk *w = NULL;
        git_oid id;
        size_t len;
-       int ret = 0;
 
        mkdir("commit", 0755);
 
@@ -459,8 +470,6 @@ writelog(FILE *fp)
 
        git_revwalk_free(w);
        relpath = "";
-
-       return ret;
 }
 
 void
@@ -554,21 +563,14 @@ writeatom(FILE *fp)
 }
 
 int
-writeblob(const git_index_entry *entry)
+writeblob(git_object *obj, const char *filename, git_off_t filesize)
 {
        char fpath[PATH_MAX];
-       char ref[PATH_MAX];
        char tmp[PATH_MAX] = "";
        char *p;
-       git_object *obj = NULL;
        FILE *fp;
 
-       snprintf(fpath, sizeof(fpath), "file/%s.html", entry->path);
-       snprintf(ref, sizeof(ref), "HEAD:%s", entry->path);
-
-       if (git_revparse_single(&obj, repo, ref))
-               return 1;
-
+       snprintf(fpath, sizeof(fpath), "file/%s.html", filename);
        if (mkdirp(dirname(fpath)))
                return 1;
 
@@ -580,9 +582,13 @@ writeblob(const git_index_entry *entry)
        }
        relpath = tmp;
 
-       fp = efopen(fpath, "w+b");
+       fp = efopen(fpath, "w");
        writeheader(fp);
-       fprintf(fp, "<p>%s (%" PRIu32 "b)</p><hr/>", entry->path, entry->file_size);
+       fputs("<p> ", fp);
+       xmlencode(fp, filename, strlen(filename));
+       fprintf(fp, " (%" PRIu32 "b)", filesize);
+       fputs("</p><hr/>", fp);
+
        if (git_blob_is_binary((git_blob *)obj)) {
                fprintf(fp, "<p>Binary file</p>\n");
        } else {
@@ -590,7 +596,6 @@ writeblob(const git_index_entry *entry)
                if (ferror(fp))
                        err(1, "fwrite");
        }
-       git_object_free(obj);
        writefooter(fp);
        fclose(fp);
 
@@ -600,35 +605,89 @@ writeblob(const git_index_entry *entry)
 }
 
 int
-writefiles(FILE *fp)
+writefilestree(FILE *fp, git_tree *tree, const char *path)
 {
-       const git_index_entry *entry;
-       git_index *index;
+       const git_tree_entry *entry = NULL;
+       const char *filename;
+       char filepath[PATH_MAX];
+       git_object *obj = NULL;
+       git_off_t filesize;
        size_t count, i;
+       int ret;
 
-       fputs("<table id=\"files\"><thead>\n"
-             "<tr><td>Mode</td><td>Name</td><td>Size</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)))
+                       return -1;
 
-       git_repository_index(&index, repo);
-       count = git_index_entrycount(index);
+               filename = git_tree_entry_name(entry);
+               if (git_tree_entry_to_object(&obj, repo, entry))
+                       return -1;
+               switch (git_object_type(obj)) {
+               case GIT_OBJ_BLOB:
+                       break;
+               case GIT_OBJ_TREE:
+                       ret = writefilestree(fp, (git_tree *)obj, filename);
+                       git_object_free(obj);
+                       if (ret)
+                               return ret;
+                       continue;
+               default:
+                       git_object_free(obj);
+                       continue;
+               }
+               if (path[0]) {
+                       snprintf(filepath, sizeof(filepath), "%s/%s", path, filename);
+                       filename = filepath;
+               }
 
-       for (i = 0; i < count; i++) {
-               entry = git_index_get_byindex(index, i);
+               filesize = git_blob_rawsize((git_blob *)obj);
 
                fputs("<tr><td>", fp);
-               fprintf(fp, "%u", entry->mode); /* TODO: fancy print, like: "-rw-r--r--" */
+               /* TODO: fancy print, like: "-rw-r--r--" */
+               fprintf(fp, "%u", git_tree_entry_filemode_raw(entry));
                fprintf(fp, "</td><td><a href=\"%sfile/", relpath);
-               xmlencode(fp, entry->path, strlen(entry->path));
+               xmlencode(fp, filename, strlen(filename));
                fputs(".html\">", fp);
-               xmlencode(fp, entry->path, strlen(entry->path));
+               xmlencode(fp, filename, strlen(filename));
                fputs("</a></td><td class=\"num\">", fp);
-               fprintf(fp, "%" PRIu32, entry->file_size);
+               fprintf(fp, "%" PRIu32, filesize);
                fputs("</td></tr>\n", fp);
 
-               writeblob(entry);
+               writeblob(obj, filename, filesize);
        }
 
+       return 0;
+}
+
+int
+writefiles(FILE *fp)
+{
+       const git_oid *id;
+       git_tree *tree = NULL;
+       git_object *obj = NULL;
+       git_commit *commit = NULL;
+
+       fputs("<table id=\"files\"><thead>\n"
+             "<tr><td>Mode</td><td>Name</td><td>Size</td></tr>\n"
+             "</thead><tbody>\n", fp);
+
+       if (git_revparse_single(&obj, repo, "HEAD"))
+               return -1;
+       id = git_object_id(obj);
+       if (git_commit_lookup(&commit, repo, id))
+               return -1;
+       if (git_commit_tree(&tree, commit)) {
+               git_commit_free(commit);
+               return -1;
+       }
+       git_commit_free(commit);
+
+       writefilestree(fp, tree, "");
+
+       git_commit_free(commit);
+       git_tree_free(tree);
+
        fputs("</tbody></table>", fp);
 
        return 0;
@@ -666,10 +725,10 @@ main(int argc, char *argv[])
        /* read description or .git/description */
        snprintf(path, sizeof(path), "%s%s%s",
                repodir, repodir[strlen(repodir)] == '/' ? "" : "/", "description");
-       if (!(fpread = fopen(path, "r+b"))) {
+       if (!(fpread = fopen(path, "r"))) {
                snprintf(path, sizeof(path), "%s%s%s",
                        repodir, repodir[strlen(repodir)] == '/' ? "" : "/", ".git/description");
-               fpread = fopen(path, "r+b");
+               fpread = fopen(path, "r");
        }
        if (fpread) {
                if (!fgets(description, sizeof(description), fpread))
@@ -684,20 +743,20 @@ main(int argc, char *argv[])
        hasreadme = !git_revparse_single(&obj, repo, "HEAD:README");
        git_object_free(obj);
 
-       fp = efopen("log.html", "w+b");
+       fp = efopen("log.html", "w");
        writeheader(fp);
        writelog(fp);
        writefooter(fp);
        fclose(fp);
 
-       fp = efopen("files.html", "w+b");
+       fp = efopen("files.html", "w");
        writeheader(fp);
        writefiles(fp);
        writefooter(fp);
        fclose(fp);
 
        /* Atom feed */
-       fp = efopen("atom.xml", "w+b");
+       fp = efopen("atom.xml", "w");
        writeatom(fp);
        fclose(fp);