commit - 282924c1e6cd7db9281df73757d81406513c0d42
commit + c75e74214f40cfb13542a5331afaf32280f708fa
blob - 9e9c1f1986ac507f2ccf5449d989cd59ff4bf43c
blob + 528451906a8ec3ab90d51ead482cb3f1dc70fa3e
--- regress/tog/diff.sh
+++ regress/tog/diff.sh
test_diff_arbitrary_commits()
{
- test_init diff_arbitrary_commits 80 18
+ test_init diff_arbitrary_commits
local commit_id1=`git_show_head $testroot/repo`
local alpha_id_old=`get_blob_id $testroot/repo "" alpha`
EOF
cat <<EOF >$testroot/view.expected
-$(trim 80 "[1/16] diff $commit_id1 $head_id_truncated")
+$(trim 80 "[1/21] diff $commit_id1 $head_id_truncated")
+M alpha | 1+ 1-
+A new | 1+ 0-
+
+2 files changed, 2 insertions(+), 1 deletion(-)
+
commit - $commit_id1
commit + $head_id
blob - $alpha_id_old
@@ -0,0 +1 @@
+new file
+
(END)
EOF
rhs_id=$(pop_idx 8 $ids)
cat <<-EOF >$testroot/view.expected
- $(trim 120 "[1/10] diff $lhs_id $rhs_id")
+ $(trim 120 "[1/14] diff $lhs_id $rhs_id")
+ M alpha | 1+ 1-
+
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
commit - $lhs_id
commit + $rhs_id
blob - $(pop_idx 5 $alpha_ids)
-
-
-
-
(END)
EOF
fi
cat <<EOF >$testroot/content.expected
+M alpha | 1+ 1-
+M beta | 1+ 1-
+
+2 files changed, 2 insertions(+), 2 deletions(-)
+
commit - $id_root
commit + $id_head
blob - $alpha_root
+modified beta
EOF
- # test diff of arbitrary commits
+ # test diff of arbitrary commits displays diffstat in patch file
cd $testroot/repo && tog diff :head:-2 :head
patchpath=$(tail -1 $testroot/view | cut -d' ' -f 5)
test_done "$testroot" $ret
}
+
+test_diff_blobs()
+{
+ test_init diff_blobs 148 14
+ local blob_alpha_root=$(get_blob_id $testroot/repo "" alpha)
+
+ echo "new alpha" > $testroot/repo/alpha
+ git_commit $testroot/repo -m "new alpha"
+
+ local blob_alpha_head=$(get_blob_id $testroot/repo "" alpha)
+
+ cat <<EOF >$TOG_TEST_SCRIPT
+SCREENDUMP
+EOF
+
+ cat <<EOF >$testroot/view.expected
+[1/12] diff $blob_alpha_root $blob_alpha_head
+M $blob_alpha_head | 1+ 1-
+
+1 file changed, 1 insertion(+), 1 deletion(-)
+
+blob - $blob_alpha_root
+blob + $blob_alpha_head
+--- $blob_alpha_root
++++ $blob_alpha_head
+@@ -1 +1 @@
+-alpha
++new alpha
+
+(END)
+EOF
+
+ cd $testroot/repo && tog diff $blob_alpha_root $blob_alpha_head
+ cmp -s $testroot/view.expected $testroot/view
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/view.expected $testroot/view
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ test_done "$testroot" $ret
+}
+
+test_diff_trees()
+{
+ test_init diff_trees 148 16
+
+ local tree_gamma_root=$(get_blob_id $testroot/repo "" gamma/)
+ local blob_delta_root=$(get_blob_id $testroot/repo gamma delta)
+
+ echo "new delta" > $testroot/repo/gamma/delta
+ git_commit $testroot/repo -m "new delta"
+
+ local tree_gamma_head=$(get_blob_id $testroot/repo "" gamma/)
+ local blob_delta_head=$(get_blob_id $testroot/repo gamma delta)
+
+ cat <<EOF >$TOG_TEST_SCRIPT
+SCREENDUMP
+EOF
+
+ cat <<EOF >$testroot/view.expected
+[1/14] diff $tree_gamma_root $tree_gamma_head
+M delta | 1+ 1-
+
+1 file changed, 1 insertion(+), 1 deletion(-)
+
+tree - $tree_gamma_root
+tree + $tree_gamma_head
+blob - $blob_delta_root
+blob + $blob_delta_head
+--- delta
++++ delta
+@@ -1 +1 @@
+-delta
++new delta
+
+(END)
+EOF
+
+ cd $testroot/repo && tog diff $tree_gamma_root $tree_gamma_head
+ cmp -s $testroot/view.expected $testroot/view
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ diff -u $testroot/view.expected $testroot/view
+ test_done "$testroot" $ret
+ return 1
+ fi
+
+ test_done "$testroot" $ret
+}
+
test_parseargs "$@"
run_test test_diff_contiguous_commits
run_test test_diff_arbitrary_commits
run_test test_diff_commit_keywords
run_test test_diff_horizontal_scroll
run_test test_diff_p_keymap
+run_test test_diff_blobs
+run_test test_diff_trees
blob - 67bde569cd6803d9fc6f03e82a82db50051d61c3
blob + 0b8323f8cea5abb4777743d902c28ee9388c52f4
--- regress/tog/log.sh
+++ regress/tog/log.sh
test_log_mark_keymap()
{
- test_init log_mark_keymap 141 10
+ test_init log_mark_keymap 141 14
local repo="$testroot/repo"
local wt="$testroot/wt"
commit $id_root [2/2]
$ymd_head $prefix_head flan_hacker ~[master] new alpha
$ymd_root $prefix_root flan_hacker >adding the test tree
+
+
+
+
commit $id_root [2/2]
$ymd_head $prefix_head flan_hacker ~[master] new alpha
$ymd_root $prefix_root flan_hacker adding the test tree
+
+
+
+
+
+
+
+
EOF
tog log
EOF
cat <<-EOF >$testroot/view.expected
- [1/10] diff $id_head $id_root
+ [1/14] diff $id_head $id_root
+ M alpha | 1+ 1-
+
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
commit - $id_head
commit + $id_root
blob - $alpha_head
blob - aef5e53ec70381644eb56e603bd13c6f3e721e5e
blob + 25ca48971a9ae7a2b798a438e632875584b4f8a9
--- tog/tog.c
+++ tog/tog.c
*d_nlines += s_nlines;
return NULL;
+}
+
+static const struct got_error *
+write_diffstat(FILE *outfile, struct got_diff_line **lines, size_t *nlines,
+ struct got_diffstat_cb_arg *dsa)
+{
+ const struct got_error *err;
+ struct got_pathlist_entry *pe;
+ off_t offset;
+ int n;
+
+ if (*nlines == 0) {
+ err = add_line_metadata(lines, nlines, 0, GOT_DIFF_LINE_NONE);
+ if (err != NULL)
+ return err;
+ offset = 0;
+ } else
+ offset = (*lines)[*nlines - 1].offset;
+
+ TAILQ_FOREACH(pe, dsa->paths, entry) {
+ struct got_diff_changed_path *cp = pe->data;
+ int pad = dsa->max_path_len - pe->path_len + 1;
+
+ n = fprintf(outfile, "%c %s%*c | %*d+ %*d-\n", cp->status,
+ pe->path, pad, ' ', dsa->add_cols + 1, cp->add,
+ dsa->rm_cols + 1, cp->rm);
+ if (n < 0)
+ return got_error_from_errno("fprintf");
+
+ offset += n;
+ err = add_line_metadata(lines, nlines, offset,
+ GOT_DIFF_LINE_CHANGES);
+ if (err != NULL)
+ return err;
+ }
+
+ if (fputc('\n', outfile) == EOF)
+ return got_error_from_errno("fputc");
+
+ offset++;
+ err = add_line_metadata(lines, nlines, offset, GOT_DIFF_LINE_NONE);
+ if (err != NULL)
+ return err;
+
+ n = fprintf(outfile,
+ "%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n",
+ dsa->nfiles, dsa->nfiles > 1 ? "s" : "", dsa->ins,
+ dsa->ins != 1 ? "s" : "", dsa->del, dsa->del != 1 ? "s" : "");
+ if (n < 0)
+ return got_error_from_errno("fprintf");
+
+ offset += n;
+ err = add_line_metadata(lines, nlines, offset, GOT_DIFF_LINE_NONE);
+ if (err != NULL)
+ return err;
+
+ if (fputc('\n', outfile) == EOF)
+ return got_error_from_errno("fputc");
+
+ offset++;
+ return add_line_metadata(lines, nlines, offset, GOT_DIFF_LINE_NONE);
}
static const struct got_error *
time_t committer_time;
const char *author, *committer;
char *refs_str = NULL;
- struct got_pathlist_entry *pe;
off_t outoff = 0;
int n;
GOT_DIFF_LINE_LOGMSG);
if (err)
goto done;
- }
-
- TAILQ_FOREACH(pe, dsa->paths, entry) {
- struct got_diff_changed_path *cp = pe->data;
- int pad = dsa->max_path_len - pe->path_len + 1;
-
- n = fprintf(outfile, "%c %s%*c | %*d+ %*d-\n", cp->status,
- pe->path, pad, ' ', dsa->add_cols + 1, cp->add,
- dsa->rm_cols + 1, cp->rm);
- if (n < 0) {
- err = got_error_from_errno("fprintf");
- goto done;
- }
- outoff += n;
- err = add_line_metadata(lines, nlines, outoff,
- GOT_DIFF_LINE_CHANGES);
- if (err)
- goto done;
- }
-
- fputc('\n', outfile);
- outoff++;
- err = add_line_metadata(lines, nlines, outoff, GOT_DIFF_LINE_NONE);
- if (err)
- goto done;
-
- n = fprintf(outfile,
- "%d file%s changed, %d insertion%s(+), %d deletion%s(-)\n",
- dsa->nfiles, dsa->nfiles > 1 ? "s" : "", dsa->ins,
- dsa->ins != 1 ? "s" : "", dsa->del, dsa->del != 1 ? "s" : "");
- if (n < 0) {
- err = got_error_from_errno("fprintf");
- goto done;
}
- outoff += n;
- err = add_line_metadata(lines, nlines, outoff, GOT_DIFF_LINE_NONE);
- if (err)
- goto done;
- fputc('\n', outfile);
- outoff++;
- err = add_line_metadata(lines, nlines, outoff, GOT_DIFF_LINE_NONE);
done:
free(id_str);
free(logmsg);
struct got_diff_line *lines = NULL;
struct got_pathlist_head changed_paths;
struct got_commit_object *commit2 = NULL;
+ struct got_diffstat_cb_arg dsa;
+ size_t nlines = 0;
TAILQ_INIT(&changed_paths);
+ memset(&dsa, 0, sizeof(dsa));
+ dsa.paths = &changed_paths;
+ dsa.diff_algo = tog_diff_algo;
+ dsa.force_text = s->force_text_diff;
+ dsa.ignore_ws = s->ignore_whitespace;
free(s->lines);
s->lines = malloc(sizeof(*s->lines));
if (s->f == NULL)
return got_error_from_errno("got_opentemp");
+ /*
+ * The diffstat requires the diff to be built first, but we want the
+ * diffstat to prepend the diff when displayed. Build the diff first
+ * in the temporary file and write the diffstat and/or commit info to
+ * the persistent file (s->f) from which views are drawn, then append
+ * the diff from the temp file to the diffstat/commit info in s->f.
+ */
tmp_diff_file = got_opentemp();
if (tmp_diff_file == NULL)
return got_error_from_errno("got_opentemp");
+ lines = malloc(sizeof(*lines));
+ if (lines == NULL) {
+ err = got_error_from_errno("malloc");
+ goto done;
+ }
+
if (s->id1)
err = got_object_get_type(&obj_type, s->repo, s->id1);
else
switch (obj_type) {
case GOT_OBJ_TYPE_BLOB:
- err = got_diff_objects_as_blobs(&s->lines, &s->nlines,
+ err = got_diff_objects_as_blobs(&lines, &nlines,
s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2,
s->label1, s->label2, tog_diff_algo, s->diff_context,
- s->ignore_whitespace, s->force_text_diff, NULL, s->repo,
- s->f);
+ s->ignore_whitespace, s->force_text_diff, &dsa, s->repo,
+ tmp_diff_file);
+ if (err != NULL)
+ goto done;
break;
case GOT_OBJ_TYPE_TREE:
- err = got_diff_objects_as_trees(&s->lines, &s->nlines,
+ err = got_diff_objects_as_trees(&lines, &nlines,
s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL, "", "",
tog_diff_algo, s->diff_context, s->ignore_whitespace,
- s->force_text_diff, NULL, s->repo, s->f);
+ s->force_text_diff, &dsa, s->repo, tmp_diff_file);
+ if (err != NULL)
+ goto done;
break;
case GOT_OBJ_TYPE_COMMIT: {
const struct got_object_id_queue *parent_ids;
struct got_object_qid *pid;
struct got_reflist_head *refs;
- size_t nlines = 0;
- struct got_diffstat_cb_arg dsa = {
- 0, 0, 0, 0, 0, 0,
- &changed_paths,
- s->ignore_whitespace,
- s->force_text_diff,
- tog_diff_algo
- };
- lines = malloc(sizeof(*lines));
- if (lines == NULL) {
- err = got_error_from_errno("malloc");
- goto done;
- }
-
- /* build diff first in tmp file then append to commit info */
err = got_diff_objects_as_commits(&lines, &nlines,
s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL,
tog_diff_algo, s->diff_context, s->ignore_whitespace,
s->force_text_diff, &dsa, s->repo, tmp_diff_file);
if (err)
- break;
+ goto done;
refs = got_reflist_object_id_map_lookup(tog_refs_idmap, s->id2);
/* Show commit info if we're diffing to a parent/root commit. */
}
}
}
-
- err = cat_diff(s->f, tmp_diff_file, &s->lines, &s->nlines,
- lines, nlines);
break;
}
default:
err = got_error(GOT_ERR_OBJ_TYPE);
- break;
+ goto done;
}
+
+ err = write_diffstat(s->f, &s->lines, &s->nlines, &dsa);
+ if (err != NULL)
+ goto done;
+
+ err = cat_diff(s->f, tmp_diff_file, &s->lines, &s->nlines,
+ lines, nlines);
+
done:
free(lines);
if (commit2 != NULL)