Commit bcb49d15e041ddffb59397d2fe851fdb1729b005

Stefan Sperling 2019-08-15T00:07:22

make 'got blame' show dates at which lines were last modified

diff --git a/got/got.c b/got/got.c
index 0a9f047..228ca70 100644
--- a/got/got.c
+++ b/got/got.c
@@ -2158,6 +2158,7 @@ struct blame_line {
 	int annotated;
 	char *id_str;
 	char *committer;
+	char datebuf[9]; /* YY-MM-DD + NUL */
 };
 
 struct blame_cb_args {
@@ -2180,6 +2181,8 @@ blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
 	size_t linesize = 0;
 	struct got_commit_object *commit = NULL;
 	off_t offset;
+	struct tm tm;
+	time_t committer_time;
 
 	if (nlines != a->nlines ||
 	    (lineno != -1 && lineno < 1) || lineno > a->nlines)
@@ -2205,6 +2208,15 @@ blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
 		err = got_error_from_errno("strdup");
 		goto done;
 	}
+
+	committer_time = got_object_commit_get_committer_time(commit);
+	if (localtime_r(&committer_time, &tm) == NULL)
+		return got_error_from_errno("localtime_r");
+	if (strftime(bline->datebuf, sizeof(bline->datebuf), "%g/%m/%d",
+	    &tm) >= sizeof(bline->datebuf)) {
+		err = got_error(GOT_ERR_NO_SPACE);
+		goto done;
+	}
 	bline->annotated = 1;
 
 	/* Print lines annotated so far. */
@@ -2242,8 +2254,8 @@ blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
 		nl = strchr(line, '\n');
 		if (nl)
 			*nl = '\0';
-		printf("%.*d) %.8s %-8s %s\n", a->nlines_prec, a->lineno_cur,
-		    bline->id_str, committer, line);
+		printf("%.*d) %.8s %s %-8s %s\n", a->nlines_prec, a->lineno_cur,
+		    bline->id_str, bline->datebuf, committer, line);
 
 		a->lineno_cur++;
 		bline = &a->lines[a->lineno_cur - 1];
diff --git a/regress/cmdline/blame.sh b/regress/cmdline/blame.sh
index ffd9450..60ecdd0 100755
--- a/regress/cmdline/blame.sh
+++ b/regress/cmdline/blame.sh
@@ -37,6 +37,7 @@ function test_blame_basic {
 	echo 3 >> $testroot/wt/alpha
 	(cd $testroot/wt && got commit -m "change 3" > /dev/null)
 	local commit3=`git_show_head $testroot/repo`
+	local author_time=`git_show_author_time $testroot/repo`
 
 	(cd $testroot/wt && got blame alpha > $testroot/stdout)
 
@@ -44,9 +45,10 @@ function test_blame_basic {
 	local short_commit2=`trim_obj_id 32 $commit2`
 	local short_commit3=`trim_obj_id 32 $commit3`
 
-	echo "1) $short_commit1 $GOT_AUTHOR_8 1" > $testroot/stdout.expected
-	echo "2) $short_commit2 $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
-	echo "3) $short_commit3 $GOT_AUTHOR_8 3" >> $testroot/stdout.expected
+	d=`date -r $author_time +"%g/%m/%d"`
+	echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
+	echo "2) $short_commit2 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
+	echo "3) $short_commit3 $d $GOT_AUTHOR_8 3" >> $testroot/stdout.expected
 
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
@@ -80,14 +82,16 @@ function test_blame_tag {
 	echo 3 >> $testroot/wt/alpha
 	(cd $testroot/wt && got commit -m "change 3" > /dev/null)
 	local commit3=`git_show_head $testroot/repo`
+	local author_time=`git_show_author_time $testroot/repo`
 
 	(cd $testroot/wt && got blame -c $tag alpha > $testroot/stdout)
 
 	local short_commit1=`trim_obj_id 32 $commit1`
 	local short_commit2=`trim_obj_id 32 $commit2`
 
-	echo "1) $short_commit1 $GOT_AUTHOR_8 1" > $testroot/stdout.expected
-	echo "2) $short_commit2 $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
+	d=`date -r $author_time +"%g/%m/%d"`
+	echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
+	echo "2) $short_commit2 $d $GOT_AUTHOR_8 2" >> $testroot/stdout.expected
 
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
@@ -110,12 +114,14 @@ function test_blame_file_single_line {
 	echo 1 > $testroot/wt/alpha
 	(cd $testroot/wt && got commit -m "change 1" > /dev/null)
 	local commit1=`git_show_head $testroot/repo`
+	local author_time=`git_show_author_time $testroot/repo`
 
 	(cd $testroot/wt && got blame alpha > $testroot/stdout)
 
 	local short_commit1=`trim_obj_id 32 $commit1`
 
-	echo "1) $short_commit1 $GOT_AUTHOR_8 1" > $testroot/stdout.expected
+	d=`date -r $author_time +"%g/%m/%d"`
+	echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
 
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
@@ -138,12 +144,14 @@ function test_blame_file_single_line_no_newline {
 	echo -n 1 > $testroot/wt/alpha
 	(cd $testroot/wt && got commit -m "change 1" > /dev/null)
 	local commit1=`git_show_head $testroot/repo`
+	local author_time=`git_show_author_time $testroot/repo`
 
 	(cd $testroot/wt && got blame alpha > $testroot/stdout)
 
 	local short_commit1=`trim_obj_id 32 $commit1`
 
-	echo "1) $short_commit1 $GOT_AUTHOR_8 1" > $testroot/stdout.expected
+	d=`date -r $author_time +"%g/%m/%d"`
+	echo "1) $short_commit1 $d $GOT_AUTHOR_8 1" > $testroot/stdout.expected
 
 	cmp -s $testroot/stdout.expected $testroot/stdout
 	ret="$?"
diff --git a/regress/cmdline/common.sh b/regress/cmdline/common.sh
index 296735a..0c8a19f 100644
--- a/regress/cmdline/common.sh
+++ b/regress/cmdline/common.sh
@@ -45,6 +45,12 @@ function git_show_head
 	(cd $repo && git show --no-patch --pretty='format:%H')
 }
 
+function git_show_author_time
+{
+	local repo="$1"
+	(cd $repo && git show --no-patch --pretty='format:%at')
+}
+
 function git_show_parent_commit
 {
 	local repo="$1"