{"thread":{"id":"35326","subject":"[PATCH v7 00/11] transport-helper: updates","startedAt":"2013-11-12T20:56:53Z","lastAt":"2013-11-18T05:08:39Z","messageCount":20,"participants":["Felipe Contreras","Junio C Hamano","Richard Hansen"],"isPatch":true,"patchVersion":7,"patchTotal":11},"messages":[{"id":"230516","messageId":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":null,"subject":"[PATCH v7 00/11] transport-helper: updates","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:53Z","receivedAt":"2013-11-12T20:56:53Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Hi,\n\nHere are the patches that allow transport helpers to be completely transparent;\nrenaming branches, deleting them, custom refspecs, --force, --dry-run,\nreporting forced update, everything works.\n\nChanges since v6:\n\ndiff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh\nindex 72f745d..aacd8a9 100755\n--- a/contrib/remote-helpers/test-hg.sh\n+++ b/contrib/remote-helpers/test-hg.sh\n@@ -599,7 +599,7 @@ test_expect_success 'remote big push fetch first' '\n \t)\n '\n \n-test_expect_failure 'remote big push force' '\n+test_expect_success 'remote big push force' '\n \ttest_when_finished \"rm -rf hgrepo gitrepo*\" &&\n \n \tsetup_big_push\n@@ -629,7 +629,7 @@ test_expect_failure 'remote big push force' '\n \tcheck_bookmark hgrepo new_bmark six\n '\n \n-test_expect_failure 'remote big push dry-run' '\n+test_expect_success 'remote big push dry-run' '\n \ttest_when_finished \"rm -rf hgrepo gitrepo*\" &&\n \n \tsetup_big_push\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 2257588..7a95125 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -863,7 +863,7 @@ static int push_refs_with_export(struct transport *transport,\n \n \tif (flags & TRANSPORT_PUSH_FORCE) {\n \t\tif (set_helper_option(transport, \"force\", \"true\") != 0)\n-\t\t\tdie(\"helper %s does not support 'force'\", data->name);\n+\t\t\twarning(\"helper %s does not support 'force'\", data->name);\n \t}\n \n \thelper = get_helper(transport);\n\nFelipe Contreras (10):\n  transport-helper: fix extra lines\n  transport-helper: don't update refs in dry-run\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\nRichard Hansen (1):\n  test-hg.sh: tests are now expected to pass\n\n Documentation/git-fast-export.txt   |  4 +++\n Documentation/git-fast-import.txt   |  3 +++\n Documentation/gitremote-helpers.txt |  4 +++\n builtin/fast-export.c               | 49 ++++++++++++++++++++++++++++++++++++-\n contrib/remote-helpers/test-hg.sh   |  4 +--\n fast-import.c                       | 13 +++++++---\n git-remote-testgit.sh               | 18 ++++++++++++++\n t/t5801-remote-helpers.sh           | 23 ++++++++++++++++-\n t/t9300-fast-import.sh              | 18 ++++++++++++++\n t/t9350-fast-export.sh              | 18 ++++++++++++++\n transport-helper.c                  | 47 +++++++++++++++++++++++------------\n 11 files changed, 179 insertions(+), 22 deletions(-)\n\n-- \n1.8.4.2+fc1\n"},{"id":"230517","messageId":"1384289830-5471-2-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 01/11] transport-helper: fix extra lines","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:54Z","receivedAt":"2013-11-12T20:56:54Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Commit 9c51558 (transport-helper: trivial code shuffle) moved these\nlines above, but 99d9ec0 (Merge branch 'fc/transport-helper-no-refspec')\nhad a wrong merge conflict and readded them.\n\nReported-by: Richard Hansen <rhansen@bbn.com>\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n transport-helper.c | 3 ---\n 1 file changed, 3 deletions(-)\n\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 673b7c2..b66c7fd 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -875,9 +875,6 @@ static int push_refs_with_export(struct transport *transport,\n \t\t}\n \t\tfree(private);\n \n-\t\tif (ref->deletion)\n-\t\t\tdie(\"remote-helpers do not support ref deletion\");\n-\n \t\tif (ref->peer_ref) {\n \t\t\tif (strcmp(ref->peer_ref->name, ref->name))\n \t\t\t\tdie(\"remote-helpers do not support old:new syntax\");\n-- \n1.8.4.2+fc1\n"},{"id":"230518","messageId":"1384289830-5471-3-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 02/11] transport-helper: don't update refs in dry-run","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:55Z","receivedAt":"2013-11-12T20:56:55Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"The remote helper namespace should not be updated.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n transport-helper.c | 9 +++++----\n 1 file changed, 5 insertions(+), 4 deletions(-)\n\ndiff --git a/transport-helper.c b/transport-helper.c\nindex b66c7fd..9558a0d 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -728,7 +728,8 @@ static int push_update_ref_status(struct strbuf *buf,\n }\n \n static void push_update_refs_status(struct helper_data *data,\n-\t\t\t\t    struct ref *remote_refs)\n+\t\t\t\t    struct ref *remote_refs,\n+\t\t\t\t    int flags)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct ref *ref = remote_refs;\n@@ -742,7 +743,7 @@ static void push_update_refs_status(struct helper_data *data,\n \t\tif (push_update_ref_status(&buf, &ref, remote_refs))\n \t\t\tcontinue;\n \n-\t\tif (!data->refspecs || data->no_private_update)\n+\t\tif (flags & TRANSPORT_PUSH_DRY_RUN || !data->refspecs || data->no_private_update)\n \t\t\tcontinue;\n \n \t\t/* propagate back the update to the remote namespace */\n@@ -833,7 +834,7 @@ static int push_refs_with_push(struct transport *transport,\n \tsendline(data, &buf);\n \tstrbuf_release(&buf);\n \n-\tpush_update_refs_status(data, remote_refs);\n+\tpush_update_refs_status(data, remote_refs, flags);\n \treturn 0;\n }\n \n@@ -887,7 +888,7 @@ static int push_refs_with_export(struct transport *transport,\n \n \tif (finish_command(&exporter))\n \t\tdie(\"Error while running fast-export\");\n-\tpush_update_refs_status(data, remote_refs);\n+\tpush_update_refs_status(data, remote_refs, flags);\n \treturn 0;\n }\n \n-- \n1.8.4.2+fc1\n"},{"id":"230519","messageId":"1384289830-5471-4-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 03/11] transport-helper: add 'force' to 'export' helpers","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:56Z","receivedAt":"2013-11-12T20:56:56Z","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\nTests-by: Richard Hansen <rhansen@bbn.com>\nDocumentation-by: Richard Hansen <rhansen@bbn.com>\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n Documentation/gitremote-helpers.txt |  4 ++++\n git-remote-testgit.sh               | 18 ++++++++++++++++++\n t/t5801-remote-helpers.sh           | 13 +++++++++++++\n transport-helper.c                  |  5 +++++\n 4 files changed, 40 insertions(+)\n\ndiff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt\nindex f1f4ca9..e75699c 100644\n--- a/Documentation/gitremote-helpers.txt\n+++ b/Documentation/gitremote-helpers.txt\n@@ -437,6 +437,10 @@ set by Git if the remote helper has the 'option' capability.\n 'option check-connectivity' \\{'true'|'false'\\}::\n \tRequest the helper to check connectivity of a clone.\n \n+'option force' \\{'true'|'false'\\}::\n+\tRequest the helper to perform a force update.  Defaults to\n+\t'false'.\n+\n SEE ALSO\n --------\n linkgit:git-remote[1]\ndiff --git a/git-remote-testgit.sh b/git-remote-testgit.sh\nindex 6d2f282..1c006a0 100755\n--- a/git-remote-testgit.sh\n+++ b/git-remote-testgit.sh\n@@ -15,6 +15,8 @@ test -z \"$refspec\" && prefix=\"refs\"\n \n export GIT_DIR=\"$url/.git\"\n \n+force=\n+\n mkdir -p \"$dir\"\n \n if test -z \"$GIT_REMOTE_TESTGIT_NO_MARKS\"\n@@ -39,6 +41,7 @@ do\n \t\tfi\n \t\ttest -n \"$GIT_REMOTE_TESTGIT_SIGNED_TAGS\" && echo \"signed-tags\"\n \t\ttest -n \"$GIT_REMOTE_TESTGIT_NO_PRIVATE_UPDATE\" && echo \"no-private-update\"\n+\t\techo 'option'\n \t\techo\n \t\t;;\n \tlist)\n@@ -93,6 +96,7 @@ do\n \t\tbefore=$(git for-each-ref --format=' %(refname) %(objectname) ')\n \n \t\tgit fast-import \\\n+\t\t\t${force:+--force} \\\n \t\t\t${testgitmarks:+\"--import-marks=$testgitmarks\"} \\\n \t\t\t${testgitmarks:+\"--export-marks=$testgitmarks\"} \\\n \t\t\t--quiet\n@@ -115,6 +119,20 @@ do\n \n \t\techo\n \t\t;;\n+\toption\\ *)\n+\t\tread cmd opt val <<-EOF\n+\t\t$line\n+\t\tEOF\n+\t\tcase $opt in\n+\t\tforce)\n+\t\t\ttest $val = \"true\" && force=\"true\" || force=\n+\t\t\techo \"ok\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\techo \"unsupported\"\n+\t\t\t;;\n+\t\tesac\n+\t\t;;\n \t'')\n \t\texit\n \t\t;;\ndiff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh\nindex 613f69a..c33cc25 100755\n--- a/t/t5801-remote-helpers.sh\n+++ b/t/t5801-remote-helpers.sh\n@@ -94,6 +94,19 @@ test_expect_failure 'push new branch with old:new refspec' '\n \tcompare_refs local HEAD server refs/heads/new-refspec\n '\n \n+test_expect_success 'forced push' '\n+\t(cd local &&\n+\tgit checkout -b force-test &&\n+\techo content >> file &&\n+\tgit commit -a -m eight &&\n+\tgit push origin force-test &&\n+\techo content >> file &&\n+\tgit commit -a --amend -m eight-modified &&\n+\tgit push --force origin force-test\n+\t) &&\n+\tcompare_refs local refs/heads/force-test server refs/heads/force-test\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 9558a0d..60fba99 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -855,6 +855,11 @@ 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\tif (set_helper_option(transport, \"force\", \"true\") != 0)\n+\t\t\twarning(\"helper %s does not support 'force'\", data->name);\n+\t}\n+\n \thelper = get_helper(transport);\n \n \twrite_constant(helper->in, \"export\\n\");\n-- \n1.8.4.2+fc1\n"},{"id":"230533","messageId":"1384289830-5471-5-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 04/11] transport-helper: check for 'forced update' message","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:57Z","receivedAt":"2013-11-12T20:56:57Z","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 60fba99..23af747 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -644,7 +644,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@@ -702,6 +702,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@@ -723,6 +728,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.4.2+fc1\n"},{"id":"230531","messageId":"1384289830-5471-6-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 05/10] fast-export: improve argument parsing","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:58Z","receivedAt":"2013-11-12T20:56:58Z","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 78250ea..eea5b8c 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -701,8 +701,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.4.2+fc1\n"},{"id":"230524","messageId":"1384289830-5471-7-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 05/11] test-hg.sh: tests are now expected to pass","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:56:59Z","receivedAt":"2013-11-12T20:56:59Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"From: Richard Hansen <rhansen@bbn.com>\n\nSigned-off-by: Richard Hansen <rhansen@bbn.com>\n---\n contrib/remote-helpers/test-hg.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh\nindex 72f745d..aacd8a9 100755\n--- a/contrib/remote-helpers/test-hg.sh\n+++ b/contrib/remote-helpers/test-hg.sh\n@@ -599,7 +599,7 @@ test_expect_success 'remote big push fetch first' '\n \t)\n '\n \n-test_expect_failure 'remote big push force' '\n+test_expect_success 'remote big push force' '\n \ttest_when_finished \"rm -rf hgrepo gitrepo*\" &&\n \n \tsetup_big_push\n@@ -629,7 +629,7 @@ test_expect_failure 'remote big push force' '\n \tcheck_bookmark hgrepo new_bmark six\n '\n \n-test_expect_failure 'remote big push dry-run' '\n+test_expect_success 'remote big push dry-run' '\n \ttest_when_finished \"rm -rf hgrepo gitrepo*\" &&\n \n \tsetup_big_push\n-- \n1.8.4.2+fc1\n"},{"id":"230528","messageId":"1384289830-5471-8-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 06/10] fast-export: add new --refspec option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:00Z","receivedAt":"2013-11-12T20:57:00Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So that we can convert 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             | 32 ++++++++++++++++++++++++++++++++\n t/t9350-fast-export.sh            |  7 +++++++\n 3 files changed, 43 insertions(+)\n\ndiff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt\nindex 85f1f30..221506b 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 eea5b8c..cf745ec 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@@ -31,6 +32,8 @@ static int use_done_feature;\n static int no_data;\n static int full_tree;\n static struct string_list extra_refs = STRING_LIST_INIT_NODUP;\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@@ -525,6 +528,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\tcommit = get_commit(e, full_name);\n \t\tif (!commit) {\n \t\t\twarning(\"%s: Unexpected object of type %s, skipping.\",\n@@ -668,6 +680,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 = STRING_LIST_INIT_NODUP;\n \tstruct option options[] = {\n \t\tOPT_INTEGER(0, \"progress\", &progress,\n \t\t\t    N_(\"show progress after <n> objects\")),\n@@ -688,6 +701,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(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@@ -707,6 +722,21 @@ 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;\n+\t\tint i;\n+\n+\t\trefspecs_str = xmalloc(sizeof(*refspecs_str) * refspecs_list.nr);\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\tfree(refspecs_str);\n+\t}\n+\n \tif (use_done_feature)\n \t\tprintf(\"feature done\\n\");\n \n@@ -741,5 +771,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 2312dec..3d475af 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -504,4 +504,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.4.2+fc1\n"},{"id":"230521","messageId":"1384289830-5471-9-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 06/11] fast-export: improve argument parsing","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:01Z","receivedAt":"2013-11-12T20:57:01Z","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 78250ea..eea5b8c 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -701,8 +701,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.4.2+fc1\n"},{"id":"230520","messageId":"1384289830-5471-10-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 07/11] fast-export: add new --refspec option","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:02Z","receivedAt":"2013-11-12T20:57:02Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"So that we can convert 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             | 32 ++++++++++++++++++++++++++++++++\n t/t9350-fast-export.sh            |  7 +++++++\n 3 files changed, 43 insertions(+)\n\ndiff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt\nindex 85f1f30..221506b 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 eea5b8c..cf745ec 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@@ -31,6 +32,8 @@ static int use_done_feature;\n static int no_data;\n static int full_tree;\n static struct string_list extra_refs = STRING_LIST_INIT_NODUP;\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@@ -525,6 +528,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\tcommit = get_commit(e, full_name);\n \t\tif (!commit) {\n \t\t\twarning(\"%s: Unexpected object of type %s, skipping.\",\n@@ -668,6 +680,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 = STRING_LIST_INIT_NODUP;\n \tstruct option options[] = {\n \t\tOPT_INTEGER(0, \"progress\", &progress,\n \t\t\t    N_(\"show progress after <n> objects\")),\n@@ -688,6 +701,8 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOL(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@@ -707,6 +722,21 @@ 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;\n+\t\tint i;\n+\n+\t\trefspecs_str = xmalloc(sizeof(*refspecs_str) * refspecs_list.nr);\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\tfree(refspecs_str);\n+\t}\n+\n \tif (use_done_feature)\n \t\tprintf(\"feature done\\n\");\n \n@@ -741,5 +771,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 2312dec..3d475af 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -504,4 +504,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.4.2+fc1\n"},{"id":"230522","messageId":"1384289830-5471-11-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 07/10] transport-helper: add support for old:new refspec","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:03Z","receivedAt":"2013-11-12T20:57:03Z","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        | 13 ++++++++++---\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh\nindex c33cc25..454337e 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 23af747..2da4259 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -850,7 +850,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@@ -888,8 +888,13 @@ static int push_refs_with_export(struct transport *transport,\n \t\tfree(private);\n \n \t\tif (ref->peer_ref) {\n-\t\t\tif (strcmp(ref->peer_ref->name, ref->name))\n-\t\t\t\tdie(\"remote-helpers do not support old:new syntax\");\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@@ -897,6 +902,8 @@ static int push_refs_with_export(struct transport *transport,\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, flags);\n-- \n1.8.4.2+fc1\n"},{"id":"230530","messageId":"1384289830-5471-12-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 08/10] fast-import: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:04Z","receivedAt":"2013-11-12T20:57:04Z","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 73f9806..2ffae42 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) specifies 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 f4d9969..fdce0b7 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@@ -1690,10 +1691,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, NULL);\n \tif (!lock)\n \t\treturn error(\"Unable to lock %s\", b->name);\n@@ -2620,8 +2624,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 27263df..5fc9ef2 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -2999,4 +2999,22 @@ test_expect_success 'T: ls root tree' '\n \ttest_cmp expect actual\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.4.2+fc1\n"},{"id":"230526","messageId":"1384289830-5471-13-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 08/11] transport-helper: add support for old:new refspec","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:05Z","receivedAt":"2013-11-12T20:57:05Z","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        | 13 ++++++++++---\n 2 files changed, 11 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh\nindex c33cc25..454337e 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 23af747..2da4259 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -850,7 +850,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@@ -888,8 +888,13 @@ static int push_refs_with_export(struct transport *transport,\n \t\tfree(private);\n \n \t\tif (ref->peer_ref) {\n-\t\t\tif (strcmp(ref->peer_ref->name, ref->name))\n-\t\t\t\tdie(\"remote-helpers do not support old:new syntax\");\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@@ -897,6 +902,8 @@ static int push_refs_with_export(struct transport *transport,\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, flags);\n-- \n1.8.4.2+fc1\n"},{"id":"230529","messageId":"1384289830-5471-14-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 09/10] fast-export: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:06Z","receivedAt":"2013-11-12T20:57:06Z","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 cf745ec..4b76222 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -673,6 +673,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@@ -764,6 +777,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t}\n \n \thandle_tags_and_duplicates();\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 3d475af..66c8b0a 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -511,4 +511,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.4.2+fc1\n"},{"id":"230527","messageId":"1384289830-5471-15-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 09/11] fast-import: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:07Z","receivedAt":"2013-11-12T20:57:07Z","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 73f9806..2ffae42 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) specifies 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 f4d9969..fdce0b7 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@@ -1690,10 +1691,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, NULL);\n \tif (!lock)\n \t\treturn error(\"Unable to lock %s\", b->name);\n@@ -2620,8 +2624,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 27263df..5fc9ef2 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -2999,4 +2999,22 @@ test_expect_success 'T: ls root tree' '\n \ttest_cmp expect actual\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.4.2+fc1\n"},{"id":"230523","messageId":"1384289830-5471-16-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 10/11] fast-export: add support to delete refs","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:08Z","receivedAt":"2013-11-12T20:57:08Z","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 cf745ec..4b76222 100644\n--- a/builtin/fast-export.c\n+++ b/builtin/fast-export.c\n@@ -673,6 +673,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@@ -764,6 +777,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)\n \t}\n \n \thandle_tags_and_duplicates();\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 3d475af..66c8b0a 100755\n--- a/t/t9350-fast-export.sh\n+++ b/t/t9350-fast-export.sh\n@@ -511,4 +511,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.4.2+fc1\n"},{"id":"230532","messageId":"1384289830-5471-17-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v6 10/10] transport-helper: add support to delete branches","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:09Z","receivedAt":"2013-11-12T20:57:09Z","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 454337e..c667965 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 'forced push' '\n \t(cd local &&\n \tgit checkout -b force-test &&\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 2da4259..7a95125 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -876,9 +876,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@@ -890,12 +887,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.4.2+fc1\n"},{"id":"230525","messageId":"1384289830-5471-18-git-send-email-felipe.contreras@gmail.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v7 11/11] transport-helper: add support to delete branches","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-11-12T20:57:10Z","receivedAt":"2013-11-12T20:57:10Z","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 454337e..c667965 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 'forced push' '\n \t(cd local &&\n \tgit checkout -b force-test &&\ndiff --git a/transport-helper.c b/transport-helper.c\nindex 2da4259..7a95125 100644\n--- a/transport-helper.c\n+++ b/transport-helper.c\n@@ -876,9 +876,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@@ -890,12 +887,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.4.2+fc1\n"},{"id":"230541","messageId":"xmqqtxfhfebw.fsf@gitster.dls.corp.google.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v7 00/11] transport-helper: updates","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-11-12T22:24:51Z","receivedAt":"2013-11-12T22:24:51Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> Here are the patches that allow transport helpers to be completely transparent;\n\nThanks, will replace what is on 'pu'.\n\n> Felipe Contreras (10):\n>   transport-helper: fix extra lines\n\nI'll retitle this one to \"mismerge fix\" to make it clear where the\nblame lies ;-)\n"},{"id":"230745","messageId":"1384751319-18798-1-git-send-email-rhansen@bbn.com","threadId":"35326","inReplyTo":"1384289830-5471-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v3] remote-bzr: support the new 'force' option","fromName":"Richard Hansen","fromEmail":"rhansen@bbn.com","sentAt":"2013-11-18T05:08:39Z","receivedAt":"2013-11-18T05:08:39Z","isPatch":true,"sender":{"key":"rhansen@rhansen.org","avatar":null},"body":"Signed-off-by: Richard Hansen <rhansen@bbn.com>\nReviewed-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n\nThis is a reroll of:\n  http://article.gmane.org/gmane.comp.version-control.git/237699\nbased on feedback from Felipe:\n  http://article.gmane.org/gmane.comp.version-control.git/237756\n\nThis patch is an optional extension to Felipe's \"transport-helper:\nupdates\" patch series:\n  http://thread.gmane.org/gmane.comp.version-control.git/237738\nand it requires those changes to work.\n\nChanges from v2:\n  * remove 'import types' (no longer necessary)\n  * change '(opt, val) = parser[1:3]' to 'opt, val = parser[1:3]'\n  * add 'Reviewed-by: Felipe Contreras <felipe.contreras@gmail.com>'\n    to commit message based on Felipe's comment in:\n    http://article.gmane.org/gmane.comp.version-control.git/237756\n\n contrib/remote-helpers/git-remote-bzr | 31 ++++++++++++++++++++++++++++++-\n contrib/remote-helpers/test-bzr.sh    | 22 +++++++++++++++++++++-\n 2 files changed, 51 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr\nindex 7e34532..ea0e82a 100755\n--- a/contrib/remote-helpers/git-remote-bzr\n+++ b/contrib/remote-helpers/git-remote-bzr\n@@ -684,7 +684,8 @@ def do_export(parser):\n                 peer = bzrlib.branch.Branch.open(peers[name],\n                                                  possible_transports=transports)\n                 try:\n-                    peer.bzrdir.push_branch(branch, revision_id=revid)\n+                    peer.bzrdir.push_branch(branch, revision_id=revid,\n+                                            overwrite=force)\n                 except bzrlib.errors.DivergedBranches:\n                     print \"error %s non-fast forward\" % ref\n                     continue\n@@ -718,8 +719,32 @@ def do_capabilities(parser):\n         print \"*import-marks %s\" % path\n     print \"*export-marks %s\" % path\n \n+    print \"option\"\n     print\n \n+class InvalidOptionValue(Exception):\n+    pass\n+\n+def get_bool_option(val):\n+    if val == 'true':\n+        return True\n+    elif val == 'false':\n+        return False\n+    else:\n+        raise InvalidOptionValue()\n+\n+def do_option(parser):\n+    global force\n+    opt, val = parser[1:3]\n+    try:\n+        if opt == 'force':\n+            force = get_bool_option(val)\n+            print 'ok'\n+        else:\n+            print 'unsupported'\n+    except InvalidOptionValue:\n+        print \"error '%s' is not a valid value for option '%s'\" % (val, opt)\n+\n def ref_is_valid(name):\n     return not True in [c in name for c in '~^: \\\\']\n \n@@ -882,6 +907,7 @@ def main(args):\n     global is_tmp\n     global branches, peers\n     global transports\n+    global force\n \n     alias = args[1]\n     url = args[2]\n@@ -895,6 +921,7 @@ def main(args):\n     branches = {}\n     peers = {}\n     transports = []\n+    force = False\n \n     if alias[5:] == url:\n         is_tmp = True\n@@ -930,6 +957,8 @@ def main(args):\n             do_import(parser)\n         elif parser.check('export'):\n             do_export(parser)\n+        elif parser.check('option'):\n+            do_option(parser)\n         else:\n             die('unhandled command: %s' % line)\n         sys.stdout.flush()\ndiff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh\nindex 1e53ff9..4f379c2 100755\n--- a/contrib/remote-helpers/test-bzr.sh\n+++ b/contrib/remote-helpers/test-bzr.sh\n@@ -66,13 +66,33 @@ test_expect_success 'pushing' '\n \ttest_cmp expected actual\n '\n \n+test_expect_success 'forced pushing' '\n+\t(\n+\tcd gitrepo &&\n+\techo three-new >content &&\n+\tgit commit -a --amend -m three-new &&\n+\tgit push -f\n+\t) &&\n+\n+\t(\n+\tcd bzrrepo &&\n+\t# the forced update overwrites the bzr branch but not the bzr\n+\t# working directory (it tries to merge instead)\n+\tbzr revert\n+\t) &&\n+\n+\techo three-new >expected &&\n+\tcat bzrrepo/content >actual &&\n+\ttest_cmp expected actual\n+'\n+\n test_expect_success 'roundtrip' '\n \t(\n \tcd gitrepo &&\n \tgit pull &&\n \tgit log --format=\"%s\" -1 origin/master >actual\n \t) &&\n-\techo three >expected &&\n+\techo three-new >expected &&\n \ttest_cmp expected actual &&\n \n \t(cd gitrepo && git push && git pull) &&\n-- \n1.8.5.rc2.10.g50cf47a\n"}]}