change first parameter for object display functions
[webgit] / src / object.c
index 582b39a7e8de463d9fd8a2078ee285c5ff1675cd..6e0679ee40f8d5ba61ee2e60a0c4f8526493ac3d 100644 (file)
 #include "object.h"
 #include "repo.h"
 
-#define SHA1_HEADER <openssl/sha.h>
-#include "git/cache.h"
-#include "git/object.h"
-
 
 Html
 webgit_object_link (struct webgit_query* query,
-                   const char* repo,
-                   int repo_len,
-                   const char* object,
-                   int object_len,
-                   const char* path,
-                   Html text)
+                    const char* repo,
+                    int repo_len,
+                    const char* object,
+                    int object_len,
+                    const char* path,
+                    const char* action,
+                    Html text)
 {
   return html (
                html_tag ("a",
@@ -43,7 +40,8 @@ webgit_object_link (struct webgit_query* query,
                                                             query->request->script_name,
                                                             repo_len, repo,
                                                             object_len, object),
-                                                  path ? html_fmt ("&path=%s", path) : html ()
+                                                  path ? html_fmt ("&path=%s", path) : html (),
+                                                  action ? html_fmt ("&action=%s", action) : html ()
                                                   )
                                     )
                          ),
@@ -53,19 +51,181 @@ webgit_object_link (struct webgit_query* query,
 
 
 
+char*
+webgit_commit_tree_parse (struct commit* commit)
+{
+  char* tree = strstr (commit->buffer, "tree ");
+  if (!tree)
+    return NULL;
+  return tree + 5;
+}
+
+time_t
+webgit_commit_author_date_parse (struct commit* commit, struct tm* tm)
+{
+  struct tm tmp;
+  if (!tm)
+    tm = &tmp;
+
+  char* author = strstr (commit->buffer, "author ");
+  if (!author)
+    return (time_t)-1;
+
+  char* beg = strchr (author, '>');
+  if (!beg)
+    return (time_t)-1;
+
+  if (!strptime (beg + 2, "%s %Z", tm))
+    return (time_t)-1;
+
+  return mktime (tm);
+}
+
+Html
+webgit_commit_author_name_parse (struct commit* commit)
+{
+  char* author = strstr (commit->buffer, "author ");
+  if (!author)
+    return NULL;
+
+  char* end = strchr (author, '<');
+  if (!end)
+    return NULL;
+
+  return html_fmt ("%.*s", end-author-8, author+7);
+}
+
+Html
+webgit_commit_author_email_parse (struct commit* commit)
+{
+  char* author = strstr (commit->buffer, "author ");
+  if (!author)
+    return NULL;
+
+  char* beg = strchr (author, '<');
+  if (!beg)
+    return NULL;
+
+  char* end = strchr (beg, '>');
+  if (!end)
+    return NULL;
+
+
+  return html_fmt ("%.*s", end-beg-1, beg+1);
+}
+
+time_t
+webgit_commit_committer_date_parse (struct commit* commit, struct tm* tm)
+{
+  struct tm tmp;
+  if (!tm)
+    tm = &tmp;
+
+  char* committer = strstr (commit->buffer, "committer ");
+  if (!committer)
+    return (time_t)-1;
+
+  char* beg = strchr (committer, '>');
+  if (!beg)
+    return (time_t)-1;
+
+  if (!strptime (beg + 2, "%s %Z", tm))
+    return (time_t)-1;
+
+  return mktime (tm);
+}
+
+Html
+webgit_commit_committer_name_parse (struct commit* commit)
+{
+  char* committer = strstr (commit->buffer, "committer ");
+  if (!committer)
+    return NULL;
+
+  char* end = strchr (committer, '<');
+  if (!end)
+    return NULL;
+
+  return html_fmt ("%.*s", end-committer-11, committer+10);
+}
+
+Html
+webgit_commit_committer_email_parse (struct commit* commit)
+{
+  char* committer = strstr (commit->buffer, "committer ");
+  if (!committer)
+    return NULL;
+
+  char* beg = strchr (committer, '<');
+  if (!beg)
+    return NULL;
+
+  char* end = strchr (beg, '>');
+  if (!end)
+    return NULL;
+
+
+  return html_fmt ("%.*s", end-beg-1, beg+1);
+}
+
+Html
+webgit_commit_header_parse (struct commit* commit)
+{
+  char* header = strstr (commit->buffer, "\n\n");
+  if (!header)
+    return NULL;
+
+  char* end = strchr (header+2, '\n');
+  if (!end)
+    end = header + strlen (header+2);
+  else
+    --end;
+
+  return html_fmt ("%.*s", end-header, header+2);
+}
+
+Html
+webgit_commit_message_parse (struct commit* commit)
+{
+  char* header = strstr (commit->buffer, "\n\n");
+  if (!header)
+    return NULL;
+
+  header = strchr (header+2, '\n');
+  if (!header)
+    return html ();
+  else
+    ++header;
+
+  return html_fmt ("%.*s", strlen (header), header);
+}
+
+
+
+
 /*
   Display commits
 */
 
 static Html
-webgit_object_commit_menu_action (struct webgit_query* query, unsigned char* sha1, void* buf, unsigned long size)
+webgit_object_commit_menu_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
 {
+  (void) repo;
+  (void) sha1;
+  (void) buf;
+  (void) size;
+
   return html ("TODO: commit-object sidebar");
 }
 
 static Html
-webgit_object_commit_content_action (struct webgit_query* query, unsigned char* sha1, void* buf, unsigned long size)
+webgit_object_commit_content_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
 {
+/*
+  TODO pass commit objects instead buf/size, use parsers from above
+*/
+  (void) sha1;
+
   Html tree = html_list ();
   Html parents = html_list ();
   Html author_text = html_list ();
@@ -76,7 +236,7 @@ webgit_object_commit_content_action (struct webgit_query* query, unsigned char*
   const char* author_end = NULL;
 
   const char* i = buf;
-  while (i && i < buf+size)
+  while (i && (void*)i < buf+size)
     {
       if (*i == '\n')
         {
@@ -86,31 +246,33 @@ webgit_object_commit_content_action (struct webgit_query* query, unsigned char*
         }
       if (!strncmp (i, "tree ", 5))
         {
-
           html_list_append (tree,
                             "Tree: ",
-                            webgit_object_link (query,
-                                                query->repo, strlen (query->repo),
+                            webgit_object_link (repo->query,
+                                                repo->name, strlen (repo->name),
                                                 i+5, 40,
                                                 NULL,
+                                                NULL,
                                                 html_fmt ("%.40s", i+5))
                             );
-
-          (i = strchr (i, '\n')) && ++i;
+          if ((i = strchr (i, '\n')))
+            ++i;
           continue;
         }
       else if (!strncmp (i, "parent ", 7))
         {
           html_list_append (parents, html (
                                            "Parent: ",
-                                           webgit_object_link (query,
-                                                               query->repo, strlen (query->repo),
+                                           webgit_object_link (repo->query,
+                                                               repo->name, strlen (repo->name),
                                                                i+7, 40,
                                                                NULL,
+                                                               NULL,
                                                                html_fmt ("%.40s", i+7))
                                            )
                             );
-          (i = strchr (i, '\n')) && ++i;
+          if ((i = strchr (i, '\n')))
+            ++i;
           continue;
         }
       else if (!strncmp (i, "author ", 7))
@@ -137,7 +299,8 @@ webgit_object_commit_content_action (struct webgit_query* query, unsigned char*
                                           html_strndup (pretty_date, 255)
                                           )
                             );
-          (i = strchr (i, '\n')) && ++i;
+          if ((i = strchr (i, '\n')))
+            ++i;
           continue;
         }
       else if (!strncmp (i, "committer ", 10))
@@ -164,7 +327,8 @@ webgit_object_commit_content_action (struct webgit_query* query, unsigned char*
           else
             html_list_append (author_text, " and Committer");
 
-          (i = strchr (i, '\n')) && ++i;
+          if ((i = strchr (i, '\n')))
+            ++i;
           continue;
         }
       ++i;
@@ -217,7 +381,7 @@ webgit_object_commit_content_action (struct webgit_query* query, unsigned char*
 }
 
 Html
-webgit_object_commit_action (struct webgit_query* query, unsigned char* sha1)
+webgit_object_commit_action (struct webgit_repo_info* repo, unsigned char* sha1)
 {
   void* buf;
   unsigned long size;
@@ -225,8 +389,8 @@ webgit_object_commit_action (struct webgit_query* query, unsigned char* sha1)
   buf = read_object_with_reference (sha1, "commit", &size, NULL);
 
   return html(
-              html(html_tag("div"), webgit_object_commit_menu_action (query, sha1, buf, size)), html_nl (),
-              html(html_tag("div"), webgit_object_commit_content_action (query, sha1, buf, size)), html_nl ()
+              html(html_tag("div"), webgit_object_commit_menu_action (repo, sha1, buf, size)), html_nl (),
+              html(html_tag("div"), webgit_object_commit_content_action (repo, sha1, buf, size)), html_nl ()
               );
 }
 
@@ -236,8 +400,11 @@ webgit_object_commit_action (struct webgit_query* query, unsigned char* sha1)
 */
 
 static Html
-webgit_object_tree_menu_action (struct webgit_query* query, unsigned char* sha1, struct tree *tree)
+webgit_object_tree_menu_action (struct webgit_repo_info* repo, unsigned char* sha1, struct tree *tree)
 {
+  (void) repo;
+  (void) sha1;
+  (void) tree;
   return html ("TODO: tree-object sidebar");
 }
 
@@ -269,7 +436,8 @@ static int
 webgit_html_tree (const unsigned char *sha1, const char *base, int baselen,
                   const char *name, unsigned mode, int stage)
 {
-  const char pathname[PATH_MAX];
+  (void) stage;
+  char pathname[PATH_MAX];
 
   snprintf (pathname, PATH_MAX-1, "%.*s%s%s", baselen, base, baselen ? "/": "", name);
 
@@ -305,6 +473,7 @@ webgit_html_tree (const unsigned char *sha1, const char *base, int baselen,
                                                                               strlen (query_in_flight->repo),
                                                                               sha1_to_hex (sha1), 40,
                                                                               pathname,
+                                                                              NULL,
                                                                               html_strndup (name, SIZE_MAX))
                                                           ),
                                                   html (html_tag ("td"), "history snap")
@@ -324,9 +493,19 @@ webgit_html_tree (const unsigned char *sha1, const char *base, int baselen,
                                                                               strlen (query_in_flight->repo),
                                                                               sha1_to_hex (sha1), 40,
                                                                               pathname,
+                                                                              NULL,
                                                                               html_strndup (name, SIZE_MAX))
                                                           ),
-                                                    html (html_tag ("td"), "history raw edit")
+                                                    html (html_tag ("td"),
+                                                          "history ",
+                                                          webgit_object_link (query_in_flight,
+                                                                              query_in_flight->repo,
+                                                                              strlen (query_in_flight->repo),
+                                                                              sha1_to_hex (sha1), 40,
+                                                                              pathname,
+                                                                              "raw",
+                                                                              html ("raw")),
+                                                          " edit")
                                                     ),
                                               html_nl()
                                               )
@@ -338,18 +517,20 @@ webgit_html_tree (const unsigned char *sha1, const char *base, int baselen,
 
 
 static Html
-webgit_object_tree_content_action (struct webgit_query* query, unsigned char* sha1, struct tree *tree)
+webgit_object_tree_content_action (struct webgit_repo_info* repo, unsigned char* sha1, struct tree *tree)
 {
-  query_in_flight = query;
+  (void) sha1;
+  query_in_flight = repo->query;
   tree_in_flight = html_list ();
 
-  read_tree_recursive (tree, query->path, query->path ? strlen (query->path): 0, 0, NULL, webgit_html_tree);
+  read_tree_recursive (tree, repo->query->path,
+                       repo->query->path ? strlen (repo->query->path) : 0, 0, NULL, webgit_html_tree);
 
   return html (html_tag ("table"), tree_in_flight);
 }
 
 Html
-webgit_object_tree_action (struct webgit_query* query, unsigned char* sha1)
+webgit_object_tree_action (struct webgit_repo_info* repo, unsigned char* sha1)
 {
   struct tree *tree;
 
@@ -358,8 +539,8 @@ webgit_object_tree_action (struct webgit_query* query, unsigned char* sha1)
     die("not a tree object");
 
   return html(
-              html(html_tag("div"), webgit_object_tree_menu_action (query, sha1, tree)), html_nl (),
-              html(html_tag("div"), webgit_object_tree_content_action (query, sha1, tree)), html_nl ()
+              html(html_tag("div"), webgit_object_tree_menu_action (repo, sha1, tree)), html_nl (),
+              html(html_tag("div"), webgit_object_tree_content_action (repo, sha1, tree)), html_nl ()
               );
 }
 
@@ -367,29 +548,60 @@ webgit_object_tree_action (struct webgit_query* query, unsigned char* sha1)
 /*
   Display blobs
 */
-
 static Html
-webgit_object_blob_menu_action (struct webgit_query* query, unsigned char* sha1, void* buf, unsigned long size)
+webgit_object_blob_menu_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
 {
+  (void) repo;
+  (void) sha1;
+  (void) buf;
+  (void) size;
   return html ("TODO: blob-object sidebar");
 }
 
 static Html
-webgit_object_blob_content_action (struct webgit_query* query, unsigned char* sha1, void* buf, unsigned long size)
+webgit_object_blob_content_action (struct webgit_repo_info* repo, unsigned char* sha1, void* buf, unsigned long size)
 {
+  (void) sha1;
+
   if (!memchr(buf, 0, size>8192 ? 8192 : size))
     {
       return html (html_tag ("pre"), html_strndup (buf, size));
     }
   else
     {
-      return html ("binary blob");
+      struct webgit_query* query = repo->query;
+      const char* mimetype = webgit_mimetype (query->path);
+
+      Html ret;
+
+      if (mimetype && !strncmp(mimetype, "image/", 6))
+        {
+          /* inline image */
+          ret = html (
+                      html_tag ("img",
+                                html_attr ("src",
+                                           html_fmt ("%s?repo=%s&action=raw&object=%s&path=%s",
+                                                     query->request->script_name,
+                                                     query->repo, query->object, query->path)
+                                           ),
+                                html_attr ("alt", query->path ? query->path : query->object)
+                                )
+                      );
+        }
+      else
+        {
+          /* link to raw data */
+          ret = html ("binary blob");
+        }
+      free ((char*)mimetype);
+
+      return ret;
     }
 }
 
 
 Html
-webgit_object_blob_action (struct webgit_query* query, unsigned char* sha1)
+webgit_object_blob_action (struct webgit_repo_info* repo, unsigned char* sha1)
 {
   void* buf;
   unsigned long size;
@@ -397,8 +609,8 @@ webgit_object_blob_action (struct webgit_query* query, unsigned char* sha1)
   buf = read_object_with_reference (sha1, "blob", &size, NULL);
 
   return html(
-              html(html_tag("div"), webgit_object_blob_menu_action (query, sha1, buf, size)), html_nl (),
-              html(html_tag("div"), webgit_object_blob_content_action (query, sha1, buf, size)), html_nl ()
+              html(html_tag("div"), webgit_object_blob_menu_action (repo, sha1, buf, size)), html_nl (),
+              html(html_tag("div"), webgit_object_blob_content_action (repo, sha1, buf, size)), html_nl ()
               );
 }