shithub: git9

Download patch

ref: 189059cc9a4f0570e25c4d580379c4119f371a06
parent: ac432ac824be5dea58ede0858f80820da6933ca4
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Feb 25 14:35:04 EST 2020

Improve file-filtered git/log, tweak git/query

	This commmit makes several changes to improve git/log,
	which now reliably and cleanly will show differences.

	The following flags are changed:

		-b is now -c:
			this is done for consistency with other
			commands.

		-s is new:
			Shows a short git summary.

	Git/query also got changed: It now shows the zero hash
	as the parent of the first git commit, instead of giving
	an error.

--- a/fs.c
+++ b/fs.c
@@ -226,25 +226,6 @@
 	}
 }
 
-/* FIXME: walk to the appropriate submodule.. */
-static Object*
-emptydir(Dirent *e)
-{
-	Object *m;
-
-	m = emalloc(sizeof(Object));
-	m->hash = e->h;
-	m->type = GTree;
-	m->tree = emalloc(sizeof(Tree));
-	m->tree->ent = nil;
-	m->tree->nent = 0;
-	m->flag |= Cloaded|Cparsed;
-	m->off = -1;
-	ref(m);
-	cache(m);
-	return m;
-}
-
 static int
 gtreegen(int i, Dir *d, void *p)
 {
@@ -260,7 +241,7 @@
 	if(i >= e->tree->nent)
 		return -1;
 	if(e->tree->ent[i].ismod)
-		o = emptydir(&e->tree->ent[i]);
+		o = emptydir();
 	else if((o = readobject(e->tree->ent[i].h)) == nil)
 		die("could not read object %H: %r", e->tree->ent[i].h, e->hash);
 	if(e->tree->ent[i].islink)
@@ -489,7 +470,7 @@
 			m = o->tree->ent[i].mode;
 			w = readobject(o->tree->ent[i].h);
 			if(!w && o->tree->ent[i].ismod)
-				w = emptydir(&o->tree->ent[i]);
+				w = emptydir();
 			if(w && o->tree->ent[i].islink)
 				if((l = walklink(aux, w->data, w->size, 1, &m)) != nil)
 					w = l;
@@ -511,7 +492,7 @@
 		assert(qdir == Qcommit || qdir == Qobject || qdir == Qcommittree || qdir == Qhead);
 		if(strcmp(name, "msg") == 0)
 			q->path = qpath(p, 0, o->id, Qcommitmsg);
-		else if(strcmp(name, "parent") == 0 && o->commit->nparent != 0)
+		else if(strcmp(name, "parent") == 0)
 			q->path = qpath(p, 1, o->id, Qcommitparent);
 		else if(strcmp(name, "hash") == 0)
 			q->path = qpath(p, 2, o->id, Qcommithash);
--- a/git.1
+++ b/git.1
@@ -83,10 +83,15 @@
 .PP
 .B git/log
 [
-.B -b
-.I branch
+.B -c
+.I commit
+.B | -q
+.I query
 ]
 [
+.B -s
+]
+[
 .I files...
 ]
 .PP
@@ -283,6 +288,19 @@
 .PP
 .B Git/log
 shows a history of the current branch.
+When passed a list of files, only commits affecting
+those files are shown.
+The
+.I -c commit
+option logs starting from the provided commit, instead of HEAD.
+The
+.I -s
+option shows a summary of the commit, instead of the full message.
+The
+.I -q query
+option shows commits matching the query provided. The query
+is specified using the syntax of
+.B git/query.
 
 .PP
 .B Git/diff
--- a/git.h
+++ b/git.h
@@ -229,6 +229,7 @@
 Object	*ref(Object *);
 void	unref(Object *);
 void	cache(Object *);
+Object	*emptydir(void);
 
 /* object sets */
 void	osinit(Objset *);
--- a/log
+++ b/log
@@ -3,7 +3,7 @@
 . /sys/lib/git/common.rc
 
 usage='
-	git/log [-q query] [file ...]
+	git/log [-q query|-c commit] [-s] [file ...]
 '
 
 gitup
@@ -11,15 +11,18 @@
 base=/mnt/git/object/
 branch=`{git/branch}
 query=()
-
+short=()
+files=()
 while(~ $1 -* && ! ~ $1 --){
 	switch($1){
-	case -b
-		branch=$2
+	case -c
+		base=$2
 		shift
 	case -q
 		query=$2
 		shift
+	case -s
+		short=true
 	case *
 		usage
 	}
@@ -31,29 +34,34 @@
 	commits=`{git/query $branch}
 if not
 	commits=`{git/query $query}
-files=()
+
 if(! ~ $#* 0)
-	files=`$nl{walk -f $*}
+	files=`"{walk -f $gitrel^$* | sort}
 
-if(! ~ $#files 0)
-	nids=`{sha1sum $base/$commits(1)^/tree/$files | awk '{print $1}' >[2]/dev/null}
-
 while(! ~ $#commits 0){
 	ids=$nids
+	show=()
 	c=$commits(1)
-	if(! ~ $#files 0)
-		nids=`{sha1sum $base/$commits(1)^/tree/$files | awk '{print $1}' >[2]/dev/null}
-		commits=$commits(2-)
-		if(~ $#query 0)
-			commits=($commits `{cat $base/$c/parent >[2]/dev/null})
+	if(! ~ $#files 0){
+		ncomm=`{comm -12 /env/files <{git/query -c $c~ $c | sed 's/^..//' | sort} | wc -l}
+		if(! ~ $ncomm 0)
+			show=true
+	}
+	commits=$commits(2-)
+	if(~ $#query 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 || ! ~ $"ids $"nids || ~ $#commits 0){
-		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}'}}
-		sed 's/^/	/g' $base/$c/msg
-		echo
+	if(~ $#files 0 || ~ $show true){
+		if(~ $short true)
+			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}'}}
+			sed 's/^/	/g' $base/$c/msg
+			echo
+		}
 	}
 }
--- a/query.c
+++ b/query.c
@@ -62,6 +62,7 @@
 	Object *a, *b;
 	int c;
 
+
 	if((a = readobject(ah)) == nil)
 		sysfatal("bad hash %H", ah);
 	if((b = readobject(bh)) == nil)
--- a/ref.c
+++ b/ref.c
@@ -220,10 +220,13 @@
 
 	o = pop(ev);
 	/* Special case: first commit has no parent. */
-	if(o->commit->nparent == 0 || (p = readobject(o->commit->parent[0])) == nil){
+	if(o->commit->nparent == 0)
+		p = emptydir();
+	else if ((p = readobject(o->commit->parent[0])) == nil){
 		werrstr("no parent for %H", o->hash);
 		return -1;
 	}
+		
 	push(ev, p);
 	return 0;
 }
--- a/save.c
+++ b/save.c
@@ -14,16 +14,6 @@
 	Maxparents = 16,
 };
 
-Object*
-emptydir(void)
-{
-	Object *t;
-
-	t = emalloc(sizeof(Object));
-	t->tree = emalloc(sizeof(Tinfo));
-	return t;
-}
-
 int
 gitmode(int m)
 {
--- a/util.c
+++ b/util.c
@@ -7,6 +7,26 @@
 Reprog *authorpat;
 Hash Zhash;
 
+Object*
+emptydir(void)
+{
+	static Object *e;
+
+	if(e != nil)
+		return e;
+	e = emalloc(sizeof(Object));
+	e->hash = Zhash;
+	e->type = GTree;
+	e->tree = emalloc(sizeof(Tinfo));
+	e->tree->ent = nil;
+	e->tree->nent = 0;
+	e->flag |= Cloaded|Cparsed;
+	e->off = -1;
+	ref(e);
+	cache(e);
+	return e;
+}
+
 int
 hasheq(Hash *a, Hash *b)
 {