summaryrefslogtreecommitdiff
path: root/builtin-fast-export.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2009-07-26 11:23:52 -0700
committerJunio C Hamano <gitster@pobox.com>2009-07-26 11:23:52 -0700
commitfeab68cd91439cb9eef26f7197ac857da1238a49 (patch)
treed917cc66d7183d7a88d110d12d1241a53a78eaca /builtin-fast-export.c
parentd8f7be2ebcb7e3ec40269080a9ab9a28bc06ba17 (diff)
parent8af15d282e59a7f566b5e7eb71caebfc40ca5cd6 (diff)
downloadgit-feab68cd91439cb9eef26f7197ac857da1238a49.tar.gz
Merge branch 'en/fast-export'
* en/fast-export: fast-export: Document the fact that git-rev-list arguments are accepted Add new fast-export testcases fast-export: Add a --tag-of-filtered-object option for newly dangling tags fast-export: Do parent rewriting to avoid dropping relevant commits fast-export: Make sure we show actual ref names instead of "(null)" fast-export: Omit tags that tag trees fast-export: Set revs.topo_order before calling setup_revisions
Diffstat (limited to 'builtin-fast-export.c')
-rw-r--r--builtin-fast-export.c82
1 files changed, 75 insertions, 7 deletions
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index ca198250c3..c48c18d0c8 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -23,7 +23,8 @@ static const char *fast_export_usage[] = {
};
static int progress;
-static enum { VERBATIM, WARN, STRIP, ABORT } signed_tag_mode = ABORT;
+static enum { ABORT, VERBATIM, WARN, STRIP } signed_tag_mode = ABORT;
+static enum { ERROR, DROP, REWRITE } tag_of_filtered_mode = ABORT;
static int fake_missing_tagger;
static int parse_opt_signed_tag_mode(const struct option *opt,
@@ -42,6 +43,20 @@ static int parse_opt_signed_tag_mode(const struct option *opt,
return 0;
}
+static int parse_opt_tag_of_filtered_mode(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset || !strcmp(arg, "abort"))
+ tag_of_filtered_mode = ABORT;
+ else if (!strcmp(arg, "drop"))
+ tag_of_filtered_mode = DROP;
+ else if (!strcmp(arg, "rewrite"))
+ tag_of_filtered_mode = REWRITE;
+ else
+ return error("Unknown tag-of-filtered mode: %s", arg);
+ return 0;
+}
+
static struct decoration idnums;
static uint32_t last_idnum;
@@ -289,6 +304,23 @@ static void handle_tag(const char *name, struct tag *tag)
char *buf;
const char *tagger, *tagger_end, *message;
size_t message_size = 0;
+ struct object *tagged;
+ int tagged_mark;
+ struct commit *p;
+
+ /* Trees have no identifer in fast-export output, thus we have no way
+ * to output tags of trees, tags of tags of trees, etc. Simply omit
+ * such tags.
+ */
+ tagged = tag->tagged;
+ while (tagged->type == OBJ_TAG) {
+ tagged = ((struct tag *)tagged)->tagged;
+ }
+ if (tagged->type == OBJ_TREE) {
+ warning("Omitting tag %s,\nsince tags of trees (or tags of tags of trees, etc.) are not supported.",
+ sha1_to_hex(tag->object.sha1));
+ return;
+ }
buf = read_sha1_file(tag->object.sha1, &type, &size);
if (!buf)
@@ -333,10 +365,45 @@ static void handle_tag(const char *name, struct tag *tag)
}
}
+ /* handle tag->tagged having been filtered out due to paths specified */
+ tagged = tag->tagged;
+ tagged_mark = get_object_mark(tagged);
+ if (!tagged_mark) {
+ switch(tag_of_filtered_mode) {
+ case ABORT:
+ die ("Tag %s tags unexported object; use "
+ "--tag-of-filtered-object=<mode> to handle it.",
+ sha1_to_hex(tag->object.sha1));
+ case DROP:
+ /* Ignore this tag altogether */
+ return;
+ case REWRITE:
+ if (tagged->type != OBJ_COMMIT) {
+ die ("Tag %s tags unexported %s!",
+ sha1_to_hex(tag->object.sha1),
+ typename(tagged->type));
+ }
+ p = (struct commit *)tagged;
+ for (;;) {
+ if (p->parents && p->parents->next)
+ break;
+ if (p->object.flags & UNINTERESTING)
+ break;
+ if (!(p->object.flags & TREESAME))
+ break;
+ if (!p->parents)
+ die ("Can't find replacement commit for tag %s\n",
+ sha1_to_hex(tag->object.sha1));
+ p = p->parents->item;
+ }
+ tagged_mark = get_object_mark(&p->object);
+ }
+ }
+
if (!prefixcmp(name, "refs/tags/"))
name += 10;
printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
- name, get_object_mark(tag->tagged),
+ name, tagged_mark,
(int)(tagger_end - tagger), tagger,
tagger == tagger_end ? "" : "\n",
(int)message_size, (int)message_size, message ? message : "");
@@ -504,6 +571,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, "mode",
"select handling of signed tags",
parse_opt_signed_tag_mode),
+ OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, "mode",
+ "select handling of tags that tag filtered objects",
+ parse_opt_tag_of_filtered_mode),
OPT_STRING(0, "export-marks", &export_filename, "FILE",
"Dump marks to this file"),
OPT_STRING(0, "import-marks", &import_filename, "FILE",
@@ -520,6 +590,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
git_config(git_default_config, NULL);
init_revisions(&revs, prefix);
+ revs.topo_order = 1;
+ revs.show_source = 1;
+ revs.rewrite_parents = 1;
argc = setup_revisions(argc, argv, &revs, NULL);
argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
if (argc > 1)
@@ -530,18 +603,13 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
get_tags_and_duplicates(&revs.pending, &extra_refs);
- revs.topo_order = 1;
if (prepare_revision_walk(&revs))
die("revision walk setup failed");
revs.diffopt.format_callback = show_filemodify;
DIFF_OPT_SET(&revs.diffopt, RECURSIVE);
while ((commit = get_revision(&revs))) {
if (has_unshown_parent(commit)) {
- struct commit_list *parent = commit->parents;
add_object_array(&commit->object, NULL, &commits);
- for (; parent; parent = parent->next)
- if (!parent->item->util)
- parent->item->util = commit->util;
}
else {
handle_commit(commit, &revs);