{"thread":{"id":"10113","subject":"mirror pushing","startedAt":"2007-10-02T07:55:45Z","lastAt":"2007-10-02T14:21:15Z","messageCount":5,"participants":["Junio C Hamano","Andy Whitcroft","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"54540","messageId":"7vhclalzlq.fsf@gitster.siamese.dyndns.org","threadId":"10113","inReplyTo":null,"subject":"mirror pushing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-10-02T07:55:45Z","receivedAt":"2007-10-02T07:55:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Existing \"git push --all\" is almost perfect for backing up to\nanother repository, except that \"--all\" only means \"all\nbranches\" in modern git, and it does not delete old branches and\ntags that exist at the back-up repository that you have removed\nfrom your local repository.\n\nThis teaches \"git-send-pack\" a new \"--mirror\" option.  The\ndifference from the \"--all\" option are that (1) it sends all\nrefs, not just branches, and (2) it deletes old refs you no\nlonger have on the local side from the remote side.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This even applies to \"maint\", but it probably should be done\n   on top of Daniel's remote.c changes.  Teaching this to \"git\n   push\" wrapper is left as an exercise to the reader.\n\n remote.c    |   15 ++++++++++-----\n send-pack.c |   35 ++++++++++++++++++++++++-----------\n 2 files changed, 34 insertions(+), 16 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex bb774d0..a3aa5ad 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -574,10 +574,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,\n  * without thinking.\n  */\n int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n-\t       int nr_refspec, char **refspec, int all)\n+\t       int nr_refspec, char **refspec, int flags)\n {\n \tstruct refspec *rs =\n \t\tparse_ref_spec(nr_refspec, (const char **) refspec);\n+\tint send_all = flags & 01;\n+\tint send_mirror = flags & 02;\n \n \tif (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))\n \t\treturn -1;\n@@ -594,7 +596,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n \t\t\tif (!pat)\n \t\t\t\tcontinue;\n \t\t}\n-\t\telse if (prefixcmp(src->name, \"refs/heads/\"))\n+\t\telse if (!send_mirror && prefixcmp(src->name, \"refs/heads/\"))\n \t\t\t/*\n \t\t\t * \"matching refs\"; traditionally we pushed everything\n \t\t\t * including refs outside refs/heads/ hierarchy, but\n@@ -615,10 +617,13 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n \t\tif (dst_peer && dst_peer->peer_ref)\n \t\t\t/* We're already sending something to this ref. */\n \t\t\tgoto free_name;\n-\t\tif (!dst_peer && !nr_refspec && !all)\n-\t\t\t/* Remote doesn't have it, and we have no\n+\n+\t\tif (!dst_peer && !nr_refspec && !(send_all || send_mirror))\n+\t\t\t/*\n+\t\t\t * Remote doesn't have it, and we have no\n \t\t\t * explicit pattern, and we don't have\n-\t\t\t * --all. */\n+\t\t\t * --all nor --mirror.\n+\t\t\t */\n \t\t\tgoto free_name;\n \t\tif (!dst_peer) {\n \t\t\t/* Create a new one and link it */\ndiff --git a/send-pack.c b/send-pack.c\nindex 9fc8a81..39b4b17 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -7,11 +7,12 @@\n #include \"remote.h\"\n \n static const char send_pack_usage[] =\n-\"git-send-pack [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n+\"git-send-pack [--all | --mirror] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n \"  --all and explicit <ref> specification are mutually exclusive.\";\n static const char *receivepack = \"git-receive-pack\";\n static int verbose;\n static int send_all;\n+static int send_mirror;\n static int force_update;\n static int use_thin_pack;\n \n@@ -200,7 +201,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \tif (!remote_tail)\n \t\tremote_tail = &remote_refs;\n \tif (match_refs(local_refs, remote_refs, &remote_tail,\n-\t\t       nr_refspec, refspec, send_all))\n+\t\t       nr_refspec, refspec, (send_all | (send_mirror << 1))))\n \t\treturn -1;\n \n \tif (!remote_refs) {\n@@ -215,19 +216,24 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \tfor (ref = remote_refs; ref; ref = ref->next) {\n \t\tchar old_hex[60], *new_hex;\n \t\tint will_delete_ref;\n+\t\tconst unsigned char *new_sha1;\n \n-\t\tif (!ref->peer_ref)\n-\t\t\tcontinue;\n-\n+\t\tif (!ref->peer_ref) {\n+\t\t\tif (!send_mirror)\n+\t\t\t\tcontinue;\n+\t\t\tnew_sha1 = null_sha1;\n+\t\t}\n+\t\telse\n+\t\t\tnew_sha1 = ref->peer_ref->new_sha1;\n \n-\t\twill_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);\n+\t\twill_delete_ref = is_null_sha1(new_sha1);\n \t\tif (will_delete_ref && !allow_deleting_refs) {\n \t\t\terror(\"remote does not support deleting refs\");\n \t\t\tret = -2;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!will_delete_ref &&\n-\t\t    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {\n+\t\t    !hashcmp(ref->old_sha1, new_sha1)) {\n \t\t\tif (verbose)\n \t\t\t\tfprintf(stderr, \"'%s': up-to-date\\n\", ref->name);\n \t\t\tcontinue;\n@@ -257,8 +263,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \t\t    !is_null_sha1(ref->old_sha1) &&\n \t\t    !ref->force) {\n \t\t\tif (!has_sha1_file(ref->old_sha1) ||\n-\t\t\t    !ref_newer(ref->peer_ref->new_sha1,\n-\t\t\t\t       ref->old_sha1)) {\n+\t\t\t    !ref_newer(new_sha1, ref->old_sha1)) {\n \t\t\t\t/* We do not have the remote ref, or\n \t\t\t\t * we know that the remote ref is not\n \t\t\t\t * an ancestor of what we are trying to\n@@ -276,7 +281,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n-\t\thashcpy(ref->new_sha1, ref->peer_ref->new_sha1);\n+\t\thashcpy(ref->new_sha1, new_sha1);\n \t\tif (!will_delete_ref)\n \t\t\tnew_refs++;\n \t\tstrcpy(old_hex, sha1_to_hex(ref->old_sha1));\n@@ -396,6 +401,10 @@ int main(int argc, char **argv)\n \t\t\t\tsend_all = 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--mirror\")) {\n+\t\t\t\tsend_mirror = 1;\n+\t\t\t\tcontinue;\n+\t\t\t}\n \t\t\tif (!strcmp(arg, \"--force\")) {\n \t\t\t\tforce_update = 1;\n \t\t\t\tcontinue;\n@@ -420,7 +429,11 @@ int main(int argc, char **argv)\n \t}\n \tif (!dest)\n \t\tusage(send_pack_usage);\n-\tif (heads && send_all)\n+\t/*\n+\t * --all and --mirror are incompatible; neither makes sense\n+\t * with any refspecs.\n+\t */\n+\tif ((heads && (send_all || send_mirror)) || (send_all && send_mirror))\n \t\tusage(send_pack_usage);\n \tverify_remote_names(nr_heads, heads);\n \n"},{"id":"54555","messageId":"20071002115903.GB30636@shadowen.org","threadId":"10113","inReplyTo":"7vhclalzlq.fsf@gitster.siamese.dyndns.org","subject":"Re: mirror pushing","fromName":"Andy Whitcroft","fromEmail":"apw@shadowen.org","sentAt":"2007-10-02T11:59:03Z","receivedAt":"2007-10-02T11:59:03Z","isPatch":false,"sender":{"key":"apw@shadowen.org","avatar":"https://gravatar.com/avatar/d3088262854661a913ef35cc40fedcc270142d4461791142bc1ea0b2a4e2e147?d=mp&s=160"},"body":"On Tue, Oct 02, 2007 at 12:55:45AM -0700, Junio C Hamano wrote:\n> Existing \"git push --all\" is almost perfect for backing up to\n> another repository, except that \"--all\" only means \"all\n> branches\" in modern git, and it does not delete old branches and\n> tags that exist at the back-up repository that you have removed\n> from your local repository.\n> \n> This teaches \"git-send-pack\" a new \"--mirror\" option.  The\n> difference from the \"--all\" option are that (1) it sends all\n> refs, not just branches, and (2) it deletes old refs you no\n> longer have on the local side from the remote side.\n> \n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n> \n>  * This even applies to \"maint\", but it probably should be done\n>    on top of Daniel's remote.c changes.  Teaching this to \"git\n>    push\" wrapper is left as an exercise to the reader.\n> \n>  remote.c    |   15 ++++++++++-----\n>  send-pack.c |   35 ++++++++++++++++++++++++-----------\n>  2 files changed, 34 insertions(+), 16 deletions(-)\n> \n> diff --git a/remote.c b/remote.c\n> index bb774d0..a3aa5ad 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -574,10 +574,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,\n>   * without thinking.\n>   */\n>  int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n> -\t       int nr_refspec, char **refspec, int all)\n> +\t       int nr_refspec, char **refspec, int flags)\n>  {\n>  \tstruct refspec *rs =\n>  \t\tparse_ref_spec(nr_refspec, (const char **) refspec);\n> +\tint send_all = flags & 01;\n> +\tint send_mirror = flags & 02;\n>  \n>  \tif (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))\n>  \t\treturn -1;\n> @@ -594,7 +596,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n>  \t\t\tif (!pat)\n>  \t\t\t\tcontinue;\n>  \t\t}\n> -\t\telse if (prefixcmp(src->name, \"refs/heads/\"))\n> +\t\telse if (!send_mirror && prefixcmp(src->name, \"refs/heads/\"))\n>  \t\t\t/*\n>  \t\t\t * \"matching refs\"; traditionally we pushed everything\n>  \t\t\t * including refs outside refs/heads/ hierarchy, but\n> @@ -615,10 +617,13 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,\n>  \t\tif (dst_peer && dst_peer->peer_ref)\n>  \t\t\t/* We're already sending something to this ref. */\n>  \t\t\tgoto free_name;\n> -\t\tif (!dst_peer && !nr_refspec && !all)\n> -\t\t\t/* Remote doesn't have it, and we have no\n> +\n> +\t\tif (!dst_peer && !nr_refspec && !(send_all || send_mirror))\n> +\t\t\t/*\n> +\t\t\t * Remote doesn't have it, and we have no\n>  \t\t\t * explicit pattern, and we don't have\n> -\t\t\t * --all. */\n> +\t\t\t * --all nor --mirror.\n> +\t\t\t */\n>  \t\t\tgoto free_name;\n>  \t\tif (!dst_peer) {\n>  \t\t\t/* Create a new one and link it */\n> diff --git a/send-pack.c b/send-pack.c\n> index 9fc8a81..39b4b17 100644\n> --- a/send-pack.c\n> +++ b/send-pack.c\n> @@ -7,11 +7,12 @@\n>  #include \"remote.h\"\n>  \n>  static const char send_pack_usage[] =\n> -\"git-send-pack [--all] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n> +\"git-send-pack [--all | --mirror] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\\n\"\n>  \"  --all and explicit <ref> specification are mutually exclusive.\";\n>  static const char *receivepack = \"git-receive-pack\";\n>  static int verbose;\n>  static int send_all;\n> +static int send_mirror;\n>  static int force_update;\n>  static int use_thin_pack;\n>  \n> @@ -200,7 +201,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n>  \tif (!remote_tail)\n>  \t\tremote_tail = &remote_refs;\n>  \tif (match_refs(local_refs, remote_refs, &remote_tail,\n> -\t\t       nr_refspec, refspec, send_all))\n> +\t\t       nr_refspec, refspec, (send_all | (send_mirror << 1))))\n>  \t\treturn -1;\n>  \n>  \tif (!remote_refs) {\n> @@ -215,19 +216,24 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n>  \tfor (ref = remote_refs; ref; ref = ref->next) {\n>  \t\tchar old_hex[60], *new_hex;\n>  \t\tint will_delete_ref;\n> +\t\tconst unsigned char *new_sha1;\n>  \n> -\t\tif (!ref->peer_ref)\n> -\t\t\tcontinue;\n> -\n> +\t\tif (!ref->peer_ref) {\n> +\t\t\tif (!send_mirror)\n> +\t\t\t\tcontinue;\n> +\t\t\tnew_sha1 = null_sha1;\n> +\t\t}\n> +\t\telse\n> +\t\t\tnew_sha1 = ref->peer_ref->new_sha1;\n>  \n> -\t\twill_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);\n> +\t\twill_delete_ref = is_null_sha1(new_sha1);\n>  \t\tif (will_delete_ref && !allow_deleting_refs) {\n>  \t\t\terror(\"remote does not support deleting refs\");\n>  \t\t\tret = -2;\n>  \t\t\tcontinue;\n>  \t\t}\n>  \t\tif (!will_delete_ref &&\n> -\t\t    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {\n> +\t\t    !hashcmp(ref->old_sha1, new_sha1)) {\n>  \t\t\tif (verbose)\n>  \t\t\t\tfprintf(stderr, \"'%s': up-to-date\\n\", ref->name);\n>  \t\t\tcontinue;\n> @@ -257,8 +263,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n>  \t\t    !is_null_sha1(ref->old_sha1) &&\n>  \t\t    !ref->force) {\n>  \t\t\tif (!has_sha1_file(ref->old_sha1) ||\n> -\t\t\t    !ref_newer(ref->peer_ref->new_sha1,\n> -\t\t\t\t       ref->old_sha1)) {\n> +\t\t\t    !ref_newer(new_sha1, ref->old_sha1)) {\n>  \t\t\t\t/* We do not have the remote ref, or\n>  \t\t\t\t * we know that the remote ref is not\n>  \t\t\t\t * an ancestor of what we are trying to\n> @@ -276,7 +281,7 @@ static int send_pack(int in, int out, struct remote *remote, int nr_refspec, cha\n>  \t\t\t\tcontinue;\n>  \t\t\t}\n>  \t\t}\n> -\t\thashcpy(ref->new_sha1, ref->peer_ref->new_sha1);\n> +\t\thashcpy(ref->new_sha1, new_sha1);\n>  \t\tif (!will_delete_ref)\n>  \t\t\tnew_refs++;\n>  \t\tstrcpy(old_hex, sha1_to_hex(ref->old_sha1));\n> @@ -396,6 +401,10 @@ int main(int argc, char **argv)\n>  \t\t\t\tsend_all = 1;\n>  \t\t\t\tcontinue;\n>  \t\t\t}\n> +\t\t\tif (!strcmp(arg, \"--mirror\")) {\n> +\t\t\t\tsend_mirror = 1;\n> +\t\t\t\tcontinue;\n> +\t\t\t}\n>  \t\t\tif (!strcmp(arg, \"--force\")) {\n>  \t\t\t\tforce_update = 1;\n>  \t\t\t\tcontinue;\n> @@ -420,7 +429,11 @@ int main(int argc, char **argv)\n>  \t}\n>  \tif (!dest)\n>  \t\tusage(send_pack_usage);\n> -\tif (heads && send_all)\n> +\t/*\n> +\t * --all and --mirror are incompatible; neither makes sense\n> +\t * with any refspecs.\n> +\t */\n> +\tif ((heads && (send_all || send_mirror)) || (send_all && send_mirror))\n>  \t\tusage(send_pack_usage);\n>  \tverify_remote_names(nr_heads, heads);\n\nOk, I put together a patch to tie this in (will post that following this\nemail).  However this mirror mode seems to do something odd.  With\nmatching repo's it reports all the tags as missing on the remote end,\nand attempts to resend them:\n\n$ git push --mirror ssh://.../~apw/git/git \nupdating 'junio-gpg-pub'\n  from 0000000000000000000000000000000000000000\n  to   a0e7d36193b96f552073558acf5fcc1f10528917\nupdating 'v0.99'\n  from 0000000000000000000000000000000000000000\n  to   d6602ec5194c87b0fc87103ca4d67251c76f233a\n[...]\nGenerating pack...\nDone counting 0 objects.\nWriting 0 objects...\nTotal 0 (delta 0), reused 0 (delta 0)\nerror: Ref junio-gpg-pub is at a0e7d36193b96f552073558acf5fcc1f10528917 but expected 0000000000000000000000000000000000000000\nerror: failed to lock junio-gpg-pub\nerror: Ref v0.99 is at d6602ec5194c87b0fc87103ca4d67251c76f233a but expected 0000000000000000000000000000000000000000\nerror: failed to lock v0.99\n[...]\n\nIt appears that they are ending up in the wrong place:\n\napw@kernel:~/git/git$ ls .git\nbranches       v0.99.5   v0.99.9a  v1.0.0b  v1.0rc5  v1.3.0      v1.4.2.1\nconfig         v0.99.6   v0.99.9b  v1.0.10  v1.0rc6  v1.3.0-rc1  v1.4.2.2\ndescription    v0.99.7   v0.99.9c  v1.0.11  v1.1.0   v1.3.0-rc2  v1.4.2.3\nHEAD           v0.99.7a  v0.99.9d  v1.0.12  v1.1.1   v1.3.0-rc3  v1.4.2.4\nhooks          v0.99.7b  v0.99.9e  v1.0.13  v1.1.2   v1.3.0-rc4  v1.4.2-rc1\nindex          v0.99.7c  v0.99.9f  v1.0.3   v1.1.3   v1.3.1      v1.4.2-rc2\ninfo           v0.99.7d  v0.99.9g  v1.0.4   v1.1.4   v1.3.2      v1.4.2-rc3\njunio-gpg-pub  v0.99.8   v0.99.9h  v1.0.5   v1.1.5   v1.3.3      v1.4.2-rc4\nlogs           v0.99.8a  v0.99.9i  v1.0.6   v1.1.6   v1.4.0      v1.4.3\nobjects        v0.99.8b  v0.99.9j  v1.0.7   v1.2.0   v1.4.0-rc1  v1.4.3.1\nrefs           v0.99.8c  v0.99.9k  v1.0.8   v1.2.1   v1.4.0-rc2  v1.4.3.2\nv0.99          v0.99.8d  v0.99.9l  v1.0.9   v1.2.2   v1.4.1      v1.4.3-rc1\nv0.99.1        v0.99.8e  v0.99.9m  v1.0rc1  v1.2.3   v1.4.1.1    v1.4.3-rc2\nv0.99.2        v0.99.8f  v0.99.9n  v1.0rc2  v1.2.4   v1.4.1-rc1  v1.4.3-rc3\nv0.99.3        v0.99.8g  v1.0.0    v1.0rc3  v1.2.5   v1.4.1-rc2\nv0.99.4        v0.99.9   v1.0.0a   v1.0rc4  v1.2.6   v1.4.2\n\n-apw\n"},{"id":"54556","messageId":"20071002120051.GC30636@shadowen.org","threadId":"10113","inReplyTo":"7vhclalzlq.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] git-push: plumb in --mirror mode","fromName":"Andy Whitcroft","fromEmail":"apw@shadowen.org","sentAt":"2007-10-02T12:00:51Z","receivedAt":"2007-10-02T12:00:51Z","isPatch":true,"sender":{"key":"apw@shadowen.org","avatar":"https://gravatar.com/avatar/d3088262854661a913ef35cc40fedcc270142d4461791142bc1ea0b2a4e2e147?d=mp&s=160"},"body":"Plumb in the --mirror mode for git-push.\n\nSigned-off-by: Andy Whitcroft <apw@shadowen.org>\n---\n builtin-push.c |   14 +++++++++++++-\n transport.c    |    8 ++++++++\n transport.h    |    1 +\n 3 files changed, 22 insertions(+), 1 deletions(-)\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 4ee36c2..e421e96 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -8,7 +8,7 @@\n #include \"remote.h\"\n #include \"transport.h\"\n \n-static const char push_usage[] = \"git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\";\n+static const char push_usage[] = \"git-push [--all | --mirror] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\";\n \n static int all, thin, verbose;\n static const char *receivepack;\n@@ -85,6 +85,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n \tint flags = 0;\n+\tint modes_specified = 0;\n \tconst char *repo = NULL;\t/* default repository */\n \n \tfor (i = 1; i < argc; i++) {\n@@ -105,6 +106,12 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\t}\n \t\tif (!strcmp(arg, \"--all\")) {\n \t\t\tflags |= TRANSPORT_PUSH_ALL;\n+\t\t\tmodes_specified++;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"--mirror\")) {\n+\t\t\tflags |= TRANSPORT_PUSH_MIRROR;\n+\t\t\tmodes_specified++;\n \t\t\tcontinue;\n \t\t}\n \t\tif (!strcmp(arg, \"--tags\")) {\n@@ -137,5 +144,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \tif (all && refspec)\n \t\tusage(push_usage);\n \n+\tif (modes_specified > 1) {\n+\t\terror(\"--all and --mirror are incompatible\");\n+\t\tusage(push_usage);\n+\t}\n+\n \treturn do_push(repo, flags);\n }\ndiff --git a/transport.c b/transport.c\nindex 7266fd3..e45f3c0 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -281,6 +281,9 @@ static int rsync_transport_push(struct transport *transport,\n \tstruct child_process rsync;\n \tconst char *args[8];\n \n+\tif (flags & TRANSPORT_PUSH_MIRROR)\n+\t\treturn error(\"rsync transport does not support mirror mode\");\n+\n \t/* first push the objects */\n \n \tstrbuf_addstr(&buf, transport->url);\n@@ -373,6 +376,9 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \tint argc;\n \tint err;\n \n+\tif (flags & TRANSPORT_PUSH_MIRROR)\n+\t\treturn error(\"http transport does not support mirror mode\");\n+\n \targv = xmalloc((refspec_nr + 11) * sizeof(char *));\n \targv[0] = \"http-push\";\n \targc = 1;\n@@ -667,6 +673,8 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n \t\targv[argc++] = \"--all\";\n \tif (flags & TRANSPORT_PUSH_FORCE)\n \t\targv[argc++] = \"--force\";\n+\tif (flags & TRANSPORT_PUSH_MIRROR)\n+\t\targv[argc++] = \"--mirror\";\n \tif (data->receivepack) {\n \t\tchar *rp = xmalloc(strlen(data->receivepack) + 16);\n \t\tsprintf(rp, \"--receive-pack=%s\", data->receivepack);\ndiff --git a/transport.h b/transport.h\nindex 6e318e4..8383774 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -29,6 +29,7 @@ struct transport {\n \n #define TRANSPORT_PUSH_ALL 1\n #define TRANSPORT_PUSH_FORCE 2\n+#define TRANSPORT_PUSH_MIRROR 4\n \n /* Returns a transport suitable for the url */\n struct transport *transport_get(struct remote *, const char *);\n"},{"id":"54559","messageId":"Pine.LNX.4.64.0710021347530.28395@racer.site","threadId":"10113","inReplyTo":"20071002120051.GC30636@shadowen.org","subject":"Re: [PATCH] git-push: plumb in --mirror mode","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-10-02T12:50:28Z","receivedAt":"2007-10-02T12:50:28Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 2 Oct 2007, Andy Whitcroft wrote:\n\n> @@ -137,5 +144,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n>  \tif (all && refspec)\n>  \t\tusage(push_usage);\n>  \n> +\tif (modes_specified > 1) {\n> +\t\terror(\"--all and --mirror are incompatible\");\n> +\t\tusage(push_usage);\n> +\t}\n> +\n\nWhy not\n\n\tif ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))?\n\nIt's more explicit.\n\n\n> @@ -667,6 +673,8 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n>  \t\targv[argc++] = \"--all\";\n>  \tif (flags & TRANSPORT_PUSH_FORCE)\n>  \t\targv[argc++] = \"--force\";\n> +\tif (flags & TRANSPORT_PUSH_MIRROR)\n> +\t\targv[argc++] = \"--mirror\";\n>  \tif (data->receivepack) {\n>  \t\tchar *rp = xmalloc(strlen(data->receivepack) + 16);\n>  \t\tsprintf(rp, \"--receive-pack=%s\", data->receivepack);\n\nShouldn't you then increment the \"11\" a few lines before that, to ensure \nenough space for the new argument?\n\nCiao,\nDscho\n"},{"id":"54563","messageId":"20071002142115.GC14110@shadowen.org","threadId":"10113","inReplyTo":"Pine.LNX.4.64.0710021347530.28395@racer.site","subject":"Re: [PATCH] git-push: plumb in --mirror mode","fromName":"Andy Whitcroft","fromEmail":"apw@shadowen.org","sentAt":"2007-10-02T14:21:15Z","receivedAt":"2007-10-02T14:21:15Z","isPatch":true,"sender":{"key":"apw@shadowen.org","avatar":"https://gravatar.com/avatar/d3088262854661a913ef35cc40fedcc270142d4461791142bc1ea0b2a4e2e147?d=mp&s=160"},"body":"On Tue, Oct 02, 2007 at 01:50:28PM +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Tue, 2 Oct 2007, Andy Whitcroft wrote:\n> \n> > @@ -137,5 +144,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n> >  \tif (all && refspec)\n> >  \t\tusage(push_usage);\n> >  \n> > +\tif (modes_specified > 1) {\n> > +\t\terror(\"--all and --mirror are incompatible\");\n> > +\t\tusage(push_usage);\n> > +\t}\n> > +\n> \n> Why not\n> \n> \tif ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))?\n> \n> It's more explicit.\n\nYep, that does seem cleaner.\n\n> > @@ -667,6 +673,8 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n> >  \t\targv[argc++] = \"--all\";\n> >  \tif (flags & TRANSPORT_PUSH_FORCE)\n> >  \t\targv[argc++] = \"--force\";\n> > +\tif (flags & TRANSPORT_PUSH_MIRROR)\n> > +\t\targv[argc++] = \"--mirror\";\n> >  \tif (data->receivepack) {\n> >  \t\tchar *rp = xmalloc(strlen(data->receivepack) + 16);\n> >  \t\tsprintf(rp, \"--receive-pack=%s\", data->receivepack);\n> \n> Shouldn't you then increment the \"11\" a few lines before that, to ensure \n> enough space for the new argument?\n\nI should have mentioned I'd not even reviewed it as the basic underlying\nfunctionality seemed to be broken.  I'll look over it if I get a chance\nto try and debug the underlying failure.\n\n-apw\n"}]}