fast forward unchanged worktrees
authorChristian Thaeter <ct@pipapo.org>
Wed, 13 Feb 2008 11:07:59 +0000 (12:07 +0100)
committerChristian Thaeter <ct@pipapo.org>
Wed, 13 Feb 2008 11:07:59 +0000 (12:07 +0100)
factored out 'worktree_create()'

when head got updated and the worktree has no pending changes it will be
forwarded to the new head

src/worktree.c

index 5e82206..744f198 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 #include "worktree.h"
+#include "object.h"
 
 #define SHA1_HEADER <openssl/sha.h>
 #include "git/cache.h"
 #include "git/refs.h"
 #include "git/tree.h"
 
+static int
+webgit_worktree_create (struct webgit_repo_info* repo,
+                        const char* ref,
+                        unsigned char* sha1_tree,
+                        unsigned char* sha1_parent,
+                        const char* message
+                        )
+{
+  char* cbuf = cwa_buffer_provide (256 /* just a good guess */ +
+                                   2*(strlen (repo->query->name) + strlen (repo->query->email)) +
+                                   strlen (message));
+  sprintf (cbuf,
+           "tree %s\n"
+           "parent %s\n"
+           "author %s <%s> %lu +0000\n"
+           "committer %s <%s> %lu +0000\n\n%s",
+           sha1_to_hex (sha1_tree),
+           sha1_to_hex (sha1_parent),
+           repo->query->name,
+           repo->query->email,
+           repo->query->now,
+           repo->query->name,
+           repo->query->email,
+           repo->query->now,
+           message
+           );
+
+  unsigned char sha1[20];
+
+  if (!!write_sha1_file (cbuf, strlen (cbuf), "commit", sha1))
+    die("error writing worktree %s\n", sha1_to_hex (sha1));
+
+  struct ref_lock * lock = lock_ref_sha1 (ref, NULL);
+
+  lock->force_write = 1;
+  return write_ref_sha1 (lock, sha1, NULL);
+}
 
-//webgit_worktree_ensure ;
 
 void
 webgit_worktree_setup (struct webgit_repo_info* repo)
 {
-  char* buf = cwa_buffer_provide (PATH_MAX);
-  snprintf (buf, PATH_MAX, "refs/worktrees/%s", repo->query->head);
+  char* worktree = cwa_buffer_provide (PATH_MAX);
+  unsigned char sha1_tree[20];
+  snprintf (worktree, PATH_MAX, "refs/worktrees/%s", repo->query->head);
 
   unsigned char sha1_head[20];
   get_sha1 (repo->query->head, sha1_head);
 
-  unsigned char sha1[20];
-
-  if (!read_ref (buf, sha1))
+  if (!read_ref (worktree, sha1_tree))
     {
-      repo->worktree = cwa_strndup (sha1_to_hex (sha1), 40);
-
-      struct commit* commit = lookup_commit_reference (sha1);
+      /* found worktree */
+      struct commit* commit = lookup_commit_reference (sha1_tree);
       parse_commit (commit);
 
-      struct commit* parent = pop_commit(&commit->parents);
+      struct commit* treehead = pop_commit (&commit->parents);
+      parse_commit (treehead);
 
-      if (!!hashcmp (sha1_head, parent->object.sha1))
+      if (!!hashcmp (sha1_head, treehead->object.sha1))
         {
-          /* uh ohh, head diverted from worktree */
-          die ("TODO: uh ohh, head diverted from worktree, needs merge strategy");
+          /* head diverted from worktree */
+
+          if (!strncmp (webgit_object_commit_tree_parse (commit),
+                        webgit_object_commit_tree_parse (treehead), 40))
+            {
+              /* workree unchanged, forward it */
+              struct commit* newhead = lookup_commit_reference (sha1_head);
+              parse_commit (newhead);
+
+              get_sha1_hex (webgit_object_commit_tree_parse (newhead), sha1_tree);
+              webgit_worktree_create (repo, worktree+5, sha1_tree, sha1_head, "");
+            }
+          else
+            /* else uhm */
+            die ("TODO: uh ohh, head diverted from worktree, needs merge strategy");
         }
     }
   else
     {
-      struct commit* commit = lookup_commit_reference (sha1_head);
-      parse_commit (commit);
+      /* create brand new worktree */
+      struct commit* parent = lookup_commit_reference (sha1_head);
+      parse_commit (parent);
 
-      repo->worktree = cwa_strndup (webgit_object_commit_tree_parse (commit), 40);
-
-      char* cbuf = cwa_buffer_provide (512);
-      sprintf (cbuf,
-               "tree %s\n"
-               "parent %s\n"
-               "author %s <%s> %lu +0000\n"
-               "committer %s <%s> %lu +0000\n\n",
-               repo->worktree,
-               sha1_to_hex (sha1_head),
-               repo->query->name,
-               repo->query->email,
-               repo->query->now,
-               repo->query->name,
-               repo->query->email,
-               repo->query->now
-               );
-
-      if (!!write_sha1_file (cbuf, strlen (cbuf), "commit", sha1))
-        die("error writing worktree %s\n", sha1_to_hex(sha1));
-
-      struct ref_lock * lock = lock_ref_sha1 (buf+5, NULL);
-
-      lock->force_write = 1;
-      write_ref_sha1 (lock, sha1, "");
+      get_sha1_hex (webgit_object_commit_tree_parse (parent), sha1_tree);
+      webgit_worktree_create (repo, worktree+5, sha1_tree, sha1_head, "");
     }
+  repo->worktree = cwa_strndup (sha1_to_hex (sha1_tree), 40);
 }