shithub: git9

Download patch

ref: c65ded47aa82d89e1998ed0e8bbc8b1009d25642
parent: 30f251641bc3be46341341f435f06a9d927b591f
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Jun 30 12:29:06 EDT 2021

all: sync with 9front

--- a/add
+++ b/add
@@ -31,9 +31,7 @@
 		# We don't want a matching qid, so that
 		# git/walk doesn't think this came from
 		# a checkout.
-		if(! test -e $addpath)
-			if(~ $add 'tracked' || test -e $gitfs/HEAD/tree/$f)
-				touch $addpath
+		echo -n > $addpath
 		rm -f $delpath
 	}
 }
--- a/branch
+++ b/branch
@@ -37,6 +37,15 @@
 if not
 	base=`{git/query HEAD}
 
+if(~ $#newbr 0){
+	if(! ~ $#baseref 0)
+		die update would clobber $branch with $baseref
+	baseref=`$nl{echo -n $new | sed s@refs/heads/@refs/remotes/origin/@}
+	echo $baseref
+	if(! test -e .git/$new)
+		if(! base=`{git/query $baseref})
+			die could not find branch $branch
+}
 modified=`$nl{git/query -c HEAD $base | grep '^[^-]' | subst '^..'}
 deleted=`$nl{git/query -c HEAD $base | grep '^-' | subst '^..'}
 
@@ -49,14 +58,6 @@
 	echo 'deleted branch' $new
 	exit
 }
-if(~ $#newbr 0){
-	if(! ~ $#baseref 0)
-		die update would clobber $branch with $baseref
-	baseref=`$nl{echo -n $new | sed s@refs/heads/@refs/remotes/origin/@}
-	if(! test -e .git/$new)
-		if(! base=`{git/query $baseref})
-			die could not find branch $branch
-}
 commit=`{git/query $base} || die 'branch does not exist:' $base
 if(~ $new */*)
 	mkdir -p .git/`{basename -d $new}
@@ -99,8 +100,10 @@
 		rm -rf .git/index9/tracked/$m
 	}
 	if(~ $b file){
-		cp  $basedir/tree/$m $m
-		walk -eq $m > .git/index9/tracked/$m
+		if(cp -x -- $basedir/tree/$m $m)
+			walk -eq $m > .git/index9/tracked/$m
+		if not
+			echo -n > .git/index9/tracked/$m
 	}
 }
 
--- a/conf.c
+++ b/conf.c
@@ -78,6 +78,7 @@
 		file[nfile++] = ".git/config";
 		if((p = getenv("home")) != nil)
 			file[nfile++] = smprint("%s/lib/git/config", p);
+		file[nfile++] = "/sys/lib/git/config";
 	}
 
 	for(i = 0; i < argc; i++){
--- a/fetch.c
+++ b/fetch.c
@@ -228,13 +228,8 @@
 		req = 1;
 	}
 	flushpkt(c);
-	if(resolveref(&h, "HEAD") != -1){
-		n = snprint(buf, sizeof(buf), "have %H\n", h);
-		if(writepkt(c, buf, n + 1) == -1)
-			sysfatal("could not send have for %H", have[i]);
-	}
 	for(i = 0; i < nref; i++){
-		if(hasheq(&have[i], &Zhash) || hasheq(&have[i], &h))
+		if(hasheq(&have[i], &Zhash))
 			continue;
 		n = snprint(buf, sizeof(buf), "have %H\n", have[i]);
 		if(writepkt(c, buf, n + 1) == -1)
--- a/fs.c
+++ b/fs.c
@@ -79,6 +79,7 @@
 
 char	gitdir[512];
 char	*username;
+char	*groupname;
 char	*mntpt = ".git/fs";
 char	**branches = nil;
 Cache	uqidcache[512];
@@ -164,7 +165,7 @@
 	d->mode = c->mode;
 	d->name = estrdup9p(name);
 	d->uid = estrdup9p(username);
-	d->gid = estrdup9p(username);
+	d->gid = estrdup9p(groupname);
 	d->muid = estrdup9p(username);
 	if(o->type == GBlob || o->type == GTag){
 		d->qid.type = 0;
@@ -188,7 +189,7 @@
 	d->qid.type = strcmp(qroot[i], "ctl") == 0 ? 0 : QTDIR;
 	d->qid.path = qpath(nil, i, i, Qroot);
 	d->uid = estrdup9p(username);
-	d->gid = estrdup9p(username);
+	d->gid = estrdup9p(groupname);
 	d->muid = estrdup9p(username);
 	d->mtime = c->mtime;
 	return 0;
@@ -210,7 +211,7 @@
 	d->qid.path = qpath(c, i, branchid(aux, aux->refpath), Qbranch | Internal);
 	d->mode = 0555 | DMDIR;
 	d->uid = estrdup9p(username);
-	d->gid = estrdup9p(username);
+	d->gid = estrdup9p(groupname);
 	d->muid = estrdup9p(username);
 	d->mtime = c->mtime;
 	d->atime = c->mtime;
@@ -251,11 +252,10 @@
 	d->qid.type = o->type == GTree ? QTDIR : 0;
 	d->qid.path = qpath(c, i, o->id, aux->qdir);
 	d->mode = m;
-	d->mode |= (o->type == GTree) ? 0755 : 0644;
 	d->atime = c->mtime;
 	d->mtime = c->mtime;
 	d->uid = estrdup9p(username);
-	d->gid = estrdup9p(username);
+	d->gid = estrdup9p(groupname);
 	d->muid = estrdup9p(username);
 	d->name = estrdup9p(e->tree->ent[i].name);
 	d->length = o->size;
@@ -271,7 +271,7 @@
 	c = crumb(p, 0);
 	o = c->obj;
 	d->uid = estrdup9p(username);
-	d->gid = estrdup9p(username);
+	d->gid = estrdup9p(groupname);
 	d->muid = estrdup9p(username);
 	d->mode = 0444;
 	d->atime = o->commit->ctime;
@@ -490,7 +490,7 @@
 	}else if(o->type == GCommit){
 		q->type = 0;
 		c->mtime = o->commit->mtime;
-		c->mode = 0444;
+		c->mode = 0644;
 		assert(qdir == Qcommit || qdir == Qobject || qdir == Qcommittree || qdir == Qhead);
 		if(strcmp(name, "msg") == 0)
 			q->path = qpath(p, 0, o->id, Qcommitmsg);
@@ -804,7 +804,7 @@
 	aux = r->fid->aux;
 	c = crumb(aux, 0);
 	r->d.uid = estrdup9p(username);
-	r->d.gid = estrdup9p(username);
+	r->d.gid = estrdup9p(groupname);
 	r->d.muid = estrdup9p(username);
 	r->d.qid = r->fid->qid;
 	r->d.mtime = c->mtime;
@@ -837,6 +837,8 @@
 void
 main(int argc, char **argv)
 {
+	Dir *d;
+
 	gitinit();
 	ARGBEGIN{
 	case 'd':
@@ -852,7 +854,12 @@
 	if(argc != 0)
 		usage();
 
-	username = getuser();
+	if((d = dirstat(".git")) == nil)
+		sysfatal("dirstat .git: %r");
+	username = strdup(d->uid);
+	groupname = strdup(d->gid);
+	free(d);
+
 	branches = emalloc(sizeof(char*));
 	branches[0] = nil;
 	postmountsrv(&gitsrv, nil, mntpt, MCREATE);
--- a/import
+++ b/import
@@ -37,7 +37,7 @@
 		date=$0
 	}
 	state=="headers" && /^Subject:/{
-		sub(/^Subject:[ \t]*(\[PATCH( [0-9]+\/[0-9]+)?\])*[ \t]*/, "", $0);
+		sub(/^Subject:[ \t]*(\[[^\]]*\][ \t]*)*/, "", $0);
 		gotmsg = 1
 		print > "/env/msg"
 	}
