Code

Merge branch 'jk/maint-fetch-ref-hier'
[git.git] / builtin-pack-objects.c
index e20851e1c9c9ad517314794b7c8d4e3615afa9c5..28207d9b3aee9f3e886384871a6632fbaf7eee4f 100644 (file)
@@ -28,7 +28,8 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\
        [--window=N] [--window-memory=N] [--depth=N] \n\
        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
        [--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
-       [--stdout | base-name] [--include-tag] [--keep-unreachable] \n\
+       [--stdout | base-name] [--include-tag] \n\
+       [--keep-unreachable | --unpack-unreachable] \n\
        [<ref-list | <object-list]";
 
 struct object_entry {
@@ -67,7 +68,7 @@ static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
 
 static int non_empty;
 static int reuse_delta = 1, reuse_object = 1;
-static int keep_unreachable, include_tag;
+static int keep_unreachable, unpack_unreachable, include_tag;
 static int local;
 static int incremental;
 static int allow_ofs_delta;
@@ -208,28 +209,6 @@ static int check_pack_inflate(struct packed_git *p,
                stream.total_in == len) ? 0 : -1;
 }
 
-static int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
-                         off_t offset, off_t len, unsigned int nr)
-{
-       const uint32_t *index_crc;
-       uint32_t data_crc = crc32(0, Z_NULL, 0);
-
-       do {
-               unsigned int avail;
-               void *data = use_pack(p, w_curs, offset, &avail);
-               if (avail > len)
-                       avail = len;
-               data_crc = crc32(data_crc, data, avail);
-               offset += avail;
-               len -= avail;
-       } while (len);
-
-       index_crc = p->index_data;
-       index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
-
-       return data_crc != ntohl(*index_crc);
-}
-
 static void copy_pack_data(struct sha1file *f,
                struct packed_git *p,
                struct pack_window **w_curs,
@@ -513,11 +492,14 @@ static void write_pack_file(void)
                 * Did we write the wrong # entries in the header?
                 * If so, rewrite it like in fast-import
                 */
-               if (pack_to_stdout || nr_written == nr_remaining) {
-                       sha1close(f, sha1, 1);
+               if (pack_to_stdout) {
+                       sha1close(f, sha1, CSUM_CLOSE);
+               } else if (nr_written == nr_remaining) {
+                       sha1close(f, sha1, CSUM_FSYNC);
                } else {
                        int fd = sha1close(f, NULL, 0);
                        fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
+                       fsync_or_die(fd, pack_tmp_name);
                        close(fd);
                }
 
@@ -1144,8 +1126,6 @@ static void get_object_details(void)
                sorted_by_offset[i] = objects + i;
        qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 
-       init_pack_revindex();
-
        for (i = 0; i < nr_objects; i++)
                check_object(sorted_by_offset[i]);
 
@@ -1759,7 +1739,7 @@ static void prepare_pack(int window, int depth)
        free(delta_list);
 }
 
-static int git_pack_config(const char *k, const char *v)
+static int git_pack_config(const char *k, const char *v, void *cb)
 {
        if(!strcmp(k, "pack.window")) {
                window = git_config_int(k, v);
@@ -1812,7 +1792,7 @@ static int git_pack_config(const char *k, const char *v)
                pack_size_limit_cfg = git_config_ulong(k, v);
                return 0;
        }
-       return git_default_config(k, v);
+       return git_default_config(k, v, cb);
 }
 
 static void read_object_list_from_stdin(void)
@@ -1946,6 +1926,32 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
        free(in_pack.array);
 }
 
+static void loosen_unused_packed_objects(struct rev_info *revs)
+{
+       struct packed_git *p;
+       uint32_t i;
+       const unsigned char *sha1;
+
+       for (p = packed_git; p; p = p->next) {
+               for (i = 0; i < revs->num_ignore_packed; i++) {
+                       if (matches_pack_name(p, revs->ignore_packed[i]))
+                               break;
+               }
+               if (revs->num_ignore_packed <= i)
+                       continue;
+
+               if (open_pack_index(p))
+                       die("cannot open pack index");
+
+               for (i = 0; i < p->num_objects; i++) {
+                       sha1 = nth_packed_object_sha1(p, i);
+                       if (!locate_object_entry(sha1))
+                               if (force_object_loose(sha1, p->mtime))
+                                       die("unable to force loose object");
+               }
+       }
+}
+
 static void get_object_list(int ac, const char **av)
 {
        struct rev_info revs;
@@ -1980,6 +1986,8 @@ static void get_object_list(int ac, const char **av)
 
        if (keep_unreachable)
                add_objects_in_unpacked_packs(&revs);
+       if (unpack_unreachable)
+               loosen_unused_packed_objects(&revs);
 }
 
 static int adjust_perm(const char *path, mode_t mode)
@@ -2004,7 +2012,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        rp_av[1] = "--objects"; /* --thin will make it --objects-edge */
        rp_ac = 2;
 
-       git_config(git_pack_config);
+       git_config(git_pack_config, NULL);
        if (!pack_compression_seen && core_compression_seen)
                pack_compression_level = core_compression_level;
 
@@ -2114,6 +2122,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
                        keep_unreachable = 1;
                        continue;
                }
+               if (!strcmp("--unpack-unreachable", arg)) {
+                       unpack_unreachable = 1;
+                       continue;
+               }
                if (!strcmp("--include-tag", arg)) {
                        include_tag = 1;
                        continue;
@@ -2179,6 +2191,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
        if (!pack_to_stdout && thin)
                die("--thin cannot be used to build an indexable pack.");
 
+       if (keep_unreachable && unpack_unreachable)
+               die("--keep-unreachable and --unpack-unreachable are incompatible.");
+
 #ifdef THREADED_DELTA_SEARCH
        if (!delta_search_threads)      /* --threads=0 means autodetect */
                delta_search_threads = online_cpus();