shithub: git9

Download patch

ref: 52bd6a558338111c5f787ccc1d3b5f999c0e010f
parent: 367ff60a52a2d73059476ec80ac2807cf5085162
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jun 5 22:29:56 EDT 2021

all: sync with 9front fixes.

--- a/add
+++ b/add
@@ -16,17 +16,18 @@
 if(~ $#* 0)
 	exec aux/usage
 
+paths=`$nl{cleanname -d $gitrel $*}
 if(~ $add tracked)
-	files=`$nl{walk -f $gitrel/$*}
+	files=`$nl{walk -f $paths}
 if not
-	files=`$nl{cd .git/index9/tracked/ && walk -f $gitrel/$*}
+	files=`$nl{cd .git/index9/tracked/ && walk -f $paths}
 
 for(f in $files){
-	if(! ~ `{cleanname $f} .git/*){
+	if(! ~ `$nl{cleanname $f} .git/*){
 		addpath=.git/index9/$add/$f
 		delpath=.git/index9/$del/$f
-		mkdir -p `{basename -d $addpath}
-		mkdir -p `{basename -d $delpath}
+		mkdir -p `$nl{basename -d $addpath}
+		mkdir -p `$nl{basename -d $delpath}
 		# We don't want a matching qid, so that
 		# git/walk doesn't think this came from
 		# a checkout.
--- a/branch
+++ b/branch
@@ -60,9 +60,10 @@
 commit=`{git/query $base} || die 'branch does not exist:' $base
 if(~ $new */*)
 	mkdir -p .git/`{basename -d $new}
-echo $commit > .git/$new
-if(! ~ $#stay 0)
+if(! ~ $#stay 0){
+	echo $commit > .git/$new
 	exit
+}
 basedir=`{git/query -p $base}
 dirtypaths=()
 cleanpaths=($modified $deleted)
