pack-objects learns a few more options to take over what's been done by git-repack.sh. cmd_repack() becomes a wrapper around cmd_pack_objects(). Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- Makefile | 2 +- builtin.h | 1 + builtin/pack-objects.c | 297 +++++++++++++++++++++++++++++++++++++++- contrib/examples/git-repack.sh | 186 +++++++++++++++++++++++++ git-repack.sh | 186 ------------------------- git.c | 1 + 6 files changed, 483 insertions(+), 190 deletions(-) create mode 100755 contrib/examples/git-repack.sh delete mode 100755 git-repack.sh diff --git a/Makefile b/Makefile index 17404c4..164052d 100644 --- a/Makefile +++ b/Makefile @@ -374,7 +374,6 @@ SCRIPT_SH += git-mergetool.sh SCRIPT_SH += git-pull.sh SCRIPT_SH += git-quiltimport.sh SCRIPT_SH += git-rebase.sh -SCRIPT_SH += git-repack.sh SCRIPT_SH += git-request-pull.sh SCRIPT_SH += git-stash.sh SCRIPT_SH += git-submodule.sh @@ -460,6 +459,7 @@ BUILT_INS += git-init$X BUILT_INS += git-merge-subtree$X BUILT_INS += git-peek-remote$X BUILT_INS += git-repo-config$X +BUILT_INS += git-repack$X BUILT_INS += git-show$X BUILT_INS += git-stage$X BUILT_INS += git-status$X diff --git a/builtin.h b/builtin.h index 0a5b511..2a890ce 100644 --- a/builtin.h +++ b/builtin.h @@ -115,6 +115,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix); extern int cmd_remote(int argc, const char **argv, const char *prefix); extern int cmd_remote_ext(int argc, const char **argv, const char *prefix); extern int cmd_remote_fd(int argc, const char **argv, const char *prefix); +extern int cmd_repack(int argc, const char **argv, const char *prefix); extern int cmd_repo_config(int argc, const char **argv, const char *prefix); extern int cmd_rerere(int argc, const char **argv, const char *prefix); extern int cmd_reset(int argc, const char **argv, const char *prefix); diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index c1ca748..7acec4c 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -17,10 +17,17 @@ #include "progress.h" #include "refs.h" #include "thread-utils.h" +#include "sigchain.h" static const char *pack_usage[] = { "git pack-objects --stdout [options...] [< ref-list | < object-list]", "git pack-objects [options...] base-name [< ref-list | < object-list]", + "git pack-objects --repack [options...]", + NULL +}; + +static char const * const repack_usage[] = { + "git repack [options]", NULL }; @@ -101,6 +108,15 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1); static uint32_t written, written_delta; static uint32_t reused, reused_delta; +#define REPACK_IN_PROGRESS (1 << 0) +#define REPACK_UPDATE_INFO (1 << 1) +#define REPACK_ALL_INTO_ONE (1 << 2) +#define REPACK_REMOVE_REDUNDANT (1 << 3) + +static int repack_flags, nr_written_packs; +static int repack_usedeltabaseoffset; +static struct string_list written_packs; +static struct string_list backup_files; static void *get_delta(struct object_entry *entry) { @@ -561,6 +577,19 @@ static struct object_entry **compute_write_order(void) return wo; } +static void backup_file(const char *path) +{ + struct stat st; + if (repack_flags & REPACK_IN_PROGRESS && + !stat(path, &st)) { + struct strbuf old = STRBUF_INIT; + strbuf_addf(&old, "%s.old", path); + if (rename(path, old.buf)) + die_errno("unable to rename pack %s", path); + string_list_append(&backup_files, strbuf_detach(&old, NULL)); + } +} + static void write_pack_file(void) { uint32_t i = 0, j; @@ -632,6 +661,7 @@ static void write_pack_file(void) free_pack_by_name(tmpname); if (adjust_shared_perm(pack_tmp_name)) die_errno("unable to make temporary pack file readable"); + backup_file(tmpname); if (rename(pack_tmp_name, tmpname)) die_errno("unable to rename temporary pack file"); @@ -660,12 +690,22 @@ static void write_pack_file(void) base_name, sha1_to_hex(sha1)); if (adjust_shared_perm(idx_tmp_name)) die_errno("unable to make temporary index file readable"); + backup_file(tmpname); if (rename(idx_tmp_name, tmpname)) die_errno("unable to rename temporary index file"); free((void *) idx_tmp_name); free(pack_tmp_name); - puts(sha1_to_hex(sha1)); + if (repack_flags & REPACK_IN_PROGRESS) { + int len = strlen(tmpname); + char *s = xmalloc(len + 2); + memcpy(s, tmpname, len - 4); + memcpy(s + len - 4, ".pack", 6); + string_list_append(&written_packs, s); + nr_written_packs++; + } + else + puts(sha1_to_hex(sha1)); } /* mark written objects as written to previous pack */ @@ -2222,7 +2262,8 @@ static void get_object_list(int ac, const char **av) save_commit_buffer = 0; setup_revisions(ac, av, &revs, NULL); - while (fgets(line, sizeof(line), stdin) != NULL) { + while (!(repack_flags & REPACK_IN_PROGRESS) && + fgets(line, sizeof(line), stdin) != NULL) { int len = strlen(line); if (len && line[len - 1] == '\n') line[--len] = 0; @@ -2250,6 +2291,31 @@ static void get_object_list(int ac, const char **av) loosen_unused_packed_objects(&revs); } +static void rollback_repack(void) +{ + struct strbuf dst = STRBUF_INIT; + int i, ret; + for (i = 0; i < backup_files.nr; i++) { + const char *src = backup_files.items[i].string; + strbuf_addstr(&dst, src); + strbuf_setlen(&dst, dst.len - 4); /* remove .old */ + ret = rename(src, dst.buf); + if (ret) + warning("failed to restore %s: %s", src, strerror(errno)); + strbuf_setlen(&dst, 0); + } + strbuf_release(&dst); + string_list_clear(&backup_files, 0); +} + +static void rollback_repack_on_signal(int signo) +{ + rollback_repack(); + sigchain_pop(signo); + raise(signo); +} + + static int option_parse_index_version(const struct option *opt, const char *arg, int unset) { @@ -2267,12 +2333,14 @@ static int option_parse_index_version(const struct option *opt, int cmd_pack_objects(int argc, const char **argv, const char *prefix) { + struct strbuf repack_base_name = STRBUF_INIT; int use_internal_rev_list = 0; int thin = 0; int all_progress_implied = 0; const char **rp_av; int rp_ac_alloc = 64; int rp_ac; + int i; struct option pack_objects_options[] = { OPT_SET_INT('q', NULL, &progress, "do not show progress meter", 0), @@ -2328,6 +2396,16 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) "pack compression level"), OPT_SET_INT(0, "keep-true-parents", &grafts_replace_parents, "do not hide commits by grafts", 0), + + OPT_BIT(0, "repack", &repack_flags, + "repack mode", REPACK_IN_PROGRESS), + OPT_BIT(0, "repack-all", &repack_flags, + "repack everything into one pack", REPACK_ALL_INTO_ONE), + OPT_BIT(0, "remove-redundant", &repack_flags, + "remove redundant objects after repack", REPACK_REMOVE_REDUNDANT), + OPT_BIT(0, "update-info", &repack_flags, + "run git-update-server-info after repack", REPACK_UPDATE_INFO), + OPT_END(), }; @@ -2374,6 +2452,39 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) if (delta_search_threads != 1) warning("no threads support, ignoring %s", arg); #endif + if ((repack_flags & REPACK_IN_PROGRESS) == 0 && + (repack_flags & ~REPACK_IN_PROGRESS)) + die("--repack must be given for any repack related options"); + if (repack_flags & REPACK_IN_PROGRESS) { + if (pack_to_stdout) + die("--stdout cannot be used with --repack"); + if (argc) + die("base name cannot be used with --repack"); + + if (rp_ac + 2 >= rp_ac_alloc) { + rp_ac_alloc = alloc_nr(rp_ac_alloc); + rp_av = xrealloc(rp_av, rp_ac_alloc * sizeof(*rp_av)); + } + rp_av[rp_ac++] = "--all"; + rp_av[rp_ac++] = "--reflog"; + use_internal_rev_list = 1; + + grafts_replace_parents = 0; /* --keep-true-parents */ + ignore_packed_keep = 1; /* --honor-pack-keep */ + non_empty = 1; /* --non-empty */ + + if (!(repack_flags & REPACK_ALL_INTO_ONE)) { + incremental = 1; /* --incremental */ + rp_av[rp_ac++] = "--unpacked"; + } + + strbuf_addf(&repack_base_name, + "%s/pack/pack", get_object_directory()); + base_name = repack_base_name.buf; + + sigchain_push_common(rollback_repack_on_signal); + atexit(rollback_repack); + } /* Traditionally "pack-objects [options] base extra" failed; * we would however want to take refs parameter that would @@ -2388,7 +2499,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) * walker. */ - if (!pack_to_stdout) { + else if (!pack_to_stdout) { if (!argc) die("base name required if --stdout is not given"); base_name = argv[0]; @@ -2439,5 +2550,185 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32")," " reused %"PRIu32" (delta %"PRIu32")\n", written, written_delta, reused, reused_delta); + + if (!(repack_flags & REPACK_IN_PROGRESS)) + return 0; + + if (!nr_written_packs) { + printf(_("Nothing new to pack.\n")); + return 0; + } + + /* At this point all new packs should be in place. We can + safely remove old ones */ + for (i = 0; i < backup_files.nr; i++) { + const char *s = backup_files.items[i].string; + int ret = unlink(s); + if (ret) + warning("failed to remove %s: %s", s, strerror(errno)); + } + string_list_clear(&backup_files, 0); + + if (repack_flags & REPACK_REMOVE_REDUNDANT) { + struct packed_git *p; + struct string_list to_be_removed = STRING_LIST_INIT_DUP; + + /* free_pack_by_name() may have freed a few packs in + write_pack_file() */ + reprepare_packed_git(); + for (p = packed_git; p; p = p->next) { + if (!p->pack_local || p->pack_keep) + continue; + + for (i = 0; i < written_packs.nr; i++) { + char *s = written_packs.items[i].string; + if (!strcmp(s, p->pack_name)) + break; + } + if (i < written_packs.nr) + continue; + + string_list_append(&to_be_removed, p->pack_name); + } + written_packs.strdup_strings = 1; + string_list_clear(&written_packs, 0); + + for (i = 0; i < to_be_removed.nr; i++) { + char *path = to_be_removed.items[i].string; + + /* Windows limitation on unlink(). + See c74faea19e39ca933492f697596310397175c329 */ + free_pack_by_name(path); + + if (unlink(path)) + warning("failed to remove %s: %s", path, strerror(errno)); + strcpy(path + strlen(path)-5, ".idx"); + if (unlink(path)) + warning("failed to remove %s: %s", path, strerror(errno)); + } + string_list_clear(&to_be_removed, 0); + + reprepare_packed_git(); + prune_packed_objects(0); + } + + if (repack_flags & REPACK_UPDATE_INFO) + update_server_info(0); + return 0; } + +static int repack_config(const char *k, const char *v, void *cb) +{ + if (!strcasecmp(k, "repack.usedeltabaseoffset")) { + repack_usedeltabaseoffset = git_config_bool(k, v); + return 0; + } + return git_default_config(k, v, cb); +} + +int cmd_repack(int argc, const char **argv, const char *prefix) +{ + int all_in_one = 0; + int all_in_one_and_unreachable = 0; + int unpack_unreachable = 0; + int remove_redundant = 0; + int no_reuse_delta = 0; + int no_reuse_object = 0; + int no_update = 0; + int quiet = 0; + int local = 0; + + struct option opts[] = { + OPT_BOOL('a', NULL, &all_in_one, + "pack everything in a single pack"), + OPT_BOOL('A', NULL, &all_in_one_and_unreachable, + "same as -a, and turn unreachable objects loose"), + OPT_BOOL('d', NULL, &remove_redundant, + "remove redundant packs, and run git-prune-packed"), + OPT_BOOL('f', NULL, &no_reuse_delta, + "pass --no-reuse-delta to git-pack-objects"), + OPT_BOOL('F', NULL, &no_reuse_object, + "pass --no-reuse-object to git-pack-objects"), + OPT_BOOL('n', NULL, &no_update, + "do not run git-update-server-info"), + OPT_BOOL('q', NULL, &quiet, "be quiet"), + OPT_BOOL('l', NULL, &local, + "pass --local to git-pack-objects"), + { OPTION_ARGUMENT, 0, "window", NULL, "n", + "size of the window used for delta compression", 0 }, + { OPTION_ARGUMENT, 0, "window-memory", NULL, "n", + "same as the above, but limit memory size instead of entries count", 0 }, + { OPTION_ARGUMENT, 0, "depth", NULL, "n", + "limits the maximum delta depth", 0 }, + { OPTION_ARGUMENT, 0, "max-pack-size", NULL, "n", + "maximum size of each packfile", 0}, + OPT_END(), + }; + + const char *av[] = { "pack-objects", "--repack", + NULL, /* --[no-]update-info */ + NULL, /* --delta-base-offset */ + NULL, /* --repack-all */ + NULL, /* --remove-redundant */ + NULL, /* --no-reuse-delta */ + NULL, /* --no-reuse-object */ + NULL, /* --local */ + NULL, /* -q */ + NULL, /* --unpack-unreachable */ + NULL, /* --window */ + NULL, /* --window-memory */ + NULL, /* --depth */ + NULL, /* --max-pack-size */ + NULL + }; + int ac = 2; + + git_config(repack_config, NULL); + + argc = parse_options(argc, argv, prefix, opts, repack_usage, 0); + + if (no_update) + av[ac++] = "--no-update-info"; + else + av[ac++] = "--update-info"; + if (repack_usedeltabaseoffset) + av[ac++] = "--delta-base-offset"; + if (all_in_one_and_unreachable) { + av[ac++] = "--repack-all"; + all_in_one = 1; + unpack_unreachable = 1; + } + if (all_in_one) + av[ac++] = "--repack-all"; + if (remove_redundant) + av[ac++] = "--remove-redundant"; + if (no_reuse_delta) + av[ac++] = "--no-reuse-delta"; + if (no_reuse_object) + av[ac++] = "--no-reuse-object"; + if (local) + av[ac++] = "--local"; + if (quiet) + av[ac++] = "-q"; + if ((ac + argc) * sizeof(*av) > sizeof(av)) + die("Too many options"); + memcpy(av + ac, argv, argc * sizeof(*argv)); + ac += argc; + + if (all_in_one && remove_redundant) { + struct packed_git *p; + + prepare_packed_git(); + for (p = packed_git; p; p = p->next) { + if (!p->pack_keep && + unpack_unreachable && remove_redundant) { + av[ac++] = "--unpack-unreachable"; + break; + } + } + } + + trace_argv_printf(av, "trace: built-in: git"); + return cmd_pack_objects(ac, av, prefix); +} diff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh new file mode 100755 index 0000000..624feec --- /dev/null +++ b/contrib/examples/git-repack.sh @@ -0,0 +1,186 @@ +#!/bin/sh +# +# Copyright (c) 2005 Linus Torvalds +# + +OPTIONS_KEEPDASHDASH= +OPTIONS_SPEC="\ +git repack [options] +-- +a pack everything in a single pack +A same as -a, and turn unreachable objects loose +d remove redundant packs, and run git-prune-packed +f pass --no-reuse-delta to git-pack-objects +F pass --no-reuse-object to git-pack-objects +n do not run git-update-server-info +q,quiet be quiet +l pass --local to git-pack-objects + Packing constraints +window= size of the window used for delta compression +window-memory= same as the above, but limit memory size instead of entries count +depth= limits the maximum delta depth +max-pack-size= maximum size of each packfile +" +SUBDIRECTORY_OK='Yes' +. git-sh-setup + +no_update_info= all_into_one= remove_redundant= unpack_unreachable= +local= no_reuse= extra= +while test $# != 0 +do + case "$1" in + -n) no_update_info=t ;; + -a) all_into_one=t ;; + -A) all_into_one=t + unpack_unreachable=--unpack-unreachable ;; + -d) remove_redundant=t ;; + -q) GIT_QUIET=t ;; + -f) no_reuse=--no-reuse-delta ;; + -F) no_reuse=--no-reuse-object ;; + -l) local=--local ;; + --max-pack-size|--window|--window-memory|--depth) + extra="$extra $1=$2"; shift ;; + --) shift; break;; + *) usage ;; + esac + shift +done + +case "`git config --bool repack.usedeltabaseoffset || echo true`" in +true) + extra="$extra --delta-base-offset" ;; +esac + +PACKDIR="$GIT_OBJECT_DIRECTORY/pack" +PACKTMP="$PACKDIR/.tmp-$$-pack" +rm -f "$PACKTMP"-* +trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15 + +# There will be more repacking strategies to come... +case ",$all_into_one," in +,,) + args='--unpacked --incremental' + ;; +,t,) + args= existing= + if [ -d "$PACKDIR" ]; then + for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \ + | sed -e 's/^\.\///' -e 's/\.pack$//'` + do + if [ -e "$PACKDIR/$e.keep" ]; then + : keep + else + existing="$existing $e" + fi + done + if test -n "$existing" -a -n "$unpack_unreachable" -a \ + -n "$remove_redundant" + then + args="$args $unpack_unreachable" + fi + fi + ;; +esac + +mkdir -p "$PACKDIR" || exit + +args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra" +names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") || + exit 1 +if [ -z "$names" ]; then + say Nothing new to pack. +fi + +# Ok we have prepared all new packfiles. + +# First see if there are packs of the same name and if so +# if we can move them out of the way (this can happen if we +# repacked immediately after packing fully. +rollback= +failed= +for name in $names +do + for sfx in pack idx + do + file=pack-$name.$sfx + test -f "$PACKDIR/$file" || continue + rm -f "$PACKDIR/old-$file" && + mv "$PACKDIR/$file" "$PACKDIR/old-$file" || { + failed=t + break + } + rollback="$rollback $file" + done + test -z "$failed" || break +done + +# If renaming failed for any of them, roll the ones we have +# already renamed back to their original names. +if test -n "$failed" +then + rollback_failure= + for file in $rollback + do + mv "$PACKDIR/old-$file" "$PACKDIR/$file" || + rollback_failure="$rollback_failure $file" + done + if test -n "$rollback_failure" + then + echo >&2 "WARNING: Some packs in use have been renamed by" + echo >&2 "WARNING: prefixing old- to their name, in order to" + echo >&2 "WARNING: replace them with the new version of the" + echo >&2 "WARNING: file. But the operation failed, and" + echo >&2 "WARNING: attempt to rename them back to their" + echo >&2 "WARNING: original names also failed." + echo >&2 "WARNING: Please rename them in $PACKDIR manually:" + for file in $rollback_failure + do + echo >&2 "WARNING: old-$file -> $file" + done + fi + exit 1 +fi + +# Now the ones with the same name are out of the way... +fullbases= +for name in $names +do + fullbases="$fullbases pack-$name" + chmod a-w "$PACKTMP-$name.pack" + chmod a-w "$PACKTMP-$name.idx" + mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" && + mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" || + exit +done + +# Remove the "old-" files +for name in $names +do + rm -f "$PACKDIR/old-pack-$name.idx" + rm -f "$PACKDIR/old-pack-$name.pack" +done + +# End of pack replacement. + +if test "$remove_redundant" = t +then + # We know $existing are all redundant. + if [ -n "$existing" ] + then + ( cd "$PACKDIR" && + for e in $existing + do + case " $fullbases " in + *" $e "*) ;; + *) rm -f "$e.pack" "$e.idx" "$e.keep" ;; + esac + done + ) + fi + git prune-packed ${GIT_QUIET:+-q} +fi + +case "$no_update_info" in +t) : ;; +*) git update-server-info ;; +esac diff --git a/git-repack.sh b/git-repack.sh deleted file mode 100755 index 624feec..0000000 --- a/git-repack.sh +++ /dev/null @@ -1,186 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Linus Torvalds -# - -OPTIONS_KEEPDASHDASH= -OPTIONS_SPEC="\ -git repack [options] --- -a pack everything in a single pack -A same as -a, and turn unreachable objects loose -d remove redundant packs, and run git-prune-packed -f pass --no-reuse-delta to git-pack-objects -F pass --no-reuse-object to git-pack-objects -n do not run git-update-server-info -q,quiet be quiet -l pass --local to git-pack-objects - Packing constraints -window= size of the window used for delta compression -window-memory= same as the above, but limit memory size instead of entries count -depth= limits the maximum delta depth -max-pack-size= maximum size of each packfile -" -SUBDIRECTORY_OK='Yes' -. git-sh-setup - -no_update_info= all_into_one= remove_redundant= unpack_unreachable= -local= no_reuse= extra= -while test $# != 0 -do - case "$1" in - -n) no_update_info=t ;; - -a) all_into_one=t ;; - -A) all_into_one=t - unpack_unreachable=--unpack-unreachable ;; - -d) remove_redundant=t ;; - -q) GIT_QUIET=t ;; - -f) no_reuse=--no-reuse-delta ;; - -F) no_reuse=--no-reuse-object ;; - -l) local=--local ;; - --max-pack-size|--window|--window-memory|--depth) - extra="$extra $1=$2"; shift ;; - --) shift; break;; - *) usage ;; - esac - shift -done - -case "`git config --bool repack.usedeltabaseoffset || echo true`" in -true) - extra="$extra --delta-base-offset" ;; -esac - -PACKDIR="$GIT_OBJECT_DIRECTORY/pack" -PACKTMP="$PACKDIR/.tmp-$$-pack" -rm -f "$PACKTMP"-* -trap 'rm -f "$PACKTMP"-*' 0 1 2 3 15 - -# There will be more repacking strategies to come... -case ",$all_into_one," in -,,) - args='--unpacked --incremental' - ;; -,t,) - args= existing= - if [ -d "$PACKDIR" ]; then - for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \ - | sed -e 's/^\.\///' -e 's/\.pack$//'` - do - if [ -e "$PACKDIR/$e.keep" ]; then - : keep - else - existing="$existing $e" - fi - done - if test -n "$existing" -a -n "$unpack_unreachable" -a \ - -n "$remove_redundant" - then - args="$args $unpack_unreachable" - fi - fi - ;; -esac - -mkdir -p "$PACKDIR" || exit - -args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra" -names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") || - exit 1 -if [ -z "$names" ]; then - say Nothing new to pack. -fi - -# Ok we have prepared all new packfiles. - -# First see if there are packs of the same name and if so -# if we can move them out of the way (this can happen if we -# repacked immediately after packing fully. -rollback= -failed= -for name in $names -do - for sfx in pack idx - do - file=pack-$name.$sfx - test -f "$PACKDIR/$file" || continue - rm -f "$PACKDIR/old-$file" && - mv "$PACKDIR/$file" "$PACKDIR/old-$file" || { - failed=t - break - } - rollback="$rollback $file" - done - test -z "$failed" || break -done - -# If renaming failed for any of them, roll the ones we have -# already renamed back to their original names. -if test -n "$failed" -then - rollback_failure= - for file in $rollback - do - mv "$PACKDIR/old-$file" "$PACKDIR/$file" || - rollback_failure="$rollback_failure $file" - done - if test -n "$rollback_failure" - then - echo >&2 "WARNING: Some packs in use have been renamed by" - echo >&2 "WARNING: prefixing old- to their name, in order to" - echo >&2 "WARNING: replace them with the new version of the" - echo >&2 "WARNING: file. But the operation failed, and" - echo >&2 "WARNING: attempt to rename them back to their" - echo >&2 "WARNING: original names also failed." - echo >&2 "WARNING: Please rename them in $PACKDIR manually:" - for file in $rollback_failure - do - echo >&2 "WARNING: old-$file -> $file" - done - fi - exit 1 -fi - -# Now the ones with the same name are out of the way... -fullbases= -for name in $names -do - fullbases="$fullbases pack-$name" - chmod a-w "$PACKTMP-$name.pack" - chmod a-w "$PACKTMP-$name.idx" - mv -f "$PACKTMP-$name.pack" "$PACKDIR/pack-$name.pack" && - mv -f "$PACKTMP-$name.idx" "$PACKDIR/pack-$name.idx" || - exit -done - -# Remove the "old-" files -for name in $names -do - rm -f "$PACKDIR/old-pack-$name.idx" - rm -f "$PACKDIR/old-pack-$name.pack" -done - -# End of pack replacement. - -if test "$remove_redundant" = t -then - # We know $existing are all redundant. - if [ -n "$existing" ] - then - ( cd "$PACKDIR" && - for e in $existing - do - case " $fullbases " in - *" $e "*) ;; - *) rm -f "$e.pack" "$e.idx" "$e.keep" ;; - esac - done - ) - fi - git prune-packed ${GIT_QUIET:+-q} -fi - -case "$no_update_info" in -t) : ;; -*) git update-server-info ;; -esac diff --git a/git.c b/git.c index 8e34903..05235ca 100644 --- a/git.c +++ b/git.c @@ -410,6 +410,7 @@ static void handle_internal_command(int argc, const char **argv) { "remote-ext", cmd_remote_ext }, { "remote-fd", cmd_remote_fd }, { "replace", cmd_replace, RUN_SETUP }, + { "repack", cmd_repack, RUN_SETUP }, { "repo-config", cmd_repo_config, RUN_SETUP_GENTLY }, { "rerere", cmd_rerere, RUN_SETUP }, { "reset", cmd_reset, RUN_SETUP }, -- 1.7.4.74.g639db -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html