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
This commit is contained in:
@ -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);
|
||||
|
Reference in New Issue
Block a user