t/test-lib.sh: add test_external and test_external_without_stderr
[gitweb.git] / builtin-pack-objects.c
index e20851e1c9c9ad517314794b7c8d4e3615afa9c5..447d492dbbfb578b8903293fa1d2a988eecfefac 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;
@@ -513,11 +514,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);
                }
 
@@ -1759,7 +1763,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 +1816,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 +1950,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 +2010,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 +2036,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 +2146,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 +2215,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();