We allow to keep existing packs by having companion .keep files. This is helpful when a pack is permanently kept. In the next patch, git-gc just wants to keep a pack temporarily, for one pack-objects run. git-gc can use --keep-pack for this use case. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- Documentation/git-pack-objects.txt | 4 ++++ Documentation/git-repack.txt | 4 ++++ builtin/pack-objects.c | 31 ++++++++++++++++++++++++++++++ builtin/repack.c | 23 +++++++++++++++++++--- t/t7700-repack.sh | 19 ++++++++++++++++++ 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 81bc490ac5..1975477160 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -126,6 +126,10 @@ base-name:: has a .keep file to be ignored, even if it would have otherwise been packed. +--keep-pack=<pack name>:: + Ignore the given pack. This is the equivalent of having + `.keep` file on the pack. Implies `--honor-pack-keep`. + --incremental:: This flag causes an object already in a pack to be ignored even if it would have otherwise been packed. diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index ae750e9e11..12b073e115 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -133,6 +133,10 @@ other objects in that pack they already have locally. with `-b` or `repack.writeBitmaps`, as it ensures that the bitmapped packfile has the necessary objects. +--keep-pack=<pack name>:: + Exclude the given pack from repacking. This is the equivalent + of having `.keep` file on the pack. Implies `--pack-kept-objects`. + --unpack-unreachable=<when>:: When loosening unreachable objects, do not bother loosening any objects older than `<when>`. This can be used to optimize out diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 5c674b2843..8e3f870d71 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -28,6 +28,7 @@ #include "argv-array.h" #include "list.h" #include "packfile.h" +#include "dir.h" static const char *pack_usage[] = { N_("git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"), @@ -2917,6 +2918,32 @@ static void get_object_list(int ac, const char **av) oid_array_clear(&recent_objects); } +static void add_extra_kept_packs(const struct string_list *names) +{ + struct packed_git *p; + + if (!names->nr) + return; + + prepare_packed_git(); + for (p = packed_git; p; p = p->next) { + const char *name = basename(p->pack_name); + int i; + + if (!p->pack_local) + continue; + + for (i = 0; i < names->nr; i++) { + if (fspathcmp(name, names->items[i].string)) + continue; + + p->pack_keep = 1; + ignore_packed_keep = 1; + break; + } + } +} + static int option_parse_index_version(const struct option *opt, const char *arg, int unset) { @@ -2956,6 +2983,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) struct argv_array rp = ARGV_ARRAY_INIT; int rev_list_unpacked = 0, rev_list_all = 0, rev_list_reflog = 0; int rev_list_index = 0; + struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; struct option pack_objects_options[] = { OPT_SET_INT('q', "quiet", &progress, N_("do not show progress meter"), 0), @@ -3022,6 +3050,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) N_("create packs suitable for shallow fetches")), OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep, N_("ignore packs that have companion .keep file")), + OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"), + N_("ignore this pack")), OPT_INTEGER(0, "compression", &pack_compression_level, N_("pack compression level")), OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents, @@ -3150,6 +3180,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) progress = 2; prepare_packed_git(); + add_extra_kept_packs(&keep_pack_list); if (ignore_packed_keep) { struct packed_git *p; for (p = packed_git; p; p = p->next) diff --git a/builtin/repack.c b/builtin/repack.c index 7bdb40142f..6a1dade0e1 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -86,7 +86,8 @@ static void remove_pack_on_signal(int signo) * have a corresponding .keep or .promisor file. These packs are not to * be kept if we are going to pack everything into one file. */ -static void get_non_kept_pack_filenames(struct string_list *fname_list) +static void get_non_kept_pack_filenames(struct string_list *fname_list, + const struct string_list *extra_keep) { DIR *dir; struct dirent *e; @@ -97,6 +98,14 @@ static void get_non_kept_pack_filenames(struct string_list *fname_list) while ((e = readdir(dir)) != NULL) { size_t len; + int i; + + for (i = 0;i < extra_keep->nr; i++) + if (!fspathcmp(e->d_name, extra_keep->items[i].string)) + break; + if (extra_keep->nr > 0 && i < extra_keep->nr) + continue; + if (!strip_suffix(e->d_name, ".pack", &len)) continue; @@ -148,7 +157,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) struct string_list rollback = STRING_LIST_INIT_NODUP; struct string_list existing_packs = STRING_LIST_INIT_DUP; struct strbuf line = STRBUF_INIT; - int ext, ret, failed; + int i, ext, ret, failed; FILE *out; /* variables to be filled by option parsing */ @@ -160,6 +169,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) const char *depth = NULL; const char *threads = NULL; const char *max_pack_size = NULL; + struct string_list keep_pack_list = STRING_LIST_INIT_NODUP; int no_reuse_delta = 0, no_reuse_object = 0; int no_update_server_info = 0; int quiet = 0; @@ -200,6 +210,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix) N_("maximum size of each packfile")), OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects, N_("repack objects in packs marked with .keep")), + OPT_STRING_LIST(0, "keep-pack", &keep_pack_list, N_("name"), + N_("do not repack this pack")), OPT_END() }; @@ -215,6 +227,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix) (unpack_unreachable || (pack_everything & LOOSEN_UNREACHABLE))) die(_("--keep-unreachable and -A are incompatible")); + if (keep_pack_list.nr && pack_kept_objects > 0) + die(_("incompatible --keep-pack and --pack-kept-objects")); if (pack_kept_objects < 0) pack_kept_objects = write_bitmaps; @@ -230,6 +244,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argv_array_push(&cmd.args, "--keep-true-parents"); if (!pack_kept_objects) argv_array_push(&cmd.args, "--honor-pack-keep"); + for (i = 0; i < keep_pack_list.nr; i++) + argv_array_pushf(&cmd.args, "--keep-pack=%s", + keep_pack_list.items[i].string); argv_array_push(&cmd.args, "--non-empty"); argv_array_push(&cmd.args, "--all"); argv_array_push(&cmd.args, "--reflog"); @@ -254,7 +271,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argv_array_push(&cmd.args, "--write-bitmap-index"); if (pack_everything & ALL_INTO_ONE) { - get_non_kept_pack_filenames(&existing_packs); + get_non_kept_pack_filenames(&existing_packs, &keep_pack_list); if (existing_packs.nr && delete_redundant) { if (unpack_unreachable) { diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 38247afbec..553d907d34 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -196,5 +196,24 @@ test_expect_success 'objects made unreachable by grafts only are kept' ' git cat-file -t $H1 ' +test_expect_success 'repack --keep-pack' ' + test_create_repo keep-pack && + ( + cd keep-pack && + for cmit in one two three four; do + test_commit $cmit && + git repack -d + done && + ( cd .git/objects/pack && ls *.pack ) >pack-list && + test_line_count = 4 pack-list && + KEEP1=`head -n1 pack-list` && + KEEP4=`tail -n1 pack-list` && + git repack -a -d --keep-pack $KEEP1 --keep-pack $KEEP4 && + ls .git/objects/pack/*.pack >new-counts && + test_line_count = 3 new-counts && + git fsck + ) +' + test_done -- 2.16.2.784.gb291bd247e