Merge part of pack-thin branch
authorJunio C Hamano <junkio@cox.net>
Thu, 23 Feb 2006 11:00:59 +0000 (03:00 -0800)
committerJunio C Hamano <junkio@cox.net>
Thu, 23 Feb 2006 11:00:59 +0000 (03:00 -0800)
1  2 
pack-objects.c

diff --combined pack-objects.c
@@@ -5,7 -5,6 +5,7 @@@
  #include "csum-file.h"
  #include "diff.h"
  #include <sys/time.h>
 +#include <signal.h>
  
  static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list";
  
@@@ -61,7 -60,6 +61,7 @@@ static int nr_objects = 0, nr_alloc = 0
  static const char *base_name;
  static unsigned char pack_file_sha1[20];
  static int progress = 1;
 +static volatile int progress_update = 0;
  
  /*
   * The object names in objects array are hashed with this hashtable,
@@@ -336,41 -334,20 +336,41 @@@ static void write_pack_file(void
        struct sha1file *f;
        unsigned long offset;
        struct pack_header hdr;
 +      unsigned last_percent = 999;
 +      int do_progress = 0;
  
        if (!base_name)
                f = sha1fd(1, "<stdout>");
 -      else
 +      else {
                f = sha1create("%s-%s.%s", base_name,
                               sha1_to_hex(object_list_sha1), "pack");
 +              do_progress = progress;
 +      }
 +      if (do_progress)
 +              fprintf(stderr, "Writing %d objects.\n", nr_result);
 +
        hdr.hdr_signature = htonl(PACK_SIGNATURE);
        hdr.hdr_version = htonl(PACK_VERSION);
        hdr.hdr_entries = htonl(nr_result);
        sha1write(f, &hdr, sizeof(hdr));
        offset = sizeof(hdr);
 -      for (i = 0; i < nr_objects; i++)
 +      if (!nr_result)
 +              goto done;
 +      for (i = 0; i < nr_objects; i++) {
                offset = write_one(f, objects + i, offset);
 -
 +              if (do_progress) {
 +                      unsigned percent = written * 100 / nr_result;
 +                      if (progress_update || percent != last_percent) {
 +                              fprintf(stderr, "%4u%% (%u/%u) done\r",
 +                                      percent, written, nr_result);
 +                              progress_update = 0;
 +                              last_percent = percent;
 +                      }
 +              }
 +      }
 +      if (do_progress)
 +              fputc('\n', stderr);
 + done:
        sha1close(f, pack_file_sha1, 1);
  }
  
@@@ -470,7 -447,7 +470,7 @@@ static int add_object_entry(const unsig
        struct packed_git *p;
        unsigned int found_offset = 0;
        struct packed_git *found_pack = NULL;
-       int ix;
+       int ix, status = 0;
  
        if (!exclude) {
                for (p = packed_git; p; p = p->next) {
                        die("internal error in object hashing.");
                object_ix[-1 - ix] = idx + 1;
        }
+       status = 1;
  
   already_added:
 +      if (progress_update) {
 +              fprintf(stderr, "Counting objects...%d\r", nr_objects);
 +              progress_update = 0;
 +      }
        if (exclude)
                entry->preferred_base = 1;
        else {
                        entry->in_pack_offset = found_offset;
                }
        }
-       return 1;
+       return status;
  }
  
  static void add_pbase_tree(struct tree_desc *tree)
                        continue;
                if (sha1_object_info(sha1, type, &size))
                        continue;
-               add_object_entry(sha1, name, 1);
+               if (!add_object_entry(sha1, name, 1))
+                       continue;
                if (!strcmp(type, "tree")) {
                        struct tree_desc sub;
                        void *elem;
@@@ -570,8 -547,8 +574,8 @@@ static void add_preferred_base(unsigne
        tree.buf = elem;
        if (!tree.buf)
                return;
-       add_object_entry(sha1, "", 1);
-       add_pbase_tree(&tree);
+       if (add_object_entry(sha1, "", 1))
+               add_pbase_tree(&tree);
        free(elem);
  }
  
@@@ -775,10 -752,11 +779,10 @@@ static int try_delta(struct unpacked *c
        }
  
        size = cur_entry->size;
 -      if (size < 50)
 -              return -1;
        oldsize = old_entry->size;
        sizediff = oldsize > size ? oldsize - size : size - oldsize;
 -      if (sizediff > size / 8)
 +
 +      if (size < 50)
                return -1;
        if (old_entry->depth >= max_depth)
                return 0;
                                 * already have a delta based on preferred
                                 * one is pointless.
                                 */
