Commit Diff


commit - 32c73ca458e21536a20a64dc160fa38d92029cce
commit + 2444c4b4557ad5f4280ab1995a634e4417897917
blob - 4251aa564ea993a3f0dd5ffc945f42dc28d5ce18
blob + bbe1eec2d576b289548f767deccdd88c00adeaf8
--- tog/tog.c
+++ tog/tog.c
@@ -371,6 +371,7 @@ struct tog_diff_view_state {
 	int force_text_diff;
 	int diff_worktree;
 	int diff_staged;
+	int use_committer;
 	struct got_repository *repo;
 	struct got_pathlist_head *paths;
 	struct got_diff_line *lines;
@@ -642,6 +643,7 @@ struct tog_help_view_state {
 	KEY_("[", "Decrease the number of context lines"), \
 	KEY_("]", "Increase the number of context lines"), \
 	KEY_("w", "Toggle ignore whitespace-only changes in the diff"), \
+	KEY_("@", "Toggle between displaying author and committer date"), \
 	\
 	KEYMAP_("Blame view", TOG_KEYMAP_BLAME), \
 	KEY_("Enter", "Display diff view of the selected line's commit"), \
@@ -5777,7 +5779,7 @@ draw_file(struct tog_view *view, const char *header)
 }
 
 static char *
-get_datestr(time_t *time, char *datebuf)
+get_datestr(const time_t *time, char *datebuf)
 {
 	struct tm mytm, *tm;
 	char *p, *s;
@@ -5928,16 +5930,41 @@ write_diffstat(FILE *outfile, struct got_diff_line **l
 }
 
 static const struct got_error *
+write_date(struct got_diff_line **lines, size_t *nlines,
+    const char *prefix, const time_t *t, FILE *outfile, off_t *outoff)
+{
+	const struct got_error *err;
+	char datebuf[26], *datestr;
+	int n;
+
+	datestr = get_datestr(t, datebuf);
+	if (datestr == NULL)
+		return NULL;	/* silently ignored */
+
+	n = fprintf(outfile, "%s %s UTC\n", prefix, datestr);
+	if (n < 0) {
+		err = got_error_from_errno("fprintf");
+		return err;
+	}
+	*outoff += n;
+	err = add_line_metadata(lines, nlines, *outoff,
+	    GOT_DIFF_LINE_DATE);
+	if (err)
+		return err;
+
+	return NULL;
+}
+
+static const struct got_error *
 write_commit_info(struct got_diff_line **lines, size_t *nlines,
     struct got_object_id *commit_id, struct got_reflist_head *refs,
     struct got_repository *repo, int ignore_ws, int force_text_diff,
-    struct got_diffstat_cb_arg *dsa, FILE *outfile)
+    int use_committer, struct got_diffstat_cb_arg *dsa, FILE *outfile)
 {
 	const struct got_error *err = NULL;
-	char datebuf[26], *datestr;
 	struct got_commit_object *commit;
 	char *id_str = NULL, *logmsg = NULL, *s = NULL, *line;
-	time_t committer_time;
+	time_t timestamp;
 	const char *author, *committer;
 	char *refs_str = NULL;
 	off_t outoff = 0;
@@ -5972,19 +5999,22 @@ write_commit_info(struct got_diff_line **lines, size_t
 	if (err)
 		goto done;
 
-	n = fprintf(outfile, "from: %s\n",
-	    got_object_commit_get_author(commit));
-	if (n < 0) {
-		err = got_error_from_errno("fprintf");
-		goto done;
-	}
-	outoff += n;
-	err = add_line_metadata(lines, nlines, outoff, GOT_DIFF_LINE_AUTHOR);
-	if (err)
-		goto done;
-
+	/* author and committer data */
 	author = got_object_commit_get_author(commit);
 	committer = got_object_commit_get_committer(commit);
+	if (use_committer)
+		timestamp = got_object_commit_get_committer_time(commit);
+	else
+		timestamp = got_object_commit_get_author_time(commit);
+	n = fprintf(outfile, "from: %s\n", author);
+	if (n < 0) {
+		err = got_error_from_errno("fprintf");
+		goto done;
+	}
+	outoff += n;
+	err = add_line_metadata(lines, nlines, outoff, GOT_DIFF_LINE_AUTHOR);
+	if (err)
+		goto done;
 	if (strcmp(author, committer) != 0) {
 		n = fprintf(outfile, "via: %s\n", committer);
 		if (n < 0) {
@@ -5997,20 +6027,11 @@ write_commit_info(struct got_diff_line **lines, size_t
 		if (err)
 			goto done;
 	}
-	committer_time = got_object_commit_get_committer_time(commit);
-	datestr = get_datestr(&committer_time, datebuf);
-	if (datestr) {
-		n = fprintf(outfile, "date: %s UTC\n", datestr);
-		if (n < 0) {
-			err = got_error_from_errno("fprintf");
-			goto done;
-		}
-		outoff += n;
-		err = add_line_metadata(lines, nlines, outoff,
-		    GOT_DIFF_LINE_DATE);
-		if (err)
-			goto done;
-	}
+	err = write_date(lines, nlines, "date:", &timestamp, outfile, &outoff);
+	if (err)
+		goto done;
+
+	/* parent commits */
 	if (got_object_commit_get_nparents(commit) > 1) {
 		const struct got_object_id_queue *parent_ids;
 		struct got_object_qid *qid;
@@ -6540,7 +6561,7 @@ tog_diff_objects(struct tog_diff_view_state *s, FILE *
 		if (s->id1 == NULL)
 			return write_commit_info(&s->lines, &s->nlines, s->id2,
 			    refs, s->repo, s->ignore_whitespace,
-			    s->force_text_diff, dsa, s->f);
+			    s->force_text_diff, s->use_committer, dsa, s->f);
 
 		err = got_object_open_as_commit(&commit2, s->repo,
 		    s->id2);
@@ -6552,7 +6573,8 @@ tog_diff_objects(struct tog_diff_view_state *s, FILE *
 			if (got_object_id_cmp(s->id1, &pid->id) == 0) {
 				err = write_commit_info(&s->lines, &s->nlines,
 				    s->id2, refs, s->repo, s->ignore_whitespace,
-				    s->force_text_diff, dsa, s->f);
+				    s->force_text_diff, s->use_committer, dsa,
+				    s->f);
 				break;
 			}
 		}
@@ -6888,6 +6910,7 @@ open_diff_view(struct tog_view *view, struct got_objec
 	s->force_text_diff = force_text_diff;
 	s->diff_worktree = diff_worktree;
 	s->diff_staged = diff_staged;
+	s->use_committer = 1;
 	s->parent_view = parent_view;
 	s->paths = paths;
 	s->repo = repo;
@@ -7406,6 +7429,12 @@ input_diff_view(struct tog_view **new_view, struct tog
 		view->count = 0;
 		err = diff_write_patch(view);
 		break;
+	case '@':
+		s->use_committer = !s->use_committer;
+		view->action = s->use_committer ?
+		    "show commit date" : "show author date";
+		err = create_diff(s);
+		break;
 	default:
 		view->count = 0;
 		break;