shithub: git9

Download patch

ref: fa02b11f83544df79b78d7cc364c5a75edbf1bb0
parent: d025a11e327a324ce750d4a8717e422e0911b538
author: glenda <glenda@9front.local>
date: Sat Jun 29 22:20:32 EDT 2019

Implement checking for force pushes

--- a/git.h
+++ b/git.h
@@ -199,6 +199,7 @@
 /* object io */
 int	resolverefs(Hash **, char *);
 int	resolveref(Hash *, char *);
+Object	*ancestor(Object *, Object *);
 Object	*readobject(Hash);
 void	parseobject(Object *);
 int	indexpack(char *, char *, Hash);
--- a/push
+++ b/push
@@ -20,6 +20,7 @@
 remote=()
 sendall=''
 remove=()
+force=()
 upstream='origin'
 branch=`{awk '$1=="branch"{print $2}' < /mnt/git/ctl}
 while(~ $1 -* && ! ~ $1 --){
@@ -35,6 +36,8 @@
 	case -r;
 		shift
 		remove=(-r$1 $remove);
+	case -f;
+		force=-f
 	case *; usage
 	}
 	shift
@@ -51,9 +54,9 @@
 	exit upstream
 }
 if(~ $sendall '')
-	updates=`$nl{git/send -b $branch  $remove $remote}
+	updates=`$nl{git/send $force -b $branch  $remove $remote}
 if not
-	updates=`$nl{git/send  $remove -a $remote}
+	updates=`$nl{git/send $force $remove -a $remote}
 if(! ~ $status '')
 	exit $status
 
--- a/ref.c
+++ b/ref.c
@@ -122,26 +122,17 @@
 	return h;
 }
 
-int
-ancestor(Eval *ev)
+Object*
+ancestor(Object *a, Object *b)
 {
-	Object *a, *b, *o, *p;
+	Object *o, *p, *r;
 	XObject *ht[256];
 	XObject *h, *q, *q1, *q2;
-	int i, r;
+	int i;
 
-	if(ev->nstk < 2){
-		werrstr("ancestor needs 2 objects");
-		return -1;
-	}
-	a = pop(ev);
-	b = pop(ev);
-	if(a == b){
-		push(ev, a);
-		return 0;
-	}
-
-	r = -1;
+	if(a == b)
+		return a;
+	r = nil;
 	memset(ht, 0, sizeof(ht));
 	q1 = nil;
 
@@ -166,8 +157,7 @@
 				h = hnode(ht, p);
 				if(h->mark != nil){
 					if(h->mark != q->mark){
-						push(ev, h->obj);
-						r = 0;
+						r = h->obj;
 						goto done;
 					}
 				} else {
@@ -194,6 +184,25 @@
 }
 
 int
+lca(Eval *ev)
+{
+	Object *a, *b, *o;
+
+	if(ev->nstk < 2){
+		werrstr("ancestor needs 2 objects");
+		return -1;
+	}
+	a = pop(ev);
+	b = pop(ev);
+	o = ancestor(a, b);
+	if(o == nil)
+		return -1;
+	push(ev, o);
+	return 0;
+}
+
+
+int
 parent(Eval *ev)
 {
 	Object *o, *p;
@@ -349,7 +358,7 @@
 			break;
 		case '@':
 			ev->p++;
-			if(ancestor(ev) == -1)
+			if(lca(ev) == -1)
 				return -1;
 			break;
 		default:
--- a/send.c
+++ b/send.c
@@ -32,6 +32,7 @@
 };
 
 int sendall;
+int force;
 char *curbranch = "refs/heads/master";
 char *removed[128];
 int nremoved;
@@ -289,6 +290,7 @@
 	int i, n, r, nupd, nsp, updating;
 	char buf[65536], *sp[3];
 	Update *upd, *u;
+	Object *a, *b;
 
 	if((nupd = readours(&upd)) == -1)
 		sysfatal("read refs: %r");
@@ -310,12 +312,17 @@
 		snprint(u->ref, sizeof(u->ref), sp[1]);
 	}
 
+	r = 0;
 	updating = 0;
 	for(i = 0; i < nupd; i++){
 		u = &upd[i];
-		if(!hasheq(&u->theirs, &Zhash) && readobject(u->theirs) == nil){
-			fprint(2, "remote has diverged: pull and try again\n");
-			updating = 0;
+		a = readobject(u->theirs);
+		b = readobject(u->ours);
+		if((!force || hasheq(&u->theirs, &Zhash)) && (a == nil || ancestor(a, b) != a)){
+			fprint(2, "remote has diverged\n");
+			werrstr("force needed");
+			updating=0;
+			r = -1;
 			break;
 		}
 		if(hasheq(&u->ours, &Zhash)){
@@ -348,7 +355,6 @@
 		updating = 1;
 	}
 	flushpkt(fd);
-	r = 0;
 	if(updating){
 		if(writepack(fd, upd, nupd) == -1)
 			return -1;
@@ -395,6 +401,7 @@
 	default:	usage();	break;
 	case 'a':	sendall++;	break;
 	case 'd':	chattygit++;	break;
+	case 'f':	force++;	break;
 	case 'r':
 		if(nremoved == nelem(removed))
 			sysfatal("too many deleted branches");