-                               return 0;
+                               return -1;
                }
                else if (!old_preferred)
                        max_size = cur_entry->delta_size-1;
        return 0;
  }
  
 +static void progress_interval(int signum)
 +{
 +      signal(SIGALRM, progress_interval);
 +      progress_update = 1;
 +}
 +
  static void find_deltas(struct object_entry **list, int window, int depth)
  {
        int i, idx;
        unsigned int array_size = window * sizeof(struct unpacked);
        struct unpacked *array = xmalloc(array_size);
 -      int eye_candy;
 +      unsigned processed = 0;
 +      unsigned last_percent = 999;
  
        memset(array, 0, array_size);
        i = nr_objects;
        idx = 0;
 -      eye_candy = i - (nr_objects / 20);
 +      if (progress)
 +              fprintf(stderr, "Deltifying %d objects.\n", nr_result);
  
        while (--i >= 0) {
                struct object_entry *entry = list[i];
                char type[10];
                int j;
  
 -              if (progress && i <= eye_candy) {
 -                      eye_candy -= nr_objects / 20;
 -                      fputc('.', stderr);
 +              if (!entry->preferred_base)
 +                      processed++;
 +
 +              if (progress) {
 +                      unsigned percent = processed * 100 / nr_result;
 +                      if (percent != last_percent || progress_update) {
 +                              fprintf(stderr, "%4u%% (%u/%u) done\r",
 +                                      percent, processed, nr_result);
 +                              progress_update = 0;
 +                              last_percent = percent;
 +                      }
                }
  
                if (entry->delta)
                        idx = 0;
        }
  
 +      if (progress)
 +              fputc('\n', stderr);
 +
        for (i = 0; i < window; ++i)
                free(array[i].data);
        free(array);
  
  static void prepare_pack(int window, int depth)
  {
 -      if (progress)
 -              fprintf(stderr, "Packing %d objects", nr_result);
        get_object_details();
 -      if (progress)
 -              fputc('.', stderr);
 -
        sorted_by_type = create_sorted_list(type_size_sort);
        if (window && depth)
                find_deltas(sorted_by_type, window+1, depth);
 -      if (progress)
 -              fputc('\n', stderr);
 -      write_pack_file();
  }
  
  static int reuse_cached_pack(unsigned char *sha1, int pack_to_stdout)
@@@ -972,6 -939,10 +976,6 @@@ int main(int argc, char **argv
        int window = 10, depth = 10, pack_to_stdout = 0;
        struct object_entry **list;
        int i;
 -      struct timeval prev_tv;
 -      int eye_candy = 0;
 -      int eye_candy_incr = 500;
 -
  
        setup_git_directory();
  
                usage(pack_usage);
  
        prepare_packed_git();
 +
        if (progress) {
 +              struct itimerval v;
 +              v.it_interval.tv_sec = 1;
 +              v.it_interval.tv_usec = 0;
 +              v.it_value = v.it_interval;
 +              signal(SIGALRM, progress_interval);
 +              setitimer(ITIMER_REAL, &v, NULL);
                fprintf(stderr, "Generating pack...\n");
 -              gettimeofday(&prev_tv, NULL);
        }
 +
        while (fgets(line, sizeof(line), stdin) != NULL) {
                unsigned char sha1[20];
  
 -              if (progress && (eye_candy <= nr_objects)) {
 -                      fprintf(stderr, "Counting objects...%d\r", nr_objects);
 -                      if (eye_candy && (50 <= eye_candy_incr)) {
 -                              struct timeval tv;
 -                              int time_diff;
 -                              gettimeofday(&tv, NULL);
 -                              time_diff = (tv.tv_sec - prev_tv.tv_sec);
 -                              time_diff <<= 10;
 -                              time_diff += (tv.tv_usec - prev_tv.tv_usec);
 -                              if ((1 << 9) < time_diff)
 -                                      eye_candy_incr += 50;
 -                              else if (50 < eye_candy_incr)
 -                                      eye_candy_incr -= 50;
 -                      }
 -                      eye_candy += eye_candy_incr;
 -              }
                if (line[0] == '-') {
                        if (get_sha1_hex(line+1, sha1))
                                die("expected edge sha1, got garbage:\n %s",
        }
        if (progress)
                fprintf(stderr, "Done counting %d objects.\n", nr_objects);
 -      if (non_empty && !nr_objects)
 +      sorted_by_sha = create_final_object_list();
 +      if (non_empty && !nr_result)
                return 0;
  
 -      sorted_by_sha = create_final_object_list();
        SHA1_Init(&ctx);
        list = sorted_by_sha;
        for (i = 0; i < nr_result; i++) {
        if (reuse_cached_pack(object_list_sha1, pack_to_stdout))
                ;
        else {
 -              prepare_pack(window, depth);
 +              if (nr_result)
 +                      prepare_pack(window, depth);
 +              if (progress && pack_to_stdout) {
 +                      /* the other end usually displays progress itself */
 +                      struct itimerval v = {{0,},};
 +                      setitimer(ITIMER_REAL, &v, NULL);
 +                      signal(SIGALRM, SIG_IGN );
 +                      progress_update = 0;
 +              }
 +              write_pack_file();
                if (!pack_to_stdout) {
                        write_index_file();
                        puts(sha1_to_hex(object_list_sha1));