Merge branch 'en/fast-imexport-nested-tags'
Updates to fast-import/export. * en/fast-imexport-nested-tags: fast-export: handle nested tags t9350: add tests for tags of things other than a commit fast-export: allow user to request tags be marked with --mark-tags fast-export: add support for --import-marks-if-exists fast-import: add support for new 'alias' command fast-import: allow tags to be identified by mark labels fast-import: fix handling of deleted tags fast-export: fix exporting a tag and nothing elsemaint
commit
16d9d7184b
|
@ -75,11 +75,20 @@ produced incorrect results if you gave these options.
|
||||||
Before processing any input, load the marks specified in
|
Before processing any input, load the marks specified in
|
||||||
<file>. The input file must exist, must be readable, and
|
<file>. The input file must exist, must be readable, and
|
||||||
must use the same format as produced by --export-marks.
|
must use the same format as produced by --export-marks.
|
||||||
|
|
||||||
|
--mark-tags::
|
||||||
|
In addition to labelling blobs and commits with mark ids, also
|
||||||
|
label tags. This is useful in conjunction with
|
||||||
|
`--export-marks` and `--import-marks`, and is also useful (and
|
||||||
|
necessary) for exporting of nested tags. It does not hurt
|
||||||
|
other cases and would be the default, but many fast-import
|
||||||
|
frontends are not prepared to accept tags with mark
|
||||||
|
identifiers.
|
||||||
+
|
+
|
||||||
Any commits that have already been marked will not be exported again.
|
Any commits (or tags) that have already been marked will not be
|
||||||
If the backend uses a similar --import-marks file, this allows for
|
exported again. If the backend uses a similar --import-marks file,
|
||||||
incremental bidirectional exporting of the repository by keeping the
|
this allows for incremental bidirectional exporting of the repository
|
||||||
marks the same across runs.
|
by keeping the marks the same across runs.
|
||||||
|
|
||||||
--fake-missing-tagger::
|
--fake-missing-tagger::
|
||||||
Some old repositories have tags without a tagger. The
|
Some old repositories have tags without a tagger. The
|
||||||
|
|
|
@ -337,6 +337,13 @@ and control the current import process. More detailed discussion
|
||||||
`commit` command. This command is optional and is not
|
`commit` command. This command is optional and is not
|
||||||
needed to perform an import.
|
needed to perform an import.
|
||||||
|
|
||||||
|
`alias`::
|
||||||
|
Record that a mark refers to a given object without first
|
||||||
|
creating any new object. Using --import-marks and referring
|
||||||
|
to missing marks will cause fast-import to fail, so aliases
|
||||||
|
can provide a way to set otherwise pruned commits to a valid
|
||||||
|
value (e.g. the nearest non-pruned ancestor).
|
||||||
|
|
||||||
`checkpoint`::
|
`checkpoint`::
|
||||||
Forces fast-import to close the current packfile, generate its
|
Forces fast-import to close the current packfile, generate its
|
||||||
unique SHA-1 checksum and index, and start a new packfile.
|
unique SHA-1 checksum and index, and start a new packfile.
|
||||||
|
@ -774,6 +781,7 @@ lightweight (non-annotated) tags see the `reset` command below.
|
||||||
|
|
||||||
....
|
....
|
||||||
'tag' SP <name> LF
|
'tag' SP <name> LF
|
||||||
|
mark?
|
||||||
'from' SP <commit-ish> LF
|
'from' SP <commit-ish> LF
|
||||||
original-oid?
|
original-oid?
|
||||||
'tagger' (SP <name>)? SP LT <email> GT SP <when> LF
|
'tagger' (SP <name>)? SP LT <email> GT SP <when> LF
|
||||||
|
@ -913,6 +921,21 @@ a data chunk which does not have an LF as its last byte.
|
||||||
+
|
+
|
||||||
The `LF` after `<delim> LF` is optional (it used to be required).
|
The `LF` after `<delim> LF` is optional (it used to be required).
|
||||||
|
|
||||||
|
`alias`
|
||||||
|
~~~~~~~
|
||||||
|
Record that a mark refers to a given object without first creating any
|
||||||
|
new object.
|
||||||
|
|
||||||
|
....
|
||||||
|
'alias' LF
|
||||||
|
mark
|
||||||
|
'to' SP <commit-ish> LF
|
||||||
|
LF?
|
||||||
|
....
|
||||||
|
|
||||||
|
For a detailed description of `<commit-ish>` see above under `from`.
|
||||||
|
|
||||||
|
|
||||||
`checkpoint`
|
`checkpoint`
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
Forces fast-import to close the current packfile, start a new one, and to
|
Forces fast-import to close the current packfile, start a new one, and to
|
||||||
|
|
|
@ -40,6 +40,7 @@ static int no_data;
|
||||||
static int full_tree;
|
static int full_tree;
|
||||||
static int reference_excluded_commits;
|
static int reference_excluded_commits;
|
||||||
static int show_original_ids;
|
static int show_original_ids;
|
||||||
|
static int mark_tags;
|
||||||
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
|
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
|
||||||
static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
|
static struct string_list tag_refs = STRING_LIST_INIT_NODUP;
|
||||||
static struct refspec refspecs = REFSPEC_INIT_FETCH;
|
static struct refspec refspecs = REFSPEC_INIT_FETCH;
|
||||||
|
@ -842,11 +843,9 @@ static void handle_tag(const char *name, struct tag *tag)
|
||||||
free(buf);
|
free(buf);
|
||||||
return;
|
return;
|
||||||
case REWRITE:
|
case REWRITE:
|
||||||
if (tagged->type != OBJ_COMMIT) {
|
if (tagged->type == OBJ_TAG && !mark_tags) {
|
||||||
die("tag %s tags unexported %s!",
|
die(_("Error: Cannot export nested tags unless --mark-tags is specified."));
|
||||||
oid_to_hex(&tag->object.oid),
|
} else if (tagged->type == OBJ_COMMIT) {
|
||||||
type_name(tagged->type));
|
|
||||||
}
|
|
||||||
p = rewrite_commit((struct commit *)tagged);
|
p = rewrite_commit((struct commit *)tagged);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
printf("reset %s\nfrom %s\n\n",
|
printf("reset %s\nfrom %s\n\n",
|
||||||
|
@ -855,12 +854,29 @@ static void handle_tag(const char *name, struct tag *tag)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tagged_mark = get_object_mark(&p->object);
|
tagged_mark = get_object_mark(&p->object);
|
||||||
|
} else {
|
||||||
|
/* tagged->type is either OBJ_BLOB or OBJ_TAG */
|
||||||
|
tagged_mark = get_object_mark(tagged);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tagged->type == OBJ_TAG) {
|
||||||
|
printf("reset %s\nfrom %s\n\n",
|
||||||
|
name, oid_to_hex(&null_oid));
|
||||||
|
}
|
||||||
if (starts_with(name, "refs/tags/"))
|
if (starts_with(name, "refs/tags/"))
|
||||||
name += 10;
|
name += 10;
|
||||||
printf("tag %s\nfrom :%d\n", name, tagged_mark);
|
printf("tag %s\n", name);
|
||||||
|
if (mark_tags) {
|
||||||
|
mark_next_object(&tag->object);
|
||||||
|
printf("mark :%"PRIu32"\n", last_idnum);
|
||||||
|
}
|
||||||
|
if (tagged_mark)
|
||||||
|
printf("from :%d\n", tagged_mark);
|
||||||
|
else
|
||||||
|
printf("from %s\n", oid_to_hex(&tagged->oid));
|
||||||
|
|
||||||
if (show_original_ids)
|
if (show_original_ids)
|
||||||
printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
|
printf("original-oid %s\n", oid_to_hex(&tag->object.oid));
|
||||||
printf("%.*s%sdata %d\n%.*s\n",
|
printf("%.*s%sdata %d\n%.*s\n",
|
||||||
|
@ -1047,11 +1063,16 @@ static void export_marks(char *file)
|
||||||
error("Unable to write marks file %s.", file);
|
error("Unable to write marks file %s.", file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void import_marks(char *input_file)
|
static void import_marks(char *input_file, int check_exists)
|
||||||
{
|
{
|
||||||
char line[512];
|
char line[512];
|
||||||
FILE *f = xfopen(input_file, "r");
|
FILE *f;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
if (check_exists && stat(input_file, &sb))
|
||||||
|
return;
|
||||||
|
|
||||||
|
f = xfopen(input_file, "r");
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
uint32_t mark;
|
uint32_t mark;
|
||||||
char *line_end, *mark_end;
|
char *line_end, *mark_end;
|
||||||
|
@ -1115,7 +1136,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
struct object_array commits = OBJECT_ARRAY_INIT;
|
struct object_array commits = OBJECT_ARRAY_INIT;
|
||||||
struct commit *commit;
|
struct commit *commit;
|
||||||
char *export_filename = NULL, *import_filename = NULL;
|
char *export_filename = NULL,
|
||||||
|
*import_filename = NULL,
|
||||||
|
*import_filename_if_exists = NULL;
|
||||||
uint32_t lastimportid;
|
uint32_t lastimportid;
|
||||||
struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
|
struct string_list refspecs_list = STRING_LIST_INIT_NODUP;
|
||||||
struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
|
struct string_list paths_of_changed_objects = STRING_LIST_INIT_DUP;
|
||||||
|
@ -1135,6 +1158,10 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||||
N_("Dump marks to this file")),
|
N_("Dump marks to this file")),
|
||||||
OPT_STRING(0, "import-marks", &import_filename, N_("file"),
|
OPT_STRING(0, "import-marks", &import_filename, N_("file"),
|
||||||
N_("Import marks from this file")),
|
N_("Import marks from this file")),
|
||||||
|
OPT_STRING(0, "import-marks-if-exists",
|
||||||
|
&import_filename_if_exists,
|
||||||
|
N_("file"),
|
||||||
|
N_("Import marks from this file if it exists")),
|
||||||
OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
|
OPT_BOOL(0, "fake-missing-tagger", &fake_missing_tagger,
|
||||||
N_("Fake a tagger when tags lack one")),
|
N_("Fake a tagger when tags lack one")),
|
||||||
OPT_BOOL(0, "full-tree", &full_tree,
|
OPT_BOOL(0, "full-tree", &full_tree,
|
||||||
|
@ -1149,6 +1176,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||||
&reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")),
|
&reference_excluded_commits, N_("Reference parents which are not in fast-export stream by object id")),
|
||||||
OPT_BOOL(0, "show-original-ids", &show_original_ids,
|
OPT_BOOL(0, "show-original-ids", &show_original_ids,
|
||||||
N_("Show original object ids of blobs/commits")),
|
N_("Show original object ids of blobs/commits")),
|
||||||
|
OPT_BOOL(0, "mark-tags", &mark_tags,
|
||||||
|
N_("Label tags with mark ids")),
|
||||||
|
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
@ -1182,8 +1211,12 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
||||||
if (use_done_feature)
|
if (use_done_feature)
|
||||||
printf("feature done\n");
|
printf("feature done\n");
|
||||||
|
|
||||||
|
if (import_filename && import_filename_if_exists)
|
||||||
|
die(_("Cannot pass both --import-marks and --import-marks-if-exists"));
|
||||||
if (import_filename)
|
if (import_filename)
|
||||||
import_marks(import_filename);
|
import_marks(import_filename, 0);
|
||||||
|
else if (import_filename_if_exists)
|
||||||
|
import_marks(import_filename_if_exists, 1);
|
||||||
lastimportid = last_idnum;
|
lastimportid = last_idnum;
|
||||||
|
|
||||||
if (import_filename && revs.prune_data.nr)
|
if (import_filename && revs.prune_data.nr)
|
||||||
|
|
|
@ -2489,18 +2489,14 @@ static void parse_from_existing(struct branch *b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_from(struct branch *b)
|
static int parse_objectish(struct branch *b, const char *objectish)
|
||||||
{
|
{
|
||||||
const char *from;
|
|
||||||
struct branch *s;
|
struct branch *s;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
|
|
||||||
if (!skip_prefix(command_buf.buf, "from ", &from))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
oidcpy(&oid, &b->branch_tree.versions[1].oid);
|
oidcpy(&oid, &b->branch_tree.versions[1].oid);
|
||||||
|
|
||||||
s = lookup_branch(from);
|
s = lookup_branch(objectish);
|
||||||
if (b == s)
|
if (b == s)
|
||||||
die("Can't create a branch from itself: %s", b->name);
|
die("Can't create a branch from itself: %s", b->name);
|
||||||
else if (s) {
|
else if (s) {
|
||||||
|
@ -2508,8 +2504,8 @@ static int parse_from(struct branch *b)
|
||||||
oidcpy(&b->oid, &s->oid);
|
oidcpy(&b->oid, &s->oid);
|
||||||
oidcpy(&b->branch_tree.versions[0].oid, t);
|
oidcpy(&b->branch_tree.versions[0].oid, t);
|
||||||
oidcpy(&b->branch_tree.versions[1].oid, t);
|
oidcpy(&b->branch_tree.versions[1].oid, t);
|
||||||
} else if (*from == ':') {
|
} else if (*objectish == ':') {
|
||||||
uintmax_t idnum = parse_mark_ref_eol(from);
|
uintmax_t idnum = parse_mark_ref_eol(objectish);
|
||||||
struct object_entry *oe = find_mark(idnum);
|
struct object_entry *oe = find_mark(idnum);
|
||||||
if (oe->type != OBJ_COMMIT)
|
if (oe->type != OBJ_COMMIT)
|
||||||
die("Mark :%" PRIuMAX " not a commit", idnum);
|
die("Mark :%" PRIuMAX " not a commit", idnum);
|
||||||
|
@ -2523,13 +2519,13 @@ static int parse_from(struct branch *b)
|
||||||
} else
|
} else
|
||||||
parse_from_existing(b);
|
parse_from_existing(b);
|
||||||
}
|
}
|
||||||
} else if (!get_oid(from, &b->oid)) {
|
} else if (!get_oid(objectish, &b->oid)) {
|
||||||
parse_from_existing(b);
|
parse_from_existing(b);
|
||||||
if (is_null_oid(&b->oid))
|
if (is_null_oid(&b->oid))
|
||||||
b->delete = 1;
|
b->delete = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
die("Invalid ref name or SHA1 expression: %s", from);
|
die("Invalid ref name or SHA1 expression: %s", objectish);
|
||||||
|
|
||||||
if (b->branch_tree.tree && !oideq(&oid, &b->branch_tree.versions[1].oid)) {
|
if (b->branch_tree.tree && !oideq(&oid, &b->branch_tree.versions[1].oid)) {
|
||||||
release_tree_content_recursive(b->branch_tree.tree);
|
release_tree_content_recursive(b->branch_tree.tree);
|
||||||
|
@ -2540,6 +2536,26 @@ static int parse_from(struct branch *b)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_from(struct branch *b)
|
||||||
|
{
|
||||||
|
const char *from;
|
||||||
|
|
||||||
|
if (!skip_prefix(command_buf.buf, "from ", &from))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return parse_objectish(b, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int parse_objectish_with_prefix(struct branch *b, const char *prefix)
|
||||||
|
{
|
||||||
|
const char *base;
|
||||||
|
|
||||||
|
if (!skip_prefix(command_buf.buf, prefix, &base))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return parse_objectish(b, base);
|
||||||
|
}
|
||||||
|
|
||||||
static struct hash_list *parse_merge(unsigned int *count)
|
static struct hash_list *parse_merge(unsigned int *count)
|
||||||
{
|
{
|
||||||
struct hash_list *list = NULL, **tail = &list, *n;
|
struct hash_list *list = NULL, **tail = &list, *n;
|
||||||
|
@ -2714,6 +2730,7 @@ static void parse_new_tag(const char *arg)
|
||||||
first_tag = t;
|
first_tag = t;
|
||||||
last_tag = t;
|
last_tag = t;
|
||||||
read_next_command();
|
read_next_command();
|
||||||
|
parse_mark();
|
||||||
|
|
||||||
/* from ... */
|
/* from ... */
|
||||||
if (!skip_prefix(command_buf.buf, "from ", &from))
|
if (!skip_prefix(command_buf.buf, "from ", &from))
|
||||||
|
@ -2770,7 +2787,7 @@ static void parse_new_tag(const char *arg)
|
||||||
strbuf_addbuf(&new_data, &msg);
|
strbuf_addbuf(&new_data, &msg);
|
||||||
free(tagger);
|
free(tagger);
|
||||||
|
|
||||||
if (store_object(OBJ_TAG, &new_data, NULL, &t->oid, 0))
|
if (store_object(OBJ_TAG, &new_data, NULL, &t->oid, next_mark))
|
||||||
t->pack_id = MAX_PACK_ID;
|
t->pack_id = MAX_PACK_ID;
|
||||||
else
|
else
|
||||||
t->pack_id = pack_id;
|
t->pack_id = pack_id;
|
||||||
|
@ -2779,6 +2796,7 @@ static void parse_new_tag(const char *arg)
|
||||||
static void parse_reset_branch(const char *arg)
|
static void parse_reset_branch(const char *arg)
|
||||||
{
|
{
|
||||||
struct branch *b;
|
struct branch *b;
|
||||||
|
const char *tag_name;
|
||||||
|
|
||||||
b = lookup_branch(arg);
|
b = lookup_branch(arg);
|
||||||
if (b) {
|
if (b) {
|
||||||
|
@ -2794,6 +2812,32 @@ static void parse_reset_branch(const char *arg)
|
||||||
b = new_branch(arg);
|
b = new_branch(arg);
|
||||||
read_next_command();
|
read_next_command();
|
||||||
parse_from(b);
|
parse_from(b);
|
||||||
|
if (b->delete && skip_prefix(b->name, "refs/tags/", &tag_name)) {
|
||||||
|
/*
|
||||||
|
* Elsewhere, we call dump_branches() before dump_tags(),
|
||||||
|
* and dump_branches() will handle ref deletions first, so
|
||||||
|
* in order to make sure the deletion actually takes effect,
|
||||||
|
* we need to remove the tag from our list of tags to update.
|
||||||
|
*
|
||||||
|
* NEEDSWORK: replace list of tags with hashmap for faster
|
||||||
|
* deletion?
|
||||||
|
*/
|
||||||
|
struct tag *t, *prev = NULL;
|
||||||
|
for (t = first_tag; t; t = t->next_tag) {
|
||||||
|
if (!strcmp(t->name, tag_name))
|
||||||
|
break;
|
||||||
|
prev = t;
|
||||||
|
}
|
||||||
|
if (t) {
|
||||||
|
if (prev)
|
||||||
|
prev->next_tag = t->next_tag;
|
||||||
|
else
|
||||||
|
first_tag = t->next_tag;
|
||||||
|
if (!t->next_tag)
|
||||||
|
last_tag = prev;
|
||||||
|
/* There is no mem_pool_free(t) function to call. */
|
||||||
|
}
|
||||||
|
}
|
||||||
if (command_buf.len > 0)
|
if (command_buf.len > 0)
|
||||||
unread_command_buf = 1;
|
unread_command_buf = 1;
|
||||||
}
|
}
|
||||||
|
@ -3060,6 +3104,28 @@ static void parse_progress(void)
|
||||||
skip_optional_lf();
|
skip_optional_lf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_alias(void)
|
||||||
|
{
|
||||||
|
struct object_entry *e;
|
||||||
|
struct branch b;
|
||||||
|
|
||||||
|
skip_optional_lf();
|
||||||
|
read_next_command();
|
||||||
|
|
||||||
|
/* mark ... */
|
||||||
|
parse_mark();
|
||||||
|
if (!next_mark)
|
||||||
|
die(_("Expected 'mark' command, got %s"), command_buf.buf);
|
||||||
|
|
||||||
|
/* to ... */
|
||||||
|
memset(&b, 0, sizeof(b));
|
||||||
|
if (!parse_objectish_with_prefix(&b, "to "))
|
||||||
|
die(_("Expected 'to' command, got %s"), command_buf.buf);
|
||||||
|
e = find_object(&b.oid);
|
||||||
|
assert(e);
|
||||||
|
insert_mark(next_mark, e);
|
||||||
|
}
|
||||||
|
|
||||||
static char* make_fast_import_path(const char *path)
|
static char* make_fast_import_path(const char *path)
|
||||||
{
|
{
|
||||||
if (!relative_marks_paths || is_absolute_path(path))
|
if (!relative_marks_paths || is_absolute_path(path))
|
||||||
|
@ -3187,6 +3253,8 @@ static int parse_one_feature(const char *feature, int from_stream)
|
||||||
option_import_marks(arg, from_stream, 1);
|
option_import_marks(arg, from_stream, 1);
|
||||||
} else if (skip_prefix(feature, "export-marks=", &arg)) {
|
} else if (skip_prefix(feature, "export-marks=", &arg)) {
|
||||||
option_export_marks(arg);
|
option_export_marks(arg);
|
||||||
|
} else if (!strcmp(feature, "alias")) {
|
||||||
|
; /* Don't die - this feature is supported */
|
||||||
} else if (!strcmp(feature, "get-mark")) {
|
} else if (!strcmp(feature, "get-mark")) {
|
||||||
; /* Don't die - this feature is supported */
|
; /* Don't die - this feature is supported */
|
||||||
} else if (!strcmp(feature, "cat-blob")) {
|
} else if (!strcmp(feature, "cat-blob")) {
|
||||||
|
@ -3343,6 +3411,8 @@ int cmd_main(int argc, const char **argv)
|
||||||
parse_checkpoint();
|
parse_checkpoint();
|
||||||
else if (!strcmp("done", command_buf.buf))
|
else if (!strcmp("done", command_buf.buf))
|
||||||
break;
|
break;
|
||||||
|
else if (!strcmp("alias", command_buf.buf))
|
||||||
|
parse_alias();
|
||||||
else if (starts_with(command_buf.buf, "progress "))
|
else if (starts_with(command_buf.buf, "progress "))
|
||||||
parse_progress();
|
parse_progress();
|
||||||
else if (skip_prefix(command_buf.buf, "feature ", &v))
|
else if (skip_prefix(command_buf.buf, "feature ", &v))
|
||||||
|
|
|
@ -85,6 +85,36 @@ test_expect_success 'A: create pack from stdin' '
|
||||||
An annotated tag that annotates a blob.
|
An annotated tag that annotates a blob.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
tag to-be-deleted
|
||||||
|
from :3
|
||||||
|
data <<EOF
|
||||||
|
Another annotated tag that annotates a blob.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
reset refs/tags/to-be-deleted
|
||||||
|
from 0000000000000000000000000000000000000000
|
||||||
|
|
||||||
|
tag nested
|
||||||
|
mark :6
|
||||||
|
from :4
|
||||||
|
data <<EOF
|
||||||
|
Tag of our lovely commit
|
||||||
|
EOF
|
||||||
|
|
||||||
|
reset refs/tags/nested
|
||||||
|
from 0000000000000000000000000000000000000000
|
||||||
|
|
||||||
|
tag nested
|
||||||
|
mark :7
|
||||||
|
from :6
|
||||||
|
data <<EOF
|
||||||
|
Tag of tag of our lovely commit
|
||||||
|
EOF
|
||||||
|
|
||||||
|
alias
|
||||||
|
mark :8
|
||||||
|
to :5
|
||||||
|
|
||||||
INPUT_END
|
INPUT_END
|
||||||
git fast-import --export-marks=marks.out <input &&
|
git fast-import --export-marks=marks.out <input &&
|
||||||
git whatchanged master
|
git whatchanged master
|
||||||
|
@ -157,12 +187,19 @@ test_expect_success 'A: verify tag/series-A-blob' '
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'A: verify tag deletion is successful' '
|
||||||
|
test_must_fail git rev-parse --verify refs/tags/to-be-deleted
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'A: verify marks output' '
|
test_expect_success 'A: verify marks output' '
|
||||||
cat >expect <<-EOF &&
|
cat >expect <<-EOF &&
|
||||||
:2 $(git rev-parse --verify master:file2)
|
:2 $(git rev-parse --verify master:file2)
|
||||||
:3 $(git rev-parse --verify master:file3)
|
:3 $(git rev-parse --verify master:file3)
|
||||||
:4 $(git rev-parse --verify master:file4)
|
:4 $(git rev-parse --verify master:file4)
|
||||||
:5 $(git rev-parse --verify master^0)
|
:5 $(git rev-parse --verify master^0)
|
||||||
|
:6 $(git cat-file tag nested | grep object | cut -d" " -f 2)
|
||||||
|
:7 $(git rev-parse --verify nested)
|
||||||
|
:8 $(git rev-parse --verify master^0)
|
||||||
EOF
|
EOF
|
||||||
test_cmp expect marks.out
|
test_cmp expect marks.out
|
||||||
'
|
'
|
||||||
|
|
|
@ -53,6 +53,33 @@ test_expect_success 'fast-export | fast-import' '
|
||||||
|
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fast-export ^muss^{commit} muss' '
|
||||||
|
git fast-export --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual &&
|
||||||
|
cat >expected <<-EOF &&
|
||||||
|
tag muss
|
||||||
|
from $(git rev-parse --verify muss^{commit})
|
||||||
|
$(git cat-file tag muss | grep tagger)
|
||||||
|
data 9
|
||||||
|
valentin
|
||||||
|
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'fast-export --mark-tags ^muss^{commit} muss' '
|
||||||
|
git fast-export --mark-tags --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual &&
|
||||||
|
cat >expected <<-EOF &&
|
||||||
|
tag muss
|
||||||
|
mark :1
|
||||||
|
from $(git rev-parse --verify muss^{commit})
|
||||||
|
$(git cat-file tag muss | grep tagger)
|
||||||
|
data 9
|
||||||
|
valentin
|
||||||
|
|
||||||
|
EOF
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'fast-export master~2..master' '
|
test_expect_success 'fast-export master~2..master' '
|
||||||
|
|
||||||
git fast-export master~2..master >actual &&
|
git fast-export master~2..master >actual &&
|
||||||
|
@ -513,10 +540,41 @@ test_expect_success 'tree_tag' '
|
||||||
'
|
'
|
||||||
|
|
||||||
# NEEDSWORK: not just check return status, but validate the output
|
# NEEDSWORK: not just check return status, but validate the output
|
||||||
|
# Note that these tests DO NOTHING other than print a warning that
|
||||||
|
# they are ommitting the one tag we asked them to export (because the
|
||||||
|
# tags resolve to a tree). They exist just to make sure we do not
|
||||||
|
# abort but instead just warn.
|
||||||
test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj'
|
test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj'
|
||||||
test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag'
|
test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag'
|
||||||
test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
|
test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
|
||||||
|
|
||||||
|
test_expect_success 'handling tags of blobs' '
|
||||||
|
git tag -a -m "Tag of a blob" blobtag $(git rev-parse master:file) &&
|
||||||
|
git fast-export blobtag >actual &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
blob
|
||||||
|
mark :1
|
||||||
|
data 9
|
||||||
|
die Luft
|
||||||
|
|
||||||
|
tag blobtag
|
||||||
|
from :1
|
||||||
|
tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
|
||||||
|
data 14
|
||||||
|
Tag of a blob
|
||||||
|
|
||||||
|
EOF
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'handling nested tags' '
|
||||||
|
git tag -a -m "This is a nested tag" nested muss &&
|
||||||
|
git fast-export --mark-tags nested >output &&
|
||||||
|
grep "^from $ZERO_OID$" output &&
|
||||||
|
grep "^tag nested$" output >tag_lines &&
|
||||||
|
test_line_count = 2 tag_lines
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'directory becomes symlink' '
|
test_expect_success 'directory becomes symlink' '
|
||||||
git init dirtosymlink &&
|
git init dirtosymlink &&
|
||||||
git init result &&
|
git init result &&
|
||||||
|
@ -567,17 +625,15 @@ test_expect_success 'fast-export quotes pathnames' '
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'test bidirectionality' '
|
test_expect_success 'test bidirectionality' '
|
||||||
>marks-cur &&
|
|
||||||
>marks-new &&
|
|
||||||
git init marks-test &&
|
git init marks-test &&
|
||||||
git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \
|
git fast-export --export-marks=marks-cur --import-marks-if-exists=marks-cur --branches | \
|
||||||
git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new &&
|
git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks-if-exists=marks-new &&
|
||||||
(cd marks-test &&
|
(cd marks-test &&
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
echo Wohlauf > file &&
|
echo Wohlauf > file &&
|
||||||
git commit -a -m "back in time") &&
|
git commit -a -m "back in time") &&
|
||||||
git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \
|
git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks-if-exists=marks-new --branches | \
|
||||||
git fast-import --export-marks=marks-cur --import-marks=marks-cur
|
git fast-import --export-marks=marks-cur --import-marks-if-exists=marks-cur
|
||||||
'
|
'
|
||||||
|
|
||||||
cat > expected << EOF
|
cat > expected << EOF
|
||||||
|
|
Loading…
Reference in New Issue