"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
configurable diff algorithm for tog
To:
gameoftrees@openbsd.org
Date:
Fri, 1 Jul 2022 00:15:03 +0200

Download raw body.

Thread
Make the diff algorithm used by 'tog diff' and 'tog blame' configurable.
This allows people (like me) who prefer slow and tidy Patience diffs over
quick and ugly Myers diffs to tell tog about this preference.

As a bonus, the diff algorithm can be toggled at run-time, in both the
diff view and the blame view, by pressing the A key.

ok?
 
diff 4b752015b5208a96c2d1b6c1c6b8589884b8b2b6 f86afd0cdf59e0214d28ee1b07f98b12e63650e2
commit - 4b752015b5208a96c2d1b6c1c6b8589884b8b2b6
commit + f86afd0cdf59e0214d28ee1b07f98b12e63650e2
blob - 728ba5ee9e20edbde20ed7f0c2ff1cbabad89c0b
blob + ed0412fd13daaa1ea18139730716db483ba49274
--- tog/tog.1
+++ tog/tog.1
@@ -295,6 +295,12 @@ Find the Nth previous line which matches the current s
 (default: 1).
 .It Cm w
 Toggle display of whitespace-only changes.
+.It Cm A
+Change the diff algorithm.
+Supported diff algorithms are Myers and Patience. 
+This is a global setting which also affects the
+.Cm blame
+view.
 .El
 .Pp
 The options for
@@ -379,6 +385,12 @@ Find the Nth next line which matches the current searc
 .It Cm N
 Find the Nth previous line which matches the current search pattern
 (default: 1).
+.It Cm A
+Change the diff algorithm.
+Supported diff algorithms are Myers and Patience. 
+This is a global setting which also affects the
+.Cm diff
+view.
 .El
 .Pp
 The options for
@@ -560,7 +572,15 @@ work tree, use the repository path associated with thi
 .El
 .El
 .Sh ENVIRONMENT
-.Bl -tag -width TOG_COLORS
+.Bl -tag -width TOG_DIFF_ALGORITHM
+.It Ev TOG_DIFF_ALGORITHM
+Determines the default diff algorithm used by
+.Nm .
+Valid values are
+.Dq patience
+and
+.Dq myers .
+If unset, the Myers diff algorithm will be used by default.
 .It Ev TOG_COLORS
 .Nm
 shows colorized output if this variable is set to a non-empty value.
blob - 800384dacf0faed4893832dd2760af45e28cb8c7
blob + 5249c995a3b1c894615555cce80987087f672a75
--- tog/tog.c
+++ tog/tog.c
@@ -136,7 +136,17 @@ STAILQ_HEAD(tog_colors, tog_color);
 
 static struct got_reflist_head tog_refs = TAILQ_HEAD_INITIALIZER(tog_refs);
 static struct got_reflist_object_id_map *tog_refs_idmap;
+static enum got_diff_algorithm tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
 
+static void
+switch_diff_algo(void)
+{
+	if (tog_diff_algo == GOT_DIFF_ALGORITHM_MYERS)
+		tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
+	else
+		tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
+}
+
 static const struct got_error *
 tog_ref_cmp_by_name(void *arg, int *cmp, struct got_reference *re1,
     struct got_reference* re2)
@@ -321,7 +331,6 @@ struct tog_diff_view_state {
 	int first_displayed_line;
 	int last_displayed_line;
 	int eof;
-	enum got_diff_algorithm diff_algo;
 	int diff_context;
 	int ignore_whitespace;
 	int force_text_diff;
@@ -3966,13 +3975,13 @@ 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->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2,
-		    s->label1, s->label2, s->diff_algo, s->diff_context,
+		    s->label1, s->label2, tog_diff_algo, 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->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL, "", "",
-		    s->diff_algo, s->diff_context, s->ignore_whitespace,
+		    tog_diff_algo, s->diff_context, s->ignore_whitespace,
 		    s->force_text_diff, s->repo, s->f);
 		break;
 	case GOT_OBJ_TYPE_COMMIT: {
@@ -4008,7 +4017,7 @@ create_diff(struct tog_diff_view_state *s)
 
 		err = got_diff_objects_as_commits(&s->line_offsets, &s->nlines,
 		    s->f1, s->f2, s->fd1, s->fd2, s->id1, s->id2, NULL,
-		    s->diff_algo, s->diff_context, s->ignore_whitespace,
+		    tog_diff_algo, s->diff_context, s->ignore_whitespace,
 		    s->force_text_diff, s->repo, s->f);
 		break;
 	}
@@ -4219,7 +4228,6 @@ open_diff_view(struct tog_view *view, struct got_objec
 
 	s->first_displayed_line = 1;
 	s->last_displayed_line = view->nlines;
-	s->diff_algo = GOT_DIFF_ALGORITHM_MYERS;
 	s->diff_context = diff_context;
 	s->ignore_whitespace = ignore_whitespace;
 	s->force_text_diff = force_text_diff;
@@ -4376,7 +4384,10 @@ input_diff_view(struct tog_view **new_view, struct tog
 			view->count = 0;
 		break;
 	case 'a':
+	case 'A':
 	case 'w':
+		if (ch == 'A')
+			switch_diff_algo();
 		if (ch == 'a')
 			s->force_text_diff = !s->force_text_diff;
 		if (ch == 'w')
@@ -4950,7 +4961,7 @@ blame_thread(void *arg)
 		goto done;
 
 	err = got_blame(ta->path, a->commit_id, ta->repo,
-	    GOT_DIFF_ALGORITHM_MYERS, blame_cb, ta->cb_args,
+	    tog_diff_algo, blame_cb, ta->cb_args,
 	    ta->cancel_cb, ta->cancel_arg, fd1, fd2, f1, f2);
 	if (err && err->code == GOT_ERR_CANCELLED)
 		err = NULL;
@@ -5455,6 +5466,18 @@ input_blame_view(struct tog_view **new_view, struct to
 		else
 			view->count = 0;
 		break;
+	case 'A':
+		view->count = 0;
+		switch_diff_algo();
+		s->done = 1;
+		thread_err = stop_blame(&s->blame);
+		s->done = 0;
+		if (thread_err)
+			break;
+		err = run_blame(view);
+		if (err)
+			break;
+		break;
 	case 'c':
 	case 'p': {
 		struct got_object_id *id = NULL;
@@ -7839,6 +7862,7 @@ main(int argc, char *argv[])
 	    { "version", no_argument, NULL, 'V' },
 	    { NULL, 0, NULL, 0}
 	};
+	char *diff_algo_str = NULL;
 
 	setlocale(LC_CTYPE, "");
 
@@ -7892,6 +7916,14 @@ main(int argc, char *argv[])
 		}
 	}
 
+	diff_algo_str = getenv("TOG_DIFF_ALGORITHM");
+	if (diff_algo_str) {
+		if (strcasecmp(diff_algo_str, "patience") == 0)
+			tog_diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
+		if (strcasecmp(diff_algo_str, "myers") == 0)
+			tog_diff_algo = GOT_DIFF_ALGORITHM_MYERS;
+	}
+
 	if (cmd == NULL) {
 		if (argc != 1)
 			usage(0, 1);