Merge branch 'po/doc-assume-unchanged'
[gitweb.git] / builtin / repack.c
index bb2314c9cb0ce3e01372c6c3a27396931c0143ab..3f852f35d1e786b2584d435d640ae830a9f34639 100644 (file)
@@ -9,6 +9,8 @@
 #include "argv-array.h"
 
 static int delta_base_offset = 1;
+static int pack_kept_objects = -1;
+static int write_bitmaps;
 static char *packdir, *packtmp;
 
 static const char *const git_repack_usage[] = {
@@ -22,6 +24,15 @@ static int repack_config(const char *var, const char *value, void *cb)
                delta_base_offset = git_config_bool(var, value);
                return 0;
        }
+       if (!strcmp(var, "repack.packkeptobjects")) {
+               pack_kept_objects = git_config_bool(var, value);
+               return 0;
+       }
+       if (!strcmp(var, "repack.writebitmaps") ||
+           !strcmp(var, "pack.writebitmaps")) {
+               write_bitmaps = git_config_bool(var, value);
+               return 0;
+       }
        return git_default_config(var, value, cb);
 }
 
@@ -72,16 +83,15 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list)
        DIR *dir;
        struct dirent *e;
        char *fname;
-       size_t len;
 
        if (!(dir = opendir(packdir)))
                return;
 
        while ((e = readdir(dir)) != NULL) {
-               if (!ends_with(e->d_name, ".pack"))
+               size_t len;
+               if (!strip_suffix(e->d_name, ".pack", &len))
                        continue;
 
-               len = strlen(e->d_name) - strlen(".pack");
                fname = xmemdupz(e->d_name, len);
 
                if (!file_exists(mkpath("%s/%s.keep", packdir, fname)))
@@ -94,7 +104,7 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list)
 
 static void remove_redundant_pack(const char *dir_name, const char *base_name)
 {
-       const char *exts[] = {".pack", ".idx", ".keep"};
+       const char *exts[] = {".pack", ".idx", ".keep", ".bitmap"};
        int i;
        struct strbuf buf = STRBUF_INIT;
        size_t plen;
@@ -115,10 +125,16 @@ static void remove_redundant_pack(const char *dir_name, const char *base_name)
 
 int cmd_repack(int argc, const char **argv, const char *prefix)
 {
-       const char *exts[2] = {".pack", ".idx"};
-       struct child_process cmd;
+       struct {
+               const char *name;
+               unsigned optional:1;
+       } exts[] = {
+               {".pack"},
+               {".idx"},
+               {".bitmap", 1},
+       };
+       struct child_process cmd = CHILD_PROCESS_INIT;
        struct string_list_item *item;
-       struct argv_array cmd_args = ARGV_ARRAY_INIT;
        struct string_list names = STRING_LIST_INIT_DUP;
        struct string_list rollback = STRING_LIST_INIT_NODUP;
        struct string_list existing_packs = STRING_LIST_INIT_DUP;
@@ -155,6 +171,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                OPT__QUIET(&quiet, N_("be quiet")),
                OPT_BOOL('l', "local", &local,
                                N_("pass --local to git-pack-objects")),
+               OPT_BOOL('b', "write-bitmap-index", &write_bitmaps,
+                               N_("write bitmap index")),
                OPT_STRING(0, "unpack-unreachable", &unpack_unreachable, N_("approxidate"),
                                N_("with -A, do not loosen objects older than this")),
                OPT_STRING(0, "window", &window, N_("n"),
@@ -165,6 +183,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                                N_("limits the maximum delta depth")),
                OPT_STRING(0, "max-pack-size", &max_pack_size, N_("bytes"),
                                N_("maximum size of each packfile")),
+               OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
+                               N_("repack objects in packs marked with .keep")),
                OPT_END()
        };
 
@@ -173,58 +193,63 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, builtin_repack_options,
                                git_repack_usage, 0);
 
