From: Junio C Hamano <junkio@cox.net>
To: git@vger.kernel.org
Subject: [PATCH 2/2] pack-object: run rev-list equivalent internally.
Date: Tue, 05 Sep 2006 00:30:40 -0700 [thread overview]
Message-ID: <7v64g2kbxb.fsf@assigned-by-dhcp.cox.net> (raw)
Instead of piping the rev-list output from its standard input,
you can say:
pack-object --revs pack --all
I am not happy about the command line parameter handling of this
patch, so the syntax is very likely to change by the final
version. Currently it understands the following:
pack-object [options including --stdout]
pack-object [options] pack-base-name
pack-object [options] --revs pack-base-name [list options] refs...
pack-object [options including --stdout] --revs [list options] refs...
The first two are for traditional behaviour and the latter two
are the new ones.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* This does not contain the "pretend that objects in these
packs are loose when handing --unpacked requests" I've sent
earlier. I've also considered doing without --revs but the
parser can quickly get confused between pack-base-name and a
ref given to (internal) rev-list. "pack-object foobla" might
be reading from standard input and creating foobla-*.pack, or
the user wanted to do a rev-list starting from foobla and
forgot to specify the base name, for example.
builtin-pack-objects.c | 273 ++++++++++++++++++++++++++++++++++--------------
1 files changed, 192 insertions(+), 81 deletions(-)
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 149fa28..74daf37 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -9,10 +9,13 @@ #include "delta.h"
#include "pack.h"
#include "csum-file.h"
#include "tree-walk.h"
+#include "diff.h"
+#include "revision.h"
+#include "list-objects.h"
#include <sys/time.h>
#include <signal.h>
-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";
+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]";
struct object_entry {
unsigned char sha1[20];
@@ -1326,13 +1329,109 @@ static int git_pack_config(const char *k
return git_default_config(k, v);
}
+static void read_object_list_from_stdin(void)
+{
+ int num_preferred_base = 0;
+ char line[40 + 1 + PATH_MAX + 2];
+ unsigned char sha1[20];
+ unsigned hash;
+
+ for (;;) {
+ if (!fgets(line, sizeof(line), stdin)) {
+ if (feof(stdin))
+ break;
+ if (!ferror(stdin))
+ die("fgets returned NULL, not EOF, not error!");
+ if (errno != EINTR)
+ die("fgets: %s", strerror(errno));
+ clearerr(stdin);
+ continue;
+ }
+ if (line[0] == '-') {
+ if (get_sha1_hex(line+1, sha1))
+ die("expected edge sha1, got garbage:\n %s",
+ line);
+ if (num_preferred_base++ < window)
+ add_preferred_base(sha1);
+ continue;
+ }
+ if (get_sha1_hex(line, sha1))
+ die("expected sha1, got garbage:\n %s", line);
+
+ hash = name_hash(line+41);
+ add_preferred_base_object(line+41, hash);
+ add_object_entry(sha1, hash, 0);
+ }
+}
+
+/* copied from rev-list but needs to do things slightly differently */
+static void mark_edge_parents_uninteresting(struct commit *commit)
+{
+ struct commit_list *parents;
+
+ for (parents = commit->parents; parents; parents = parents->next) {
+ struct commit *parent = parents->item;
+ if (!(parent->object.flags & UNINTERESTING))
+ continue;
+ mark_tree_uninteresting(parent->tree);
+ }
+}
+
+static void mark_edges_uninteresting(struct commit_list *list)
+{
+ for ( ; list; list = list->next) {
+ struct commit *commit = list->item;
+
+ if (commit->object.flags & UNINTERESTING) {
+ mark_tree_uninteresting(commit->tree);
+ continue;
+ }
+ mark_edge_parents_uninteresting(commit);
+ }
+}
+
+static void show_commit(struct commit *commit)
+{
+ unsigned hash = name_hash("");
+ add_object_entry(commit->object.sha1, hash, 0);
+}
+
+static void show_object(struct object_array_entry *p)
+{
+ unsigned hash = name_hash(p->name);
+ add_object_entry(p->item->sha1, hash, 0);
+}
+
+static void get_object_list(int ac, const char **av)
+{
+ struct rev_info revs;
+ const char **revav = xcalloc(ac + 3, sizeof(*revav));
+
+ revav[0] = "pack-objects";
+ revav[1] = "--objects";
+ memcpy(revav + 2, av, sizeof(*av) * ac);
+
+ init_revisions(&revs, NULL);
+ save_commit_buffer = 0;
+ track_object_refs = 0;
+ setup_revisions(ac + 2, revav, &revs, NULL);
+
+ /* make sure we did not get pathspecs */
+ if (revs.prune_data)
+ die("pathspec given");
+
+ prepare_revision_walk(&revs);
+ mark_edges_uninteresting(revs.commits);
+
+ traverse_commit_list(&revs, show_commit, show_object);
+}
+
int cmd_pack_objects(int argc, const char **argv, const char *prefix)
{
SHA_CTX ctx;
- char line[40 + 1 + PATH_MAX + 2];
int depth = 10;
struct object_entry **list;
- int num_preferred_base = 0;
+ int read_from_stdin = 1;
int i;
git_config(git_pack_config);
@@ -1341,58 +1440,94 @@ int cmd_pack_objects(int argc, const cha
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
- if (*arg == '-') {
- if (!strcmp("--non-empty", arg)) {
- non_empty = 1;
- continue;
- }
- if (!strcmp("--local", arg)) {
- local = 1;
- continue;
- }
- if (!strcmp("--progress", arg)) {
- progress = 1;
- continue;
- }
- if (!strcmp("--incremental", arg)) {
- incremental = 1;
- continue;
- }
- if (!strncmp("--window=", arg, 9)) {
- char *end;
- window = strtoul(arg+9, &end, 0);
- if (!arg[9] || *end)
- usage(pack_usage);
- continue;
- }
- if (!strncmp("--depth=", arg, 8)) {
- char *end;
- depth = strtoul(arg+8, &end, 0);
- if (!arg[8] || *end)
- usage(pack_usage);
- continue;
- }
- if (!strcmp("--progress", arg)) {
- progress = 1;
- continue;
- }
- if (!strcmp("-q", arg)) {
- progress = 0;
- continue;
- }
- if (!strcmp("--no-reuse-delta", arg)) {
- no_reuse_delta = 1;
- continue;
- }
- if (!strcmp("--stdout", arg)) {
- pack_to_stdout = 1;
+ if (*arg != '-')
+ break;
+
+ if (!strcmp("--non-empty", arg)) {
+ non_empty = 1;
+ continue;
+ }
+ if (!strcmp("--local", arg)) {
+ local = 1;
+ continue;
+ }
+ if (!strcmp("--progress", arg)) {
+ progress = 1;
+ continue;
+ }
+ if (!strcmp("--incremental", arg)) {
+ incremental = 1;
+ continue;
+ }
+ if (!strncmp("--window=", arg, 9)) {
+ char *end;
+ window = strtoul(arg+9, &end, 0);
+ if (!arg[9] || *end)
+ usage(pack_usage);
+ continue;
+ }
+ if (!strncmp("--depth=", arg, 8)) {
+ char *end;
+ depth = strtoul(arg+8, &end, 0);
+ if (!arg[8] || *end)
+ usage(pack_usage);
+ continue;
+ }
+ if (!strcmp("--progress", arg)) {
+ progress = 1;
+ continue;
+ }
+ if (!strcmp("-q", arg)) {
+ progress = 0;
+ continue;
+ }
+ if (!strcmp("--no-reuse-delta", arg)) {
+ no_reuse_delta = 1;
+ continue;
+ }
+ if (!strcmp("--stdout", arg)) {
+ pack_to_stdout = 1;
+ continue;
+ }
+ if (!strcmp("--revs", arg)) {
+ read_from_stdin = 0;
+ i++;
+ break;
+ }
+ usage(pack_usage);
+ }
+
+ /* Traditionally "pack-objects [options] base extra" failed;
+ * we would however want to take refs parameter that would
+ * have been given to upstream rev-list ourselves, which means
+ * we somehow want to say what the base name is. So the
+ * syntax would be:
+ *
+ * pack-objects [options] base <refs...>
+ *
+ * in other words, we would treat the first non-option as the
+ * base_name and send everything else to the internal revision
+ * walker.
+ */
+
+ if (!pack_to_stdout)
+ base_name = argv[i++];
+
+ if (!read_from_stdin) {
+ int j;
+ /* the rest are used as refs parameter to rev-list;
+ * we only allow refs (including a..b and a...b notation),
+ * --all, --not, and --unpacked.
+ */
+ for (j = i; j < argc; j++) {
+ const char *arg = argv[j];
+ if ((arg[0] != '-') ||
+ !strcmp(arg, "--unpacked") ||
+ !strcmp(arg, "--all") ||
+ !strcmp(arg, "--not"))
continue;
- }
- usage(pack_usage);
+ die("cannot use --revs with %s", arg);
}
- if (base_name)
- usage(pack_usage);
- base_name = arg;
}
if (pack_to_stdout != !base_name)
@@ -1405,35 +1540,11 @@ int cmd_pack_objects(int argc, const cha
setup_progress_signal();
}
- for (;;) {
- unsigned char sha1[20];
- unsigned hash;
-
- if (!fgets(line, sizeof(line), stdin)) {
- if (feof(stdin))
- break;
- if (!ferror(stdin))
- die("fgets returned NULL, not EOF, not error!");
- if (errno != EINTR)
- die("fgets: %s", strerror(errno));
- clearerr(stdin);
- continue;
- }
+ if (read_from_stdin)
+ read_object_list_from_stdin();
+ else
+ get_object_list(argc - i, argv + i);
- if (line[0] == '-') {
- if (get_sha1_hex(line+1, sha1))
- die("expected edge sha1, got garbage:\n %s",
- line+1);
- if (num_preferred_base++ < window)
- add_preferred_base(sha1);
- continue;
- }
- if (get_sha1_hex(line, sha1))
- die("expected sha1, got garbage:\n %s", line);
- hash = name_hash(line+41);
- add_preferred_base_object(line+41, hash);
- add_object_entry(sha1, hash, 0);
- }
if (progress)
fprintf(stderr, "Done counting %d objects.\n", nr_objects);
sorted_by_sha = create_final_object_list();
--
1.4.2.g552e5
reply other threads:[~2006-09-05 7:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7v64g2kbxb.fsf@assigned-by-dhcp.cox.net \
--to=junkio@cox.net \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox