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

From:
Mark Jamsek <mark@jamsek.com>
Subject:
Re: speed up tog blame
To:
gameoftrees@openbsd.org
Date:
Fri, 1 Jul 2022 01:32:41 +1000

Download raw body.

Thread
On 22-06-30 04:46pm, Stefan Sperling wrote:
> Profiling 'got blame' shows that it spends a lot of time in the patience
> diff algorithm sorting lines in files. With the Myers algorithm, diffing
> files is almost twice as fast. Both 'diff' and 'blame' need to use the
> same diffing algorithm, otherwise results displayed will be inconsistent
> between the two commands.
> 
> I think it is fine for 'got diff' and 'got blame' to be slow but show
> very pretty patience diffs that are nice to review.
> 
> However, when using 'tog blame' interactively it is good to see results
> as quickly as possible. So the patch below switches tog to Myers diff,
> and leaves got with patience diff (and also gotweb, for now).
> 
> $ time tog blame got/got.c
>     0m10.71s real     0m06.24s user     0m03.72s system
> $ time got blame got/got.c >/dev/null
>     0m18.66s real     0m14.75s user     0m03.49s system
> 
> ok?

Yes, I really like this! Thanks :)

> diff 0dca135e7628142c56b3f71c3b5eb875f4fe6c7f cbb1e6608a9607294e718e8891917a96bbc88dca
> commit - 0dca135e7628142c56b3f71c3b5eb875f4fe6c7f
> commit + cbb1e6608a9607294e718e8891917a96bbc88dca
> blob - d9c4a8353c2a3778cc4d66443ac60c9d35daa07b
> blob + 5f7f00007937a048564e685aac0a8c6b9e98adab
> --- got/got.c
> +++ got/got.c
> @@ -3584,7 +3584,8 @@ diff_blobs(struct got_object_id *blob_id1, struct got_
>  	while (path[0] == '/')
>  		path++;
>  	err = got_diff_blob(NULL, NULL, blob1, blob2, f1, f2, path, path,
> -	    diff_context, ignore_whitespace, force_text_diff, outfile);
> +	    GOT_DIFF_ALGORITHM_PATIENCE, diff_context, ignore_whitespace,
> +	    force_text_diff, outfile);
>  done:
>  	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
>  		err = got_error_from_errno("close");
> @@ -3645,6 +3646,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.diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
>  	arg.outfile = outfile;
>  	arg.line_offsets = NULL;
>  	arg.nlines = 0;
> @@ -4590,6 +4592,7 @@ struct print_diff_arg {
>  	const char *id_str;
>  	int header_shown;
>  	int diff_staged;
> +	enum got_diff_algorithm diff_algo;
>  	int ignore_whitespace;
>  	int force_text_diff;
>  	FILE *f1;
> @@ -4720,8 +4723,8 @@ print_diff(void *arg, unsigned char status, unsigned c
>  		}
>  		err = got_diff_objects_as_blobs(NULL, NULL, a->f1, a->f2,
>  		    fd1, fd2, blob_id, staged_blob_id, label1, label2,
> -		    a->diff_context, a->ignore_whitespace, a->force_text_diff,
> -		    a->repo, stdout);
> +		    a->diff_algo, a->diff_context, a->ignore_whitespace,
> +		    a->force_text_diff, a->repo, stdout);
>  		goto done;
>  	}
>  
> @@ -4812,8 +4815,8 @@ print_diff(void *arg, unsigned char status, unsigned c
>  	}
>  
>  	err = got_diff_blob_file(blob1, a->f1, size1, label1, f2 ? f2 : a->f2,
> -	    f2_exists, sb.st_size, path, a->diff_context, a->ignore_whitespace,
> -	    a->force_text_diff, stdout);
> +	    f2_exists, sb.st_size, path, GOT_DIFF_ALGORITHM_PATIENCE,
> +	    a->diff_context, a->ignore_whitespace, a->force_text_diff, stdout);
>  done:
>  	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
>  		err = got_error_from_errno("close");
> @@ -5031,6 +5034,7 @@ cmd_diff(int argc, char *argv[])
>  			goto done;
>  		arg.repo = repo;
>  		arg.worktree = worktree;
> +		arg.diff_algo = GOT_DIFF_ALGORITHM_PATIENCE;
>  		arg.diff_context = diff_context;
>  		arg.id_str = id_str;
>  		arg.header_shown = 0;
> @@ -5175,18 +5179,21 @@ cmd_diff(int argc, char *argv[])
>  	switch (type1 == GOT_OBJ_TYPE_ANY ? type2 : type1) {
>  	case GOT_OBJ_TYPE_BLOB:
>  		error = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
> -		    fd1, fd2, ids[0], ids[1], NULL, NULL, diff_context,
> +		    fd1, fd2, ids[0], ids[1], NULL, NULL,
> +		    GOT_DIFF_ALGORITHM_PATIENCE, diff_context,
>  		    ignore_whitespace, force_text_diff, repo, stdout);
>  		break;
>  	case GOT_OBJ_TYPE_TREE:
>  		error = got_diff_objects_as_trees(NULL, NULL, f1, f2, fd1, fd2,
> -		    ids[0], ids[1], &paths, "", "", diff_context,
> +		    ids[0], ids[1], &paths, "", "",
> +		    GOT_DIFF_ALGORITHM_PATIENCE, diff_context,
>  		    ignore_whitespace, force_text_diff, repo, stdout);
>  		break;
>  	case GOT_OBJ_TYPE_COMMIT:
>  		printf("diff %s %s\n", labels[0], labels[1]);
>  		error = got_diff_objects_as_commits(NULL, NULL, f1, f2,
> -		    fd1, fd2, ids[0], ids[1], &paths, diff_context,
> +		    fd1, fd2, ids[0], ids[1], &paths,
> +		    GOT_DIFF_ALGORITHM_PATIENCE, diff_context,
>  		    ignore_whitespace, force_text_diff, repo, stdout);
>  		break;
>  	default:
> @@ -5569,7 +5576,8 @@ cmd_blame(int argc, char *argv[])
>  		goto done;
>  	}
>  	error = got_blame(link_target ? link_target : in_repo_path, commit_id,
> -	    repo, blame_cb, &bca, check_cancelled, NULL, fd2, fd3, f1, f2);
> +	    repo, GOT_DIFF_ALGORITHM_PATIENCE, blame_cb, &bca,
> +	    check_cancelled, NULL, fd2, fd3, f1, f2);
>  done:
>  	free(in_repo_path);
>  	free(link_target);
> blob - 80bd351ec9bb5cf498aee6074d91b588a3566650
> blob + da9f041cbfef9184c60aa257ec187e714ee04860
> --- gotweb/gotweb.c
> +++ gotweb/gotweb.c
> @@ -2912,17 +2912,18 @@ gw_output_diff(struct gw_trans *gw_trans, struct gw_he
>  	switch (obj_type) {
>  	case GOT_OBJ_TYPE_BLOB:
>  		error = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
> -		    fd1, fd2, id1, id2, NULL, NULL, 3, 0, 0,
> -		    gw_trans->repo, f);
> +		    fd1, fd2, id1, id2, NULL, NULL, GOT_DIFF_ALGORITHM_PATIENCE,
> +		    3, 0, 0, gw_trans->repo, f);
>  		break;
>  	case GOT_OBJ_TYPE_TREE:
>  		error = got_diff_objects_as_trees(NULL, NULL, f1, f2,
> -		    fd1, fd2, id1, id2, NULL, "", "", 3, 0, 0,
> -		    gw_trans->repo, f);
> +		    fd1, fd2, id1, id2, NULL, "", "",
> +		    GOT_DIFF_ALGORITHM_PATIENCE, 3, 0, 0, gw_trans->repo, f);
>  		break;
>  	case GOT_OBJ_TYPE_COMMIT:
>  		error = got_diff_objects_as_commits(NULL, NULL, f1, f2,
> -		    fd1, fd2, id1, id2, NULL, 3, 0, 0, gw_trans->repo, f);
> +		    fd1, fd2, id1, id2, NULL, GOT_DIFF_ALGORITHM_PATIENCE,
> +		    3, 0, 0, gw_trans->repo, f);
>  		break;
>  	default:
>  		error = got_error(GOT_ERR_OBJ_TYPE);
> @@ -4194,8 +4195,9 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
>  		goto done;
>  	}
>  
> -	error = got_blame(in_repo_path, commit_id, gw_trans->repo, gw_blame_cb,
> -	    &bca, NULL, NULL, fd2, fd3, f1, f2);
> +	error = got_blame(in_repo_path, commit_id, gw_trans->repo,
> +	    GOT_DIFF_ALGORITHM_PATIENCE, gw_blame_cb, &bca, NULL, NULL,
> +	    fd2, fd3, f1, f2);
>  done:
>  	free(in_repo_path);
>  	free(commit_id);
> blob - 5d01c0034c2587d4dffbfd407a94631f1cfe7e7c
> blob + 7a5d61c35cf7807ba8f820712005a94d28e118fe
> --- include/got_blame.h
> +++ include/got_blame.h
> @@ -35,5 +35,5 @@ typedef const struct got_error *(*got_blame_cb)(void *
>   * aborted and the callback's error is returned from this function.
>   */
>  const struct got_error *got_blame(const char *,
> -    struct got_object_id *, struct got_repository *,
> +    struct got_object_id *, struct got_repository *, enum got_diff_algorithm,
>      got_blame_cb, void *, got_cancel_cb, void *, int, int, FILE *, FILE *);
> blob - e04cc7fd9e3459de5ae8004badfe6704feaea240
> blob + 4243be1c5479449f6d3623e760d1979bd58682b8
> --- include/got_diff.h
> +++ include/got_diff.h
> @@ -14,6 +14,11 @@
>   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  
> +enum got_diff_algorithm {
> +	GOT_DIFF_ALGORITHM_MYERS,
> +	GOT_DIFF_ALGORITHM_PATIENCE,
> +};
> +
>  /*
>   * Compute the differences between two blobs and write unified diff text
>   * to the provided output file. Two open temporary files must be provided
> @@ -31,7 +36,8 @@
>   */
>  const struct got_error *got_diff_blob(off_t **, size_t *,
>      struct got_blob_object *, struct got_blob_object *, FILE *, FILE *,
> -    const char *, const char *, int, int, int, FILE *);
> +    const char *, const char *, enum got_diff_algorithm, int, int, int,
> +    FILE *);
>  
>  /*
>   * Compute the differences between a blob and a file and write unified diff
> @@ -43,8 +49,8 @@ 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 *, FILE *,
> -    off_t, const char *, FILE *, int, size_t, const char *, int, int, int,
> -    FILE *);
> +    off_t, const char *, FILE *, int, size_t, const char *,
> +    enum got_diff_algorithm, int, int, int, FILE *);
>  
>  /*
>   * A callback function invoked to handle the differences between two blobs
> @@ -74,6 +80,7 @@ struct got_diff_blob_output_unidiff_arg {
>  	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. */
> +	enum got_diff_algorithm diff_algo; /* Diffing algorithm to use. */
>  
>  	/*
>  	 * The number of lines contained in produced unidiff text output,
> @@ -150,9 +157,11 @@ const struct got_error *got_diff_tree_collect_changed_
>   */
>  const struct got_error *got_diff_objects_as_blobs(off_t **, size_t *,
>      FILE *, FILE *, int, int, struct got_object_id *, struct got_object_id *,
> -    const char *, const char *, int, int, int,
> +    const char *, const char *, enum got_diff_algorithm, int, int, int,
>      struct got_repository *, FILE *);
>  
> +struct got_pathlist_head;
> +
>  /*
>   * Diff two objects, assuming both objects are trees. Two const char * diff
>   * header labels may be provided which will be used to identify each blob in
> @@ -170,8 +179,8 @@ const struct got_error *got_diff_objects_as_blobs(off_
>   */
>  const struct got_error *got_diff_objects_as_trees(off_t **, size_t *,
>      FILE *, FILE *, int, int, struct got_object_id *, struct got_object_id *,
> -    struct got_pathlist_head *, const char *, const char *, int, int, int,
> -    struct got_repository *, FILE *);
> +    struct got_pathlist_head *, const char *, const char *,
> +    enum got_diff_algorithm, int, int, int, struct got_repository *, FILE *);
>  
>  /*
>   * Diff two objects, assuming both objects are commits.
> @@ -187,6 +196,7 @@ const struct got_error *got_diff_objects_as_trees(off_
>   */
>  const struct got_error *got_diff_objects_as_commits(off_t **, size_t *,
>      FILE *, FILE *, int, int, struct got_object_id *, struct got_object_id *,
> -    struct got_pathlist_head *, int, int, int, struct got_repository *, FILE *);
> +    struct got_pathlist_head *, enum got_diff_algorithm, int, int, int,
> +    struct got_repository *, FILE *);
>  
>  #define GOT_DIFF_MAX_CONTEXT	64
> blob - f08e9f18773211db7d75c2ee3de198ad23a08e01
> blob + 05701b819fcf75cc1c3d627b88c1f75ff8597911
> --- lib/blame.c
> +++ lib/blame.c
> @@ -32,9 +32,10 @@
>  #include "got_error.h"
>  #include "got_object.h"
>  #include "got_cancel.h"
> -#include "got_blame.h"
>  #include "got_commit_graph.h"
>  #include "got_opentemp.h"
> +#include "got_diff.h"
> +#include "got_blame.h"
>  
>  #include "got_lib_inflate.h"
>  #include "got_lib_delta.h"
> @@ -493,7 +494,8 @@ flip_files(struct got_blame *blame)
>  static const struct got_error *
>  blame_open(struct got_blame **blamep, const char *path,
>      struct got_object_id *start_commit_id, struct got_repository *repo,
> -    got_blame_cb cb, void *arg, got_cancel_cb cancel_cb, void *cancel_arg,
> +    enum got_diff_algorithm diff_algo, got_blame_cb cb, void *arg,
> +    got_cancel_cb cancel_cb, void *cancel_arg,
>      int fd1, int fd2, FILE *f1, FILE *f2)
>  {
>  	const struct got_error *err = NULL;
> @@ -540,8 +542,8 @@ blame_open(struct got_blame **blamep, const char *path
>  	blame->f2 = f2;
>  	blame->fd = fd2;
>  
> -	err = got_diff_get_config(&blame->cfg, GOT_DIFF_ALGORITHM_PATIENCE,
> -	    blame_atomize_file, blame);
> +	err = got_diff_get_config(&blame->cfg, diff_algo, blame_atomize_file,
> +	    blame);
>  	if (err)
>  		goto done;
>  
> @@ -643,9 +645,9 @@ done:
>  
>  const struct got_error *
>  got_blame(const char *path, struct got_object_id *commit_id,
> -    struct got_repository *repo, got_blame_cb cb, void *arg,
> -    got_cancel_cb cancel_cb, void* cancel_arg, int fd1, int fd2, FILE *f1,
> -    FILE *f2)
> +    struct got_repository *repo, enum got_diff_algorithm diff_algo,
> +    got_blame_cb cb, void *arg, got_cancel_cb cancel_cb, void* cancel_arg,
> +    int fd1, int fd2, FILE *f1, FILE *f2)
>  {
>  	const struct got_error *err = NULL, *close_err = NULL;
>  	struct got_blame *blame;
> @@ -654,8 +656,8 @@ got_blame(const char *path, struct got_object_id *comm
>  	if (asprintf(&abspath, "%s%s", path[0] == '/' ? "" : "/", path) == -1)
>  		return got_error_from_errno2("asprintf", path);
>  
> -	err = blame_open(&blame, abspath, commit_id, repo, cb, arg,
> -	    cancel_cb, cancel_arg, fd1, fd2, f1, f2);
> +	err = blame_open(&blame, abspath, commit_id, repo, diff_algo,
> +	    cb, arg, cancel_cb, cancel_arg, fd1, fd2, f1, f2);
>  	free(abspath);
>  	if (blame)
>  		close_err = blame_close(blame);
> blob - 500149f5a3358f499c291ab40acdc5142bf68184
> blob + 7268a714345f26eb33869d80941662fdd7688b13
> --- lib/diff.c
> +++ lib/diff.c
> @@ -57,7 +57,8 @@ diff_blobs(off_t **line_offsets, size_t *nlines,
>      struct got_diffreg_result **resultp, struct got_blob_object *blob1,
>      struct got_blob_object *blob2, FILE *f1, FILE *f2,
>      const char *label1, const char *label2, mode_t mode1, mode_t mode2,
> -    int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile)
> +    int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile,
> +    enum got_diff_algorithm diff_algo)
>  {
>  	const struct got_error *err = NULL, *free_err;
>  	char hex1[SHA1_DIGEST_STRING_LENGTH];
> @@ -160,8 +161,8 @@ diff_blobs(off_t **line_offsets, size_t *nlines,
>  		free(modestr1);
>  		free(modestr2);
>  	}
> -	err = got_diffreg(&result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE,
> -	    ignore_whitespace, force_text_diff);
> +	err = got_diffreg(&result, f1, f2, diff_algo, ignore_whitespace,
> +	     force_text_diff);
>  	if (err)
>  		goto done;
>  
> @@ -197,26 +198,27 @@ got_diff_blob_output_unidiff(void *arg, struct got_blo
>  
>  	return diff_blobs(&a->line_offsets, &a->nlines, NULL,
>  	    blob1, blob2, f1, f2, label1, label2, mode1, mode2, a->diff_context,
> -	    a->ignore_whitespace, a->force_text_diff, a->outfile);
> +	    a->ignore_whitespace, a->force_text_diff, a->outfile, a->diff_algo);
>  }
>  
>  const struct got_error *
>  got_diff_blob(off_t **line_offsets, size_t *nlines,
>      struct got_blob_object *blob1, struct got_blob_object *blob2,
>      FILE *f1, FILE *f2, const char *label1, const char *label2,
> -    int diff_context, int ignore_whitespace, int force_text_diff,
> -    FILE *outfile)
> +    enum got_diff_algorithm diff_algo, int diff_context,
> +    int ignore_whitespace, int force_text_diff, FILE *outfile)
>  {
>  	return diff_blobs(line_offsets, nlines, NULL, blob1, blob2, f1, f2,
>  	    label1, label2, 0, 0, diff_context, ignore_whitespace,
> -	    force_text_diff, outfile);
> +	    force_text_diff, outfile, diff_algo);
>  }
>  
>  static const struct got_error *
>  diff_blob_file(struct got_diffreg_result **resultp,
>      struct got_blob_object *blob1, FILE *f1, off_t size1, const char *label1,
> -    FILE *f2, int f2_exists, size_t size2, const char *label2, int diff_context,
> -    int ignore_whitespace, int force_text_diff, FILE *outfile)
> +    FILE *f2, int f2_exists, size_t size2, const char *label2,
> +    enum got_diff_algorithm diff_algo, int diff_context, int ignore_whitespace,
> +    int force_text_diff, FILE *outfile)
>  {
>  	const struct got_error *err = NULL, *free_err;
>  	char hex1[SHA1_DIGEST_STRING_LENGTH];
> @@ -237,8 +239,8 @@ diff_blob_file(struct got_diffreg_result **resultp,
>  		    f2_exists ? label2 : "/dev/null");
>  	}
>  
> -	err = got_diffreg(&result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE, 
> -	    ignore_whitespace, force_text_diff);
> +	err = got_diffreg(&result, f1, f2, diff_algo, ignore_whitespace,
> +	    force_text_diff);
>  	if (err)
>  		goto done;
>  
> @@ -266,12 +268,12 @@ done:
>  const struct got_error *
>  got_diff_blob_file(struct got_blob_object *blob1, FILE *f1, off_t size1,
>      const char *label1, FILE *f2, int f2_exists, size_t size2,
> -    const char *label2, int diff_context, int ignore_whitespace,
> -    int force_text_diff, FILE *outfile)
> +    const char *label2, enum got_diff_algorithm diff_algo, int diff_context,
> +    int ignore_whitespace, int force_text_diff, FILE *outfile)
>  {
>  	return diff_blob_file(NULL, blob1, f1, size1, label1, f2, f2_exists,
> -	    size2, label2, diff_context, ignore_whitespace, force_text_diff,
> -	    outfile);
> +	    size2, label2, diff_algo, diff_context, ignore_whitespace,
> +	    force_text_diff, outfile );
>  }
>  
>  static const struct got_error *
> @@ -727,7 +729,8 @@ const struct got_error *
>  got_diff_objects_as_blobs(off_t **line_offsets, size_t *nlines,
>      FILE *f1, FILE *f2, int fd1, int fd2,
>      struct got_object_id *id1, struct got_object_id *id2,
> -    const char *label1, const char *label2, int diff_context,
> +    const char *label1, const char *label2,
> +    enum got_diff_algorithm diff_algo, int diff_context,
>      int ignore_whitespace, int force_text_diff,
>      struct got_repository *repo, FILE *outfile)
>  {
> @@ -748,8 +751,8 @@ got_diff_objects_as_blobs(off_t **line_offsets, size_t
>  			goto done;
>  	}
>  	err = got_diff_blob(line_offsets, nlines, blob1, blob2, f1, f2,
> -	    label1, label2, diff_context, ignore_whitespace, force_text_diff,
> -	    outfile);
> +	    label1, label2, diff_algo, diff_context, ignore_whitespace,
> +	    force_text_diff, outfile);
>  done:
>  	if (blob1)
>  		got_object_blob_close(blob1);
> @@ -918,7 +921,8 @@ diff_objects_as_trees(off_t **line_offsets, size_t *nl
>      struct got_object_id *id1, struct got_object_id *id2,
>      struct got_pathlist_head *paths, const char *label1, const char *label2,
>      int diff_context, int ignore_whitespace, int force_text_diff,
> -    struct got_repository *repo, FILE *outfile)
> +    struct got_repository *repo, FILE *outfile,
> +    enum got_diff_algorithm diff_algo)
>  {
>  	const struct got_error *err;
>  	struct got_tree_object *tree1 = NULL, *tree2 = NULL;
> @@ -939,6 +943,7 @@ diff_objects_as_trees(off_t **line_offsets, size_t *nl
>  			goto done;
>  	}
>  
> +	arg.diff_algo = diff_algo;
>  	arg.diff_context = diff_context;
>  	arg.ignore_whitespace = ignore_whitespace;
>  	arg.force_text_diff = force_text_diff;
> @@ -975,8 +980,8 @@ got_diff_objects_as_trees(off_t **line_offsets, size_t
>      FILE *f1, FILE *f2, int fd1, int fd2,
>      struct got_object_id *id1, struct got_object_id *id2,
>      struct got_pathlist_head *paths, const char *label1, const char *label2,
> -    int diff_context, int ignore_whitespace, int force_text_diff,
> -    struct got_repository *repo, FILE *outfile)
> +    enum got_diff_algorithm diff_algo, int diff_context, int ignore_whitespace,
> +    int force_text_diff, struct got_repository *repo, FILE *outfile)
>  {
>  	const struct got_error *err;
>  	char *idstr = NULL;
> @@ -1020,7 +1025,7 @@ got_diff_objects_as_trees(off_t **line_offsets, size_t
>  
>  	err = diff_objects_as_trees(line_offsets, nlines, f1, f2, fd1, fd2,
>  	    id1, id2, paths, label1, label2, diff_context, ignore_whitespace,
> -	    force_text_diff, repo, outfile);
> +	    force_text_diff, repo, outfile, diff_algo);
>  done:
>  	free(idstr);
>  	return err;
> @@ -1030,7 +1035,7 @@ const struct got_error *
>  got_diff_objects_as_commits(off_t **line_offsets, size_t *nlines,
>      FILE *f1, FILE *f2, int fd1, int fd2,
>      struct got_object_id *id1, struct got_object_id *id2,
> -    struct got_pathlist_head *paths,
> +    struct got_pathlist_head *paths, enum got_diff_algorithm diff_algo,
>      int diff_context, int ignore_whitespace, int force_text_diff,
>      struct got_repository *repo, FILE *outfile)
>  {
> @@ -1076,7 +1081,8 @@ got_diff_objects_as_commits(off_t **line_offsets, size
>  	err = diff_objects_as_trees(line_offsets, nlines, f1, f2, fd1, fd2,
>  	    commit1 ? got_object_commit_get_tree_id(commit1) : NULL,
>  	    got_object_commit_get_tree_id(commit2), paths, "", "",
> -	    diff_context, ignore_whitespace, force_text_diff, repo, outfile);
> +	    diff_context, ignore_whitespace, force_text_diff, repo, outfile,
> +	    diff_algo);
>  done:
>  	if (commit1)
>  		got_object_commit_close(commit1);
> @@ -1090,7 +1096,7 @@ const struct got_error *
>  got_diff_files(struct got_diffreg_result **resultp,
>      FILE *f1, int f1_exists, const char *label1, FILE *f2, int f2_exists,
>      const char *label2, int diff_context, int ignore_whitespace,
> -    int force_text_diff, FILE *outfile)
> +    int force_text_diff, FILE *outfile, enum got_diff_algorithm diff_algo)
>  {
>  	const struct got_error *err = NULL;
>  	struct got_diffreg_result *diffreg_result = NULL;
> @@ -1105,7 +1111,7 @@ got_diff_files(struct got_diffreg_result **resultp,
>  		    f2_exists ? label2 : "/dev/null");
>  	}
>  
> -	err = got_diffreg(&diffreg_result, f1, f2, GOT_DIFF_ALGORITHM_PATIENCE,
> +	err = got_diffreg(&diffreg_result, f1, f2, diff_algo,
>  	    ignore_whitespace, force_text_diff);
>  	if (err)
>  		goto done;
> blob - f28b50b2a51b0e0f388b22fcf87b63f52408a2e1
> blob + 3acd317409597e7f1fcd02cd18e0db989737c6f4
> --- lib/diff3.c
> +++ lib/diff3.c
> @@ -80,6 +80,7 @@
>  #include "got_error.h"
>  #include "got_opentemp.h"
>  #include "got_object.h"
> +#include "got_diff.h"
>  
>  #include "buf.h"
>  #include "rcsutil.h"
> blob - 186401edf2e3a5402baefc29f867ea4fcbf0b2db
> blob + 30c7388ad74a1c5e2b958cf79a9f5c1790de245d
> --- lib/diffreg.c
> +++ lib/diffreg.c
> @@ -28,6 +28,7 @@
>  #include "got_object.h"
>  #include "got_opentemp.h"
>  #include "got_error.h"
> +#include "got_diff.h"
>  
>  #include "got_lib_diff.h"
>  
> blob - 0157c869fff0c97a45ce1c6fc4f72dcca8c9f2b6
> blob + 3ff8d96891722f9a89a5245a2fb9b5e5c8424e83
> --- lib/got_lib_diff.h
> +++ lib/got_lib_diff.h
> @@ -18,11 +18,6 @@
>  #include "diff_main.h"
>  #include "diff_output.h"
>  
> -enum got_diff_algorithm {
> -	GOT_DIFF_ALGORITHM_MYERS,
> -	GOT_DIFF_ALGORITHM_PATIENCE,
> -};
> -
>  enum got_diff_output_format {
>  	GOT_DIFF_OUTPUT_UNIDIFF,
>  	GOT_DIFF_OUTPUT_EDSCRIPT,
> @@ -63,4 +58,5 @@ const struct got_error *got_merge_diff3(int *, int, FI
>      const char *, const char *, const char *, enum got_diff_algorithm);
>  
>  const struct got_error *got_diff_files(struct got_diffreg_result **, FILE *,
> -    int, const char *, FILE *, int, const char *, int, int, int, FILE *);
> +    int, const char *, FILE *, int, const char *, int, int, int, FILE *,
> +    enum got_diff_algorithm);
> blob - 0d8af2c12bd05d1cd95f0b8226a4e9a708ea99a0
> blob + 6b6915f9998d30a1ae5b1846365b299ba2c974fe
> --- lib/patch.c
> +++ lib/patch.c
> @@ -45,6 +45,7 @@
>  #include "got_repository.h"
>  #include "got_opentemp.h"
>  #include "got_patch.h"
> +#include "got_diff.h"
>  
>  #include "got_lib_delta.h"
>  #include "got_lib_diff.h"
> blob - c6a2aa553557aa15a464291525d9d8c0ee48bcb8
> blob + 585486aa9bd3b5620681a9e4ccad89befbbaf36b
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -4547,7 +4547,7 @@ create_patched_content(char **path_outfile, int revers
>  		goto done;
>  
>  	err = got_diff_files(&diffreg_result, f1, 1, id_str, f2, 1, path2,
> -	    3, 0, 1, NULL);
> +	    3, 0, 1, NULL, GOT_DIFF_ALGORITHM_MYERS);
>  	if (err)
>  		goto done;
>  
> @@ -8362,7 +8362,7 @@ create_unstaged_content(char **path_unstaged_content,
>  		goto done;
>  
>  	err = got_diff_files(&diffreg_result, f1, 1, label1, f2, 1,
> -	    path2, 3, 0, 1, NULL);
> +	    path2, 3, 0, 1, NULL, GOT_DIFF_ALGORITHM_MYERS);
>  	if (err)
>  		goto done;
>  
> blob - e7cd627fd82955639423a579cf6346f539437542
> blob + 800384dacf0faed4893832dd2760af45e28cb8c7
> --- tog/tog.c
> +++ tog/tog.c
> @@ -321,6 +321,7 @@ 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;
> @@ -3965,14 +3966,14 @@ 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_context,
> +		    s->label1, s->label2, s->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_context, s->ignore_whitespace, s->force_text_diff,
> -		    s->repo, s->f);
> +		    s->diff_algo, 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;
> @@ -4007,8 +4008,8 @@ 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_context, s->ignore_whitespace, s->force_text_diff,
> -		    s->repo, s->f);
> +		    s->diff_algo, s->diff_context, s->ignore_whitespace,
> +		    s->force_text_diff, s->repo, s->f);
>  		break;
>  	}
>  	default:
> @@ -4218,6 +4219,7 @@ 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;
> @@ -4948,8 +4950,8 @@ blame_thread(void *arg)
>  		goto done;
>  
>  	err = got_blame(ta->path, a->commit_id, ta->repo,
> -	    blame_cb, ta->cb_args, ta->cancel_cb, ta->cancel_arg, fd1, fd2, f1,
> -	    f2);
> +	    GOT_DIFF_ALGORITHM_MYERS, blame_cb, ta->cb_args,
> +	    ta->cancel_cb, ta->cancel_arg, fd1, fd2, f1, f2);
>  	if (err && err->code == GOT_ERR_CANCELLED)
>  		err = NULL;
>  
> 

-- 
Mark Jamsek <fnc.bsdbox.org>
GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68