~ori/git9

c65ded47aa82d89e1998ed0e8bbc8b1009d25642 — Ori Bernstein 3 years ago 30f2516
all: sync with 9front
14 files changed, 152 insertions(+), 56 deletions(-)

M add -rwxr-xr-x => -rw-r--r--
M branch -rw-r--r-- => -rwxr-xr-x
M commit -rwxr-xr-x => -rw-r--r--
M conf.c
M diff -rwxr-xr-x => -rw-r--r--
M fetch.c
M fs.c
M import
A log
M log.c
M pack.c
M push
M revert
M save.c
M add => add +1 -3
@@ 31,9 31,7 @@ for(f in $files){
		# 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
	}
}

M branch => branch +13 -10
@@ 37,6 37,15 @@ if not if(test -e .git/$new)
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 @@ if(~ $delete 1){
	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 @@ for(m in $cleanpaths){
		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
	}
}


M commit => commit +0 -0
M conf.c => conf.c +1 -0
@@ 78,6 78,7 @@ main(int argc, char **argv)
		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++){

M diff => diff +0 -0
M fetch.c => fetch.c +1 -6
@@ 228,13 228,8 @@ fetchpack(Conn *c, int pfd, char *packtmp)
		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)

M fs.c => fs.c +16 -9
@@ 79,6 79,7 @@ char *qroot[] = {

char	gitdir[512];
char	*username;
char	*groupname;
char	*mntpt = ".git/fs";
char	**branches = nil;
Cache	uqidcache[512];


@@ 164,7 165,7 @@ obj2dir(Dir *d, Crumb *c, Object *o, char *name)
	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 @@ rootgen(int i, Dir *d, void *p)
	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 @@ branchgen(int i, Dir *d, void *p)
	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 @@ gtreegen(int i, Dir *d, void *p)
	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 @@ gcommitgen(int i, Dir *d, void *p)
	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 @@ objwalk1(Qid *q, Object *o, Crumb *p, Crumb *c, char *name, vlong qdir, Gitaux *
	}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 @@ gitstat(Req *r)
	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 @@ usage(void)
void
main(int argc, char **argv)
{
	Dir *d;

	gitinit();
	ARGBEGIN{
	case 'd':


@@ 852,7 854,12 @@ main(int argc, char **argv)
	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);

M import => import +11 -3
@@ 37,7 37,7 @@ fn apply @{
		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 @@ eval `''{aux/getflags $*} || exec aux/usage
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 ''

A log => log +49 -0
@@ 0,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 ''

M log.c => log.c +11 -5
@@ 282,7 282,7 @@ void
main(int argc, char **argv)
{
	char path[1024], repo[1024], *p, *r;
	int i;
	int i, nrepo;

	ARGBEGIN{
	case 'e':


@@ 301,15 301,21 @@ main(int argc, char **argv)

	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);

M pack.c => pack.c +44 -15
@@ 70,6 70,7 @@ int	cachemax = 4096;
Packf	*packf;
int	npackf;
int	openpacks;
int	gitdirmode = -1;

static void
clear(Object *o)


@@ 887,7 888,7 @@ parsecommit(Object *o)
static void
parsetree(Object *o)
{
	int m, entsz, nent;
	int m, a, entsz, nent;
	Dirent *t, *ent;
	char *p, *ep;



@@ 908,7 909,15 @@ parsetree(Object *o)
		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 @@ Object*
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 @@ indexpack(char *pack, char *idx, Hash ph)
		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 @@ indexpack(char *pack, char *idx, Hash ph)
			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 @@ genpack(int fd, Meta **meta, int nmeta, Hash *h, int odelta)
	DigestState *st;
	Biobuf *bfd;
	Meta *m;
	Object *o, *b;
	Object *o, *po, *b;
	char *p, buf[32];

	st = nil;


@@ 1655,27 1677,34 @@ genpack(int fd, Meta **meta, int nmeta, Hash *h, int odelta)
	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){
				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);

M push => push +1 -1
@@ 31,7 31,7 @@ branch=-b^$branch
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'/'}

M revert => revert +4 -3
@@ 1,5 1,5 @@
#!/bin/rc
rfork e
rfork en
. /sys/lib/git/common.rc

gitup


@@ 11,9 11,10 @@ commit=$gitfs/HEAD
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 ''

M save.c => save.c +0 -1
@@ 351,7 351,6 @@ main(int argc, char **argv)
	Object *t;

	gitinit();
	gitinit();
	if(access(".git", AEXIST) != 0)
		sysfatal("could not find git repo: %r");
	if(getwd(cwd, sizeof(cwd)) == nil)