{"thread":{"id":"33927","subject":"[PATCH 0/9] transport-helper: a bunch of improvements","startedAt":"2013-05-25T02:47:31Z","lastAt":"2013-05-25T06:27:00Z","messageCount":11,"participants":["Felipe Contreras","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":9},"messages":[{"id":"218490","messageId":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":null,"subject":"[PATCH 0/9] transport-helper: a bunch of improvements","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:31Z","receivedAt":"2013-05-25T02:47:31Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Hi,\n\nAfter these remote helpers that use 'export' are able to do everything:\n\n 1) push --dry-run\n 2) push --force\n 2.1) report which branches were forced\n 3) push old:new\n 4) push :to-delete\n\nI know these won't be applied, which is too bad for the users, which could\nenjoy these features, which are implemented properly, with documentation,\ntests, and everything.\n\nSorry users, I don't have Jedi powers to convince Git developers of what's\nactually good.\n\nFelipe Contreras (9):\n  transport-helper: check if the dry-run is supported\n  transport-helper: add 'force' to 'export' helpers\n  transport-helper: check for 'forced update' message\n  fast-export: improve argument parsing\n  fast-export: add new --refspec option\n  transport-helper: add support for old:new refspec\n  fast-import: add support to delete refs\n  fast-export: add support to delete refs\n  transport-helper: add support to delete branches\n\n Documentation/git-fast-export.txt |  4 ++++\n Documentation/git-fast-import.txt |  3 +++\n builtin/fast-export.c             | 47 ++++++++++++++++++++++++++++++++++++++-\n fast-import.c                     | 13 ++++++++---\n t/t5801-remote-helpers.sh         | 10 ++++++++-\n t/t9300-fast-import.sh            | 18 +++++++++++++++\n t/t9350-fast-export.sh            | 18 +++++++++++++++\n transport-helper.c                | 39 ++++++++++++++++++++++++++------\n 8 files changed, 140 insertions(+), 12 deletions(-)\n\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218491","messageId":"1369450060-19011-2-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 1/9] transport-helper: check if the dry-run is supported","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:32Z","receivedAt":"2013-05-25T02:47:32Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Certain remote-helpers (the ones with 'export') would try to push\nregardless.\n\nObviously this is not what the user wants.\n\nAlso, add a check for the 'dry-run' option, so remote-helpers can\nimplement it.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n transport-helper.c | 5 +++++\n 1 file changed, 5 insertions(+)\n\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 2f5ac3f..85c951f 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -809,6 +809,11 @@ static int push_refs_with_export(struct transport *transport,\n \tif (!data->refspecs)\n \t\tdie(\"remote-helper doesn't support push; refspec needed\");\n \n+\tif (flags & TRANSPORT_PUSH_DRY_RUN) {\n+\t\tif (set_helper_option(transport, \"dry-run\", \"true\") != 0)\n+\t\t\tdie(\"helper %s does not support dry-run\", data->name);\n+\t}\n+\n \thelper = get_helper(transport);\n \n \twrite_constant(helper->in, \"export\\n\");\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218492","messageId":"1369450060-19011-3-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 2/9] transport-helper: add 'force' to 'export' helpers","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:33Z","receivedAt":"2013-05-25T02:47:33Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Otherwise they cannot know when to force the push or not (other than\nhacks).\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n transport-helper.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 85c951f..22f31a2 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -814,6 +814,9 @@ static int push_refs_with_export(struct transport *transport,\n \t\t\tdie(\"helper %s does not support dry-run\", data->name);\n \t}\n \n+\tif (flags & TRANSPORT_PUSH_FORCE)\n+\t\tset_helper_option(transport, \"force\", \"true\");\n+\n \thelper = get_helper(transport);\n \n \twrite_constant(helper->in, \"export\\n\");\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218493","messageId":"1369450060-19011-4-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 3/9] transport-helper: check for 'forced update' message","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:34Z","receivedAt":"2013-05-25T02:47:34Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So the remote-helpers can tell us when a forced push was needed.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n transport-helper.c | 8 +++++++-\n 1 file changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 22f31a2..e461764 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -630,7 +630,7 @@ static int push_update_ref_status(struct strbuf *buf,\n \t\t\t\t   struct ref *remote_refs)\n {\n \tchar *refname, *msg;\n-\tint status;\n+\tint status, forced = 0;\n \n \tif (!prefixcmp(buf->buf, \"ok \")) {\n \t\tstatus = REF_STATUS_OK;\n@@ -683,6 +683,11 @@ static int push_update_ref_status(struct strbuf *buf,\n \t\t\tfree(msg);\n \t\t\tmsg = NULL;\n \t\t}\n+\t\telse if (!strcmp(msg, \"forced update\")) {\n+\t\t\tforced = 1;\n+\t\t\tfree(msg);\n+\t\t\tmsg = NULL;\n+\t\t}\n \t}\n \n \tif (*ref)\n@@ -704,6 +709,7 @@ static int push_update_ref_status(struct strbuf *buf,\n \t}\n \n \t(*ref)->status = status;\n+\t(*ref)->forced_update = forced;\n \t(*ref)->remote_status = msg;\n \treturn !(status == REF_STATUS_OK);\n }\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218494","messageId":"1369450060-19011-5-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 4/9] fast-export: improve argument parsing","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:35Z","receivedAt":"2013-05-25T02:47:35Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"We don't want to pass arguments specific to fast-export to\nsetup_revisions.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n builtin/fast-export.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex d1d68e9..3e1c4d4 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -694,8 +694,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \trevs.topo_order = 1;\n \trevs.show_source = 1;\n \trevs.rewrite_parents = 1;\n+\targc = parse_options(argc, argv, prefix, options, fast_export_usage,\n+\t\t\tPARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);\n \targc = setup_revisions(argc, argv, &revs, NULL);\n-\targc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);\n \tif (argc > 1)\n \t\tusage_with_options (fast_export_usage, options);\n \n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218496","messageId":"1369450060-19011-6-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 5/9] fast-export: add new --refspec option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:36Z","receivedAt":"2013-05-25T02:47:36Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So that we can covert the exported ref names.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/git-fast-export.txt |  4 ++++\n builtin/fast-export.c             | 30 ++++++++++++++++++++++++++++++\n t/t9350-fast-export.sh            |  7 +++++++\n 3 files changed, 41 insertions(+)\n\ndiff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt\nindex efb0380..041c6b8 100644\n--- a/Documentation/git-fast-export.txt\n+++ b/Documentation/git-fast-export.txt\n@@ -105,6 +105,10 @@ marks the same across runs.\n \tin the commit (as opposed to just listing the files which are\n \tdifferent from the commit's first parent).\n \n+--refspec::\n+\tApply the specified refspec to each ref exported. Multiple of them can\n+\tbe specified.\n+\n [<git-rev-list-args>...]::\n \tA list of arguments, acceptable to 'git rev-parse' and\n \t'git rev-list', that specifies the specific objects and references\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex 3e1c4d4..ba4b0ba 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -17,6 +17,7 @@\n #include \"utf8.h\"\n #include \"parse-options.h\"\n #include \"quote.h\"\n+#include \"remote.h\"\n \n static const char *fast_export_usage[] = {\n \tN_(\"git fast-export [rev-list-opts]\"),\n@@ -30,6 +31,8 @@ static int fake_missing_tagger;\n static int use_done_feature;\n static int no_data;\n static int full_tree;\n+static struct refspec *refspecs;\n+static int refspecs_nr;\n \n static int parse_opt_signed_tag_mode(const struct option *opt,\n \t\t\t\t     const char *arg, int unset)\n@@ -502,6 +505,15 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info,\n \t\tif (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)\n \t\t\tcontinue;\n \n+\t\tif (refspecs) {\n+\t\t\tchar *private;\n+\t\t\tprivate = apply_refspecs(refspecs, refspecs_nr, full_name);\n+\t\t\tif (private) {\n+\t\t\t\tfree(full_name);\n+\t\t\t\tfull_name = private;\n+\t\t\t}\n+\t\t}\n+\n \t\tswitch (e->item->type) {\n \t\tcase OBJ_COMMIT:\n \t\t\tcommit = (struct commit *)e->item;\n@@ -661,6 +673,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \tstruct commit *commit;\n \tchar *export_filename = NULL, *import_filename = NULL;\n \tuint32_t lastimportid;\n+\tstruct string_list refspecs_list;\n \tstruct option options[] = {\n \t\tOPT_INTEGER(0, \"progress\", &progress,\n \t\t\t    N_(\"show progress after <n> objects\")),\n@@ -681,6 +694,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOLEAN(0, \"use-done-feature\", &use_done_feature,\n \t\t\t     N_(\"Use the done feature to terminate the stream\")),\n \t\tOPT_BOOL(0, \"no-data\", &no_data, N_(\"Skip output of blob data\")),\n+\t\tOPT_STRING_LIST(0, \"refspec\", &refspecs_list, N_(\"refspec\"),\n+\t\t\t     N_(\"Apply refspec to exported refs\")),\n \t\tOPT_END()\n \t};\n \n@@ -700,6 +715,19 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \tif (argc > 1)\n \t\tusage_with_options (fast_export_usage, options);\n \n+\tif (refspecs_list.nr) {\n+\t\tconst char *refspecs_str[refspecs_list.nr];\n+\t\tint i;\n+\n+\t\tfor (i = 0; i < refspecs_list.nr; i++)\n+\t\t\trefspecs_str[i] = refspecs_list.items[i].string;\n+\n+\t\trefspecs_nr = refspecs_list.nr;\n+\t\trefspecs = parse_fetch_refspec(refspecs_nr, refspecs_str);\n+\n+\t\tstring_list_clear(&refspecs_list, 1);\n+\t}\n+\n \tif (use_done_feature)\n \t\tprintf(\"feature done\\n\");\n \n@@ -734,5 +762,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \tif (use_done_feature)\n \t\tprintf(\"done\\n\");\n \n+\tfree_refspec(refspecs_nr, refspecs);\n+\n \treturn 0;\n }\ndiff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh\nindex 2471bc6..ef2d76e 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -505,4 +505,11 @@ test_expect_success 'refs are updated even if no commits need to be exported' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'use refspec' '\n+\tgit fast-export --refspec refs/heads/master:refs/heads/foobar master | \\\n+\t\tgrep \"^commit \" | sort | uniq > actual &&\n+\techo \"commit refs/heads/foobar\" > expected &&\n+\ttest_cmp expected actual\n+'\n+\n test_done\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218497","messageId":"1369450060-19011-7-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 6/9] transport-helper: add support for old:new refspec","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:37Z","receivedAt":"2013-05-25T02:47:37Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"By using fast-export's new --refspec option.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t5801-remote-helpers.sh |  2 +-\n transport-helper.c        | 14 ++++++++++++--\n 2 files changed, 13 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh\nindex 4899af3..6a7db8b 100755\n--- a/t/t5801-remote-helpers.sh\n+++ b/t/t5801-remote-helpers.sh\n@@ -87,7 +87,7 @@ test_expect_success 'push new branch by name' '\n \tcompare_refs local HEAD server refs/heads/new-name\n '\n \n-test_expect_failure 'push new branch with old:new refspec' '\n+test_expect_success 'push new branch with old:new refspec' '\n \t(cd local &&\n \t git push origin new-name:new-refspec\n \t) &&\ndiff --git a/transport-helper.c b/transport-helper.c\nindex e461764..cc2150f 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -809,7 +809,7 @@ static int push_refs_with_export(struct transport *transport,\n \tstruct ref *ref;\n \tstruct child_process *helper, exporter;\n \tstruct helper_data *data = transport->data;\n-\tstruct string_list revlist_args = STRING_LIST_INIT_NODUP;\n+\tstruct string_list revlist_args = STRING_LIST_INIT_DUP;\n \tstruct strbuf buf = STRBUF_INIT;\n \n \tif (!data->refspecs)\n@@ -844,13 +844,23 @@ static int push_refs_with_export(struct transport *transport,\n \t\t}\n \t\tfree(private);\n \n-\t\tif (ref->peer_ref)\n+\t\tif (ref->peer_ref) {\n+\t\t\tif (strcmp(ref->name, ref->peer_ref->name)) {\n+\t\t\t\tstruct strbuf buf = STRBUF_INIT;\n+\t\t\t\tstrbuf_addf(&buf, \"%s:%s\", ref->peer_ref->name, ref->name);\n+\t\t\t\tstring_list_append(&revlist_args, \"--refspec\");\n+\t\t\t\tstring_list_append(&revlist_args, buf.buf);\n+\t\t\t\tstrbuf_release(&buf);\n+\t\t\t}\n \t\t\tstring_list_append(&revlist_args, ref->peer_ref->name);\n+\t\t}\n \t}\n \n \tif (get_exporter(transport, &exporter, &revlist_args))\n \t\tdie(\"Couldn't run fast-export\");\n \n+\tstring_list_clear(&revlist_args, 1);\n+\n \tif (finish_command(&exporter))\n \t\tdie(\"Error while running fast-export\");\n \tpush_update_refs_status(data, remote_refs);\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218495","messageId":"1369450060-19011-8-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 7/9] fast-import: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:38Z","receivedAt":"2013-05-25T02:47:38Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/git-fast-import.txt |  3 +++\n fast-import.c                     | 13 ++++++++++---\n t/t9300-fast-import.sh            | 18 ++++++++++++++++++\n 3 files changed, 31 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex bf1a02a..fe5c952 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -483,6 +483,9 @@ Marks must be declared (via `mark`) before they can be used.\n * Any valid Git SHA-1 expression that resolves to a commit.  See\n   ``SPECIFYING REVISIONS'' in linkgit:gitrevisions[7] for details.\n \n+* The special null SHA-1 (40 zeros) specifices that the branch is to be\n+  removed.\n+\n The special case of restarting an incremental import from the\n current branch value should be written as:\n ----\ndiff --git a/fast-import.c b/fast-import.c\nindex 23f625f..b6be7a7 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -248,6 +248,7 @@ struct branch {\n \tuintmax_t last_commit;\n \tuintmax_t num_notes;\n \tunsigned active : 1;\n+\tunsigned delete : 1;\n \tunsigned pack_id : PACK_ID_BITS;\n \tunsigned char sha1[20];\n };\n@@ -1674,10 +1675,13 @@ static int update_branch(struct branch *b)\n \tstruct ref_lock *lock;\n \tunsigned char old_sha1[20];\n \n-\tif (is_null_sha1(b->sha1))\n-\t\treturn 0;\n \tif (read_ref(b->name, old_sha1))\n \t\thashclr(old_sha1);\n+\tif (is_null_sha1(b->sha1)) {\n+\t\tif (b->delete)\n+\t\t\tdelete_ref(b->name, old_sha1, 0);\n+\t\treturn 0;\n+\t}\n \tlock = lock_any_ref_for_update(b->name, old_sha1, 0);\n \tif (!lock)\n \t\treturn error(\"Unable to lock %s\", b->name);\n@@ -2604,8 +2608,11 @@ static int parse_from(struct branch *b)\n \t\t\tfree(buf);\n \t\t} else\n \t\t\tparse_from_existing(b);\n-\t} else if (!get_sha1(from, b->sha1))\n+\t} else if (!get_sha1(from, b->sha1)) {\n \t\tparse_from_existing(b);\n+\t\tif (is_null_sha1(b->sha1))\n+\t\t\tb->delete = 1;\n+\t}\n \telse\n \t\tdie(\"Invalid ref name or SHA1 expression: %s\", from);\n \ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex ac6f3b6..0150aa6 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -2934,4 +2934,22 @@ test_expect_success 'S: ls with garbage after sha1 must fail' '\n \ttest_i18ngrep \"space after tree-ish\" err\n '\n \n+test_expect_success 'T: delete branch' '\n+\tgit branch to-delete &&\n+\tgit fast-import <<-EOF &&\n+\treset refs/heads/to-delete\n+\tfrom 0000000000000000000000000000000000000000\n+\tEOF\n+\ttest_must_fail git rev-parse --verify refs/heads/to-delete\n+'\n+\n+test_expect_success 'T: empty reset doesnt delete branch' '\n+\tgit branch not-to-delete &&\n+\tgit fast-import <<-EOF &&\n+\treset refs/heads/not-to-delete\n+\tEOF\n+\tgit show-ref &&\n+\tgit rev-parse --verify refs/heads/not-to-delete\n+'\n+\n test_done\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218498","messageId":"1369450060-19011-9-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 8/9] fast-export: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:39Z","receivedAt":"2013-05-25T02:47:39Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n builtin/fast-export.c  | 14 ++++++++++++++\n t/t9350-fast-export.sh | 11 +++++++++++\n 2 files changed, 25 insertions(+)\n\ndiff --git a/builtin/fast-export.c b/builtin/fast-export.c\nindex ba4b0ba..8db00a8 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -665,6 +665,19 @@ static void import_marks(char *input_file)\n \tfclose(f);\n }\n \n+static void handle_deletes(void)\n+{\n+\tint i;\n+\tfor (i = 0; i < refspecs_nr; i++) {\n+\t\tstruct refspec *refspec = &refspecs[i];\n+\t\tif (*refspec->src)\n+\t\t\tcontinue;\n+\n+\t\tprintf(\"reset %s\\nfrom %s\\n\\n\",\n+\t\t\t\trefspec->dst, sha1_to_hex(null_sha1));\n+\t}\n+}\n+\n int cmd_fast_export(int argc, const char **argv, const char *prefix)\n {\n \tstruct rev_info revs;\n@@ -755,6 +768,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t}\n \n \thandle_tags_and_duplicates(&extra_refs);\n+\thandle_deletes();\n \n \tif (export_filename && lastimportid != last_idnum)\n \t\texport_marks(export_filename);\ndiff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh\nindex ef2d76e..779ee22 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -512,4 +512,15 @@ test_expect_success 'use refspec' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'delete refspec' '\n+\tgit branch to-delete &&\n+\tgit fast-export --refspec :refs/heads/to-delete to-delete ^to-delete > actual &&\n+\tcat > expected <<-EOF &&\n+\treset refs/heads/to-delete\n+\tfrom 0000000000000000000000000000000000000000\n+\n+\tEOF\n+\ttest_cmp expected actual\n+'\n+\n test_done\n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218499","messageId":"1369450060-19011-10-git-send-email-felipe.contreras@gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH 9/9] transport-helper: add support to delete branches","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-05-25T02:47:40Z","receivedAt":"2013-05-25T02:47:40Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"For remote-helpers that use 'export' to push.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n t/t5801-remote-helpers.sh |  8 ++++++++\n transport-helper.c        | 11 ++++++-----\n 2 files changed, 14 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh\nindex 6a7db8b..a4643ce 100755\n--- a/t/t5801-remote-helpers.sh\n+++ b/t/t5801-remote-helpers.sh\n@@ -94,6 +94,14 @@ test_expect_success 'push new branch with old:new refspec' '\n \tcompare_refs local HEAD server refs/heads/new-refspec\n '\n \n+test_expect_success 'push delete branch' '\n+\t(cd local &&\n+\t git push origin :new-name\n+\t) &&\n+\ttest_must_fail git --git-dir=\"server/.git\" \\\n+\t rev-parse --verify refs/heads/new-name\n+'\n+\n test_expect_success 'cloning without refspec' '\n \tGIT_REMOTE_TESTGIT_REFSPEC=\"\" \\\n \tgit clone \"testgit::${PWD}/server\" local2 2>error &&\ndiff --git a/transport-helper.c b/transport-helper.c\nindex cc2150f..3ac4ced 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -833,9 +833,6 @@ static int push_refs_with_export(struct transport *transport,\n \t\tchar *private;\n \t\tunsigned char sha1[20];\n \n-\t\tif (ref->deletion)\n-\t\t\tdie(\"remote-helpers do not support ref deletion\");\n-\n \t\tprivate = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);\n \t\tif (private && !get_sha1(private, sha1)) {\n \t\t\tstrbuf_addf(&buf, \"^%s\", private);\n@@ -847,12 +844,16 @@ static int push_refs_with_export(struct transport *transport,\n \t\tif (ref->peer_ref) {\n \t\t\tif (strcmp(ref->name, ref->peer_ref->name)) {\n \t\t\t\tstruct strbuf buf = STRBUF_INIT;\n-\t\t\t\tstrbuf_addf(&buf, \"%s:%s\", ref->peer_ref->name, ref->name);\n+\t\t\t\tif (!ref->deletion)\n+\t\t\t\t\tstrbuf_addf(&buf, \"%s:%s\", ref->peer_ref->name, ref->name);\n+\t\t\t\telse\n+\t\t\t\t\tstrbuf_addf(&buf, \":%s\", ref->name);\n \t\t\t\tstring_list_append(&revlist_args, \"--refspec\");\n \t\t\t\tstring_list_append(&revlist_args, buf.buf);\n \t\t\t\tstrbuf_release(&buf);\n \t\t\t}\n-\t\t\tstring_list_append(&revlist_args, ref->peer_ref->name);\n+\t\t\tif (!ref->deletion)\n+\t\t\t\tstring_list_append(&revlist_args, ref->peer_ref->name);\n \t\t}\n \t}\n \n-- \n1.8.3.rc3.312.g47657de\n"},{"id":"218504","messageId":"CAPig+cQQBF-fCK2kQA35F_AuD=uFY0KVNMAurRA1U10ctDxxBA@mail.gmail.com","threadId":"33927","inReplyTo":"1369450060-19011-6-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH 5/9] fast-export: add new --refspec option","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2013-05-25T06:27:00Z","receivedAt":"2013-05-25T06:27:00Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, May 24, 2013 at 10:47 PM, Felipe Contreras\n<felipe.contreras@gmail.com> wrote:\n> So that we can covert the exported ref names.\n\ns/covert/convert/\n\n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n"}]}