{"thread":{"id":"5480","subject":"[PATCH 2/2] pack-object: run rev-list equivalent internally.","startedAt":"2006-09-05T07:30:40Z","lastAt":"2006-09-05T07:30:40Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"26347","messageId":"7v64g2kbxb.fsf@assigned-by-dhcp.cox.net","threadId":"5480","inReplyTo":null,"subject":"[PATCH 2/2] pack-object: run rev-list equivalent internally.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-09-05T07:30:40Z","receivedAt":"2006-09-05T07:30:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Instead of piping the rev-list output from its standard input,\nyou can say:\n\n\tpack-object --revs pack --all\n\nI am not happy about the command line parameter handling of this\npatch, so the syntax is very likely to change by the final\nversion.  Currently it understands the following:\n\n\tpack-object [options including --stdout]\n\tpack-object [options] pack-base-name\n\tpack-object [options] --revs pack-base-name [list options] refs...\n\tpack-object [options including --stdout] --revs [list options] refs...\n\nThe first two are for traditional behaviour and the latter two\nare the new ones.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n * This does not contain the \"pretend that objects in these\n   packs are loose when handing --unpacked requests\" I've sent\n   earlier.  I've also considered doing without --revs but the\n   parser can quickly get confused between pack-base-name and a\n   ref given to (internal) rev-list.  \"pack-object foobla\" might\n   be reading from standard input and creating foobla-*.pack, or\n   the user wanted to do a rev-list starting from foobla and\n   forgot to specify the base name, for example.\n\n builtin-pack-objects.c |  273 ++++++++++++++++++++++++++++++++++--------------\n 1 files changed, 192 insertions(+), 81 deletions(-)\n\ndiff --git a/builtin-pack-objects.c b/builtin-pack-objects.c\nindex 149fa28..74daf37 100644\n--- a/builtin-pack-objects.c\n+++ b/builtin-pack-objects.c\n@@ -9,10 +9,13 @@ #include \"delta.h\"\n #include \"pack.h\"\n #include \"csum-file.h\"\n #include \"tree-walk.h\"\n+#include \"diff.h\"\n+#include \"revision.h\"\n+#include \"list-objects.h\"\n #include <sys/time.h>\n #include <signal.h>\n \n-static const char pack_usage[] = \"git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list\";\n+static const char pack_usage[] = \"git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} [ --revs [--unpacked | --all | --not | <ref>]* | <object-list]\";\n \n struct object_entry {\n \tunsigned char sha1[20];\n@@ -1326,13 +1329,109 @@ static int git_pack_config(const char *k\n \treturn git_default_config(k, v);\n }\n \n+static void read_object_list_from_stdin(void)\n+{\n+\tint num_preferred_base = 0;\n+\tchar line[40 + 1 + PATH_MAX + 2];\n+\tunsigned char sha1[20];\n+\tunsigned hash;\n+\n+\tfor (;;) {\n+\t\tif (!fgets(line, sizeof(line), stdin)) {\n+\t\t\tif (feof(stdin))\n+\t\t\t\tbreak;\n+\t\t\tif (!ferror(stdin))\n+\t\t\t\tdie(\"fgets returned NULL, not EOF, not error!\");\n+\t\t\tif (errno != EINTR)\n+\t\t\t\tdie(\"fgets: %s\", strerror(errno));\n+\t\t\tclearerr(stdin);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (line[0] == '-') {\n+\t\t\tif (get_sha1_hex(line+1, sha1))\n+\t\t\t\tdie(\"expected edge sha1, got garbage:\\n %s\",\n+\t\t\t\t    line);\n+\t\t\tif (num_preferred_base++ < window)\n+\t\t\t\tadd_preferred_base(sha1);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (get_sha1_hex(line, sha1))\n+\t\t\tdie(\"expected sha1, got garbage:\\n %s\", line);\n+\n+\t\thash = name_hash(line+41);\n+\t\tadd_preferred_base_object(line+41, hash);\n+\t\tadd_object_entry(sha1, hash, 0);\n+\t}\n+}\n+\n+/* copied from rev-list but needs to do things slightly differently */\n+static void mark_edge_parents_uninteresting(struct commit *commit)\n+{\n+\tstruct commit_list *parents;\n+\n+\tfor (parents = commit->parents; parents; parents = parents->next) {\n+\t\tstruct commit *parent = parents->item;\n+\t\tif (!(parent->object.flags & UNINTERESTING))\n+\t\t\tcontinue;\n+\t\tmark_tree_uninteresting(parent->tree);\n+\t}\n+}\n+\n+static void mark_edges_uninteresting(struct commit_list *list)\n+{\n+\tfor ( ; list; list = list->next) {\n+\t\tstruct commit *commit = list->item;\n+\n+\t\tif (commit->object.flags & UNINTERESTING) {\n+\t\t\tmark_tree_uninteresting(commit->tree);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tmark_edge_parents_uninteresting(commit);\n+\t}\n+}\n+\n+static void show_commit(struct commit *commit)\n+{\n+\tunsigned hash = name_hash(\"\");\n+\tadd_object_entry(commit->object.sha1, hash, 0);\n+}\n+\n+static void show_object(struct object_array_entry *p)\n+{\n+\tunsigned hash = name_hash(p->name);\n+\tadd_object_entry(p->item->sha1, hash, 0);\n+}\n+\n+static void get_object_list(int ac, const char **av)\n+{\n+\tstruct rev_info revs;\n+\tconst char **revav = xcalloc(ac + 3, sizeof(*revav));\n+\n+\trevav[0] = \"pack-objects\";\n+\trevav[1] = \"--objects\";\n+\tmemcpy(revav + 2, av, sizeof(*av) * ac);\n+\n+\tinit_revisions(&revs, NULL);\n+\tsave_commit_buffer = 0;\n+\ttrack_object_refs = 0;\n+\tsetup_revisions(ac + 2, revav, &revs, NULL);\n+\n+\t/* make sure we did not get pathspecs */\n+\tif (revs.prune_data)\n+\t\tdie(\"pathspec given\");\n+\n+\tprepare_revision_walk(&revs);\n+\tmark_edges_uninteresting(revs.commits);\n+\n+\ttraverse_commit_list(&revs, show_commit, show_object);\n+}\n+\n int cmd_pack_objects(int argc, const char **argv, const char *prefix)\n {\n \tSHA_CTX ctx;\n-\tchar line[40 + 1 + PATH_MAX + 2];\n \tint depth = 10;\n \tstruct object_entry **list;\n-\tint num_preferred_base = 0;\n+\tint read_from_stdin = 1;\n \tint i;\n \n \tgit_config(git_pack_config);\n@@ -1341,58 +1440,94 @@ int cmd_pack_objects(int argc, const cha\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n \n-\t\tif (*arg == '-') {\n-\t\t\tif (!strcmp(\"--non-empty\", arg)) {\n-\t\t\t\tnon_empty = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--local\", arg)) {\n-\t\t\t\tlocal = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--progress\", arg)) {\n-\t\t\t\tprogress = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--incremental\", arg)) {\n-\t\t\t\tincremental = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strncmp(\"--window=\", arg, 9)) {\n-\t\t\t\tchar *end;\n-\t\t\t\twindow = strtoul(arg+9, &end, 0);\n-\t\t\t\tif (!arg[9] || *end)\n-\t\t\t\t\tusage(pack_usage);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strncmp(\"--depth=\", arg, 8)) {\n-\t\t\t\tchar *end;\n-\t\t\t\tdepth = strtoul(arg+8, &end, 0);\n-\t\t\t\tif (!arg[8] || *end)\n-\t\t\t\t\tusage(pack_usage);\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--progress\", arg)) {\n-\t\t\t\tprogress = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"-q\", arg)) {\n-\t\t\t\tprogress = 0;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--no-reuse-delta\", arg)) {\n-\t\t\t\tno_reuse_delta = 1;\n-\t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tif (!strcmp(\"--stdout\", arg)) {\n-\t\t\t\tpack_to_stdout = 1;\n+\t\tif (*arg != '-')\n+\t\t\tbreak;\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(\"--progress\", arg)) {\n+\t\t\tprogress = 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 (!strncmp(\"--window=\", arg, 9)) {\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 (!strncmp(\"--depth=\", arg, 8)) {\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(\"-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\tno_reuse_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\tread_from_stdin = 0;\n+\t\t\ti++;\n+\t\t\tbreak;\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+\t * have been given to upstream rev-list ourselves, which means\n+\t * we somehow want to say what the base name is.  So the\n+\t * syntax would be:\n+\t *\n+\t * pack-objects [options] base <refs...>\n+\t *\n+\t * in other words, we would treat the first non-option as the\n+\t * base_name and send everything else to the internal revision\n+\t * walker.\n+\t */\n+\n+\tif (!pack_to_stdout)\n+\t\tbase_name = argv[i++];\n+\n+\tif (!read_from_stdin) {\n+\t\tint j;\n+\t\t/* the rest are used as refs parameter to rev-list;\n+\t\t * we only allow refs (including a..b and a...b notation),\n+\t\t * --all, --not, and --unpacked.\n+\t\t */\n+\t\tfor (j = i; j < argc; j++) {\n+\t\t\tconst char *arg = argv[j];\n+\t\t\tif ((arg[0] != '-') ||\n+\t\t\t    !strcmp(arg, \"--unpacked\") ||\n+\t\t\t    !strcmp(arg, \"--all\") ||\n+\t\t\t    !strcmp(arg, \"--not\"))\n \t\t\t\tcontinue;\n-\t\t\t}\n-\t\t\tusage(pack_usage);\n+\t\t\tdie(\"cannot use --revs with %s\", arg);\n \t\t}\n-\t\tif (base_name)\n-\t\t\tusage(pack_usage);\n-\t\tbase_name = arg;\n \t}\n \n \tif (pack_to_stdout != !base_name)\n@@ -1405,35 +1540,11 @@ int cmd_pack_objects(int argc, const cha\n \t\tsetup_progress_signal();\n \t}\n \n-\tfor (;;) {\n-\t\tunsigned char sha1[20];\n-\t\tunsigned hash;\n-\n-\t\tif (!fgets(line, sizeof(line), stdin)) {\n-\t\t\tif (feof(stdin))\n-\t\t\t\tbreak;\n-\t\t\tif (!ferror(stdin))\n-\t\t\t\tdie(\"fgets returned NULL, not EOF, not error!\");\n-\t\t\tif (errno != EINTR)\n-\t\t\t\tdie(\"fgets: %s\", strerror(errno));\n-\t\t\tclearerr(stdin);\n-\t\t\tcontinue;\n-\t\t}\n+\tif (read_from_stdin)\n+\t\tread_object_list_from_stdin();\n+\telse\n+\t\tget_object_list(argc - i, argv + i);\n \n-\t\tif (line[0] == '-') {\n-\t\t\tif (get_sha1_hex(line+1, sha1))\n-\t\t\t\tdie(\"expected edge sha1, got garbage:\\n %s\",\n-\t\t\t\t    line+1);\n-\t\t\tif (num_preferred_base++ < window)\n-\t\t\t\tadd_preferred_base(sha1);\n-\t\t\tcontinue;\n-\t\t}\n-\t\tif (get_sha1_hex(line, sha1))\n-\t\t\tdie(\"expected sha1, got garbage:\\n %s\", line);\n-\t\thash = name_hash(line+41);\n-\t\tadd_preferred_base_object(line+41, hash);\n-\t\tadd_object_entry(sha1, hash, 0);\n-\t}\n \tif (progress)\n \t\tfprintf(stderr, \"Done counting %d objects.\\n\", nr_objects);\n \tsorted_by_sha = create_final_object_list();\n-- \n1.4.2.g552e5\n"}]}