When a revision is specified on the commandline we explicitly output a 'reset' command for it if it was not handled already. This allows for example the remote-helper protocol to use fast-export to create branches that point to a commit that has already been exported. Initial-patch-by: Johannes Schindelin <Johannes.Schindelin@xxxxxx> Signed-off-by: Sverre Rabbelier <srabbelier@xxxxxxxxx> --- Most of the hard work for this patch was done by Dscho. The rest of it was basically me applying the technique used by jch in c3502fa (25-08-2011 do not include sibling history in --ancestry-path). The if statement dealing with tag_of_filtered_mode is not as elegant as either me or Dscho would have liked, but we couldn't find a better way to determine if a ref is a tag at this point in the code. Additionally, the elem->whence != REV_CMD_RIGHT case should really check if REV_CMD_RIGHT_REF, but as this is not provided by the ref_info structure this is left as is. A result of this is that incorrect input will result in incorrect output, rather than an error message. That is: `git fast-export a..<sha1>` will incorrectly generate a `reset <sha1>` statement in the fast-export stream. The dwim_ref bit is a double work (it has already been done by the caller of this function), but I decided it would be more work to pass this information along than to recompute it for the few commandline refs that were relevant. builtin/fast-export.c | 31 +++++++++++++++++++++++++++++-- t/t9350-fast-export.sh | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/builtin/fast-export.c b/builtin/fast-export.c index c4c4391..bcfec38 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -18,6 +18,8 @@ #include "parse-options.h" #include "quote.h" +#define REF_HANDLED (ALL_REV_FLAGS + 1) + static const char *fast_export_usage[] = { "git fast-export [rev-list-opts]", NULL @@ -541,10 +543,34 @@ static void handle_reset(const char *name, struct object *object) sha1_to_hex(object->sha1)); } -static void handle_tags_and_duplicates(struct string_list *extra_refs) +static void handle_tags_and_duplicates(struct rev_info *revs, struct string_list *extra_refs) { int i; + /* even if no commits were exported, we need to export the ref */ + for (i = 0; i < revs->cmdline.nr; i++) { + struct rev_cmdline_entry *elem = &revs->cmdline.rev[i]; + + if (elem->flags & UNINTERESTING) + continue; + + if (elem->whence != REV_CMD_REV && elem->whence != REV_CMD_RIGHT) + continue; + + char *full_name; + dwim_ref(elem->name, strlen(elem->name), elem->item->sha1, &full_name); + + if (!prefixcmp(full_name, "refs/tags/") && + (tag_of_filtered_mode != REWRITE || + !get_object_mark(elem->item))) + continue; + + if (!(elem->flags & REF_HANDLED)) { + handle_reset(full_name, elem->item); + elem->flags |= REF_HANDLED; + } + } + for (i = extra_refs->nr - 1; i >= 0; i--) { const char *name = extra_refs->items[i].string; struct object *object = extra_refs->items[i].util; @@ -698,11 +724,12 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) } else { handle_commit(commit, &revs); + commit->object.flags |= REF_HANDLED; handle_tail(&commits, &revs); } } - handle_tags_and_duplicates(&extra_refs); + handle_tags_and_duplicates(&revs, &extra_refs); if (export_filename) export_marks(export_filename); diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 74914dc..ea7dc21 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -446,7 +446,7 @@ from $(git rev-parse master) EOF -test_expect_failure 'refs are updated even if no commits need to be exported' ' +test_expect_success 'refs are updated even if no commits need to be exported' ' git fast-export master..master > actual && test_cmp expected actual ' -- 1.7.8.rc0.36.g67522.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html