commit - 9c659ea03e148f73684817fbc7104feb365ee820
commit + 3dbaef42733b9b959e3fdbd00ea0dc98f1aadd9e
blob - 2998a0230cfb9957985eaba7c922178ec4868278
blob + bba1d695475b78e770ce4a96eb79d9359c360c0e
--- tog/tog.1
+++ tog/tog.1
.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.
-An abbreviated hash argument will be expanded to a full SHA1 hash
-automatically, provided the abbreviation is unique.
+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.
.Pp
The key bindings for
.Cm tog diff
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
.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
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
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;
};
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 **,
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;
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);
}
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;
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;
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:
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;
s->refs = refs;
s->id1 = id1;
s->id2 = id2;
+ s->label1 = label1;
+ s->label2 = label2;
if (id1) {
s->id1 = got_object_id_dup(id1);
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;
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);
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;
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);
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 */
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;
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)
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);