Merge branch 'maint'
[gitweb.git] / builtin-pack-objects.c
index 840d4d697a74901599bf9d9222375811c6a0e668..966f843e4357d45b8c9acf96617bdacd8dc1b133 100644 (file)
@@ -12,6 +12,7 @@
 #include "diff.h"
 #include "revision.h"
 #include "list-objects.h"
+#include "progress.h"
 
 static const char pack_usage[] = "\
 git-pack-objects [{ -q | --progress | --all-progress }] \n\
@@ -62,10 +63,11 @@ static const char *pack_tmp_name, *idx_tmp_name;
 static char tmpname[PATH_MAX];
 static unsigned char pack_file_sha1[20];
 static int progress = 1;
-static volatile sig_atomic_t progress_update;
 static int window = 10;
+static int depth = 50;
 static int pack_to_stdout;
 static int num_preferred_base;
+static struct progress progress_state;
 
 /*
  * The object names in objects array are hashed with this hashtable,
@@ -558,22 +560,25 @@ static off_t write_one(struct sha1file *f,
        return offset + size;
 }
 
+static int open_object_dir_tmp(const char *path)
+{
+    snprintf(tmpname, sizeof(tmpname), "%s/%s", get_object_directory(), path);
+    return mkstemp(tmpname);
+}
+
 static off_t write_pack_file(void)
 {
        uint32_t i;
        struct sha1file *f;
        off_t offset, last_obj_offset = 0;
        struct pack_header hdr;
-       unsigned last_percent = 999;
        int do_progress = progress;
 
        if (pack_to_stdout) {
                f = sha1fd(1, "<stdout>");
                do_progress >>= 1;
        } else {
-               int fd;
-               snprintf(tmpname, sizeof(tmpname), "tmp_pack_XXXXXX");
-               fd = mkstemp(tmpname);
+               int fd = open_object_dir_tmp("tmp_pack_XXXXXX");
                if (fd < 0)
                        die("unable to create %s: %s\n", tmpname, strerror(errno));
                pack_tmp_name = xstrdup(tmpname);
@@ -581,7 +586,7 @@ static off_t write_pack_file(void)
        }
 
        if (do_progress)
-               fprintf(stderr, "Writing %u objects.\n", nr_result);
+               start_progress(&progress_state, "Writing %u objects...", "", nr_result);
 
        hdr.hdr_signature = htonl(PACK_SIGNATURE);
        hdr.hdr_version = htonl(PACK_VERSION);
@@ -593,18 +598,11 @@ static off_t write_pack_file(void)
        for (i = 0; i < nr_objects; i++) {
                last_obj_offset = offset;
                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)
+                       display_progress(&progress_state, written);
        }
        if (do_progress)
-               fputc('\n', stderr);
+               stop_progress(&progress_state);
  done:
        if (written != nr_result)
                die("wrote %u objects while expecting %u", written, nr_result);
@@ -630,10 +628,8 @@ static void write_index_file(off_t last_obj_offset, unsigned char *sha1)
        uint32_t array[256];
        uint32_t i, index_version;
        SHA_CTX ctx;
-       int fd;
 
-       snprintf(tmpname, sizeof(tmpname), "tmp_idx_XXXXXX");
-       fd = mkstemp(tmpname);
+       int fd = open_object_dir_tmp("tmp_idx_XXXXXX");
        if (fd < 0)
                die("unable to create %s: %s\n", tmpname, strerror(errno));
        idx_tmp_name = xstrdup(tmpname);
@@ -865,10 +861,8 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
        else
                object_ix[-1 - ix] = nr_objects;
 
-       if (progress_update) {
-               fprintf(stderr, "Counting objects...%u\r", nr_objects);
-               progress_update = 0;
-       }
+       if (progress)
+               display_progress(&progress_state, nr_objects);
 
        return 1;
 }
@@ -1390,7 +1384,6 @@ static void find_deltas(struct object_entry **list, int window, int depth)
        uint32_t i = nr_objects, idx = 0, processed = 0;
        unsigned int array_size = window * sizeof(struct unpacked);
        struct unpacked *array;
-       unsigned last_percent = 999;
        int max_depth;
 
        if (!nr_objects)
@@ -1398,7 +1391,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
        array = xmalloc(array_size);
        memset(array, 0, array_size);
        if (progress)
-               fprintf(stderr, "Deltifying %u objects.\n", nr_result);
+               start_progress(&progress_state, "Deltifying %u objects...", "", nr_result);
 
        do {
                struct object_entry *entry = list[--i];
@@ -1408,15 +1401,8 @@ static void find_deltas(struct object_entry **list, int window, int depth)
                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 (progress)
+                       display_progress(&progress_state, processed);
 
                if (entry->delta)
                        /* This happens if we decided to reuse existing
@@ -1471,7 +1457,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
        } while (i > 0);
 
        if (progress)
-               fputc('\n', stderr);
+               stop_progress(&progress_state);
 
        for (i = 0; i < window; ++i) {
                free_delta_index(array[i].index);
@@ -1498,34 +1484,16 @@ static void prepare_pack(int window, int depth)
        free(delta_list);
 }
 
-static void progress_interval(int signum)
-{
-       progress_update = 1;
-}
-
-static void setup_progress_signal(void)
-{
-       struct sigaction sa;
-       struct itimerval v;
-
-       memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = progress_interval;
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = SA_RESTART;
-       sigaction(SIGALRM, &sa, NULL);
-
-       v.it_interval.tv_sec = 1;
-       v.it_interval.tv_usec = 0;
-       v.it_value = v.it_interval;
-       setitimer(ITIMER_REAL, &v, NULL);
-}
-
 static int git_pack_config(const char *k, const char *v)
 {
        if(!strcmp(k, "pack.window")) {
                window = git_config_int(k, v);
                return 0;
        }
+       if(!strcmp(k, "pack.depth")) {
+               depth = git_config_int(k, v);
+               return 0;
+       }
        return git_default_config(k, v);
 }
 
@@ -1612,9 +1580,15 @@ static void get_object_list(int ac, const char **av)
        traverse_commit_list(&revs, show_commit, show_object);
 }
 
+static int adjust_perm(const char *path, mode_t mode)
+{
+       if (chmod(path, mode))
+               return -1;
+       return adjust_shared_perm(path);
+}
+
 int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 {
-       int depth = 10;
        int use_internal_rev_list = 0;
        int thin = 0;
        uint32_t i;
@@ -1750,40 +1724,38 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
 
        prepare_packed_git();
 
-       if (progress) {
-               fprintf(stderr, "Generating pack...\n");
-               setup_progress_signal();
-       }
-
+       if (progress)
+               start_progress(&progress_state, "Generating pack...",
+                              "Counting objects: ", 0);
        if (!use_internal_rev_list)
                read_object_list_from_stdin();
        else {
                rp_av[rp_ac] = NULL;
                get_object_list(rp_ac, rp_av);
        }
-
-       if (progress)
+       if (progress) {
+               stop_progress(&progress_state);
                fprintf(stderr, "Done counting %u objects.\n", nr_objects);
+       }
+
        if (non_empty && !nr_result)
                return 0;
        if (progress && (nr_objects != nr_result))
                fprintf(stderr, "Result has %u objects.\n", nr_result);
        if (nr_result)
                prepare_pack(window, depth);
-       if (progress == 1 && 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;
-       }
        last_obj_offset = write_pack_file();
        if (!pack_to_stdout) {
                unsigned char object_list_sha1[20];
+               mode_t mode = umask(0);
+
+               umask(mode);
+               mode = 0444 & ~mode;
+
                write_index_file(last_obj_offset, object_list_sha1);
                snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
                         base_name, sha1_to_hex(object_list_sha1));
-               if (chmod(pack_tmp_name, 0644))
+               if (adjust_perm(pack_tmp_name, mode))
                        die("unable to make temporary pack file readable: %s",
                            strerror(errno));
                if (rename(pack_tmp_name, tmpname))
@@ -1791,7 +1763,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                            strerror(errno));
                snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
                         base_name, sha1_to_hex(object_list_sha1));
-               if (chmod(idx_tmp_name, 0644))
+               if (adjust_perm(idx_tmp_name, mode))
                        die("unable to make temporary index file readable: %s",
                            strerror(errno));
                if (rename(idx_tmp_name, tmpname))