{"thread":{"id":"28902","subject":"[PATCH 1/6] Print trace in rev-list machinery","startedAt":"2011-11-10T07:12:30Z","lastAt":"2011-11-10T07:12:35Z","messageCount":6,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"179238","messageId":"1320909155-4575-1-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":null,"subject":"[PATCH 1/6] Print trace in rev-list machinery","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:30Z","receivedAt":"2011-11-10T07:12:30Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n revision.c |    5 +++++\n 1 files changed, 5 insertions(+), 0 deletions(-)\n\ndiff --git a/revision.c b/revision.c\nindex 8764dde..0aa3638 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1690,6 +1690,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s\n \tif (opt)\n \t\tsubmodule = opt->submodule;\n \n+\tif (argc)\n+\t\ttrace_argv_printf(argv + 1, \"trace: rev-list\");\n+\telse\n+\t\ttrace_printf(\"trace: rev-list\\n\");\n+\n \t/* First, search for \"--\" */\n \tseen_dashdash = 0;\n \tfor (i = 1; i < argc; i++) {\n-- \n1.7.4.74.g639db\n"},{"id":"179239","messageId":"1320909155-4575-2-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":"1320909155-4575-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/6] find_pack_entry(): do not keep packed_git pointer locally","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:31Z","receivedAt":"2011-11-10T07:12:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit f7c22cc (always start looking up objects in the last used pack\nfirst - 2007-05-30) introduce a static packed_git* pointer as an\noptimization.\n\nHowever keeping the pointer may become invalid if free_pack_by_name()\nhappens to free that particular pack.\n\nMove the pointer out and reset the pointer in free_pack_by_name() if we\nfree it.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n sha1_file.c |   13 ++++++++-----\n 1 files changed, 8 insertions(+), 5 deletions(-)\n\ndiff --git a/sha1_file.c b/sha1_file.c\nindex 3401301..155c808 100644\n--- a/sha1_file.c\n+++ b/sha1_file.c\n@@ -53,6 +53,8 @@ static struct cached_object empty_tree = {\n \t0\n };\n \n+static struct packed_git *find_pack_entry_last_found = (void *)1;\n+\n static struct cached_object *find_cached_object(const unsigned char *sha1)\n {\n \tint i;\n@@ -719,6 +721,8 @@ void free_pack_by_name(const char *pack_name)\n \t\t\tclose_pack_index(p);\n \t\t\tfree(p->bad_object_sha1);\n \t\t\t*pp = p->next;\n+\t\t\tif (find_pack_entry_last_found == p)\n+\t\t\t\tfind_pack_entry_last_found = (void*)1;\n \t\t\tfree(p);\n \t\t\treturn;\n \t\t}\n@@ -2010,14 +2014,13 @@ static int is_pack_valid(struct packed_git *p)\n \n static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)\n {\n-\tstatic struct packed_git *last_found = (void *)1;\n \tstruct packed_git *p;\n \toff_t offset;\n \n \tprepare_packed_git();\n \tif (!packed_git)\n \t\treturn 0;\n-\tp = (last_found == (void *)1) ? packed_git : last_found;\n+\tp = (find_pack_entry_last_found == (void *)1) ? packed_git : find_pack_entry_last_found;\n \n \tdo {\n \t\tif (p->num_bad_objects) {\n@@ -2044,16 +2047,16 @@ static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)\n \t\t\te->offset = offset;\n \t\t\te->p = p;\n \t\t\thashcpy(e->sha1, sha1);\n-\t\t\tlast_found = p;\n+\t\t\tfind_pack_entry_last_found = p;\n \t\t\treturn 1;\n \t\t}\n \n \t\tnext:\n-\t\tif (p == last_found)\n+\t\tif (p == find_pack_entry_last_found)\n \t\t\tp = packed_git;\n \t\telse\n \t\t\tp = p->next;\n-\t\tif (p == last_found)\n+\t\tif (p == find_pack_entry_last_found)\n \t\t\tp = p->next;\n \t} while (p);\n \treturn 0;\n-- \n1.7.4.74.g639db\n"},{"id":"179240","messageId":"1320909155-4575-3-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":"1320909155-4575-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 3/6] parse-options: add OPT_ULONG","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:32Z","receivedAt":"2011-11-10T07:12:32Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c |   15 +++++++++++++++\n parse-options.h |    2 ++\n 2 files changed, 17 insertions(+), 0 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex f0098eb..58bb83d 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -144,6 +144,21 @@ static int get_value(struct parse_opt_ctx_t *p,\n \t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n \t\treturn 0;\n \n+\tcase OPTION_ULONG:\n+\t\tif (unset) {\n+\t\t\t*(unsigned long *)opt->value = 0;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tif (opt->flags & PARSE_OPT_OPTARG && !p->opt) {\n+\t\t\t*(unsigned long *)opt->value = opt->defval;\n+\t\t\treturn 0;\n+\t\t}\n+\t\tif (get_arg(p, opt, flags, &arg))\n+\t\t\treturn -1;\n+\t\tif (!git_parse_ulong(arg, (unsigned long *)opt->value))\n+\t\t\treturn opterror(opt, \"expects a numerical value\", flags);\n+\t\treturn 0;\n+\n \tdefault:\n \t\tdie(\"should not happen, someone must be hit on the forehead\");\n \t}\ndiff --git a/parse-options.h b/parse-options.h\nindex 2e811dc..12294d7 100644\n--- a/parse-options.h\n+++ b/parse-options.h\n@@ -16,6 +16,7 @@ enum parse_opt_type {\n \t/* options with arguments (usually) */\n \tOPTION_STRING,\n \tOPTION_INTEGER,\n+\tOPTION_ULONG,\n \tOPTION_CALLBACK,\n \tOPTION_LOWLEVEL_CALLBACK,\n \tOPTION_FILENAME\n@@ -133,6 +134,7 @@ struct option {\n #define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, \\\n \t\t\t\t      (h), PARSE_OPT_NOARG, NULL, (p) }\n #define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), \"n\", (h) }\n+#define OPT_ULONG(s, l, v, h)       { OPTION_ULONG, (s), (l), (v), \"n\", (h) }\n #define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }\n #define OPT_STRING_LIST(s, l, v, a, h) \\\n \t\t\t\t    { OPTION_CALLBACK, (s), (l), (v), (a), \\\n-- \n1.7.4.74.g639db\n"},{"id":"179241","messageId":"1320909155-4575-4-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":"1320909155-4575-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 4/6] pack-objects: use parse_options()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:33Z","receivedAt":"2011-11-10T07:12:33Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n There is a side effect of this conversion: --window and --depth now\n can take units because git_parse_ulong() is always used by\n OPTION_ULONG\n\n builtin/pack-objects.c |  276 +++++++++++++++++++-----------------------------\n 1 files changed, 110 insertions(+), 166 deletions(-)\n\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex 2b18de5..c1ca748 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -18,16 +18,11 @@\n #include \"refs.h\"\n #include \"thread-utils.h\"\n \n-static const char pack_usage[] =\n-  \"git pack-objects [ -q | --progress | --all-progress ]\\n\"\n-  \"        [--all-progress-implied]\\n\"\n-  \"        [--max-pack-size=<n>] [--local] [--incremental]\\n\"\n-  \"        [--window=<n>] [--window-memory=<n>] [--depth=<n>]\\n\"\n-  \"        [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset]\\n\"\n-  \"        [--threads=<n>] [--non-empty] [--revs [--unpacked | --all]]\\n\"\n-  \"        [--reflog] [--stdout | base-name] [--include-tag]\\n\"\n-  \"        [--keep-unreachable | --unpack-unreachable]\\n\"\n-  \"        [< ref-list | < object-list]\";\n+static const char *pack_usage[] = {\n+\t\"git pack-objects --stdout [options...] [< ref-list | < object-list]\",\n+\t\"git pack-objects [options...] base-name [< ref-list | < object-list]\",\n+\tNULL\n+};\n \n struct object_entry {\n \tstruct pack_idx_entry idx;\n@@ -2255,15 +2250,86 @@ static void get_object_list(int ac, const char **av)\n \t\tloosen_unused_packed_objects(&revs);\n }\n \n+static int option_parse_index_version(const struct option *opt,\n+\t\t\t\t      const char *arg, int unset)\n+{\n+\tchar *c;\n+\tconst char *val = arg;\n+\tpack_idx_opts.version = strtoul(val, &c, 10);\n+\tif (pack_idx_opts.version > 2)\n+\t\tdie(\"bad %s\", val);\n+\tif (*c == ',')\n+\t\tpack_idx_opts.off32_limit = strtoul(c+1, &c, 0);\n+\tif (*c || pack_idx_opts.off32_limit & 0x80000000)\n+\t\tdie(\"bad %s\", val);\n+\treturn 0;\n+}\n+\n int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n {\n \tint use_internal_rev_list = 0;\n \tint thin = 0;\n \tint all_progress_implied = 0;\n-\tuint32_t i;\n \tconst char **rp_av;\n \tint rp_ac_alloc = 64;\n \tint rp_ac;\n+\tstruct option pack_objects_options[] = {\n+\t\tOPT_SET_INT('q', NULL, &progress,\n+\t\t\t    \"do not show progress meter\", 0),\n+\t\tOPT_SET_INT(0, \"progress\", &progress,\n+\t\t\t    \"show progress meter\", 1),\n+\t\tOPT_SET_INT(0, \"all-progress\", &progress,\n+\t\t\t    \"show progress meter during object writing phase\", 2),\n+\t\tOPT_BOOL(0, \"all-progress-implied\",\n+\t\t\t &all_progress_implied,\n+\t\t\t \"similar to --all-progress when progress meter is shown\"),\n+\t\t{ OPTION_CALLBACK, 0, \"index-version\", NULL, \"version\",\n+\t\t  \"force generating pack index at a particular version\",\n+\t\t  0, option_parse_index_version },\n+\t\tOPT_ULONG(0, \"max-pack-size\", &pack_size_limit,\n+\t\t\t  \"maximum size of each output pack file\"),\n+\t\tOPT_BOOL(0, \"local\", &local,\n+\t\t\t \"ignore borrowed objects from alternate object store\"),\n+\t\tOPT_BOOL(0, \"incremental\", &incremental,\n+\t\t\t \"ignore packed objects\"),\n+\t\tOPT_ULONG(0, \"window\", &window, \"limit pack window by objects\"),\n+\t\tOPT_ULONG(0, \"window-memory\", &window_memory_limit,\n+\t\t\t  \"limit pack window by memory\"),\n+\t\tOPT_INTEGER(0, \"depth\", &depth,\n+\t\t\t    \"limit pack window by maximum delta depth\"),\n+\t\tOPT_BOOL(0, \"reuse-delta\", &reuse_delta,\n+\t\t\t \"reusing existing deltas\"),\n+\t\tOPT_BOOL(0, \"reuse-object\", &reuse_object,\n+\t\t\t \"reusing existing objects\"),\n+\t\tOPT_BOOL(0, \"delta-base-offset\", &allow_ofs_delta,\n+\t\t\t \"use OFS_DELTA objects\"),\n+\t\tOPT_INTEGER(0, \"threads\", &delta_search_threads,\n+\t\t\t    \"use threads when searching for best delta matches\"),\n+\t\tOPT_BOOL(0, \"non-empty\", &non_empty,\n+\t\t\t \"only create if it would contain at least one object\"),\n+\t\tOPT_BOOL(0, \"revs\", &use_internal_rev_list,\n+\t\t\t \"read revision arguments from standard output\"),\n+\t\tOPT_ARGUMENT(\"unpacked\", \"limit the objects to those that are not already packed\"),\n+\t\tOPT_ARGUMENT(\"all\", \"include all refs under $GIT_DIR/refs directory\"),\n+\t\tOPT_ARGUMENT(\"reflog\", \"include objects referred by reflog entries\"),\n+\t\tOPT_BOOL(0, \"stdout\", &pack_to_stdout,\n+\t\t\t \"output pack to stdout\"),\n+\t\tOPT_BOOL(0, \"include-tag\", &include_tag,\n+\t\t\t \"include unasked-for annotated tags\"),\n+\t\tOPT_BOOL(0, \"keep-unreachable\", &keep_unreachable,\n+\t\t\t \"keep unreachable objects\"),\n+\t\tOPT_BOOL(0, \"unpack-unreachable\", &unpack_unreachable,\n+\t\t\t \"unpack unreachable objects\"),\n+\t\tOPT_BOOL(0, \"thin\", &thin,\n+\t\t\t \"create thin packs\"),\n+\t\tOPT_BOOL(0, \"honor-pack-keep\", &ignore_packed_keep,\n+\t\t\t \"ignore packs that have companion .keep file\"),\n+\t\tOPT_INTEGER(0, \"compression\", &pack_compression_level,\n+\t\t\t    \"pack compression level\"),\n+\t\tOPT_SET_INT(0, \"keep-true-parents\", &grafts_replace_parents,\n+\t\t\t    \"do not hide commits by grafts\", 0),\n+\t\tOPT_END(),\n+\t};\n \n \tread_replace_refs = 0;\n \n@@ -2279,160 +2345,35 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \t\tpack_compression_level = core_compression_level;\n \n \tprogress = isatty(2);\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\n-\t\tif (*arg != '-')\n-\t\t\tbreak;\n+\targc = parse_options(argc, argv, prefix, pack_objects_options,\n+\t\t\t     pack_usage, 0);\n \n-\t\tif (!strcmp(\"--non-empty\", arg)) {\n-\t\t\tnon_empty = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--local\", arg)) {\n-\t\t\tlocal = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--incremental\", arg)) {\n-\t\t\tincremental = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--honor-pack-keep\", arg)) {\n-\t\t\tignore_packed_keep = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--compression=\")) {\n-\t\t\tchar *end;\n-\t\t\tint level = strtoul(arg+14, &end, 0);\n-\t\t\tif (!arg[14] || *end)\n-\t\t\t\tusage(pack_usage);\n-\t\t\tif (level == -1)\n-\t\t\t\tlevel = Z_DEFAULT_COMPRESSION;\n-\t\t\telse if (level < 0 || level > Z_BEST_COMPRESSION)\n-\t\t\t\tdie(\"bad pack compression level %d\", level);\n-\t\t\tpack_compression_level = level;\n-\t\t\tcontinue;\n+\twhile (argc && argv[0][0] == '-') {\n+\t\tuse_internal_rev_list = 1;\n+\t\tif (rp_ac >= rp_ac_alloc - 1) {\n+\t\t\trp_ac_alloc = alloc_nr(rp_ac_alloc);\n+\t\t\trp_av = xrealloc(rp_av,\n+\t\t\t\t\t rp_ac_alloc * sizeof(*rp_av));\n \t\t}\n-\t\tif (!prefixcmp(arg, \"--max-pack-size=\")) {\n-\t\t\tpack_size_limit_cfg = 0;\n-\t\t\tif (!git_parse_ulong(arg+16, &pack_size_limit))\n-\t\t\t\tusage(pack_usage);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--window=\")) {\n-\t\t\tchar *end;\n-\t\t\twindow = strtoul(arg+9, &end, 0);\n-\t\t\tif (!arg[9] || *end)\n-\t\t\t\tusage(pack_usage);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--window-memory=\")) {\n-\t\t\tif (!git_parse_ulong(arg+16, &window_memory_limit))\n-\t\t\t\tusage(pack_usage);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--threads=\")) {\n-\t\t\tchar *end;\n-\t\t\tdelta_search_threads = strtoul(arg+10, &end, 0);\n-\t\t\tif (!arg[10] || *end || delta_search_threads < 0)\n-\t\t\t\tusage(pack_usage);\n+\t\trp_av[rp_ac++] = *argv;\n+\t\targv++;\n+\t\targc--;\n+\t}\n+\n+\tif (!reuse_object)\n+\t\treuse_delta = 0;\n+\tif (thin) {\n+\t\tuse_internal_rev_list = 1;\n+\t\trp_av[1] = \"--objects-edge\";\n+\t}\n+\tif (pack_compression_level == -1)\n+\t\tpack_compression_level = Z_DEFAULT_COMPRESSION;\n+\telse if (pack_compression_level < 0 || pack_compression_level > Z_BEST_COMPRESSION)\n+\t\tdie(\"bad pack compression level %d\", pack_compression_level);\n #ifdef NO_PTHREADS\n-\t\t\tif (delta_search_threads != 1)\n-\t\t\t\twarning(\"no threads support, \"\n-\t\t\t\t\t\"ignoring %s\", arg);\n+\tif (delta_search_threads != 1)\n+\t\twarning(\"no threads support, ignoring %s\", arg);\n #endif\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--depth=\")) {\n-\t\t\tchar *end;\n-\t\t\tdepth = strtoul(arg+8, &end, 0);\n-\t\t\tif (!arg[8] || *end)\n-\t\t\t\tusage(pack_usage);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--progress\", arg)) {\n-\t\t\tprogress = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--all-progress\", arg)) {\n-\t\t\tprogress = 2;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--all-progress-implied\", arg)) {\n-\t\t\tall_progress_implied = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"-q\", arg)) {\n-\t\t\tprogress = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--no-reuse-delta\", arg)) {\n-\t\t\treuse_delta = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--no-reuse-object\", arg)) {\n-\t\t\treuse_object = reuse_delta = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--delta-base-offset\", arg)) {\n-\t\t\tallow_ofs_delta = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--stdout\", arg)) {\n-\t\t\tpack_to_stdout = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--revs\", arg)) {\n-\t\t\tuse_internal_rev_list = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--keep-unreachable\", arg)) {\n-\t\t\tkeep_unreachable = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--unpack-unreachable\", arg)) {\n-\t\t\tunpack_unreachable = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--include-tag\", arg)) {\n-\t\t\tinclude_tag = 1;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--unpacked\", arg) ||\n-\t\t    !strcmp(\"--reflog\", arg) ||\n-\t\t    !strcmp(\"--all\", arg)) {\n-\t\t\tuse_internal_rev_list = 1;\n-\t\t\tif (rp_ac >= rp_ac_alloc - 1) {\n-\t\t\t\trp_ac_alloc = alloc_nr(rp_ac_alloc);\n-\t\t\t\trp_av = xrealloc(rp_av,\n-\t\t\t\t\t\t rp_ac_alloc * sizeof(*rp_av));\n-\t\t\t}\n-\t\t\trp_av[rp_ac++] = arg;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(\"--thin\", arg)) {\n-\t\t\tuse_internal_rev_list = 1;\n-\t\t\tthin = 1;\n-\t\t\trp_av[1] = \"--objects-edge\";\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!prefixcmp(arg, \"--index-version=\")) {\n-\t\t\tchar *c;\n-\t\t\tpack_idx_opts.version = strtoul(arg + 16, &c, 10);\n-\t\t\tif (pack_idx_opts.version > 2)\n-\t\t\t\tdie(\"bad %s\", arg);\n-\t\t\tif (*c == ',')\n-\t\t\t\tpack_idx_opts.off32_limit = strtoul(c+1, &c, 0);\n-\t\t\tif (*c || pack_idx_opts.off32_limit & 0x80000000)\n-\t\t\t\tdie(\"bad %s\", arg);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (!strcmp(arg, \"--keep-true-parents\")) {\n-\t\t\tgrafts_replace_parents = 0;\n-\t\t\tcontinue;\n-\t\t}\n-\t\tusage(pack_usage);\n-\t}\n \n \t/* Traditionally \"pack-objects [options] base extra\" failed;\n \t * we would however want to take refs parameter that would\n@@ -2447,11 +2388,14 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \t * walker.\n \t */\n \n-\tif (!pack_to_stdout)\n-\t\tbase_name = argv[i++];\n-\n-\tif (pack_to_stdout != !base_name)\n-\t\tusage(pack_usage);\n+\tif (!pack_to_stdout) {\n+\t\tif (!argc)\n+\t\t\tdie(\"base name required if --stdout is not given\");\n+\t\tbase_name = argv[0];\n+\t\targc--;\n+\t}\n+\tif (argc)\n+\t\tdie(\"base name or --stdout are mutually exclusive\");\n \n \tif (!pack_to_stdout && !pack_size_limit)\n \t\tpack_size_limit = pack_size_limit_cfg;\n-- \n1.7.4.74.g639db\n"},{"id":"179242","messageId":"1320909155-4575-5-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":"1320909155-4575-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 5/6] parse-options: allow OPTION_ARGUMENT to take argument","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:34Z","receivedAt":"2011-11-10T07:12:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n parse-options.c |   18 +++++++++++++++---\n 1 files changed, 15 insertions(+), 3 deletions(-)\n\ndiff --git a/parse-options.c b/parse-options.c\nindex 58bb83d..3a1575a 100644\n--- a/parse-options.c\n+++ b/parse-options.c\n@@ -218,11 +218,23 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,\n \t\tif (options->type == OPTION_ARGUMENT) {\n \t\t\tif (!rest)\n \t\t\t\tcontinue;\n-\t\t\tif (*rest == '=')\n-\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\tif (*rest == '=') {\n+\t\t\t\tif (options->flags & PARSE_OPT_NOARG)\n+\t\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\t\tp->out[p->cpidx++] = *p->argv;\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\n \t\t\tif (*rest)\n \t\t\t\tcontinue;\n-\t\t\tp->out[p->cpidx++] = arg - 2;\n+\t\t\tp->out[p->cpidx++] = *p->argv;\n+\t\t\tif (!(options->flags & PARSE_OPT_NOARG)) {\n+\t\t\t\tp->argv++;\n+\t\t\t\tp->argc--;\n+\t\t\t\tif (!*p->argv)\n+\t\t\t\t\treturn opterror(options, \"takes no value\", flags);\n+\t\t\t\tp->out[p->cpidx++] = *p->argv;\n+\t\t\t}\n \t\t\treturn 0;\n \t\t}\n \t\tif (!rest) {\n-- \n1.7.4.74.g639db\n"},{"id":"179243","messageId":"1320909155-4575-6-git-send-email-pclouds@gmail.com","threadId":"28902","inReplyTo":"1320909155-4575-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 6/6] Build in git-repack","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-11-10T07:12:35Z","receivedAt":"2011-11-10T07:12:35Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"pack-objects learns a few more options to take over what's been done\nby git-repack.sh. cmd_repack() becomes a wrapper around\ncmd_pack_objects().\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Makefile                       |    2 +-\n builtin.h                      |    1 +\n builtin/pack-objects.c         |  297 +++++++++++++++++++++++++++++++++++++++-\n contrib/examples/git-repack.sh |  186 +++++++++++++++++++++++++\n git-repack.sh                  |  186 -------------------------\n git.c                          |    1 +\n 6 files changed, 483 insertions(+), 190 deletions(-)\n create mode 100755 contrib/examples/git-repack.sh\n delete mode 100755 git-repack.sh\n\ndiff --git a/Makefile b/Makefile\nindex 17404c4..164052d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -374,7 +374,6 @@ SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-pull.sh\n SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n-SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\n SCRIPT_SH += git-submodule.sh\n@@ -460,6 +459,7 @@ BUILT_INS += git-init$X\n BUILT_INS += git-merge-subtree$X\n BUILT_INS += git-peek-remote$X\n BUILT_INS += git-repo-config$X\n+BUILT_INS += git-repack$X\n BUILT_INS += git-show$X\n BUILT_INS += git-stage$X\n BUILT_INS += git-status$X\ndiff --git a/builtin.h b/builtin.h\nindex 0a5b511..2a890ce 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -115,6 +115,7 @@ extern int cmd_reflog(int argc, const char **argv, const char *prefix);\n extern int cmd_remote(int argc, const char **argv, const char *prefix);\n extern int cmd_remote_ext(int argc, const char **argv, const char *prefix);\n extern int cmd_remote_fd(int argc, const char **argv, const char *prefix);\n+extern int cmd_repack(int argc, const char **argv, const char *prefix);\n extern int cmd_repo_config(int argc, const char **argv, const char *prefix);\n extern int cmd_rerere(int argc, const char **argv, const char *prefix);\n extern int cmd_reset(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/pack-objects.c b/builtin/pack-objects.c\nindex c1ca748..7acec4c 100644\n--- a/builtin/pack-objects.c\n+++ b/builtin/pack-objects.c\n@@ -17,10 +17,17 @@\n #include \"progress.h\"\n #include \"refs.h\"\n #include \"thread-utils.h\"\n+#include \"sigchain.h\"\n \n static const char *pack_usage[] = {\n \t\"git pack-objects --stdout [options...] [< ref-list | < object-list]\",\n \t\"git pack-objects [options...] base-name [< ref-list | < object-list]\",\n+\t\"git pack-objects --repack [options...]\",\n+\tNULL\n+};\n+\n+static char const * const repack_usage[] = {\n+\t\"git repack [options]\",\n \tNULL\n };\n \n@@ -101,6 +108,15 @@ static struct object_entry *locate_object_entry(const unsigned char *sha1);\n static uint32_t written, written_delta;\n static uint32_t reused, reused_delta;\n \n+#define REPACK_IN_PROGRESS\t\t(1 << 0)\n+#define REPACK_UPDATE_INFO\t\t(1 << 1)\n+#define REPACK_ALL_INTO_ONE\t\t(1 << 2)\n+#define REPACK_REMOVE_REDUNDANT\t\t(1 << 3)\n+\n+static int repack_flags, nr_written_packs;\n+static int repack_usedeltabaseoffset;\n+static struct string_list written_packs;\n+static struct string_list backup_files;\n \n static void *get_delta(struct object_entry *entry)\n {\n@@ -561,6 +577,19 @@ static struct object_entry **compute_write_order(void)\n \treturn wo;\n }\n \n+static void backup_file(const char *path)\n+{\n+\tstruct stat st;\n+\tif (repack_flags & REPACK_IN_PROGRESS &&\n+\t    !stat(path, &st)) {\n+\t\tstruct strbuf old = STRBUF_INIT;\n+\t\tstrbuf_addf(&old, \"%s.old\", path);\n+\t\tif (rename(path, old.buf))\n+\t\t\tdie_errno(\"unable to rename pack %s\", path);\n+\t\tstring_list_append(&backup_files, strbuf_detach(&old, NULL));\n+\t}\n+}\n+\n static void write_pack_file(void)\n {\n \tuint32_t i = 0, j;\n@@ -632,6 +661,7 @@ static void write_pack_file(void)\n \t\t\tfree_pack_by_name(tmpname);\n \t\t\tif (adjust_shared_perm(pack_tmp_name))\n \t\t\t\tdie_errno(\"unable to make temporary pack file readable\");\n+\t\t\tbackup_file(tmpname);\n \t\t\tif (rename(pack_tmp_name, tmpname))\n \t\t\t\tdie_errno(\"unable to rename temporary pack file\");\n \n@@ -660,12 +690,22 @@ static void write_pack_file(void)\n \t\t\t\t base_name, sha1_to_hex(sha1));\n \t\t\tif (adjust_shared_perm(idx_tmp_name))\n \t\t\t\tdie_errno(\"unable to make temporary index file readable\");\n+\t\t\tbackup_file(tmpname);\n \t\t\tif (rename(idx_tmp_name, tmpname))\n \t\t\t\tdie_errno(\"unable to rename temporary index file\");\n \n \t\t\tfree((void *) idx_tmp_name);\n \t\t\tfree(pack_tmp_name);\n-\t\t\tputs(sha1_to_hex(sha1));\n+\t\t\tif (repack_flags & REPACK_IN_PROGRESS) {\n+\t\t\t\tint len = strlen(tmpname);\n+\t\t\t\tchar *s = xmalloc(len + 2);\n+\t\t\t\tmemcpy(s, tmpname, len - 4);\n+\t\t\t\tmemcpy(s + len - 4, \".pack\", 6);\n+\t\t\t\tstring_list_append(&written_packs, s);\n+\t\t\t\tnr_written_packs++;\n+\t\t\t}\n+\t\t\telse\n+\t\t\t\tputs(sha1_to_hex(sha1));\n \t\t}\n \n \t\t/* mark written objects as written to previous pack */\n@@ -2222,7 +2262,8 @@ static void get_object_list(int ac, const char **av)\n \tsave_commit_buffer = 0;\n \tsetup_revisions(ac, av, &revs, NULL);\n \n-\twhile (fgets(line, sizeof(line), stdin) != NULL) {\n+\twhile (!(repack_flags & REPACK_IN_PROGRESS) &&\n+\t       fgets(line, sizeof(line), stdin) != NULL) {\n \t\tint len = strlen(line);\n \t\tif (len && line[len - 1] == '\\n')\n \t\t\tline[--len] = 0;\n@@ -2250,6 +2291,31 @@ static void get_object_list(int ac, const char **av)\n \t\tloosen_unused_packed_objects(&revs);\n }\n \n+static void rollback_repack(void)\n+{\n+\tstruct strbuf dst = STRBUF_INIT;\n+\tint i, ret;\n+\tfor (i = 0; i < backup_files.nr; i++) {\n+\t\tconst char *src = backup_files.items[i].string;\n+\t\tstrbuf_addstr(&dst, src);\n+\t\tstrbuf_setlen(&dst, dst.len - 4); /* remove .old */\n+\t\tret = rename(src, dst.buf);\n+\t\tif (ret)\n+\t\t\twarning(\"failed to restore %s: %s\", src, strerror(errno));\n+\t\tstrbuf_setlen(&dst, 0);\n+\t}\n+\tstrbuf_release(&dst);\n+\tstring_list_clear(&backup_files, 0);\n+}\n+\n+static void rollback_repack_on_signal(int signo)\n+{\n+\trollback_repack();\n+\tsigchain_pop(signo);\n+\traise(signo);\n+}\n+\n+\n static int option_parse_index_version(const struct option *opt,\n \t\t\t\t      const char *arg, int unset)\n {\n@@ -2267,12 +2333,14 @@ static int option_parse_index_version(const struct option *opt,\n \n int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n {\n+\tstruct strbuf repack_base_name = STRBUF_INIT;\n \tint use_internal_rev_list = 0;\n \tint thin = 0;\n \tint all_progress_implied = 0;\n \tconst char **rp_av;\n \tint rp_ac_alloc = 64;\n \tint rp_ac;\n+\tint i;\n \tstruct option pack_objects_options[] = {\n \t\tOPT_SET_INT('q', NULL, &progress,\n \t\t\t    \"do not show progress meter\", 0),\n@@ -2328,6 +2396,16 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \t\t\t    \"pack compression level\"),\n \t\tOPT_SET_INT(0, \"keep-true-parents\", &grafts_replace_parents,\n \t\t\t    \"do not hide commits by grafts\", 0),\n+\n+\t\tOPT_BIT(0, \"repack\", &repack_flags,\n+\t\t\t\"repack mode\", REPACK_IN_PROGRESS),\n+\t\tOPT_BIT(0, \"repack-all\", &repack_flags,\n+\t\t\t\"repack everything into one pack\", REPACK_ALL_INTO_ONE),\n+\t\tOPT_BIT(0, \"remove-redundant\", &repack_flags,\n+\t\t\t\"remove redundant objects after repack\", REPACK_REMOVE_REDUNDANT),\n+\t\tOPT_BIT(0, \"update-info\", &repack_flags,\n+\t\t\t\"run git-update-server-info after repack\", REPACK_UPDATE_INFO),\n+\n \t\tOPT_END(),\n \t};\n \n@@ -2374,6 +2452,39 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \tif (delta_search_threads != 1)\n \t\twarning(\"no threads support, ignoring %s\", arg);\n #endif\n+\tif ((repack_flags & REPACK_IN_PROGRESS) == 0 &&\n+\t    (repack_flags & ~REPACK_IN_PROGRESS))\n+\t\tdie(\"--repack must be given for any repack related options\");\n+\tif (repack_flags & REPACK_IN_PROGRESS) {\n+\t\tif (pack_to_stdout)\n+\t\t\tdie(\"--stdout cannot be used with --repack\");\n+\t\tif (argc)\n+\t\t\tdie(\"base name cannot be used with --repack\");\n+\n+\t\tif (rp_ac + 2 >= rp_ac_alloc) {\n+\t\t\trp_ac_alloc = alloc_nr(rp_ac_alloc);\n+\t\t\trp_av = xrealloc(rp_av, rp_ac_alloc * sizeof(*rp_av));\n+\t\t}\n+\t\trp_av[rp_ac++] = \"--all\";\n+\t\trp_av[rp_ac++] = \"--reflog\";\n+\t\tuse_internal_rev_list = 1;\n+\n+\t\tgrafts_replace_parents = 0; /* --keep-true-parents */\n+\t\tignore_packed_keep = 1;\t    /* --honor-pack-keep */\n+\t\tnon_empty = 1;\t\t    /* --non-empty */\n+\n+\t\tif (!(repack_flags & REPACK_ALL_INTO_ONE)) {\n+\t\t\tincremental = 1; /* --incremental */\n+\t\t\trp_av[rp_ac++] = \"--unpacked\";\n+\t\t}\n+\n+\t\tstrbuf_addf(&repack_base_name,\n+\t\t\t    \"%s/pack/pack\", get_object_directory());\n+\t\tbase_name = repack_base_name.buf;\n+\n+\t\tsigchain_push_common(rollback_repack_on_signal);\n+\t\tatexit(rollback_repack);\n+\t}\n \n \t/* Traditionally \"pack-objects [options] base extra\" failed;\n \t * we would however want to take refs parameter that would\n@@ -2388,7 +2499,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \t * walker.\n \t */\n \n-\tif (!pack_to_stdout) {\n+\telse if (!pack_to_stdout) {\n \t\tif (!argc)\n \t\t\tdie(\"base name required if --stdout is not given\");\n \t\tbase_name = argv[0];\n@@ -2439,5 +2550,185 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n \t\tfprintf(stderr, \"Total %\"PRIu32\" (delta %\"PRIu32\"),\"\n \t\t\t\" reused %\"PRIu32\" (delta %\"PRIu32\")\\n\",\n \t\t\twritten, written_delta, reused, reused_delta);\n+\n+\tif (!(repack_flags & REPACK_IN_PROGRESS))\n+\t\treturn 0;\n+\n+\tif (!nr_written_packs) {\n+\t\tprintf(_(\"Nothing new to pack.\\n\"));\n+\t\treturn 0;\n+\t}\n+\n+\t/* At this point all new packs should be in place. We can\n+\t   safely remove old ones */\n+\tfor (i = 0; i < backup_files.nr; i++) {\n+\t\tconst char *s = backup_files.items[i].string;\n+\t\tint ret = unlink(s);\n+\t\tif (ret)\n+\t\t\twarning(\"failed to remove %s: %s\", s, strerror(errno));\n+\t}\n+\tstring_list_clear(&backup_files, 0);\n+\n+\tif (repack_flags & REPACK_REMOVE_REDUNDANT) {\n+\t\tstruct packed_git *p;\n+\t\tstruct string_list to_be_removed = STRING_LIST_INIT_DUP;\n+\n+\t\t/* free_pack_by_name() may have freed a few packs in\n+\t\t   write_pack_file() */\n+\t\treprepare_packed_git();\n+\t\tfor (p = packed_git; p; p = p->next) {\n+\t\t\tif (!p->pack_local || p->pack_keep)\n+\t\t\t\tcontinue;\n+\n+\t\t\tfor (i = 0; i < written_packs.nr; i++) {\n+\t\t\t\tchar *s = written_packs.items[i].string;\n+\t\t\t\tif (!strcmp(s, p->pack_name))\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tif (i < written_packs.nr)\n+\t\t\t\tcontinue;\n+\n+\t\t\tstring_list_append(&to_be_removed, p->pack_name);\n+\t\t}\n+\t\twritten_packs.strdup_strings = 1;\n+\t\tstring_list_clear(&written_packs, 0);\n+\n+\t\tfor (i = 0; i < to_be_removed.nr; i++) {\n+\t\t\tchar *path = to_be_removed.items[i].string;\n+\n+\t\t\t/* Windows limitation on unlink().\n+\t\t\t   See c74faea19e39ca933492f697596310397175c329 */\n+\t\t\tfree_pack_by_name(path);\n+\n+\t\t\tif (unlink(path))\n+\t\t\t\twarning(\"failed to remove %s: %s\", path, strerror(errno));\n+\t\t\tstrcpy(path + strlen(path)-5, \".idx\");\n+\t\t\tif (unlink(path))\n+\t\t\t\twarning(\"failed to remove %s: %s\", path, strerror(errno));\n+\t\t}\n+\t\tstring_list_clear(&to_be_removed, 0);\n+\n+\t\treprepare_packed_git();\n+\t\tprune_packed_objects(0);\n+\t}\n+\n+\tif (repack_flags & REPACK_UPDATE_INFO)\n+\t\tupdate_server_info(0);\n+\n \treturn 0;\n }\n+\n+static int repack_config(const char *k, const char *v, void *cb)\n+{\n+\tif (!strcasecmp(k, \"repack.usedeltabaseoffset\")) {\n+\t\trepack_usedeltabaseoffset = git_config_bool(k, v);\n+\t\treturn 0;\n+\t}\n+\treturn git_default_config(k, v, cb);\n+}\n+\n+int cmd_repack(int argc, const char **argv, const char *prefix)\n+{\n+\tint all_in_one = 0;\n+\tint all_in_one_and_unreachable = 0;\n+\tint unpack_unreachable = 0;\n+\tint remove_redundant = 0;\n+\tint no_reuse_delta = 0;\n+\tint no_reuse_object = 0;\n+\tint no_update = 0;\n+\tint quiet = 0;\n+\tint local = 0;\n+\n+\tstruct option opts[] = {\n+\t\tOPT_BOOL('a', NULL, &all_in_one,\n+\t\t\t \"pack everything in a single pack\"),\n+\t\tOPT_BOOL('A', NULL, &all_in_one_and_unreachable,\n+\t\t\t \"same as -a, and turn unreachable objects loose\"),\n+\t\tOPT_BOOL('d', NULL, &remove_redundant,\n+\t\t\t \"remove redundant packs, and run git-prune-packed\"),\n+\t\tOPT_BOOL('f', NULL, &no_reuse_delta,\n+\t\t\t \"pass --no-reuse-delta to git-pack-objects\"),\n+\t\tOPT_BOOL('F', NULL, &no_reuse_object,\n+\t\t\t \"pass --no-reuse-object to git-pack-objects\"),\n+\t\tOPT_BOOL('n', NULL, &no_update,\n+\t\t\t \"do not run git-update-server-info\"),\n+\t\tOPT_BOOL('q', NULL, &quiet, \"be quiet\"),\n+\t\tOPT_BOOL('l', NULL, &local,\n+\t\t\t \"pass --local to git-pack-objects\"),\n+\t\t{ OPTION_ARGUMENT, 0, \"window\", NULL, \"n\",\n+\t\t \"size of the window used for delta compression\", 0 },\n+\t\t{ OPTION_ARGUMENT, 0, \"window-memory\", NULL, \"n\",\n+\t\t  \"same as the above, but limit memory size instead of entries count\", 0 },\n+\t\t{ OPTION_ARGUMENT, 0, \"depth\", NULL, \"n\",\n+\t\t  \"limits the maximum delta depth\", 0 },\n+\t\t{ OPTION_ARGUMENT, 0, \"max-pack-size\", NULL, \"n\",\n+\t\t  \"maximum size of each packfile\", 0},\n+\t\tOPT_END(),\n+\t};\n+\n+\tconst char *av[] = { \"pack-objects\", \"--repack\",\n+\t\t\t     NULL, /* --[no-]update-info */\n+\t\t\t     NULL, /* --delta-base-offset */\n+\t\t\t     NULL, /* --repack-all */\n+\t\t\t     NULL, /* --remove-redundant */\n+\t\t\t     NULL, /* --no-reuse-delta */\n+\t\t\t     NULL, /* --no-reuse-object */\n+\t\t\t     NULL, /* --local */\n+\t\t\t     NULL, /* -q */\n+\t\t\t     NULL, /* --unpack-unreachable */\n+\t\t\t     NULL, /* --window */\n+\t\t\t     NULL, /* --window-memory */\n+\t\t\t     NULL, /* --depth */\n+\t\t\t     NULL, /* --max-pack-size */\n+\t\t\t     NULL\n+\t};\n+\tint ac = 2;\n+\n+\tgit_config(repack_config, NULL);\n+\n+\targc = parse_options(argc, argv, prefix, opts, repack_usage, 0);\n+\n+\tif (no_update)\n+\t\tav[ac++] = \"--no-update-info\";\n+\telse\n+\t\tav[ac++] = \"--update-info\";\n+\tif (repack_usedeltabaseoffset)\n+\t\tav[ac++] = \"--delta-base-offset\";\n+\tif (all_in_one_and_unreachable) {\n+\t\tav[ac++] = \"--repack-all\";\n+\t\tall_in_one = 1;\n+\t\tunpack_unreachable = 1;\n+\t}\n+\tif (all_in_one)\n+\t\tav[ac++] = \"--repack-all\";\n+\tif (remove_redundant)\n+\t\tav[ac++] = \"--remove-redundant\";\n+\tif (no_reuse_delta)\n+\t\tav[ac++] = \"--no-reuse-delta\";\n+\tif (no_reuse_object)\n+\t\tav[ac++] = \"--no-reuse-object\";\n+\tif (local)\n+\t\tav[ac++] = \"--local\";\n+\tif (quiet)\n+\t\tav[ac++] = \"-q\";\n+\tif ((ac + argc) * sizeof(*av) > sizeof(av))\n+\t\tdie(\"Too many options\");\n+\tmemcpy(av + ac, argv, argc * sizeof(*argv));\n+\tac += argc;\n+\n+\tif (all_in_one && remove_redundant) {\n+\t\tstruct packed_git *p;\n+\n+\t\tprepare_packed_git();\n+\t\tfor (p = packed_git; p; p = p->next) {\n+\t\t\tif (!p->pack_keep &&\n+\t\t\t    unpack_unreachable && remove_redundant) {\n+\t\t\t\tav[ac++] = \"--unpack-unreachable\";\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\ttrace_argv_printf(av, \"trace: built-in: git\");\n+\treturn cmd_pack_objects(ac, av, prefix);\n+}\ndiff --git a/contrib/examples/git-repack.sh b/contrib/examples/git-repack.sh\nnew file mode 100755\nindex 0000000..624feec\n--- /dev/null\n+++ b/contrib/examples/git-repack.sh\n@@ -0,0 +1,186 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Linus Torvalds\n+#\n+\n+OPTIONS_KEEPDASHDASH=\n+OPTIONS_SPEC=\"\\\n+git repack [options]\n+--\n+a               pack everything in a single pack\n+A               same as -a, and turn unreachable objects loose\n+d               remove redundant packs, and run git-prune-packed\n+f               pass --no-reuse-delta to git-pack-objects\n+F               pass --no-reuse-object to git-pack-objects\n+n               do not run git-update-server-info\n+q,quiet         be quiet\n+l               pass --local to git-pack-objects\n+ Packing constraints\n+window=         size of the window used for delta compression\n+window-memory=  same as the above, but limit memory size instead of entries count\n+depth=          limits the maximum delta depth\n+max-pack-size=  maximum size of each packfile\n+\"\n+SUBDIRECTORY_OK='Yes'\n+. git-sh-setup\n+\n+no_update_info= all_into_one= remove_redundant= unpack_unreachable=\n+local= no_reuse= extra=\n+while test $# != 0\n+do\n+\tcase \"$1\" in\n+\t-n)\tno_update_info=t ;;\n+\t-a)\tall_into_one=t ;;\n+\t-A)\tall_into_one=t\n+\t\tunpack_unreachable=--unpack-unreachable ;;\n+\t-d)\tremove_redundant=t ;;\n+\t-q)\tGIT_QUIET=t ;;\n+\t-f)\tno_reuse=--no-reuse-delta ;;\n+\t-F)\tno_reuse=--no-reuse-object ;;\n+\t-l)\tlocal=--local ;;\n+\t--max-pack-size|--window|--window-memory|--depth)\n+\t\textra=\"$extra $1=$2\"; shift ;;\n+\t--) shift; break;;\n+\t*)\tusage ;;\n+\tesac\n+\tshift\n+done\n+\n+case \"`git config --bool repack.usedeltabaseoffset || echo true`\" in\n+true)\n+\textra=\"$extra --delta-base-offset\" ;;\n+esac\n+\n+PACKDIR=\"$GIT_OBJECT_DIRECTORY/pack\"\n+PACKTMP=\"$PACKDIR/.tmp-$$-pack\"\n+rm -f \"$PACKTMP\"-*\n+trap 'rm -f \"$PACKTMP\"-*' 0 1 2 3 15\n+\n+# There will be more repacking strategies to come...\n+case \",$all_into_one,\" in\n+,,)\n+\targs='--unpacked --incremental'\n+\t;;\n+,t,)\n+\targs= existing=\n+\tif [ -d \"$PACKDIR\" ]; then\n+\t\tfor e in `cd \"$PACKDIR\" && find . -type f -name '*.pack' \\\n+\t\t\t| sed -e 's/^\\.\\///' -e 's/\\.pack$//'`\n+\t\tdo\n+\t\t\tif [ -e \"$PACKDIR/$e.keep\" ]; then\n+\t\t\t\t: keep\n+\t\t\telse\n+\t\t\t\texisting=\"$existing $e\"\n+\t\t\tfi\n+\t\tdone\n+\t\tif test -n \"$existing\" -a -n \"$unpack_unreachable\" -a \\\n+\t\t\t-n \"$remove_redundant\"\n+\t\tthen\n+\t\t\targs=\"$args $unpack_unreachable\"\n+\t\tfi\n+\tfi\n+\t;;\n+esac\n+\n+mkdir -p \"$PACKDIR\" || exit\n+\n+args=\"$args $local ${GIT_QUIET:+-q} $no_reuse$extra\"\n+names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null \"$PACKTMP\") ||\n+\texit 1\n+if [ -z \"$names\" ]; then\n+\tsay Nothing new to pack.\n+fi\n+\n+# Ok we have prepared all new packfiles.\n+\n+# First see if there are packs of the same name and if so\n+# if we can move them out of the way (this can happen if we\n+# repacked immediately after packing fully.\n+rollback=\n+failed=\n+for name in $names\n+do\n+\tfor sfx in pack idx\n+\tdo\n+\t\tfile=pack-$name.$sfx\n+\t\ttest -f \"$PACKDIR/$file\" || continue\n+\t\trm -f \"$PACKDIR/old-$file\" &&\n+\t\tmv \"$PACKDIR/$file\" \"$PACKDIR/old-$file\" || {\n+\t\t\tfailed=t\n+\t\t\tbreak\n+\t\t}\n+\t\trollback=\"$rollback $file\"\n+\tdone\n+\ttest -z \"$failed\" || break\n+done\n+\n+# If renaming failed for any of them, roll the ones we have\n+# already renamed back to their original names.\n+if test -n \"$failed\"\n+then\n+\trollback_failure=\n+\tfor file in $rollback\n+\tdo\n+\t\tmv \"$PACKDIR/old-$file\" \"$PACKDIR/$file\" ||\n+\t\trollback_failure=\"$rollback_failure $file\"\n+\tdone\n+\tif test -n \"$rollback_failure\"\n+\tthen\n+\t\techo >&2 \"WARNING: Some packs in use have been renamed by\"\n+\t\techo >&2 \"WARNING: prefixing old- to their name, in order to\"\n+\t\techo >&2 \"WARNING: replace them with the new version of the\"\n+\t\techo >&2 \"WARNING: file.  But the operation failed, and\"\n+\t\techo >&2 \"WARNING: attempt to rename them back to their\"\n+\t\techo >&2 \"WARNING: original names also failed.\"\n+\t\techo >&2 \"WARNING: Please rename them in $PACKDIR manually:\"\n+\t\tfor file in $rollback_failure\n+\t\tdo\n+\t\t\techo >&2 \"WARNING:   old-$file -> $file\"\n+\t\tdone\n+\tfi\n+\texit 1\n+fi\n+\n+# Now the ones with the same name are out of the way...\n+fullbases=\n+for name in $names\n+do\n+\tfullbases=\"$fullbases pack-$name\"\n+\tchmod a-w \"$PACKTMP-$name.pack\"\n+\tchmod a-w \"$PACKTMP-$name.idx\"\n+\tmv -f \"$PACKTMP-$name.pack\" \"$PACKDIR/pack-$name.pack\" &&\n+\tmv -f \"$PACKTMP-$name.idx\"  \"$PACKDIR/pack-$name.idx\" ||\n+\texit\n+done\n+\n+# Remove the \"old-\" files\n+for name in $names\n+do\n+\trm -f \"$PACKDIR/old-pack-$name.idx\"\n+\trm -f \"$PACKDIR/old-pack-$name.pack\"\n+done\n+\n+# End of pack replacement.\n+\n+if test \"$remove_redundant\" = t\n+then\n+\t# We know $existing are all redundant.\n+\tif [ -n \"$existing\" ]\n+\tthen\n+\t\t( cd \"$PACKDIR\" &&\n+\t\t  for e in $existing\n+\t\t  do\n+\t\t\tcase \" $fullbases \" in\n+\t\t\t*\" $e \"*) ;;\n+\t\t\t*)\trm -f \"$e.pack\" \"$e.idx\" \"$e.keep\" ;;\n+\t\t\tesac\n+\t\t  done\n+\t\t)\n+\tfi\n+\tgit prune-packed ${GIT_QUIET:+-q}\n+fi\n+\n+case \"$no_update_info\" in\n+t) : ;;\n+*) git update-server-info ;;\n+esac\ndiff --git a/git-repack.sh b/git-repack.sh\ndeleted file mode 100755\nindex 624feec..0000000\n--- a/git-repack.sh\n+++ /dev/null\n@@ -1,186 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Linus Torvalds\n-#\n-\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_SPEC=\"\\\n-git repack [options]\n---\n-a               pack everything in a single pack\n-A               same as -a, and turn unreachable objects loose\n-d               remove redundant packs, and run git-prune-packed\n-f               pass --no-reuse-delta to git-pack-objects\n-F               pass --no-reuse-object to git-pack-objects\n-n               do not run git-update-server-info\n-q,quiet         be quiet\n-l               pass --local to git-pack-objects\n- Packing constraints\n-window=         size of the window used for delta compression\n-window-memory=  same as the above, but limit memory size instead of entries count\n-depth=          limits the maximum delta depth\n-max-pack-size=  maximum size of each packfile\n-\"\n-SUBDIRECTORY_OK='Yes'\n-. git-sh-setup\n-\n-no_update_info= all_into_one= remove_redundant= unpack_unreachable=\n-local= no_reuse= extra=\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t-n)\tno_update_info=t ;;\n-\t-a)\tall_into_one=t ;;\n-\t-A)\tall_into_one=t\n-\t\tunpack_unreachable=--unpack-unreachable ;;\n-\t-d)\tremove_redundant=t ;;\n-\t-q)\tGIT_QUIET=t ;;\n-\t-f)\tno_reuse=--no-reuse-delta ;;\n-\t-F)\tno_reuse=--no-reuse-object ;;\n-\t-l)\tlocal=--local ;;\n-\t--max-pack-size|--window|--window-memory|--depth)\n-\t\textra=\"$extra $1=$2\"; shift ;;\n-\t--) shift; break;;\n-\t*)\tusage ;;\n-\tesac\n-\tshift\n-done\n-\n-case \"`git config --bool repack.usedeltabaseoffset || echo true`\" in\n-true)\n-\textra=\"$extra --delta-base-offset\" ;;\n-esac\n-\n-PACKDIR=\"$GIT_OBJECT_DIRECTORY/pack\"\n-PACKTMP=\"$PACKDIR/.tmp-$$-pack\"\n-rm -f \"$PACKTMP\"-*\n-trap 'rm -f \"$PACKTMP\"-*' 0 1 2 3 15\n-\n-# There will be more repacking strategies to come...\n-case \",$all_into_one,\" in\n-,,)\n-\targs='--unpacked --incremental'\n-\t;;\n-,t,)\n-\targs= existing=\n-\tif [ -d \"$PACKDIR\" ]; then\n-\t\tfor e in `cd \"$PACKDIR\" && find . -type f -name '*.pack' \\\n-\t\t\t| sed -e 's/^\\.\\///' -e 's/\\.pack$//'`\n-\t\tdo\n-\t\t\tif [ -e \"$PACKDIR/$e.keep\" ]; then\n-\t\t\t\t: keep\n-\t\t\telse\n-\t\t\t\texisting=\"$existing $e\"\n-\t\t\tfi\n-\t\tdone\n-\t\tif test -n \"$existing\" -a -n \"$unpack_unreachable\" -a \\\n-\t\t\t-n \"$remove_redundant\"\n-\t\tthen\n-\t\t\targs=\"$args $unpack_unreachable\"\n-\t\tfi\n-\tfi\n-\t;;\n-esac\n-\n-mkdir -p \"$PACKDIR\" || exit\n-\n-args=\"$args $local ${GIT_QUIET:+-q} $no_reuse$extra\"\n-names=$(git pack-objects --keep-true-parents --honor-pack-keep --non-empty --all --reflog $args </dev/null \"$PACKTMP\") ||\n-\texit 1\n-if [ -z \"$names\" ]; then\n-\tsay Nothing new to pack.\n-fi\n-\n-# Ok we have prepared all new packfiles.\n-\n-# First see if there are packs of the same name and if so\n-# if we can move them out of the way (this can happen if we\n-# repacked immediately after packing fully.\n-rollback=\n-failed=\n-for name in $names\n-do\n-\tfor sfx in pack idx\n-\tdo\n-\t\tfile=pack-$name.$sfx\n-\t\ttest -f \"$PACKDIR/$file\" || continue\n-\t\trm -f \"$PACKDIR/old-$file\" &&\n-\t\tmv \"$PACKDIR/$file\" \"$PACKDIR/old-$file\" || {\n-\t\t\tfailed=t\n-\t\t\tbreak\n-\t\t}\n-\t\trollback=\"$rollback $file\"\n-\tdone\n-\ttest -z \"$failed\" || break\n-done\n-\n-# If renaming failed for any of them, roll the ones we have\n-# already renamed back to their original names.\n-if test -n \"$failed\"\n-then\n-\trollback_failure=\n-\tfor file in $rollback\n-\tdo\n-\t\tmv \"$PACKDIR/old-$file\" \"$PACKDIR/$file\" ||\n-\t\trollback_failure=\"$rollback_failure $file\"\n-\tdone\n-\tif test -n \"$rollback_failure\"\n-\tthen\n-\t\techo >&2 \"WARNING: Some packs in use have been renamed by\"\n-\t\techo >&2 \"WARNING: prefixing old- to their name, in order to\"\n-\t\techo >&2 \"WARNING: replace them with the new version of the\"\n-\t\techo >&2 \"WARNING: file.  But the operation failed, and\"\n-\t\techo >&2 \"WARNING: attempt to rename them back to their\"\n-\t\techo >&2 \"WARNING: original names also failed.\"\n-\t\techo >&2 \"WARNING: Please rename them in $PACKDIR manually:\"\n-\t\tfor file in $rollback_failure\n-\t\tdo\n-\t\t\techo >&2 \"WARNING:   old-$file -> $file\"\n-\t\tdone\n-\tfi\n-\texit 1\n-fi\n-\n-# Now the ones with the same name are out of the way...\n-fullbases=\n-for name in $names\n-do\n-\tfullbases=\"$fullbases pack-$name\"\n-\tchmod a-w \"$PACKTMP-$name.pack\"\n-\tchmod a-w \"$PACKTMP-$name.idx\"\n-\tmv -f \"$PACKTMP-$name.pack\" \"$PACKDIR/pack-$name.pack\" &&\n-\tmv -f \"$PACKTMP-$name.idx\"  \"$PACKDIR/pack-$name.idx\" ||\n-\texit\n-done\n-\n-# Remove the \"old-\" files\n-for name in $names\n-do\n-\trm -f \"$PACKDIR/old-pack-$name.idx\"\n-\trm -f \"$PACKDIR/old-pack-$name.pack\"\n-done\n-\n-# End of pack replacement.\n-\n-if test \"$remove_redundant\" = t\n-then\n-\t# We know $existing are all redundant.\n-\tif [ -n \"$existing\" ]\n-\tthen\n-\t\t( cd \"$PACKDIR\" &&\n-\t\t  for e in $existing\n-\t\t  do\n-\t\t\tcase \" $fullbases \" in\n-\t\t\t*\" $e \"*) ;;\n-\t\t\t*)\trm -f \"$e.pack\" \"$e.idx\" \"$e.keep\" ;;\n-\t\t\tesac\n-\t\t  done\n-\t\t)\n-\tfi\n-\tgit prune-packed ${GIT_QUIET:+-q}\n-fi\n-\n-case \"$no_update_info\" in\n-t) : ;;\n-*) git update-server-info ;;\n-esac\ndiff --git a/git.c b/git.c\nindex 8e34903..05235ca 100644\n--- a/git.c\n+++ b/git.c\n@@ -410,6 +410,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"remote-ext\", cmd_remote_ext },\n \t\t{ \"remote-fd\", cmd_remote_fd },\n \t\t{ \"replace\", cmd_replace, RUN_SETUP },\n+\t\t{ \"repack\", cmd_repack, RUN_SETUP },\n \t\t{ \"repo-config\", cmd_repo_config, RUN_SETUP_GENTLY },\n \t\t{ \"rerere\", cmd_rerere, RUN_SETUP },\n \t\t{ \"reset\", cmd_reset, RUN_SETUP },\n-- \n1.7.4.74.g639db\n"}]}