Merge branch 'jc/upload-pack-hook'
authorJunio C Hamano <gitster@pobox.com>
Mon, 7 Sep 2009 22:24:47 +0000 (15:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Sep 2009 22:24:47 +0000 (15:24 -0700)
* jc/upload-pack-hook:
upload-pack: feed "kind [clone|fetch]" to post-upload-pack hook
upload-pack: add a trigger for post-upload-pack hook

1  2 
upload-pack.c
diff --combined upload-pack.c
index 25e222ffaac1d1a855f274d92087e6c7dfbd48b0,8e82179c93b8286329670a9b236da6632c3aba6b..c77ab710c459cb292ee2162919ed28e260e5da88
@@@ -32,7 -32,6 +32,7 @@@ static int no_progress, daemon_mode
  static int shallow_nr;
  static struct object_array have_obj;
  static struct object_array want_obj;
 +static struct object_array extra_edge_obj;
  static unsigned int timeout;
  /* 0 for no sideband,
   * otherwise maximum packet size (up to 65520 bytes).
@@@ -136,18 -135,72 +136,76 @@@ static int do_rev_list(int fd, void *cr
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
        mark_edges_uninteresting(revs.commits, &revs, show_edge);
 +      if (use_thin_pack)
 +              for (i = 0; i < extra_edge_obj.nr; i++)
 +                      fprintf(pack_pipe, "-%s\n", sha1_to_hex(
 +                                      extra_edge_obj.objects[i].item->sha1));
        traverse_commit_list(&revs, show_commit, show_object, NULL);
        fflush(pack_pipe);
        fclose(pack_pipe);
        return 0;
  }
  
+ static int feed_msg_to_hook(int fd, const char *fmt, ...)
+ {
+       int cnt;
+       char buf[1024];
+       va_list params;
+       va_start(params, fmt);
+       cnt = vsprintf(buf, fmt, params);
+       va_end(params);
+       return write_in_full(fd, buf, cnt) != cnt;
+ }
+ static int feed_obj_to_hook(const char *label, struct object_array *oa, int i, int fd)
+ {
+       return feed_msg_to_hook(fd, "%s %s\n", label,
+                               sha1_to_hex(oa->objects[i].item->sha1));
+ }
+ static int run_post_upload_pack_hook(size_t total, struct timeval *tv)
+ {
+       const char *argv[2];
+       struct child_process proc;
+       int err, i;
+       argv[0] = "hooks/post-upload-pack";
+       argv[1] = NULL;
+       if (access(argv[0], X_OK) < 0)
+               return 0;
+       memset(&proc, 0, sizeof(proc));
+       proc.argv = argv;
+       proc.in = -1;
+       proc.stdout_to_stderr = 1;
+       err = start_command(&proc);
+       if (err)
+               return err;
+       for (i = 0; !err && i < want_obj.nr; i++)
+               err |= feed_obj_to_hook("want", &want_obj, i, proc.in);
+       for (i = 0; !err && i < have_obj.nr; i++)
+               err |= feed_obj_to_hook("have", &have_obj, i, proc.in);
+       if (!err)
+               err |= feed_msg_to_hook(proc.in, "time %ld.%06ld\n",
+                                       (long)tv->tv_sec, (long)tv->tv_usec);
+       if (!err)
+               err |= feed_msg_to_hook(proc.in, "size %ld\n", (long)total);
+       if (!err)
+               err |= feed_msg_to_hook(proc.in, "kind %s\n",
+                                       (nr_our_refs == want_obj.nr && !have_obj.nr)
+                                       ? "clone" : "fetch");
+       if (close(proc.in))
+               err = 1;
+       if (finish_command(&proc))
+               err = 1;
+       return err;
+ }
  static void create_pack_file(void)
  {
+       struct timeval start_tv, tv;
        struct async rev_list;
        struct child_process pack_objects;
        int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
        int buffered = -1;
-       ssize_t sz;
+       ssize_t sz, total_sz;
        const char *argv[10];
        int arg = 0;
  
+       gettimeofday(&start_tv, NULL);
+       total_sz = 0;
        if (shallow_nr) {
                rev_list.proc = do_rev_list;
                rev_list.data = 0;
                        sz = xread(pack_objects.out, cp,
                                  sizeof(data) - outsz);
                        if (0 < sz)
-                                       ;
+                               total_sz += sz;
                        else if (sz == 0) {
                                close(pack_objects.out);
                                pack_objects.out = -1;
        }
        if (use_sideband)
                packet_flush(1);
+       gettimeofday(&tv, NULL);
+       tv.tv_sec -= start_tv.tv_sec;
+       if (tv.tv_usec < start_tv.tv_usec) {
+               tv.tv_sec--;
+               tv.tv_usec += 1000000;
+       }
+       tv.tv_usec -= start_tv.tv_usec;
+       if (run_post_upload_pack_hook(total_sz, &tv))
+               warning("post-upload-hook failed");
        return;
  
   fail:
@@@ -432,7 -497,7 +502,7 @@@ static int get_common_commits(void
  
        save_commit_buffer = 0;
  
 -      for(;;) {
 +      for (;;) {
                int len = packet_read_line(0, line, sizeof(line));
                reset_timeout();
  
@@@ -497,6 -562,7 +567,6 @@@ static void receive_needs(void
                if (!prefixcmp(line, "shallow ")) {
                        unsigned char sha1[20];
                        struct object *object;
 -                      use_thin_pack = 0;
                        if (get_sha1(line + 8, sha1))
                                die("invalid shallow line: %s", line);
                        object = parse_object(sha1);
                }
                if (!prefixcmp(line, "deepen ")) {
                        char *end;
 -                      use_thin_pack = 0;
                        depth = strtol(line + 7, &end, 0);
                        if (end == line + 7 || depth <= 0)
                                die("Invalid deepen: %s", line);
                                                        NULL, &want_obj);
                                        parents = parents->next;
                                }
 +                              add_object_array(object, NULL, &extra_edge_obj);
                        }
                        /* make sure commit traversal conforms to client */
                        register_shallow(object->sha1);