+       if (pack_kept_objects < 0)
+               pack_kept_objects = write_bitmaps;
+
        packdir = mkpathdup("%s/pack", get_object_directory());
        packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
 
        sigchain_push_common(remove_pack_on_signal);
 
-       argv_array_push(&cmd_args, "pack-objects");
-       argv_array_push(&cmd_args, "--keep-true-parents");
-       argv_array_push(&cmd_args, "--honor-pack-keep");
-       argv_array_push(&cmd_args, "--non-empty");
-       argv_array_push(&cmd_args, "--all");
-       argv_array_push(&cmd_args, "--reflog");
+       argv_array_push(&cmd.args, "pack-objects");
+       argv_array_push(&cmd.args, "--keep-true-parents");
+       if (!pack_kept_objects)
+               argv_array_push(&cmd.args, "--honor-pack-keep");
+       argv_array_push(&cmd.args, "--non-empty");
+       argv_array_push(&cmd.args, "--all");
+       argv_array_push(&cmd.args, "--reflog");
+       argv_array_push(&cmd.args, "--indexed-objects");
        if (window)
-               argv_array_pushf(&cmd_args, "--window=%s", window);
+               argv_array_pushf(&cmd.args, "--window=%s", window);
        if (window_memory)
-               argv_array_pushf(&cmd_args, "--window-memory=%s", window_memory);
+               argv_array_pushf(&cmd.args, "--window-memory=%s", window_memory);
        if (depth)
-               argv_array_pushf(&cmd_args, "--depth=%s", depth);
+               argv_array_pushf(&cmd.args, "--depth=%s", depth);
        if (max_pack_size)
-               argv_array_pushf(&cmd_args, "--max-pack-size=%s", max_pack_size);
+               argv_array_pushf(&cmd.args, "--max-pack-size=%s", max_pack_size);
        if (no_reuse_delta)
-               argv_array_pushf(&cmd_args, "--no-reuse-delta");
+               argv_array_pushf(&cmd.args, "--no-reuse-delta");
        if (no_reuse_object)
