All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andy Whitcroft <apw@shadowen.org>
To: git@vger.kernel.org
Subject: [PATCH 1/2] mirror pushing
Date: Thu, 8 Nov 2007 14:24:50 -0000	[thread overview]
Message-ID: <1194531890.0@pinky> (raw)
In-Reply-To: 20071108121136.GG9736@shadowen.org


From: Junio C Hamano <gitster@pobox.com>

Existing "git push --all" is almost perfect for backing up to
another repository, except that "--all" only means "all
branches" in modern git, and it does not delete old branches and
tags that exist at the back-up repository that you have removed
from your local repository.

This teaches "git-send-pack" a new "--mirror" option.  The
difference from the "--all" option are that (1) it sends all
refs, not just branches, and (2) it deletes old refs you no
longer have on the local side from the remote side.

[apw@shadowen.org: rebase to next post arguments update]
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Andy Whitcroft <apw@shadowen.org>
---
 builtin-send-pack.c |   40 ++++++++++++++++++++++++++++------------
 remote.c            |   15 ++++++++++-----
 send-pack.h         |    1 +
 3 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 5a0f5c6..d5ead97 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -8,7 +8,7 @@
 #include "send-pack.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
+"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
 static struct send_pack_args args = {
@@ -242,7 +242,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 	if (!remote_tail)
 		remote_tail = &remote_refs;
 	if (match_refs(local_refs, remote_refs, &remote_tail,
-		       nr_refspec, refspec, args.send_all))
+		       nr_refspec, refspec, args.send_all | (args.send_mirror << 1)))
 		return -1;
 
 	if (!remote_refs) {
@@ -259,20 +259,28 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		char old_hex[60], *new_hex;
 		int will_delete_ref;
 		const char *pretty_ref;
-		const char *pretty_peer;
+		const char *pretty_peer = NULL; /* only used when not deleting */
+		const unsigned char *new_sha1;
 
-		if (!ref->peer_ref)
-			continue;
+		if (!ref->peer_ref) {
+			if (!args.send_mirror)
+				continue;
+			new_sha1 = null_sha1;
+		}
+		else
+			new_sha1 = ref->peer_ref->new_sha1;
 
 		if (!shown_dest) {
 			fprintf(stderr, "To %s\n", dest);
 			shown_dest = 1;
 		}
 
+		will_delete_ref = is_null_sha1(new_sha1);
+
 		pretty_ref = prettify_ref(ref->name);
-		pretty_peer = prettify_ref(ref->peer_ref->name);
+		if (!will_delete_ref)
+			pretty_peer = prettify_ref(ref->peer_ref->name);
 
-		will_delete_ref = is_null_sha1(ref->peer_ref->new_sha1);
 		if (will_delete_ref && !allow_deleting_refs) {
 			fprintf(stderr, " ! %-*s %s (remote does not support deleting refs)\n",
 					SUMMARY_WIDTH, "[rejected]", pretty_ref);
@@ -280,7 +288,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 			continue;
 		}
 		if (!will_delete_ref &&
-		    !hashcmp(ref->old_sha1, ref->peer_ref->new_sha1)) {
+		    !hashcmp(ref->old_sha1, new_sha1)) {
 			if (args.verbose)
 				fprintf(stderr, " = %-*s %s -> %s\n",
 					SUMMARY_WIDTH, "[up to date]",
@@ -312,8 +320,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		    !is_null_sha1(ref->old_sha1) &&
 		    !ref->force) {
 			if (!has_sha1_file(ref->old_sha1) ||
-			    !ref_newer(ref->peer_ref->new_sha1,
-				       ref->old_sha1)) {
+			    !ref_newer(new_sha1, ref->old_sha1)) {
 				/* We do not have the remote ref, or
 				 * we know that the remote ref is not
 				 * an ancestor of what we are trying to
@@ -328,7 +335,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 				continue;
 			}
 		}
-		hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+		hashcpy(ref->new_sha1, new_sha1);
 		if (!will_delete_ref)
 			new_refs++;
 		strcpy(old_hex, sha1_to_hex(ref->old_sha1));
@@ -459,6 +466,10 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 				args.dry_run = 1;
 				continue;
 			}
+			if (!strcmp(arg, "--mirror")) {
+				args.send_mirror = 1;
+				continue;
+			}
 			if (!strcmp(arg, "--force")) {
 				args.force_update = 1;
 				continue;
@@ -483,7 +494,12 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	}
 	if (!dest)
 		usage(send_pack_usage);
-	if (heads && args.send_all)
+	/*
+	 * --all and --mirror are incompatible; neither makes sense
+	 * with any refspecs.
+	 */
+	if ((heads && (args.send_all || args.send_mirror)) ||
+					(args.send_all && args.send_mirror))
 		usage(send_pack_usage);
 
 	if (remote_name) {
diff --git a/remote.c b/remote.c
index 59defdb..45dd59b 100644
--- a/remote.c
+++ b/remote.c
@@ -722,10 +722,12 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
  * without thinking.
  */
 int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
-	       int nr_refspec, const char **refspec, int all)
+	       int nr_refspec, const char **refspec, int flags)
 {
 	struct refspec *rs =
 		parse_ref_spec(nr_refspec, (const char **) refspec);
+	int send_all = flags & 01;
+	int send_mirror = flags & 02;
 
 	if (match_explicit_refs(src, dst, dst_tail, rs, nr_refspec))
 		return -1;
@@ -742,7 +744,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 			if (!pat)
 				continue;
 		}
-		else if (prefixcmp(src->name, "refs/heads/"))
+		else if (!send_mirror && prefixcmp(src->name, "refs/heads/"))
 			/*
 			 * "matching refs"; traditionally we pushed everything
 			 * including refs outside refs/heads/ hierarchy, but
@@ -763,10 +765,13 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 		if (dst_peer && dst_peer->peer_ref)
 			/* We're already sending something to this ref. */
 			goto free_name;
-		if (!dst_peer && !nr_refspec && !all)
-			/* Remote doesn't have it, and we have no
+
+		if (!dst_peer && !nr_refspec && !(send_all || send_mirror))
+			/*
+			 * Remote doesn't have it, and we have no
 			 * explicit pattern, and we don't have
-			 * --all. */
+			 * --all nor --mirror.
+			 */
 			goto free_name;
 		if (!dst_peer) {
 			/* Create a new one and link it */
diff --git a/send-pack.h b/send-pack.h
index 7a24f71..8ff1dc3 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -5,6 +5,7 @@ struct send_pack_args {
 	const char *receivepack;
 	unsigned verbose:1,
 		send_all:1,
+		send_mirror:1,
 		force_update:1,
 		use_thin_pack:1,
 		dry_run:1;

  parent reply	other threads:[~2007-11-08 14:25 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-11-08 12:11 git push mirror mode Andy Whitcroft
2007-11-08 12:12 ` [PATCH 1/2] mirror pushing Andy Whitcroft
2007-11-08 12:12 ` [PATCH 2/2] git-push: plumb in --mirror mode Andy Whitcroft
2007-11-08 12:19 ` git push mirror mode Johannes Schindelin
2007-11-08 12:44   ` Andy Whitcroft
2007-11-08 13:14     ` Andreas Ericsson
2007-11-08 13:44       ` Andy Whitcroft
2007-11-08 13:48         ` Andreas Ericsson
2007-11-08 12:49   ` Andy Whitcroft
2007-11-08 21:53   ` Junio C Hamano
2007-11-08 14:24 ` Andy Whitcroft [this message]
2007-11-08 15:03   ` [PATCH 1/2] mirror pushing Johannes Schindelin
2007-11-08 14:25 ` [PATCH 2/2] git-push: plumb in --mirror mode Andy Whitcroft
2007-11-08 16:58 ` git push mirror mode V3 Andy Whitcroft
2007-11-08 17:00   ` [PATCH 1/4] mirror pushing Andy Whitcroft
2007-11-08 17:01   ` [PATCH 2/4] mirror pushing -- clean up match_refs flags Andy Whitcroft
2007-11-08 17:01   ` [PATCH 3/4] git-push: plumb in --mirror mode Andy Whitcroft
2007-11-08 17:01   ` [PATCH 4/4] tests: git push mirror mode tests Andy Whitcroft
2007-11-09 10:21     ` [PATCH] tests: git push mirror mode tests V2 Andy Whitcroft
2007-11-09 14:45       ` [PATCH] tests: git push mirror mode tests V2 -- add tag tests Andy Whitcroft
2007-11-09 15:01         ` [PATCH] git-push: add documentation for the newly add --mirror mode Andy Whitcroft
2007-11-09 20:05       ` [PATCH] tests: git push mirror mode tests V2 Junio C Hamano
2007-11-12 15:25         ` Andy Whitcroft

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1194531890.0@pinky \
    --to=apw@shadowen.org \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.