@@ -74,11 +75,12 @@
 	cleanpaths=`$nl{echo $"x$nl$"y | sort | uniq -u}
 }
 if(! ~ $#cleanpaths 0)
-	cleandirs=`$nl{{for(p in $cleanpaths) basename -d $p} | uniq}
+	cleandirs=`$nl{echo $nl^$cleanpaths | sed 's@/[^/]+/?$@@' | uniq}
 if(! ~ $#cleandirs 0){
 	mkdir -p $cleandirs
 	mkdir -p .git/index9/tracked/$cleandirs
 }
+echo $commit > .git/$new
 for(m in $cleanpaths){
 	# Modifications can turn a file into
 	# a directory, or vice versa, so we
--- a/clone
+++ b/clone
@@ -17,7 +17,7 @@
 if(~ $#branch 1)
 	branchflag=(-b $branch)
 
-if(! ~ `{ls $local | wc -l} 0)
+if(test -e $local)
 	die 'repository already exists:' $local
 
 fn clone{
--- a/commit
+++ b/commit
@@ -135,7 +135,7 @@
 
 files=()
 if(! ~ $#* 0)
-	files=`$nl{git/walk -c `$nl{cleanname $gitrel/$*}}
+	files=`$nl{git/walk -c `$nl{cleanname -d $gitrel $*}}
 if(~ $status '' || ~ $#files 0 && ! test -f .git/index9/merge-parents && ~ $#revise 0)
 	die 'nothing to commit' $status
 @{
--- a/common.rc
+++ b/common.rc
@@ -40,12 +40,13 @@
 }
 
 # merge1 out theirs base ours
-fn merge1 {
+fn merge1 {@{
+	rfork e
 	n=$pid
 	out=$1
-	theirs=$2
+	ours=$2
 	base=$3
-	ours=$4
+	theirs=$4
 	tmp=$out.tmp
 	while(test -f $tmp){
 		tmp=$tmp.$n
@@ -59,7 +60,7 @@
 	if(! test -f $theirs)
 		theirs=/dev/null
 	if(! ape/diff3 -3 -m $ours $base $theirs > $tmp)
-		echo merge needed: $out
+		echo merge needed: $out >[1=2]
 
 	if(present $ours $base $theirs){
 		mv $tmp $out
@@ -69,7 +70,7 @@
 		rm -f $tmp $out
 		git/rm $out
 	}
-}
+}}
 
 fn gitup{
 	gitroot=`{git/conf -r >[2]/dev/null}
--- a/diff
+++ b/diff
@@ -12,7 +12,7 @@
 
 files=()
 if(! ~ $#* 0)
-	files=`{cleanname $gitrel/$*}
+	files=`{cleanname -d $gitrel $*}
 
 branch=`{git/query -p $commit}
 if(~ $summarize 1){
--- a/init
+++ b/init
@@ -20,7 +20,7 @@
 }
 
 mkdir -p $dir/.git/refs/^(heads remotes)
-mkdri -p $dir/.git/fs
+mkdir -p $dir/.git/fs
 >$dir/.git/config {
 	echo '[core]'
 	echo '	repositoryformatversion = p9.0'
--- a/mkfile
+++ b/mkfile
@@ -51,12 +51,6 @@
 		mk $MKFLAGS $i.install
 	for (i in $RC)
 		mk $MKFLAGS $i.rcinstall
-	cp git.1.man /sys/man/1/git
-	cp gitfs.4.man /sys/man/4/gitfs
-	cp common.rc /sys/lib/git/common.rc
-
-uninstall:V:
-	rm -rf $BIN /sys/lib/git /sys/man/1/git /sys/man/4/gitfs
 
 %.rcinstall:V:
 	cp $stem $BIN/$stem
--- a/proto.c
+++ b/proto.c
@@ -285,19 +285,37 @@
 		snprint(cmd, sizeof(cmd), "git-%s-pack", direction);
 		dprint(1, "exec ssh '%s' '%s' %s\n", host, cmd, path);
 		execl("/bin/ssh", "ssh", host, cmd, path, nil);
-	}else{
-		close(pfd[0]);
-		c->type = ConnSsh;
-		c->rfd = pfd[1];
-		c->wfd = dup(pfd[1], -1);
+		sysfatal("exec: %r");
 	}
+	close(pfd[0]);
+	c->type = ConnSsh;
+	c->rfd = pfd[1];
+	c->wfd = dup(pfd[1], -1);
 	return 0;
 }
 
 static int
+githandshake(Conn *c, char *host, char *path, char *direction)
+{
+	char *p, *e, cmd[512];
+
+	p = cmd;
+	e = cmd + sizeof(cmd);
+	p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
+	if(host != nil)
+		p = seprint(p + 1, e, "host=%s", host);
+	if(writepkt(c, cmd, p - cmd + 1) == -1){
+		fprint(2, "failed to write message\n");
+		closeconn(c);
+		return -1;
+	}
+	return 0;
+}
+
+static int
 dialhjgit(Conn *c, char *host, char *port, char *path, char *direction, int auth)
 {
-	char *ds, *p, *e, cmd[512];
+	char *ds;
 	int pid, pfd[2];
 
 	if((ds = netmkaddr(host, "tcp", port)) == nil)
@@ -317,30 +335,26 @@
 		else
 			execl("/bin/tlsclient", "tlsclient", ds, nil);
 		sysfatal("exec: %r");
-	}else{
-		close(pfd[0]);
-		p = cmd;
-		e = cmd + sizeof(cmd);
-		p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
-		p = seprint(p + 1, e, "host=%s", host);
-		c->type = ConnGit9;
-		c->rfd = pfd[1];
-		c->wfd = dup(pfd[1], -1);
-		if(writepkt(c, cmd, p - cmd + 1) == -1){
-			fprint(2, "failed to write message\n");
-			close(c->rfd);
-			close(c->wfd);
-			return -1;
-		}
 	}
-	return 0;
+	close(pfd[0]);
+	c->type = ConnGit9;
+	c->rfd = pfd[1];
+	c->wfd = dup(pfd[1], -1);
+	return githandshake(c, host, path, direction);
 }
 
+void
+initconn(Conn *c, int rd, int wr)
+{
+	c->type = ConnGit;
+	c->rfd = rd;
+	c->wfd = wr;
+}
 
 static int
 dialgit(Conn *c, char *host, char *port, char *path, char *direction)
 {
-	char *ds, *p, *e, cmd[512];
+	char *ds;
 	int fd;
 
 	if((ds = netmkaddr(host, "tcp", port)) == nil)
@@ -349,29 +363,53 @@
 	fd = dial(ds, nil, nil, nil);
 	if(fd == -1)
 		return -1;
-	p = cmd;
-	e = cmd + sizeof(cmd);
-	p = seprint(p, e - 1, "git-%s-pack %s", direction, path);
-	p = seprint(p + 1, e, "host=%s", host);
 	c->type = ConnGit;
 	c->rfd = fd;
 	c->wfd = dup(fd, -1);
-	if(writepkt(c, cmd, p - cmd + 1) == -1){
-		fprint(2, "failed to write message\n");
-		close(fd);
-		return -1;
-	}
-	return 0;
+	return githandshake(c, host, path, direction);
 }
 
-void
-initconn(Conn *c, int rd, int wr)
+static int
+servelocal(Conn *c, char *path, char *direction)
 {
+	int pid, pfd[2];
+
+	if(pipe(pfd) == -1)
+		sysfatal("unable to open pipe: %r");
+	pid = fork();
+	if(pid == -1)
+		sysfatal("unable to fork");
+	if(pid == 0){
+		close(pfd[1]);
+		dup(pfd[0], 0);
+		dup(pfd[0], 1);
+		execl("/bin/git/serve", "serve", "-w", nil);
+		sysfatal("exec: %r");
+	}
+	close(pfd[0]);
 	c->type = ConnGit;
-	c->rfd = rd;
-	c->wfd = wr;
+	c->rfd = pfd[1];
+	c->wfd = dup(pfd[1], -1);
+	return githandshake(c, nil, path, direction);
 }
 
+static int
+localrepo(char *uri, char *path, int npath)
+{
+	int fd;
+
+	snprint(path, npath, "%s/.git/../", uri);
+	fd = open(path, OREAD);
+	if(fd < 0)
+		return -1;
+	if(fd2path(fd, path, npath) != 0){
+		close(fd);
+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
 int
 gitconnect(Conn *c, char *uri, char *direction)
 {
@@ -378,12 +416,16 @@
 	char proto[Nproto], host[Nhost], port[Nport];
 	char repo[Nrepo], path[Npath];
 
+	memset(c, 0, sizeof(Conn));
+	c->rfd = c->wfd = c->cfd = -1;
+
+	if(localrepo(uri, path, sizeof(path)) == 0)
+		return servelocal(c, path, direction);
+
 	if(parseuri(uri, proto, host, port, path, repo) == -1){
 		werrstr("bad uri %s", uri);
 		return -1;
 	}
-
-	memset(c, 0, sizeof(Conn));
 	if(strcmp(proto, "ssh") == 0)
 		return dialssh(c, host, port, path, direction);
 	else if(strcmp(proto, "git") == 0)
--- a/save.c
+++ b/save.c
@@ -345,11 +345,17 @@
 main(int argc, char **argv)
 {
 	Hash th, ch, parents[Maxparents];
-	char *msg, *name, *email, *dstr;
-	int i, r, nparents;
+	char *msg, *name, *email, *dstr, cwd[1024];
+	int i, r, ncwd, nparents;
 	vlong date;
 	Object *t;
 
+	gitinit();
+	gitinit();
+	if(access(".git", AEXIST) != 0)
+		sysfatal("could not find git repo: %r");
+	if(getwd(cwd, sizeof(cwd)) == nil)
+		sysfatal("getcwd: %r");
 	msg = nil;
 	name = nil;
 	email = nil;
@@ -356,7 +362,8 @@
 	dstr = nil;
 	date = time(nil);
 	nparents = 0;
-	gitinit();
+	ncwd = strlen(cwd);
+
 	ARGBEGIN{
 	case 'm':	msg = EARGF(usage());	break;
 	case 'n':	name = EARGF(usage());	break;
@@ -385,12 +392,14 @@
 	}
 	if(msg == nil || name == nil)
 		usage();
-	for(i = 0; i < argc; i++)
+	for(i = 0; i < argc; i++){
 		cleanname(argv[i]);
+		if(*argv[i] == '/' && strncmp(argv[i], cwd, ncwd) == 0)
+			argv[i] += ncwd;
+		while(*argv[i] == '/')
+			argv[i]++;
+	}
 
-	gitinit();
-	if(access(".git", AEXIST) != 0)
-		sysfatal("could not find git repo: %r");
 	t = findroot();
 	r = treeify(t, argv, argv + argc, 0, &th);
 	if(r == -1)
--- a/serve.c
+++ b/serve.c
@@ -5,8 +5,7 @@
 
 #include "git.h"
 
-char	*pathpfx = "/usr/git";
-char	*namespace = nil;
+char	*pathpfx = nil;
 int	allowwrite;
 
 int
@@ -498,7 +497,6 @@
 main(int argc, char **argv)
 {
 	char *repo, cmd[32], buf[512];
-	char *user;
 	Conn c;
 
 	ARGBEGIN{
@@ -510,9 +508,6 @@
 		if(*pathpfx != '/')
 			sysfatal("path prefix must begin with '/'");
 		break;
-	case 'n':
-		namespace=EARGF(usage());
-		break;
 	case 'w':
 		allowwrite++;
 		break;
@@ -522,14 +517,13 @@
 	}ARGEND;
 
 	gitinit();
-	user = "none";
 	interactive = 0;
-	if(allowwrite)
-		user = getuser();
-	if(newns(user, namespace) == -1)
-		sysfatal("addns: %r");
-	if(bind(pathpfx, "/", MREPL) == -1)
-		sysfatal("bind: %r");
+	if(rfork(RFNAMEG) == -1)
+		sysfatal("rfork: %r");
+	if(pathpfx != nil){
+		if(bind(pathpfx, "/", MREPL) == -1)
+			sysfatal("bind: %r");
+	}
 	if(rfork(RFNOMNT) == -1)
 		sysfatal("rfork: %r");