commit 64453f7e55c4c69b6cd08229929ed8227b789ff8 from: Stefan Sperling date: Sat Nov 21 13:35:00 2020 UTC handle binary files in got/tog diff commands; add -a options to force text commit - b67f3bcb5237084aa51e21704775e3df1b159ad0 commit + 64453f7e55c4c69b6cd08229929ed8227b789ff8 blob - 2af328db5bc16371a9ab63961a5e8cdffad041e8 blob + c44524c54ba55850265ed0fc7be1f083914d1309 --- got/got.1 +++ got/got.1 @@ -785,7 +785,7 @@ This option has no effect if the specified .Ar commit is never traversed. .El -.It Cm diff Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path +.It Cm diff Oo Fl a Oc Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path When invoked within a work tree with less than two arguments, display local changes in the work tree. If a @@ -803,6 +803,8 @@ The options for .Cm got diff are as follows: .Bl -tag -width Ds +.It Fl a +Treat file contents as ASCII text even if binary data is detected. .It Fl C Ar number Set the number of context lines shown in the diff. By default, 3 lines of context are shown. blob - d471800beafe3df5995d9268f91ecb6e56f38953 blob + 3b8ba655c02b9df7b4088a73f765a46b9f598e97 --- got/got.c +++ got/got.c @@ -3124,7 +3124,7 @@ done: static const struct got_error * diff_blobs(struct got_object_id *blob_id1, struct got_object_id *blob_id2, const char *path, int diff_context, int ignore_whitespace, - struct got_repository *repo) + int force_text_diff, struct got_repository *repo) { const struct got_error *err = NULL; struct got_blob_object *blob1 = NULL, *blob2 = NULL; @@ -3142,7 +3142,7 @@ diff_blobs(struct got_object_id *blob_id1, struct got_ while (path[0] == '/') path++; err = got_diff_blob(NULL, NULL, blob1, blob2, path, path, - diff_context, ignore_whitespace, stdout); + diff_context, ignore_whitespace, force_text_diff, stdout); done: if (blob1) got_object_blob_close(blob1); @@ -3153,7 +3153,7 @@ done: static const struct got_error * diff_trees(struct got_object_id *tree_id1, struct got_object_id *tree_id2, const char *path, int diff_context, int ignore_whitespace, - struct got_repository *repo) + int force_text_diff, struct got_repository *repo) { const struct got_error *err = NULL; struct got_tree_object *tree1 = NULL, *tree2 = NULL; @@ -3171,6 +3171,7 @@ diff_trees(struct got_object_id *tree_id1, struct got_ arg.diff_context = diff_context; arg.ignore_whitespace = ignore_whitespace; + arg.force_text_diff = force_text_diff; arg.outfile = stdout; arg.line_offsets = NULL; arg.nlines = 0; @@ -3282,11 +3283,11 @@ print_patch(struct got_commit_object *commit, struct g switch (obj_type) { case GOT_OBJ_TYPE_BLOB: err = diff_blobs(obj_id1, obj_id2, path, diff_context, - 0, repo); + 0, 0, repo); break; case GOT_OBJ_TYPE_TREE: err = diff_trees(obj_id1, obj_id2, path, diff_context, - 0, repo); + 0, 0, repo); break; default: err = got_error(GOT_ERR_OBJ_TYPE); @@ -3305,8 +3306,10 @@ print_patch(struct got_commit_object *commit, struct g if (err) goto done; } - printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null", id_str2); - err = diff_trees(obj_id1, obj_id2, "", diff_context, 0, repo); + printf("diff %s %s\n", id_str1 ? id_str1 : "/dev/null", + id_str2); + err = diff_trees(obj_id1, obj_id2, "", diff_context, 0, 0, + repo); } done: free(id_str1); @@ -3887,8 +3890,8 @@ done: __dead static void usage_diff(void) { - fprintf(stderr, "usage: %s diff [-C number] [-r repository-path] [-s] " - "[-w] [object1 object2 | path]\n", getprogname()); + fprintf(stderr, "usage: %s diff [-a] [-C number] [-r repository-path] " + "[-s] [-w] [object1 object2 | path]\n", getprogname()); exit(1); } @@ -3900,6 +3903,7 @@ struct print_diff_arg { int header_shown; int diff_staged; int ignore_whitespace; + int force_text_diff; }; /* @@ -4004,7 +4008,7 @@ print_diff(void *arg, unsigned char status, unsigned c } return got_diff_objects_as_blobs(NULL, NULL, blob_id, staged_blob_id, label1, label2, a->diff_context, - a->ignore_whitespace, a->repo, stdout); + a->ignore_whitespace, a->force_text_diff, a->repo, stdout); } if (staged_status == GOT_STATUS_ADD || @@ -4077,7 +4081,7 @@ print_diff(void *arg, unsigned char status, unsigned c sb.st_size = 0; err = got_diff_blob_file(blob1, label1, f2, sb.st_size, path, - a->diff_context, a->ignore_whitespace, stdout); + a->diff_context, a->ignore_whitespace, a->force_text_diff, stdout); done: if (blob1) got_object_blob_close(blob1); @@ -4101,6 +4105,7 @@ cmd_diff(int argc, char *argv[]) char *label1 = NULL, *label2 = NULL; int type1, type2; int diff_context = 3, diff_staged = 0, ignore_whitespace = 0, ch; + int force_text_diff = 0; const char *errstr; char *path = NULL; @@ -4110,8 +4115,11 @@ cmd_diff(int argc, char *argv[]) err(1, "pledge"); #endif - while ((ch = getopt(argc, argv, "C:r:sw")) != -1) { + while ((ch = getopt(argc, argv, "aC:r:sw")) != -1) { switch (ch) { + case 'a': + force_text_diff = 1; + break; case 'C': diff_context = strtonum(optarg, 0, GOT_DIFF_MAX_CONTEXT, &errstr); @@ -4229,6 +4237,7 @@ cmd_diff(int argc, char *argv[]) arg.header_shown = 0; arg.diff_staged = diff_staged; arg.ignore_whitespace = ignore_whitespace; + arg.force_text_diff = force_text_diff; error = got_pathlist_append(&paths, path, NULL); if (error) @@ -4267,17 +4276,19 @@ cmd_diff(int argc, char *argv[]) switch (type1) { case GOT_OBJ_TYPE_BLOB: error = got_diff_objects_as_blobs(NULL, NULL, id1, id2, - NULL, NULL, diff_context, ignore_whitespace, repo, - stdout); + NULL, NULL, diff_context, ignore_whitespace, + force_text_diff, repo, stdout); break; case GOT_OBJ_TYPE_TREE: error = got_diff_objects_as_trees(NULL, NULL, id1, id2, - "", "", diff_context, ignore_whitespace, repo, stdout); + "", "", diff_context, ignore_whitespace, force_text_diff, + repo, stdout); break; case GOT_OBJ_TYPE_COMMIT: printf("diff %s %s\n", label1, label2); error = got_diff_objects_as_commits(NULL, NULL, id1, id2, - diff_context, ignore_whitespace, repo, stdout); + diff_context, ignore_whitespace, force_text_diff, repo, + stdout); break; default: error = got_error(GOT_ERR_OBJ_TYPE); blob - 6e5a0c492ea1eaa3cc496e6131fd71978725ad78 blob + 2e56321573d28e2eeb0cb21dadfcb6110292501c --- include/got_diff.h +++ include/got_diff.h @@ -26,7 +26,7 @@ */ const struct got_error *got_diff_blob(off_t **, size_t *, struct got_blob_object *, struct got_blob_object *, - const char *, const char *, int, int, FILE *); + const char *, const char *, int, int, int, FILE *); /* * Compute the differences between a blob and a file and write unified diff @@ -37,7 +37,7 @@ const struct got_error *got_diff_blob(off_t **, size_t * Whitespace differences may optionally be ignored. */ const struct got_error *got_diff_blob_file(struct got_blob_object *, - const char *, FILE *, size_t, const char *, int, int, FILE *); + const char *, FILE *, size_t, const char *, int, int, int, FILE *); /* * A callback function invoked to handle the differences between two blobs @@ -64,6 +64,7 @@ struct got_diff_blob_output_unidiff_arg { FILE *outfile; /* Unidiff text will be written here. */ int diff_context; /* Sets the number of context lines. */ int ignore_whitespace; /* Ignore whitespace differences. */ + int force_text_diff; /* Assume text even if binary data detected. */ /* * The number of lines contained in produced unidiff text output, @@ -128,7 +129,7 @@ const struct got_error *got_diff_tree_collect_changed_ */ const struct got_error *got_diff_objects_as_blobs(off_t **, size_t *, struct got_object_id *, struct got_object_id *, - const char *, const char *, int, int, + const char *, const char *, int, int, int, struct got_repository *, FILE *); /* @@ -142,7 +143,7 @@ const struct got_error *got_diff_objects_as_blobs(off_ */ const struct got_error *got_diff_objects_as_trees(off_t **, size_t *, struct got_object_id *, struct got_object_id *, char *, char *, - int, int, struct got_repository *, FILE *); + int, int, int, struct got_repository *, FILE *); /* * Diff two objects, assuming both objects are commits. @@ -152,7 +153,7 @@ const struct got_error *got_diff_objects_as_trees(off_ * array of line offsets for, and the number of lines in, the unidiff text. */ const struct got_error *got_diff_objects_as_commits(off_t **, size_t *, - struct got_object_id *, struct got_object_id *, int, int, + struct got_object_id *, struct got_object_id *, int, int, int, struct got_repository *, FILE *); #define GOT_DIFF_MAX_CONTEXT 64 blob - 1b319f38e537a78f703878f6a497ceef443622fd blob + f48f80f88a4377e0ddd59fea3e98da4649a1d494 --- lib/diff.c +++ lib/diff.c @@ -57,7 +57,7 @@ diff_blobs(off_t **line_offsets, size_t *nlines, struct got_diffreg_result **resultp, struct got_blob_object *blob1, struct got_blob_object *blob2, const char *label1, const char *label2, mode_t mode1, mode_t mode2, - int diff_context, int ignore_whitespace, FILE *outfile) + int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile) { const struct got_error *err = NULL, *free_err; FILE *f1 = NULL, *f2 = NULL; @@ -161,7 +161,7 @@ diff_blobs(off_t **line_offsets, size_t *nlines, free(modestr2); } err = got_diffreg(&result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE, - ignore_whitespace); + ignore_whitespace, force_text_diff); if (err) goto done; @@ -199,23 +199,25 @@ got_diff_blob_output_unidiff(void *arg, struct got_blo return diff_blobs(&a->line_offsets, &a->nlines, NULL, blob1, blob2, label1, label2, mode1, mode2, a->diff_context, - a->ignore_whitespace, a->outfile); + a->ignore_whitespace, a->force_text_diff, a->outfile); } const struct got_error * got_diff_blob(off_t **line_offsets, size_t *nlines, struct got_blob_object *blob1, struct got_blob_object *blob2, const char *label1, const char *label2, int diff_context, - int ignore_whitespace, FILE *outfile) + int ignore_whitespace, int force_text_diff, FILE *outfile) { return diff_blobs(line_offsets, nlines, NULL, blob1, blob2, - label1, label2, 0, 0, diff_context, ignore_whitespace, outfile); + label1, label2, 0, 0, diff_context, ignore_whitespace, + force_text_diff, outfile); } static const struct got_error * diff_blob_file(struct got_diffreg_result **resultp, struct got_blob_object *blob1, const char *label1, FILE *f2, size_t size2, - const char *label2, int diff_context, int ignore_whitespace, FILE *outfile) + const char *label2, int diff_context, int ignore_whitespace, + int force_text_diff, FILE *outfile) { const struct got_error *err = NULL, *free_err; FILE *f1 = NULL; @@ -248,7 +250,7 @@ diff_blob_file(struct got_diffreg_result **resultp, } err = got_diffreg(&result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE, - ignore_whitespace); + ignore_whitespace, force_text_diff); if (err) goto done; @@ -276,10 +278,10 @@ done: const struct got_error * got_diff_blob_file(struct got_blob_object *blob1, const char *label1, FILE *f2, size_t size2, const char *label2, int diff_context, - int ignore_whitespace, FILE *outfile) + int ignore_whitespace, int force_text_diff, FILE *outfile) { return diff_blob_file(NULL, blob1, label1, f2, size2, label2, - diff_context, ignore_whitespace, outfile); + diff_context, ignore_whitespace, force_text_diff, outfile); } static const struct got_error * @@ -720,7 +722,8 @@ const struct got_error * got_diff_objects_as_blobs(off_t **line_offsets, size_t *nlines, struct got_object_id *id1, struct got_object_id *id2, const char *label1, const char *label2, int diff_context, - int ignore_whitespace, struct got_repository *repo, FILE *outfile) + int ignore_whitespace, int force_text_diff, + struct got_repository *repo, FILE *outfile) { const struct got_error *err; struct got_blob_object *blob1 = NULL, *blob2 = NULL; @@ -739,7 +742,8 @@ got_diff_objects_as_blobs(off_t **line_offsets, size_t goto done; } err = got_diff_blob(line_offsets, nlines, blob1, blob2, - label1, label2, diff_context, ignore_whitespace, outfile); + label1, label2, diff_context, ignore_whitespace, force_text_diff, + outfile); done: if (blob1) got_object_blob_close(blob1); @@ -752,7 +756,7 @@ const struct got_error * got_diff_objects_as_trees(off_t **line_offsets, size_t *nlines, struct got_object_id *id1, struct got_object_id *id2, char *label1, char *label2, int diff_context, int ignore_whitespace, - struct got_repository *repo, FILE *outfile) + int force_text_diff, struct got_repository *repo, FILE *outfile) { const struct got_error *err; struct got_tree_object *tree1 = NULL, *tree2 = NULL; @@ -774,6 +778,7 @@ got_diff_objects_as_trees(off_t **line_offsets, size_t } arg.diff_context = diff_context; arg.ignore_whitespace = ignore_whitespace; + arg.force_text_diff = force_text_diff; arg.outfile = outfile; if (want_lineoffsets) { arg.line_offsets = *line_offsets; @@ -800,7 +805,7 @@ done: const struct got_error * got_diff_objects_as_commits(off_t **line_offsets, size_t *nlines, struct got_object_id *id1, struct got_object_id *id2, - int diff_context, int ignore_whitespace, + int diff_context, int ignore_whitespace, int force_text_diff, struct got_repository *repo, FILE *outfile) { const struct got_error *err; @@ -822,7 +827,7 @@ got_diff_objects_as_commits(off_t **line_offsets, size err = got_diff_objects_as_trees(line_offsets, nlines, commit1 ? got_object_commit_get_tree_id(commit1) : NULL, got_object_commit_get_tree_id(commit2), "", "", diff_context, - ignore_whitespace, repo, outfile); + ignore_whitespace, force_text_diff, repo, outfile); done: if (commit1) got_object_commit_close(commit1); @@ -834,7 +839,8 @@ done: const struct got_error * got_diff_files(struct got_diffreg_result **resultp, FILE *f1, const char *label1, FILE *f2, const char *label2, - int diff_context, int ignore_whitespace, FILE *outfile) + int diff_context, int ignore_whitespace, int force_text_diff, + FILE *outfile) { const struct got_error *err = NULL; struct got_diffreg_result *diffreg_result = NULL; @@ -850,7 +856,7 @@ got_diff_files(struct got_diffreg_result **resultp, } err = got_diffreg(&diffreg_result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE, - ignore_whitespace); + ignore_whitespace, force_text_diff); if (err) goto done; blob - d685f9e10bd4f51dc68c4cb81c4adbec7998b4fa blob + 7b8449a42173543736e1f5d0836bb64451ab832f --- lib/diff3.c +++ lib/diff3.c @@ -223,7 +223,7 @@ diffreg(BUF **d, const char *path1, const char *path2) goto done; err = got_diffreg(&diffreg_result, f1, f2, - GOT_DIFF_ALGORITHM_PATIENCE, 0); + GOT_DIFF_ALGORITHM_PATIENCE, 0, 1); if (err) goto done; blob - e22e81b5097ae6ae7772a348e7f8f31f7b2c6421 blob + 8683b991a4378f8e61d26b25a83570f7cf3a3351 --- lib/diffreg.c +++ lib/diffreg.c @@ -139,7 +139,7 @@ got_diff_get_config(struct diff_config **cfg, const struct got_error * got_diff_prepare_file(FILE *f, char **p, size_t *size, struct diff_data *diff_data, const struct diff_config *cfg, - int ignore_whitespace) + int ignore_whitespace, int force_text_diff) { const struct got_error *err = NULL; struct stat st; @@ -150,6 +150,8 @@ got_diff_prepare_file(FILE *f, char **p, size_t *size, diff_flags |= DIFF_FLAG_SHOW_PROTOTYPES; if (ignore_whitespace) diff_flags |= DIFF_FLAG_IGNORE_WHITESPACE; + if (force_text_diff) + diff_flags |= DIFF_FLAG_FORCE_TEXT_DATA; if (fstat(fileno(f), &st) == -1) { err = got_error_from_errno("fstat"); @@ -177,7 +179,8 @@ done: const struct got_error * got_diffreg(struct got_diffreg_result **diffreg_result, FILE *f1, FILE *f2, - enum got_diff_algorithm algorithm, int ignore_whitespace) + enum got_diff_algorithm algorithm, int ignore_whitespace, + int force_text_diff) { const struct got_error *err = NULL; struct diff_config *cfg = NULL; @@ -223,12 +226,12 @@ got_diffreg(struct got_diffreg_result **diffreg_result } err = got_diff_prepare_file(f1, &p1, &size1, left, cfg, - ignore_whitespace); + ignore_whitespace, force_text_diff); if (err) goto done; err = got_diff_prepare_file(f2, &p2, &size2, right, cfg, - ignore_whitespace); + ignore_whitespace, force_text_diff); if (err) goto done; blob - 3a995c48e676b6b3ef159bad68c8c69a070427d5 blob + f3e58cc505cffa4e06ca6a0ec16396a3e5307747 --- lib/got_lib_diff.h +++ lib/got_lib_diff.h @@ -48,9 +48,9 @@ struct got_diffreg_result { const struct got_error *got_diff_get_config(struct diff_config **, enum got_diff_algorithm, diff_atomize_func_t, void *); const struct got_error *got_diff_prepare_file(FILE *, char **, size_t *, - struct diff_data *, const struct diff_config *, int); -const struct got_error *got_diffreg(struct got_diffreg_result **, FILE *, FILE *, - enum got_diff_algorithm, int); + struct diff_data *, const struct diff_config *, int, int); +const struct got_error *got_diffreg(struct got_diffreg_result **, FILE *, + FILE *, enum got_diff_algorithm, int, int); const struct got_error *got_diffreg_output(off_t **, size_t *, struct got_diffreg_result *, FILE *, FILE *, const char *, const char *, enum got_diff_output_format, int, FILE *); @@ -66,4 +66,4 @@ const struct got_error *got_merge_diff3(int *, int, co const char *, const char *, const char *, const char *); const struct got_error *got_diff_files(struct got_diffreg_result **, FILE *, - const char *, FILE *, const char *, int, int, FILE *); + const char *, FILE *, const char *, int, int, int, FILE *); blob - b012446a6b55a2c0ce73c346d370b6a2b7d964b7 blob + 971955fbafa7d712d0e5a61dfe60def65321b0f0 --- lib/worktree.c +++ lib/worktree.c @@ -4324,7 +4324,7 @@ create_patched_content(char **path_outfile, int revers if (err) goto done; - err = got_diff_files(&diffreg_result, f1, id_str, f2, path2, 3, 0, + err = got_diff_files(&diffreg_result, f1, id_str, f2, path2, 3, 0, 1, NULL); if (err) goto done; @@ -7450,7 +7450,7 @@ create_unstaged_content(char **path_unstaged_content, goto done; err = got_diff_files(&diffreg_result, f1, label1, f2, - path2, 3, 0, NULL); + path2, 3, 0, 1, NULL); if (err) goto done; blob - 40f48b0786ea4b80be8d254a65d81296572408a1 blob + 92cd8f39cbdc7a59932a05599b57b808a8814472 --- regress/cmdline/diff.sh +++ regress/cmdline/diff.sh @@ -596,6 +596,20 @@ test_diff_binary_files() { printf '\377\377\0\0\377\377\0\0' > $testroot/wt/foo (cd $testroot/wt && got add foo >/dev/null) + + echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected + echo 'blob - /dev/null' >> $testroot/stdout.expected + echo 'file + foo' >> $testroot/stdout.expected + echo "Binary files foo and foo differ" >> $testroot/stdout.expected + + (cd $testroot/wt && got diff > $testroot/stdout) + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -a -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi echo "diff $head_rev $testroot/wt" > $testroot/stdout.expected echo 'blob - /dev/null' >> $testroot/stdout.expected @@ -606,7 +620,7 @@ test_diff_binary_files() { printf '+\377\377\0\0\377\377\0\0\n' >> $testroot/stdout.expected echo '\\ No newline at end of file' >> $testroot/stdout.expected - (cd $testroot/wt && got diff > $testroot/stdout) + (cd $testroot/wt && got diff -a > $testroot/stdout) cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then @@ -633,7 +647,7 @@ test_diff_binary_files() { printf '+\377\200\0\0\377\200\0\0\n' >> $testroot/stdout.expected echo '\\ No newline at end of file' >> $testroot/stdout.expected - (cd $testroot/wt && got diff > $testroot/stdout) + (cd $testroot/wt && got diff -a > $testroot/stdout) cmp -s $testroot/stdout.expected $testroot/stdout ret="$?" if [ "$ret" != "0" ]; then blob - c6cc6c9fe1d1bc5c155e3f4b780dabe521ee8157 blob + 2998a0230cfb9957985eaba7c922178ec4868278 --- tog/tog.1 +++ tog/tog.1 @@ -175,7 +175,7 @@ If this directory is a .Xr got 1 work tree, use the repository path associated with this work tree. .El -.It Cm diff Oo Fl r Ar repository-path Oc Ar object1 object2 +.It Cm diff Oo Fl a Oc Oo Fl r Ar repository-path Oc Ar object1 object2 Display the differences between two objects in the repository. Each .Ar object @@ -188,6 +188,9 @@ The key bindings for .Cm tog diff are as follows: .Bl -tag -width Ds +.It Cm a +Toggle treatment of file contents as ASCII text even if binary data was +detected. .It Cm Down-arrow, j Scroll down. .It Cm Up-arrow, k @@ -220,6 +223,8 @@ The options for .Cm tog diff are as follows: .Bl -tag -width Ds +.It Fl a +Treat file contents as ASCII text even if binary data is detected. .It Fl r Ar repository-path Use the repository at the specified path. If not specified, assume the repository is located at or above the current blob - 54c37e9784d2d00193462315edb6f7cfc5bd6479 blob + e4b6922ea70550bd65bf25da483b6f095898670d --- tog/tog.c +++ tog/tog.c @@ -249,6 +249,7 @@ struct tog_diff_view_state { int last_displayed_line; int eof; int diff_context; + int force_text_diff; struct got_repository *repo; struct got_reflist_head *refs; struct tog_colors colors; @@ -445,7 +446,7 @@ struct tog_view { }; static const struct got_error *open_diff_view(struct tog_view *, - struct got_object_id *, struct got_object_id *, struct tog_view *, + struct got_object_id *, struct got_object_id *, int, struct tog_view *, struct got_reflist_head *, struct got_repository *); static const struct got_error *show_diff_view(struct tog_view *); static const struct got_error *input_diff_view(struct tog_view **, @@ -1768,7 +1769,7 @@ open_diff_view_for_commit(struct tog_view **new_view, parent_id = SIMPLEQ_FIRST(got_object_commit_get_parent_ids(commit)); err = open_diff_view(diff_view, parent_id ? parent_id->id : NULL, - commit_id, log_view, refs, repo); + commit_id, 0, log_view, refs, repo); if (err == NULL) *new_view = diff_view; return err; @@ -2757,8 +2758,8 @@ __dead static void usage_diff(void) { endwin(); - fprintf(stderr, "usage: %s diff [-r repository-path] object1 object2\n", - getprogname()); + fprintf(stderr, "usage: %s diff [-a] [-r repository-path] " + "object1 object2\n", getprogname()); exit(1); } @@ -3217,11 +3218,12 @@ create_diff(struct tog_diff_view_state *s) case GOT_OBJ_TYPE_BLOB: err = got_diff_objects_as_blobs(&s->line_offsets, &s->nlines, s->id1, s->id2, NULL, NULL, s->diff_context, 0, - s->repo, s->f); + s->force_text_diff, s->repo, s->f); break; case GOT_OBJ_TYPE_TREE: err = got_diff_objects_as_trees(&s->line_offsets, &s->nlines, - s->id1, s->id2, "", "", s->diff_context, 0, s->repo, s->f); + s->id1, s->id2, "", "", s->diff_context, 0, + s->force_text_diff, s->repo, s->f); break; case GOT_OBJ_TYPE_COMMIT: { const struct got_object_id_queue *parent_ids; @@ -3253,7 +3255,8 @@ create_diff(struct tog_diff_view_state *s) got_object_commit_close(commit2); err = got_diff_objects_as_commits(&s->line_offsets, &s->nlines, - s->id1, s->id2, s->diff_context, 0, s->repo, s->f); + s->id1, s->id2, s->diff_context, 0, s->force_text_diff, + s->repo, s->f); break; } default: @@ -3357,7 +3360,7 @@ search_next_diff_view(struct tog_view *view) static const struct got_error * open_diff_view(struct tog_view *view, struct got_object_id *id1, - struct got_object_id *id2, struct tog_view *log_view, + struct got_object_id *id2, int force_text_diff, struct tog_view *log_view, struct got_reflist_head *refs, struct got_repository *repo) { const struct got_error *err; @@ -3400,6 +3403,7 @@ open_diff_view(struct tog_view *view, struct got_objec s->first_displayed_line = 1; s->last_displayed_line = view->nlines; s->diff_context = 3; + s->force_text_diff = force_text_diff; s->log_view = log_view; s->repo = repo; s->refs = refs; @@ -3563,6 +3567,14 @@ input_diff_view(struct tog_view **new_view, struct tog int i; switch (ch) { + case 'a': + s->force_text_diff = !s->force_text_diff; + wclear(view->window); + s->first_displayed_line = 1; + s->last_displayed_line = view->nlines; + diff_view_indicate_progress(view); + err = create_diff(s); + break; case 'k': case KEY_UP: if (s->first_displayed_line > 1) @@ -3687,7 +3699,7 @@ cmd_diff(int argc, char *argv[]) struct got_object_id *id1 = NULL, *id2 = NULL; char *repo_path = NULL, *cwd = NULL; char *id_str1 = NULL, *id_str2 = NULL; - int ch; + int ch, force_text_diff = 0; struct tog_view *view; SIMPLEQ_INIT(&refs); @@ -3698,8 +3710,11 @@ cmd_diff(int argc, char *argv[]) err(1, "pledge"); #endif - while ((ch = getopt(argc, argv, "r:")) != -1) { + while ((ch = getopt(argc, argv, "ar:")) != -1) { switch (ch) { + case 'a': + force_text_diff = 1; + break; case 'r': repo_path = realpath(optarg, NULL); if (repo_path == NULL) @@ -3772,7 +3787,8 @@ cmd_diff(int argc, char *argv[]) error = got_error_from_errno("view_open"); goto done; } - error = open_diff_view(view, id1, id2, NULL, &refs, repo); + error = open_diff_view(view, id1, id2, force_text_diff, NULL, &refs, + repo); if (error) goto done; error = view_loop(view); @@ -4533,7 +4549,7 @@ input_blame_view(struct tog_view **new_view, struct to break; } err = open_diff_view(diff_view, pid ? pid->id : NULL, - id, NULL, s->refs, s->repo); + id, 0, NULL, s->refs, s->repo); got_object_commit_close(commit); if (err) { view_close(diff_view);