shithub: git9

Download patch

ref: d6fa07c6a0190bc922f11a117263264518d155f5
parent: 72000ca276cc993a2f6924da9e321bfea91ac92e
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Mar 29 13:35:35 EDT 2020

unref objects from git/send

When pushing a large repo, git/send will run out of memory fairly
quickly. This makes git/send run out of memory fairly slowly, and
only on large repos.

--- a/pack.c
+++ b/pack.c
@@ -880,6 +880,7 @@
 		goto error;
 	Bterm(f);
 	parseobject(obj);
+	free(d);
 	cache(obj);
 	return obj;
 error:
--- a/send.c
+++ b/send.c
@@ -37,6 +37,8 @@
 char **branch;
 char *removed[128];
 int nremoved;
+int npacked;
+int nsent;
 
 static int
 hwrite(int fd, void *buf, int nbuf, DigestState **st)
@@ -62,6 +64,7 @@
 		if((s = readobject(o->commit->tree)) == nil)
 			sysfatal("could not read tree %H: %r", o->hash);
 		pack(send, skip, s);
+		unref(s);
 		break;
 	case GTree:
 		for(i = 0; i < o->tree->nent; i++){
@@ -69,6 +72,7 @@
 			if ((s = readobject(e->h)) == nil)
 				sysfatal("could not read entry %H: %r", e->h);
 			pack(send, skip, s);
+			unref(s);
 		}
 		break;
 	default:
@@ -172,6 +176,7 @@
 		if((o = readobject(u->theirs)) == nil)
 			sysfatal("could not read %H", u->theirs);
 		pack(&skip, &skip, o);
+		unref(o);
 	}
 
 	q = nil;
@@ -179,14 +184,13 @@
 	for(i = 0; i < nupd; i++){
 		u = &upd[i];
 		if((o = readobject(u->ours)) == nil){
-			if(force)
-				continue;
-			else
+			if(!force)
 				sysfatal("could not read object %H", u->ours);
+			continue;
 		}
-
 		n = emalloc(sizeof(Objq));
 		n->obj = o;
+		unref(o);
 		if(!q){
 			q = n;
 			e = n;
@@ -213,6 +217,7 @@
 		n = q->next;
 		free(q);
 	}
+	fprint(2, "\n");
 
 	st = nil;
 	PUTBE32(buf, send.nobj);
@@ -223,8 +228,10 @@
 	for(i = 0; i < send.sz; i++){
 		if(!send.obj[i])
 			continue;
-		if(writeobject(c->wfd, send.obj[i], &st) == -1)
+		o = readobject(send.obj[i]->hash);
+		if(writeobject(c->wfd, o, &st) == -1)
 			return -1;
+		unref(o);
 	}
 	sha1(nil, 0, h.h, st);
 	if(write(c->wfd, h.h, sizeof(h.h)) == -1)
@@ -284,7 +291,7 @@
 	int i, n, r, nupd, nsp, send;
 	char buf[Pktmax], *sp[3];
 	Update *upd, *u;
-	Object *a, *b;
+	Object *a, *b, *p;
 
 	nupd = readours(&upd);
 	while(1){
@@ -313,7 +320,10 @@
 		u = &upd[i];
 		a = readobject(u->theirs);
 		b = readobject(u->ours);
-		if(!force && !hasheq(&u->theirs, &Zhash) && (a == nil || ancestor(a, b) != a)){
+		p = nil;
+		if(a && b)
+			p = ancestor(a, b);
+		if(!force && !hasheq(&u->theirs, &Zhash) && (a == nil || p != a)){
 			fprint(2, "remote has diverged\n");
 			werrstr("force needed");
 			send=0;
@@ -320,6 +330,9 @@
 			r = -1;
 			break;
 		}
+		unref(a);
+		unref(b);
+		unref(p);
 		if(hasheq(&u->ours, &Zhash)){
 			print("removed %s\n", u->ref);
 			continue;