-               argv_array_pushf(&cmd_args, "--no-reuse-object");
+               argv_array_pushf(&cmd.args, "--no-reuse-object");
+       if (write_bitmaps)
+               argv_array_push(&cmd.args, "--write-bitmap-index");
 
        if (pack_everything & ALL_INTO_ONE) {
                get_non_kept_pack_filenames(&existing_packs);
 
                if (existing_packs.nr && delete_redundant) {
                        if (unpack_unreachable)
-                               argv_array_pushf(&cmd_args,
+                               argv_array_pushf(&cmd.args,
                                                "--unpack-unreachable=%s",
                                                unpack_unreachable);
                        else if (pack_everything & LOOSEN_UNREACHABLE)
-                               argv_array_push(&cmd_args,
+                               argv_array_push(&cmd.args,
                                                "--unpack-unreachable");
                }
        } else {
-               argv_array_push(&cmd_args, "--unpacked");
-               argv_array_push(&cmd_args, "--incremental");
+               argv_array_push(&cmd.args, "--unpacked");
+               argv_array_push(&cmd.args, "--incremental");
        }
 
        if (local)
-               argv_array_push(&cmd_args,  "--local");
+               argv_array_push(&cmd.args,  "--local");
        if (quiet)
-               argv_array_push(&cmd_args,  "--quiet");
+               argv_array_push(&cmd.args,  "--quiet");
        if (delta_base_offset)
-               argv_array_push(&cmd_args,  "--delta-base-offset");
+               argv_array_push(&cmd.args,  "--delta-base-offset");
 
-       argv_array_push(&cmd_args, packtmp);
+       argv_array_push(&cmd.args, packtmp);
 
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.argv = cmd_args.argv;
        cmd.git_cmd = 1;
        cmd.out = -1;
        cmd.no_stdin = 1;
@@ -243,7 +268,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        ret = finish_command(&cmd);
        if (ret)
                return ret;
-       argv_array_clear(&cmd_args);
 
        if (!names.nr && !quiet)
                printf("Nothing new to pack.\n");
@@ -256,17 +280,17 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
         */
        failed = 0;
        for_each_string_list_item(item, &names) {
-               for (ext = 0; ext < 2; ext++) {
+               for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
                        char *fname, *fname_old;
                        fname = mkpathdup("%s/pack-%s%s", packdir,
-                                               item->string, exts[ext]);
+                                               item->string, exts[ext].name);
                        if (!file_exists(fname)) {
                                free(fname);
                                continue;
                        }
 
                        fname_old = mkpath("%s/old-%s%s", packdir,
-                                               item->string, exts[ext]);
+                                               item->string, exts[ext].name);
                        if (file_exists(fname_old))
                                if (unlink(fname_old))
                                        failed = 1;
@@ -313,19 +337,23 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        /* Now the ones with the same name are out of the way... */
        for_each_string_list_item(item, &names) {
-               for (ext = 0; ext < 2; ext++) {
+               for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
                        char *fname, *fname_old;
                        struct stat statbuffer;
+                       int exists = 0;
                        fname = mkpathdup("%s/pack-%s%s",
-                                       packdir, item->string, exts[ext]);
+                                       packdir, item->string, exts[ext].name);
                        fname_old = mkpathdup("%s-%s%s",
-                                       packtmp, item->string, exts[ext]);
+                                       packtmp, item->string, exts[ext].name);
                        if (!stat(fname_old, &statbuffer)) {
                                statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
                                chmod(fname_old, statbuffer.st_mode);
+                               exists = 1;
+                       }
+                       if (exists || !exts[ext].optional) {
+                               if (rename(fname_old, fname))
+                                       die_errno(_("renaming '%s' failed"), fname_old);
                        }
-                       if (rename(fname_old, fname))
-                               die_errno(_("renaming '%s' failed"), fname_old);
                        free(fname);
                        free(fname_old);
                }
@@ -333,12 +361,12 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        /* Remove the "old-" files */
        for_each_string_list_item(item, &names) {
-               for (ext = 0; ext < 2; ext++) {
+               for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
                        char *fname;
                        fname = mkpath("%s/old-%s%s",
                                        packdir,
                                        item->string,
-                                       exts[ext]);
+                                       exts[ext].name);
                        if (remove_path(fname))
                                warning(_("removing '%s' failed"), fname);
                }
@@ -347,7 +375,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
        /* End of pack replacement. */
 
        if (delete_redundant) {
-               sort_string_list(&names);
+               int opts = 0;
+               string_list_sort(&names);
                for_each_string_list_item(item, &existing_packs) {
                        char *sha1;
                        size_t len = strlen(item->string);
@@ -357,25 +386,13 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                        if (!string_list_has_string(&names, sha1))
                                remove_redundant_pack(packdir, item->string);
                }
-               argv_array_push(&cmd_args, "prune-packed");
-               if (quiet)
-                       argv_array_push(&cmd_args, "--quiet");
-
-               memset(&cmd, 0, sizeof(cmd));
-               cmd.argv = cmd_args.argv;
-               cmd.git_cmd = 1;
-               run_command(&cmd);
-               argv_array_clear(&cmd_args);
+               if (!quiet && isatty(2))
+                       opts |= PRUNE_PACKED_VERBOSE;
+               prune_packed_objects(opts);
        }
 
-       if (!no_update_server_info) {
-               argv_array_push(&cmd_args, "update-server-info");
-               memset(&cmd, 0, sizeof(cmd));
-               cmd.argv = cmd_args.argv;
-               cmd.git_cmd = 1;
-               run_command(&cmd);
-               argv_array_clear(&cmd_args);
-       }
+       if (!no_update_server_info)
+               update_server_info(0);
        remove_temporary_files();
        string_list_clear(&names, 0);
        string_list_clear(&rollback, 0);