Subject: [PATCH] git-send-pack: don't consider branch lagging behind as errors.

From: Pierre Habouzit <[email-masked]>
Date: Thu, 19 Jun 2008 12:51:55 +0200

It's really painful to have git push error out when it's just that one of
your tracking branches isn't up to date with respect to a remote branch.

Let just add a new status: "lagging", always print it to screen when we're
lagging, but don't exit with a non 0 value, as it really alarms users.

Signed-off-by: Pierre Habouzit <[email-masked]>
---

  "lagging" is probably not a very nice name, and anyone is welcomed to use
  a better word for the concept.

  Another little glitch is that with this patch you can see:

	  $ git push
	  To {your-remote}
	   < [lagging]         {local-branch} -> {remote-branch}
	  Everything up-to-date

  The "Everything up-to-date" is slightly confusing, so maybe we should make it
  better like "Everything up-to-date or strict parent" or whatever.

 builtin-send-pack.c |   10 +++++++++-
 cache.h             |    1 +
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 8d1e7be..cfbc108 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -339,6 +339,9 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count)
 		print_ref_status('=', "[up to date]", ref,
 				ref->peer_ref, NULL);
 		break;
+	case REF_STATUS_LAGGING_BEHIND:
+		print_ref_status('<', "[lagging]", ref, ref->peer_ref, NULL);
+		break;
 	case REF_STATUS_REJECT_NONFASTFORWARD:
 		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 				"non-fast forward");
@@ -390,6 +393,7 @@ static int refs_pushed(struct ref *ref)
 		switch(ref->status) {
 		case REF_STATUS_NONE:
 		case REF_STATUS_UPTODATE:
+		case REF_STATUS_LAGGING_BEHIND:
 			break;
 		default:
 			return 1;
@@ -568,7 +572,10 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		      || !ref_newer(new_sha1, ref->old_sha1));
 
 		if (ref->nonfastforward && !ref->force && !args.force_update) {
-			ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+			if (ref_newer(ref->old_sha1, new_sha1))
+				ref->status = REF_STATUS_LAGGING_BEHIND;
+			else
+				ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
 			continue;
 		}
 
@@ -628,6 +635,7 @@ static int do_send_pack(int in, int out, struct remote *remote, const char *dest
 		switch (ref->status) {
 		case REF_STATUS_NONE:
 		case REF_STATUS_UPTODATE:
+		case REF_STATUS_LAGGING_BEHIND:
 		case REF_STATUS_OK:
 			break;
 		default:
diff --git a/cache.h b/cache.h
index 23f3b92..b9b32eb 100644
--- a/cache.h
+++ b/cache.h
@@ -673,6 +673,7 @@ struct ref {
 		REF_STATUS_UPTODATE,
 		REF_STATUS_REMOTE_REJECT,
 		REF_STATUS_EXPECTING_REPORT,
+		REF_STATUS_LAGGING_BEHIND,
 	} status;
 	char *remote_status;
 	struct ref *peer_ref; /* when renaming */
-- 
1.5.6.rc3.158.g1a80c.dirty