commit 3dbaef42733b9b959e3fdbd00ea0dc98f1aadd9e from: Stefan Sperling date: Tue Nov 24 15:52:41 2020 UTC make 'tog diff' accept reference and tag arguments; add -w and -C options ok naddy tracey commit - 9c659ea03e148f73684817fbc7104feb365ee820 commit + 3dbaef42733b9b959e3fdbd00ea0dc98f1aadd9e blob - 2998a0230cfb9957985eaba7c922178ec4868278 blob + bba1d695475b78e770ce4a96eb79d9359c360c0e --- tog/tog.1 +++ tog/tog.1 @@ -177,12 +177,11 @@ work tree, use the repository path associated with thi .El .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 -argument is an object ID SHA1 hash. +Treat each of the two arguments as a reference, a tag name, or an object +ID SHA1 hash, and display differences between the corresponding objects. +Both objects must be of the same type (blobs, trees, or commits). An abbreviated hash argument will be expanded to a full SHA1 hash automatically, provided the abbreviation is unique. -Both objects must be of the same type (blobs, trees, or commits). .Pp The key bindings for .Cm tog diff @@ -217,6 +216,8 @@ Regular expression syntax is documented in Find the next line which matches the current search pattern. .It Cm N Find the previous line which matches the current search pattern. +.It Cm w +Toggle display of whitespace-only changes. .El .Pp The options for @@ -225,6 +226,9 @@ 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. .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 @@ -232,6 +236,8 @@ working directory. If this directory is a .Xr got 1 work tree, use the repository path associated with this work tree. +.It Fl w +Ignore whitespace-only changes. .El .It Cm blame Oo Fl c Ar commit Oc Oo Fl r Ar repository-path Oc Ar path Display line-by-line history of a file at the specified path. blob - 49c80746f8d60ea5028ac0e1a672c50689c129ce blob + a92d64abe3a51e0a2f932fb0d2ce40e470052d21 --- tog/tog.c +++ tog/tog.c @@ -244,11 +244,13 @@ get_color_value(const char *envvar) struct tog_diff_view_state { struct got_object_id *id1, *id2; + const char *label1, *label2; FILE *f; int first_displayed_line; int last_displayed_line; int eof; int diff_context; + int ignore_whitespace; int force_text_diff; struct got_repository *repo; struct got_reflist_head *refs; @@ -446,7 +448,8 @@ struct tog_view { }; static const struct got_error *open_diff_view(struct tog_view *, - struct got_object_id *, struct got_object_id *, int, struct tog_view *, + struct got_object_id *, struct got_object_id *, + const char *, const char *, int, int, 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 **, @@ -1769,7 +1772,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, 0, log_view, refs, repo); + commit_id, NULL, NULL, 3, 0, 0, log_view, refs, repo); if (err == NULL) *new_view = diff_view; return err; @@ -2758,8 +2761,8 @@ __dead static void usage_diff(void) { endwin(); - fprintf(stderr, "usage: %s diff [-a] [-r repository-path] " - "object1 object2\n", getprogname()); + fprintf(stderr, "usage: %s diff [-a] [-C number] [-r repository-path] " + "[-w] object1 object2\n", getprogname()); exit(1); } @@ -2861,7 +2864,7 @@ add_matched_line(int *wtotal, const char *line, int wl static const struct got_error * draw_file(struct tog_view *view, FILE *f, int first_displayed_line, int nlines, off_t *line_offsets, int selected_line, int max_lines, - int *last_displayed_line, int *eof, char *header, + int *last_displayed_line, int *eof, const char *header, struct tog_colors *colors, int matched_line, regmatch_t *regmatch) { const struct got_error *err; @@ -3217,13 +3220,13 @@ create_diff(struct tog_diff_view_state *s) switch (obj_type) { 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->force_text_diff, s->repo, s->f); + s->id1, s->id2, s->label1, s->label2, s->diff_context, + s->ignore_whitespace, 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->force_text_diff, s->repo, s->f); + s->id1, s->id2, "", "", s->diff_context, + s->ignore_whitespace, s->force_text_diff, s->repo, s->f); break; case GOT_OBJ_TYPE_COMMIT: { const struct got_object_id_queue *parent_ids; @@ -3255,8 +3258,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->force_text_diff, - s->repo, s->f); + s->id1, s->id2, s->diff_context, s->ignore_whitespace, + s->force_text_diff, s->repo, s->f); break; } default: @@ -3360,8 +3363,10 @@ 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, int force_text_diff, struct tog_view *log_view, - struct got_reflist_head *refs, struct got_repository *repo) + struct got_object_id *id2, const char *label1, const char *label2, + int diff_context, int ignore_whitespace, int force_text_diff, + struct tog_view *log_view, struct got_reflist_head *refs, + struct got_repository *repo) { const struct got_error *err; struct tog_diff_view_state *s = &view->state.diff; @@ -3385,6 +3390,8 @@ open_diff_view(struct tog_view *view, struct got_objec s->refs = refs; s->id1 = id1; s->id2 = id2; + s->label1 = label1; + s->label2 = label2; if (id1) { s->id1 = got_object_id_dup(id1); @@ -3402,7 +3409,8 @@ open_diff_view(struct tog_view *view, struct got_objec s->f = NULL; s->first_displayed_line = 1; s->last_displayed_line = view->nlines; - s->diff_context = 3; + s->diff_context = diff_context; + s->ignore_whitespace = ignore_whitespace; s->force_text_diff = force_text_diff; s->log_view = log_view; s->repo = repo; @@ -3505,18 +3513,22 @@ show_diff_view(struct tog_view *view) const struct got_error *err; struct tog_diff_view_state *s = &view->state.diff; char *id_str1 = NULL, *id_str2, *header; + const char *label1, *label2; if (s->id1) { err = got_object_id_str(&id_str1, s->id1); if (err) return err; - } + label1 = s->label1 ? : id_str1; + } else + label1 = "/dev/null"; + err = got_object_id_str(&id_str2, s->id2); if (err) return err; + label2 = s->label2 ? : id_str2; - if (asprintf(&header, "diff %s %s", - id_str1 ? id_str1 : "/dev/null", id_str2) == -1) { + if (asprintf(&header, "diff %s %s", label1, label2) == -1) { err = got_error_from_errno("asprintf"); free(id_str1); free(id_str2); @@ -3568,7 +3580,11 @@ input_diff_view(struct tog_view **new_view, struct tog switch (ch) { case 'a': - s->force_text_diff = !s->force_text_diff; + case 'w': + if (ch == 'a') + s->force_text_diff = !s->force_text_diff; + if (ch == 'w') + s->ignore_whitespace = !s->ignore_whitespace; wclear(view->window); s->first_displayed_line = 1; s->last_displayed_line = view->nlines; @@ -3704,7 +3720,10 @@ 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; + char *label1 = NULL, *label2 = NULL; + int diff_context = 3, ignore_whitespace = 0; int ch, force_text_diff = 0; + const char *errstr; struct tog_view *view; SIMPLEQ_INIT(&refs); @@ -3714,18 +3733,27 @@ cmd_diff(int argc, char *argv[]) NULL) == -1) err(1, "pledge"); #endif - - while ((ch = getopt(argc, argv, "ar:")) != -1) { + while ((ch = getopt(argc, argv, "aC:r:w")) != -1) { switch (ch) { case 'a': force_text_diff = 1; + break; + case 'C': + diff_context = strtonum(optarg, 0, GOT_DIFF_MAX_CONTEXT, + &errstr); + if (errstr != NULL) + err(1, "-C option %s", errstr); break; case 'r': repo_path = realpath(optarg, NULL); if (repo_path == NULL) return got_error_from_errno2("realpath", optarg); + got_path_strip_trailing_slashes(repo_path); break; + case 'w': + ignore_whitespace = 1; + break; default: usage_diff(); /* NOTREACHED */ @@ -3773,13 +3801,13 @@ cmd_diff(int argc, char *argv[]) if (error) goto done; - error = got_repo_match_object_id_prefix(&id1, id_str1, - GOT_OBJ_TYPE_ANY, repo); + error = got_repo_match_object_id(&id1, &label1, id_str1, + GOT_OBJ_TYPE_ANY, 1, repo); if (error) goto done; - error = got_repo_match_object_id_prefix(&id2, id_str2, - GOT_OBJ_TYPE_ANY, repo); + error = got_repo_match_object_id(&id2, &label2, id_str2, + GOT_OBJ_TYPE_ANY, 1, repo); if (error) goto done; @@ -3792,12 +3820,14 @@ cmd_diff(int argc, char *argv[]) error = got_error_from_errno("view_open"); goto done; } - error = open_diff_view(view, id1, id2, force_text_diff, NULL, &refs, - repo); + error = open_diff_view(view, id1, id2, label1, label2, diff_context, + ignore_whitespace, force_text_diff, NULL, &refs, repo); if (error) goto done; error = view_loop(view); done: + free(label1); + free(label2); free(repo_path); free(cwd); if (repo) @@ -4554,7 +4584,7 @@ input_blame_view(struct tog_view **new_view, struct to break; } err = open_diff_view(diff_view, pid ? pid->id : NULL, - id, 0, NULL, s->refs, s->repo); + id, NULL, NULL, 3, 0, 0, NULL, s->refs, s->repo); got_object_commit_close(commit); if (err) { view_close(diff_view);