@@ -94,6 +94,14 @@
 patches=(/fd/0)
 if(! ~ $#* 0)
 	patches=$*
-for(f in $patches)
-	apply < $f || die $status 
+for(p in $patches){
+	# upas serves the decoded header and body separately,
+	# so we cat them together when applying a upas message.
+	#
+	# this allows mime-encoded or line-wrapped patches.
+	if(test -d $p && test -f $p/header && test -f $p/body)
+		{{cat $p/header; echo; cat $p/body} | apply} || die $status
+	if not
+		apply < $p || die $status
+}
 exit ''
--- /dev/null
+++ b/log
@@ -1,0 +1,49 @@
+#!/bin/rc -e
+rfork en
+. /sys/lib/git/common.rc
+
+gitup
+
+flagfmt='e:expr expression, c:branch commit, s:short'; args='file ...'
+eval `''{aux/getflags $*} || exec aux/usage
+
+base=/mnt/git/object/
+if(~ $#branch 0)
+	branch=`{git/branch}
+if(~ $#expr 0)
+	commits=`{git/query $branch}
+if not
+	commits=`{git/query $expr}
+
+files=()
+if(! ~ $#* 0)
+	files=`"{walk -f $gitrel/^$* | subst '^\./' | sort}
+
+while(! ~ $#commits 0){
+	ids=$nids
+	show=()
+	c=$commits(1)
+	if(! ~ $#files 0){
+		ncomm=`{comm -12 /env/files <{git/query -c $c~ $c | subst '^..' | sort} | wc -l}
+		if(! ~ $ncomm 0)
+			show=true
+	}
+	commits=$commits(2-)
+	if(~ $#expr 0)
+		commits=($commits `{cat $base/$c/parent >[2]/dev/null})
+	if(! ~ $#commits 0)
+		commits=`$nl{walk -emp -n0 $base^$commits | sort -rn | uniq | awk -F/ '{print $NF}'}
+
+	if(~ $#files 0 || ~ $show true){
+		if(~ $short 1)
+			echo $c `{cat $base/$c/msg | sed 1q}
+		if not{
+			echo -n 'Hash:	'`''{cat $base/$c/hash}
+			echo -n 'Author:	'`''{cat $base/$c/author}
+			echo -n 'Date:	'`''{date `{mtime $base/$c/msg | awk '{print $1}'}}
+			subst -g '^' '	' <$base/$c/msg 
+			echo
+		}
+	}
+}
+exit ''
--- a/log.c
+++ b/log.c
@@ -282,7 +282,7 @@
 main(int argc, char **argv)
 {
 	char path[1024], repo[1024], *p, *r;
-	int i;
+	int i, nrepo;
 
 	ARGBEGIN{
 	case 'e':
@@ -301,15 +301,21 @@
 
 	if(findrepo(repo, sizeof(repo)) == -1)
 		sysfatal("find root: %r");
+	nrepo = strlen(repo);
 	if(argc != 0){
 		if(getwd(path, sizeof(path)) == nil)
 			sysfatal("getwd: %r");
-		if(strlen(path) < strlen(repo))
-			sysfatal("path changed");
-		p = path + strlen(repo);
+		if(strncmp(path, repo, nrepo) != 0)
+			sysfatal("path shifted??");
+		p = path + nrepo;
 		pathfilt = emalloc(sizeof(Pfilt));
 		for(i = 0; i < argc; i++){
-			r = smprint("./%s/%s", p, argv[i]);
+			if(*argv[i] == '/'){
+				if(strncmp(argv[i], repo, nrepo) != 0)
+					continue;
+				r = smprint("./%s", argv[i]+nrepo);
+			}else
+				r = smprint("./%s/%s", p, argv[i]);
 			cleanname(r);
 			filteradd(pathfilt, r);
 			free(r);
--- a/pack.c
+++ b/pack.c
@@ -70,6 +70,7 @@
 Packf	*packf;
 int	npackf;
 int	openpacks;
+int	gitdirmode = -1;
 
 static void
 clear(Object *o)
@@ -887,7 +888,7 @@
 static void
 parsetree(Object *o)
 {
-	int m, entsz, nent;
+	int m, a, entsz, nent;
 	Dirent *t, *ent;
 	char *p, *ep;
 
@@ -908,7 +909,15 @@
 		if(*p != ' ')
 			sysfatal("malformed tree %H: *p=(%d) %c\n", o->hash, *p, *p);
 		p++;
-		t->mode = m & 0777;	
+		/*
+		 * only the stored permissions for the user
+		 * are relevant; git fills group and world
+		 * bits with whatever -- so to serve with
+		 * useful permissions, replicate the mode
+		 * of the git repo dir.
+		 */
+		a = (m & 0777)>>6;
+		t->mode = ((a<<6)|(a<<3)|a) & gitdirmode;
 		t->ismod = 0;
 		t->islink = 0;
 		if(m == 0160000){
@@ -1048,7 +1057,14 @@
 readobject(Hash h)
 {
 	Object *o;
+	Dir *d;
 
+	if(gitdirmode == -1){
+		if((d = dirstat(".git")) == nil)
+			sysfatal("stat .git: %r");
+		gitdirmode = d->mode & 0777;
+		free(d);
+	}
 	if((o = readidxobject(nil, h, 0)) == nil)
 		return nil;
 	parseobject(o);
@@ -1202,16 +1218,19 @@
 		while(c < nobj && (obj[c]->hash.h[0] & 0xff) <= i)
 			c++;
 		PUTBE32(buf, c);
-		hwrite(f, buf, 4, &st);
+		if(hwrite(f, buf, 4, &st) == -1)
+			goto error;
 	}
 	for(i = 0; i < nobj; i++){
 		o = obj[i];
-		hwrite(f, o->hash.h, sizeof(o->hash.h), &st);
+		if(hwrite(f, o->hash.h, sizeof(o->hash.h), &st) == -1)
+			goto error;
 	}
 
 	for(i = 0; i < nobj; i++){
 		PUTBE32(buf, obj[i]->crc);
-		hwrite(f, buf, 4, &st);
+		if(hwrite(f, buf, 4, &st) == -1)
+			goto error;
 	}
 
 	nbig = 0;
@@ -1222,15 +1241,18 @@
 			PUTBE32(buf, (1ull << 31) | nbig);
 			nbig++;
 		}
-		hwrite(f, buf, 4, &st);
+		if(hwrite(f, buf, 4, &st) == -1)
+			goto error;
 	}
 	for(i = 0; i < nobj; i++){
 		if(obj[i]->off >= (1ull<<31)){
 			PUTBE64(buf, obj[i]->off);
-			hwrite(f, buf, 8, &st);
+			if(hwrite(f, buf, 8, &st) == -1)
+				goto error;
 		}
 	}
-	hwrite(f, ph.h, sizeof(ph.h), &st);
+	if(hwrite(f, ph.h, sizeof(ph.h), &st) == -1)
+		goto error;
 	sha1(nil, 0, h.h, st);
 	Bwrite(f, h.h, sizeof(h.h));
 
@@ -1630,7 +1652,7 @@
 	DigestState *st;
 	Biobuf *bfd;
 	Meta *m;
-	Object *o, *b;
+	Object *o, *po, *b;
 	char *p, buf[32];
 
 	st = nil;
@@ -1655,16 +1677,19 @@
 	for(i = 0; i < nmeta; i++){
 		pct = showprogress((i*100)/nmeta, pct);
 		m = meta[i];
-		m->off = Boffset(bfd);
+		if((m->off = Boffset(bfd)) == -1)
+			goto error;
 		if((o = readobject(m->obj->hash)) == nil)
 			return -1;
 		if(m->delta == nil){
 			nh = packhdr(buf, o->type, o->size);
-			hwrite(bfd, buf, nh, &st);
+			if(hwrite(bfd, buf, nh, &st) == -1)
+				goto error;
 			if(hcompress(bfd, o->data, o->size, &st) == -1)
 				goto error;
 		}else{
-			b = readobject(m->prev->obj->hash);
+			if((b = readobject(m->prev->obj->hash)) == nil)
+				goto error;
 			nd = encodedelta(m, o, b, &p);
 			unref(b);
 			if(odelta && m->prev->off != 0){
@@ -1671,11 +1696,15 @@
 				nh = 0;
 				nh += packhdr(buf, GOdelta, nd);
 				nh += packoff(buf+nh, m->off - m->prev->off);
-				hwrite(bfd, buf, nh, &st);
+				if(hwrite(bfd, buf, nh, &st) == -1)
+					goto error;
 			}else{
 				nh = packhdr(buf, GRdelta, nd);
-				hwrite(bfd, buf, nh, &st);
-				hwrite(bfd, m->prev->obj->hash.h, sizeof(m->prev->obj->hash.h), &st);
+				po = m->prev->obj;
+				if(hwrite(bfd, buf, nh, &st) == -1)
+					goto error;
+				if(hwrite(bfd, po->hash.h, sizeof(po->hash.h), &st) == -1)
+					goto error;
 			}
 			res = hcompress(bfd, p, nd, &st);
 			free(p);
--- a/push
+++ b/push
@@ -31,7 +31,7 @@
 if(! ~ $#remove 0)
 	remove=-r^$remove
 for(remote in $remotes){
-	updates=`$nl{git/send $debug $force $branch $remove $remote || die $status}
+	updates=`$nl{git/send $debug $force $branch $remove $remote} || die $status
 	for(ln in $updates){
 		u=`{echo $ln}
 		refpath=`{echo $u(2) | subst '^refs/heads/' '.git/refs/remotes/'$upstream'/'}
--- a/revert
+++ b/revert
@@ -1,5 +1,5 @@
 #!/bin/rc
-rfork e
+rfork en
 . /sys/lib/git/common.rc
 
 gitup
@@ -11,9 +11,10 @@
 if(~ $#query 1)
 	commit=`{git/query -p $query}
 
-for(f in `$nl{cd $commit/tree/ && walk -f ./$gitrel/$*}){
+files=`$nl{cleanname -d $gitrel $*}
+for(f in `$nl{cd $commit/tree/ && walk -f $files}){
 	mkdir -p `{basename -d $f}
-	cp -- $commit/tree/$f $f
+	cp -x -- $commit/tree/$f $f
 	git/add $f
 }
 exit ''
--- a/save.c
+++ b/save.c
@@ -351,7 +351,6 @@
 	Object *t;
 
 	gitinit();
-	gitinit();
 	if(access(".git", AEXIST) != 0)
 		sysfatal("could not find git repo: %r");
 	if(getwd(cwd, sizeof(cwd)) == nil)