Download raw body.
move creation of tempfiles out of lib/diff.c
On Tue, May 31, 2022 at 09:07:41PM +0200, Stefan Sperling wrote:
> On Tue, May 31, 2022 at 05:18:37PM +0200, Stefan Sperling wrote:
> > This patch moves got_opentemp() calls from lib/diff.c into callers.
> >
> > ok?
>
ok
> Previous version of this patch broke the gotweb build. Fixed here.
>
> diff f1cdc1932167666c113e55d67b377d9e1c920c6f 6c756902fd7a43df1c39ce796b34c48863348907
> blob - cf96009500ac33bb3b660dd7e99902801b0cb975
> blob + d88f23ce5b63a9d80862b5fac05c212d054a0b74
> --- got/got.c
> +++ got/got.c
> @@ -3481,25 +3481,41 @@ diff_blobs(struct got_object_id *blob_id1, struct got_
> {
> const struct got_error *err = NULL;
> struct got_blob_object *blob1 = NULL, *blob2 = NULL;
> + FILE *f1 = NULL, *f2 = NULL;
>
> if (blob_id1) {
> err = got_object_open_as_blob(&blob1, repo, blob_id1, 8192);
> if (err)
> goto done;
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> }
>
> err = got_object_open_as_blob(&blob2, repo, blob_id2, 8192);
> if (err)
> goto done;
>
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> while (path[0] == '/')
> path++;
> - err = got_diff_blob(NULL, NULL, blob1, blob2, path, path,
> + err = got_diff_blob(NULL, NULL, blob1, blob2, f1, f2, path, path,
> diff_context, ignore_whitespace, force_text_diff, stdout);
> done:
> if (blob1)
> got_object_blob_close(blob1);
> got_object_blob_close(blob2);
> + if (f1 && fclose(f1) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> + if (f2 && fclose(f2) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> return err;
> }
>
> @@ -3511,17 +3527,29 @@ diff_trees(struct got_object_id *tree_id1, struct got_
> const struct got_error *err = NULL;
> struct got_tree_object *tree1 = NULL, *tree2 = NULL;
> struct got_diff_blob_output_unidiff_arg arg;
> + FILE *f1 = NULL, *f2 = NULL;
>
> if (tree_id1) {
> err = got_object_open_as_tree(&tree1, repo, tree_id1);
> if (err)
> goto done;
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> }
>
> err = got_object_open_as_tree(&tree2, repo, tree_id2);
> if (err)
> goto done;
>
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> arg.diff_context = diff_context;
> arg.ignore_whitespace = ignore_whitespace;
> arg.force_text_diff = force_text_diff;
> @@ -3530,13 +3558,17 @@ diff_trees(struct got_object_id *tree_id1, struct got_
> arg.nlines = 0;
> while (path[0] == '/')
> path++;
> - err = got_diff_tree(tree1, tree2, path, path, repo,
> + err = got_diff_tree(tree1, tree2, f1, f2, path, path, repo,
> got_diff_blob_output_unidiff, &arg, 1);
> done:
> if (tree1)
> got_object_tree_close(tree1);
> if (tree2)
> got_object_tree_close(tree2);
> + if (f1 && fclose(f1) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> + if (f2 && fclose(f2) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> return err;
> }
>
> @@ -3578,7 +3610,7 @@ get_changed_paths(struct got_pathlist_head *paths,
> if (err)
> goto done;
>
> - err = got_diff_tree(tree1, tree2, "", "", repo,
> + err = got_diff_tree(tree1, tree2, NULL, NULL, "", "", repo,
> got_diff_tree_collect_changed_paths, paths, 0);
> done:
> if (tree1)
> @@ -4369,9 +4401,10 @@ print_diff(void *arg, unsigned char status, unsigned c
> const struct got_error *err = NULL;
> struct got_blob_object *blob1 = NULL;
> int fd = -1;
> - FILE *f2 = NULL;
> + FILE *f1 = NULL, *f2 = NULL;
> char *abspath = NULL, *label1 = NULL;
> struct stat sb;
> + off_t size1 = 0;
>
> if (a->diff_staged) {
> if (staged_status != GOT_STATUS_MODIFY &&
> @@ -4413,9 +4446,20 @@ print_diff(void *arg, unsigned char status, unsigned c
> default:
> return got_error(GOT_ERR_FILE_STATUS);
> }
> - return got_diff_objects_as_blobs(NULL, NULL, blob_id,
> - staged_blob_id, label1, label2, a->diff_context,
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> + err = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
> + blob_id, staged_blob_id, label1, label2, a->diff_context,
> a->ignore_whitespace, a->force_text_diff, a->repo, stdout);
> + goto done;
> }
>
> if (staged_status == GOT_STATUS_ADD ||
> @@ -4488,11 +4532,26 @@ print_diff(void *arg, unsigned char status, unsigned c
> } else
> sb.st_size = 0;
>
> - err = got_diff_blob_file(blob1, label1, f2, sb.st_size, path,
> - a->diff_context, a->ignore_whitespace, a->force_text_diff, stdout);
> + if (blob1) {
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> + err = got_object_blob_dump_to_file(&size1, NULL, NULL, f1,
> + blob1);
> + if (err)
> + goto done;
> + }
> +
> + err = got_diff_blob_file(blob1, f1, size1, label1, f2, sb.st_size,
> + path, a->diff_context, a->ignore_whitespace, a->force_text_diff,
> + stdout);
> done:
> if (blob1)
> got_object_blob_close(blob1);
> + if (f1 && fclose(f1) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> if (f2 && fclose(f2) == EOF && err == NULL)
> err = got_error_from_errno("fclose");
> if (fd != -1 && close(fd) == -1 && err == NULL)
> @@ -4519,6 +4578,7 @@ cmd_diff(int argc, char *argv[])
> struct got_reflist_head refs;
> struct got_pathlist_head paths;
> struct got_pathlist_entry *pe;
> + FILE *f1 = NULL, *f2 = NULL;
>
> TAILQ_INIT(&refs);
> TAILQ_INIT(&paths);
> @@ -4811,22 +4871,34 @@ cmd_diff(int argc, char *argv[])
> worktree = NULL;
> }
>
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + error = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + error = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> switch (type1 == GOT_OBJ_TYPE_ANY ? type2 : type1) {
> case GOT_OBJ_TYPE_BLOB:
> - error = got_diff_objects_as_blobs(NULL, NULL, ids[0], ids[1],
> - NULL, NULL, diff_context, ignore_whitespace,
> - force_text_diff, repo, stdout);
> + error = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
> + ids[0], ids[1], 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, ids[0], ids[1],
> - &paths, "", "", diff_context, ignore_whitespace,
> - force_text_diff, repo, stdout);
> + error = got_diff_objects_as_trees(NULL, NULL, f1, f2,
> + ids[0], ids[1], &paths, "", "", 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, ids[0], ids[1],
> - &paths, diff_context, ignore_whitespace, force_text_diff,
> - repo, stdout);
> + error = got_diff_objects_as_commits(NULL, NULL, f1, f2,
> + ids[0], ids[1], &paths, diff_context, ignore_whitespace,
> + force_text_diff, repo, stdout);
> break;
> default:
> error = got_error(GOT_ERR_OBJ_TYPE);
> @@ -4847,6 +4919,10 @@ done:
> free((char *)pe->path);
> got_pathlist_free(&paths);
> got_ref_list_free(&refs);
> + if (f1 && fclose(f1) == EOF && error == NULL)
> + error = got_error_from_errno("fclose");
> + if (f2 && fclose(f2) == EOF && error == NULL)
> + error = got_error_from_errno("fclose");
> return error;
> }
>
> @@ -8827,8 +8903,9 @@ struct check_path_prefix_arg {
>
> static const struct got_error *
> check_path_prefix_in_diff(void *arg, struct got_blob_object *blob1,
> - struct got_blob_object *blob2, struct got_object_id *id1,
> - struct got_object_id *id2, const char *path1, const char *path2,
> + struct got_blob_object *blob2, FILE *f1, FILE *f2,
> + struct got_object_id *id1, struct got_object_id *id2,
> + const char *path1, const char *path2,
> mode_t mode1, mode_t mode2, struct got_repository *repo)
> {
> struct check_path_prefix_arg *a = arg;
> @@ -8876,7 +8953,7 @@ check_path_prefix(struct got_object_id *parent_id,
> cpp_arg.path_prefix++;
> cpp_arg.len = strlen(cpp_arg.path_prefix);
> cpp_arg.errcode = errcode;
> - err = got_diff_tree(tree1, tree2, "", "", repo,
> + err = got_diff_tree(tree1, tree2, NULL, NULL, "", "", repo,
> check_path_prefix_in_diff, &cpp_arg, 0);
> done:
> if (tree1)
> blob - 3d8c00182e1858eae16c7d8308e2673b82997bad
> blob + 613976ee0e8a3f55e862ceb0aa730fd85f3e46e3
> --- gotweb/gotweb.c
> +++ gotweb/gotweb.c
> @@ -2851,7 +2851,7 @@ static const struct got_error *
> gw_output_diff(struct gw_trans *gw_trans, struct gw_header *header)
> {
> const struct got_error *error;
> - FILE *f = NULL;
> + FILE *f = NULL, *f1 = NULL, *f2 = NULL;
> struct got_object_id *id1 = NULL, *id2 = NULL;
> char *label1 = NULL, *label2 = NULL, *line = NULL;
> int obj_type;
> @@ -2863,6 +2863,18 @@ gw_output_diff(struct gw_trans *gw_trans, struct gw_he
> if (f == NULL)
> return NULL;
>
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + error = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + error = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> if (header->parent_id != NULL &&
> strncmp(header->parent_id, "/dev/null", 9) != 0) {
> error = got_repo_match_object_id(&id1, &label1,
> @@ -2883,16 +2895,16 @@ gw_output_diff(struct gw_trans *gw_trans, struct gw_he
> goto done;
> switch (obj_type) {
> case GOT_OBJ_TYPE_BLOB:
> - error = got_diff_objects_as_blobs(NULL, NULL, id1, id2,
> - NULL, NULL, 3, 0, 0, gw_trans->repo, f);
> + error = got_diff_objects_as_blobs(NULL, NULL, f1, f2,
> + id1, id2, NULL, NULL, 3, 0, 0, gw_trans->repo, f);
> break;
> case GOT_OBJ_TYPE_TREE:
> - error = got_diff_objects_as_trees(NULL, NULL, id1, id2,
> - NULL, "", "", 3, 0, 0, gw_trans->repo, f);
> + error = got_diff_objects_as_trees(NULL, NULL, f1, f2,
> + id1, id2, NULL, "", "", 3, 0, 0, gw_trans->repo, f);
> break;
> case GOT_OBJ_TYPE_COMMIT:
> - error = got_diff_objects_as_commits(NULL, NULL, id1, id2,
> - NULL, 3, 0, 0, gw_trans->repo, f);
> + error = got_diff_objects_as_commits(NULL, NULL, f1, f2,
> + id1, id2, NULL, 3, 0, 0, gw_trans->repo, f);
> break;
> default:
> error = got_error(GOT_ERR_OBJ_TYPE);
> @@ -2922,6 +2934,10 @@ gw_output_diff(struct gw_trans *gw_trans, struct gw_he
> done:
> if (f && fclose(f) == EOF && error == NULL)
> error = got_error_from_errno("fclose");
> + if (f1 && fclose(f1) == EOF && error == NULL)
> + error = got_error_from_errno("fclose");
> + if (f2 && fclose(f2) == EOF && error == NULL)
> + error = got_error_from_errno("fclose");
> free(line);
> free(label1);
> free(label2);
> blob - 47d14eddfbf3c27bb83d461d7330e04389cd0700
> blob + 5dbe18b856a53a58bee722d773249a93e91993a8
> --- include/got_diff.h
> +++ include/got_diff.h
> @@ -16,8 +16,15 @@
>
> /*
> * Compute the differences between two blobs and write unified diff text
> - * to the provided output FILE. Two const char * diff header labels may
> - * be provided which will be used to identify each blob in the diff output.
> + * to the provided output file. Two open temporary files must be provided
> + * for internal use; these files can be obtained from got_opentemp() and
> + * must be closed by the caller.
> + * If one of the blobs being diffed does not exist, all corresponding
> + * blob object and temporary file arguments should be set to NULL.
> + * Two const char * diff header labels may be provided which will be used
> + * to identify each blob in the diff output.
> + * The set of arguments relating to either blob may be NULL to indicate
> + * that no content is present on its respective side of the diff.
> * If a label is NULL, use the blob's SHA1 checksum instead.
> * The number of context lines to show in the diff must be specified as well.
> * Whitespace differences may optionally be ignored.
> @@ -25,19 +32,20 @@
> * array of line offsets for, and the number of lines in, the unidiff text.
> */
> const struct got_error *got_diff_blob(off_t **, size_t *,
> - struct got_blob_object *, struct got_blob_object *,
> + struct got_blob_object *, struct got_blob_object *, FILE *, FILE *,
> const char *, const char *, int, int, int, FILE *);
>
> /*
> * Compute the differences between a blob and a file and write unified diff
> - * text to the provided output file. The file's size must be provided, as
> - * well as a const char * diff header label which identifies the file.
> + * text to the provided output file. The blob object, its content, and its
> + * size must be provided.The file's size must be provided, as well as a
> + * const char * diff header label which identifies the file.
> * An optional const char * diff header label for the blob may be provided, too.
> * The number of context lines to show in the diff must be specified as well.
> * 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, int, FILE *);
> +const struct got_error *got_diff_blob_file(struct got_blob_object *, FILE *,
> + off_t, const char *, FILE *, size_t, const char *, int, int, int, FILE *);
>
> /*
> * A callback function invoked to handle the differences between two blobs
> @@ -45,13 +53,15 @@ const struct got_error *got_diff_blob_file(struct got_
> * their respective IDs, and two corresponding paths within the diffed trees.
> * The first blob contains content from the old side of the diff, and
> * the second blob contains content on the new side of the diff.
> + * Two open temporary files must be provided for internal use; these files
> + * can be obtained from got_opentemp() and must be closed by the caller.
> * The set of arguments relating to either blob may be NULL to indicate
> * that no content is present on its respective side of the diff.
> * File modes from relevant tree objects which contain the blobs may
> * also be passed. These will be zero if not available.
> */
> typedef const struct got_error *(*got_diff_blob_cb)(void *,
> - struct got_blob_object *, struct got_blob_object *,
> + struct got_blob_object *, struct got_blob_object *, FILE *, FILE *,
> struct got_object_id *, struct got_object_id *,
> const char *, const char *, mode_t, mode_t, struct got_repository *);
>
> @@ -82,7 +92,7 @@ struct got_diff_blob_output_unidiff_arg {
> off_t *line_offsets; /* Dispose of with free(3) when done. */
> };
> const struct got_error *got_diff_blob_output_unidiff(void *,
> - struct got_blob_object *, struct got_blob_object *,
> + struct got_blob_object *, struct got_blob_object *, FILE *, FILE *,
> struct got_object_id *, struct got_object_id *,
> const char *, const char *, mode_t, mode_t, struct got_repository *);
>
> @@ -92,9 +102,14 @@ const struct got_error *got_diff_blob_output_unidiff(v
> * Diffing of blob content can be suppressed by passing zero for the
> * 'diff_content' parameter. The callback will then only receive blob
> * object IDs and diff labels, but NULL pointers instead of blob objects.
> + * If 'diff_content' is set, two open temporary files must be provided
> + * for internal use; these files can be obtained from got_opentemp()
> + * and must be closed by the caller. Otherwise the files can be NULL.
> + * The set of arguments relating to either tree may be NULL to indicate
> + * that no content is present on its respective side of the diff.
> */
> const struct got_error *got_diff_tree(struct got_tree_object *,
> - struct got_tree_object *, const char *, const char *,
> + struct got_tree_object *, FILE *, FILE *, const char *, const char *,
> struct got_repository *, got_diff_blob_cb cb, void *cb_arg, int);
>
> /*
> @@ -114,7 +129,7 @@ struct got_diff_changed_path {
> int status;
> };
> const struct got_error *got_diff_tree_collect_changed_paths(void *,
> - struct got_blob_object *, struct got_blob_object *,
> + struct got_blob_object *, struct got_blob_object *, FILE *, FILE *,
> struct got_object_id *, struct got_object_id *,
> const char *, const char *, mode_t, mode_t, struct got_repository *);
>
> @@ -122,13 +137,17 @@ const struct got_error *got_diff_tree_collect_changed_
> * Diff two objects, assuming both objects are blobs. Two const char * diff
> * header labels may be provided which will be used to identify each blob in
> * the diff output. If a label is NULL, use the blob's SHA1 checksum instead.
> + * Two open temporary files must be provided for internal use; these files
> + * can be obtained from got_opentemp() and must be closed by the caller.
> + * The set of arguments relating to either blob may be NULL to indicate
> + * that no content is present on its respective side of the diff.
> * The number of context lines to show in the diff must be specified as well.
> * Write unified diff text to the provided output FILE.
> * If not NULL, the two initial output arguments will be populated with an
> * array of line offsets for, and the number of lines in, the unidiff text.
> */
> const struct got_error *got_diff_objects_as_blobs(off_t **, size_t *,
> - struct got_object_id *, struct got_object_id *,
> + FILE *, FILE *, struct got_object_id *, struct got_object_id *,
> const char *, const char *, int, int, int,
> struct got_repository *, FILE *);
>
> @@ -137,23 +156,32 @@ const struct got_error *got_diff_objects_as_blobs(off_
> * header labels may be provided which will be used to identify each blob in
> * the trees. If a label is NULL, use the blob's SHA1 checksum instead.
> * The number of context lines to show in diffs must be specified.
> + * Two open temporary files must be provided for internal use; these files
> + * can be obtained from got_opentemp() and must be closed by the caller.
> + * The set of arguments relating to either tree may be NULL to indicate
> + * that no content is present on its respective side of the diff.
> * Write unified diff text to the provided output FILE.
> * If not NULL, the two initial output arguments will be populated with an
> * array of line offsets for, and the number of lines in, the unidiff text.
> */
> const struct got_error *got_diff_objects_as_trees(off_t **, size_t *,
> - struct got_object_id *, struct got_object_id *, struct got_pathlist_head *,
> - char *, char *, int, int, int, struct got_repository *, FILE *);
> + FILE *, FILE *, struct got_object_id *, struct got_object_id *,
> + struct got_pathlist_head *, char *, char *, int, int, int,
> + struct got_repository *, FILE *);
>
> /*
> * Diff two objects, assuming both objects are commits.
> * The number of context lines to show in diffs must be specified.
> + * Two open temporary files must be provided for internal use; these files
> + * can be obtained from got_opentemp() and must be closed by the caller.
> + * The set of arguments relating to either commit may be NULL to indicate
> + * that no content is present on its respective side of the diff.
> * Write unified diff text to the provided output FILE.
> * If not NULL, the two initial output arguments will be populated with an
> * 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 *, struct got_pathlist_head *,
> - int, int, int, struct got_repository *, FILE *);
> + FILE *, FILE *, struct got_object_id *, struct got_object_id *,
> + struct got_pathlist_head *, int, int, int, struct got_repository *, FILE *);
>
> #define GOT_DIFF_MAX_CONTEXT 64
> blob - da3c26b1d829a76ecc75775909353f514f618f42
> blob + 1c12d8425dd6f7aa30fb805c6ff288d3b84161c0
> --- lib/diff.c
> +++ lib/diff.c
> @@ -28,7 +28,6 @@
> #include "got_repository.h"
> #include "got_error.h"
> #include "got_diff.h"
> -#include "got_opentemp.h"
> #include "got_path.h"
> #include "got_cancel.h"
> #include "got_worktree.h"
> @@ -53,14 +52,25 @@ add_line_offset(off_t **line_offsets, size_t *nlines,
> }
>
> static const struct got_error *
> +reset_file(FILE *f)
> +{
> + if (fpurge(f) == EOF)
> + return got_error_from_errno("fpurge");
> + if (ftruncate(fileno(f), 0L) == -1)
> + return got_error_from_errno("ftruncate");
> + if (fseeko(f, 0L, SEEK_SET) == -1)
> + return got_error_from_errno("fseeko");
> + return NULL;
> +}
> +
> +static const struct got_error *
> diff_blobs(off_t **line_offsets, size_t *nlines,
> struct got_diffreg_result **resultp, struct got_blob_object *blob1,
> - struct got_blob_object *blob2,
> + 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)
> {
> const struct got_error *err = NULL, *free_err;
> - FILE *f1 = NULL, *f2 = NULL;
> char hex1[SHA1_DIGEST_STRING_LENGTH];
> char hex2[SHA1_DIGEST_STRING_LENGTH];
> char *idstr1 = NULL, *idstr2 = NULL;
> @@ -80,20 +90,15 @@ diff_blobs(off_t **line_offsets, size_t *nlines,
> if (resultp)
> *resultp = NULL;
>
> - if (blob1) {
> - f1 = got_opentemp();
> - if (f1 == NULL)
> - return got_error_from_errno("got_opentemp");
> + if (f1) {
> + err = reset_file(f1);
> + if (err)
> + goto done;
> }
> -
> - if (blob2) {
> - f2 = got_opentemp();
> - if (f2 == NULL) {
> - err = got_error_from_errno("got_opentemp");
> - if (f1)
> - fclose(f1);
> - return err;
> - }
> + if (f2) {
> + err = reset_file(f2);
> + if (err)
> + goto done;
> }
>
> size1 = 0;
> @@ -189,66 +194,53 @@ diff_blobs(off_t **line_offsets, size_t *nlines,
> err = free_err;
> }
> done:
> - if (f1 && fclose(f1) == EOF && err == NULL)
> - err = got_error_from_errno("fclose");
> - if (f2 && fclose(f2) == EOF && err == NULL)
> - err = got_error_from_errno("fclose");
> return err;
> }
>
> const struct got_error *
> got_diff_blob_output_unidiff(void *arg, struct got_blob_object *blob1,
> - struct got_blob_object *blob2, struct got_object_id *id1,
> - struct got_object_id *id2, const char *label1, const char *label2,
> - mode_t mode1, mode_t mode2, struct got_repository *repo)
> + struct got_blob_object *blob2, FILE *f1, FILE *f2,
> + struct got_object_id *id1, struct got_object_id *id2,
> + const char *label1, const char *label2, mode_t mode1, mode_t mode2,
> + struct got_repository *repo)
> {
> struct got_diff_blob_output_unidiff_arg *a = arg;
>
> return diff_blobs(&a->line_offsets, &a->nlines, NULL,
> - blob1, blob2, label1, label2, mode1, mode2, a->diff_context,
> + blob1, blob2, f1, f2, label1, label2, mode1, mode2, a->diff_context,
> 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, int force_text_diff, FILE *outfile)
> + FILE *f1, FILE *f2, const char *label1, const char *label2,
> + int diff_context, int ignore_whitespace, int force_text_diff,
> + FILE *outfile)
> {
> - return diff_blobs(line_offsets, nlines, NULL, blob1, blob2,
> + return diff_blobs(line_offsets, nlines, NULL, blob1, blob2, f1, f2,
> 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,
> - int force_text_diff, FILE *outfile)
> + struct got_blob_object *blob1, FILE *f1, off_t size1, const char *label1,
> + FILE *f2, size_t size2, 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;
> char hex1[SHA1_DIGEST_STRING_LENGTH];
> char *idstr1 = NULL;
> - off_t size1;
> struct got_diffreg_result *result = NULL;
>
> if (resultp)
> *resultp = NULL;
>
> - size1 = 0;
> - if (blob1) {
> - f1 = got_opentemp();
> - if (f1 == NULL)
> - return got_error_from_errno("got_opentemp");
> + if (blob1)
> idstr1 = got_object_blob_id_str(blob1, hex1, sizeof(hex1));
> - err = got_object_blob_dump_to_file(&size1, NULL, NULL, f1,
> - blob1);
> - if (err)
> - goto done;
> - } else {
> + else
> idstr1 = "/dev/null";
> - }
>
> if (outfile) {
> fprintf(outfile, "blob - %s\n", label1 ? label1 : idstr1);
> @@ -263,7 +255,7 @@ diff_blob_file(struct got_diffreg_result **resultp,
>
> if (outfile) {
> err = got_diffreg_output(NULL, NULL, result,
> - blob1 != NULL, f2 != NULL,
> + f1 != NULL, f2 != NULL,
> label2, /* show local file's path, not a blob ID */
> label2, GOT_DIFF_OUTPUT_UNIDIFF,
> diff_context, outfile);
> @@ -279,23 +271,22 @@ diff_blob_file(struct got_diffreg_result **resultp,
> err = free_err;
> }
> done:
> - if (f1 && fclose(f1) == EOF && err == NULL)
> - err = got_error_from_errno("fclose");
> return err;
> }
>
> 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, int force_text_diff, FILE *outfile)
> +got_diff_blob_file(struct got_blob_object *blob1, FILE *f1, off_t size1,
> + const char *label1, FILE *f2, size_t size2, const char *label2,
> + int diff_context, int ignore_whitespace, int force_text_diff, FILE *outfile)
> {
> - return diff_blob_file(NULL, blob1, label1, f2, size2, label2,
> + return diff_blob_file(NULL, blob1, f1, size1, label1, f2, size2, label2,
> diff_context, ignore_whitespace, force_text_diff, outfile);
> }
>
> static const struct got_error *
> -diff_added_blob(struct got_object_id *id, const char *label, mode_t mode,
> - struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
> +diff_added_blob(struct got_object_id *id, FILE *f, const char *label,
> + mode_t mode, struct got_repository *repo,
> + got_diff_blob_cb cb, void *cb_arg)
> {
> const struct got_error *err;
> struct got_blob_object *blob = NULL;
> @@ -308,7 +299,8 @@ diff_added_blob(struct got_object_id *id, const char *
> err = got_object_blob_open(&blob, repo, obj, 8192);
> if (err)
> goto done;
> - err = cb(cb_arg, NULL, blob, NULL, id, NULL, label, 0, mode, repo);
> + err = cb(cb_arg, NULL, blob, NULL, f, NULL, id,
> + NULL, label, 0, mode, repo);
> done:
> got_object_close(obj);
> if (blob)
> @@ -318,8 +310,9 @@ done:
>
> static const struct got_error *
> diff_modified_blob(struct got_object_id *id1, struct got_object_id *id2,
> - const char *label1, const char *label2, mode_t mode1, mode_t mode2,
> - struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
> + FILE *f1, FILE *f2, const char *label1, const char *label2,
> + mode_t mode1, mode_t mode2, struct got_repository *repo,
> + got_diff_blob_cb cb, void *cb_arg)
> {
> const struct got_error *err;
> struct got_object *obj1 = NULL;
> @@ -351,8 +344,8 @@ diff_modified_blob(struct got_object_id *id1, struct g
> if (err)
> goto done;
>
> - err = cb(cb_arg, blob1, blob2, id1, id2, label1, label2, mode1, mode2,
> - repo);
> + err = cb(cb_arg, blob1, blob2, f1, f2, id1, id2, label1, label2,
> + mode1, mode2, repo);
> done:
> if (obj1)
> got_object_close(obj1);
> @@ -366,8 +359,8 @@ done:
> }
>
> static const struct got_error *
> -diff_deleted_blob(struct got_object_id *id, const char *label, mode_t mode,
> - struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
> +diff_deleted_blob(struct got_object_id *id, FILE *f, const char *label,
> + mode_t mode, struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
> {
> const struct got_error *err;
> struct got_blob_object *blob = NULL;
> @@ -380,7 +373,8 @@ diff_deleted_blob(struct got_object_id *id, const char
> err = got_object_blob_open(&blob, repo, obj, 8192);
> if (err)
> goto done;
> - err = cb(cb_arg, blob, NULL, id, NULL, label, NULL, mode, 0, repo);
> + err = cb(cb_arg, blob, NULL, f, NULL, id, NULL, label, NULL,
> + mode, 0, repo);
> done:
> got_object_close(obj);
> if (blob)
> @@ -389,7 +383,7 @@ done:
> }
>
> static const struct got_error *
> -diff_added_tree(struct got_object_id *id, const char *label,
> +diff_added_tree(struct got_object_id *id, FILE *f, const char *label,
> struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> int diff_content)
> {
> @@ -410,8 +404,8 @@ diff_added_tree(struct got_object_id *id, const char *
> if (err)
> goto done;
>
> - err = got_diff_tree(NULL, tree, NULL, label, repo, cb, cb_arg,
> - diff_content);
> + err = got_diff_tree(NULL, tree, NULL, f, NULL, label,
> + repo, cb, cb_arg, diff_content);
> done:
> if (tree)
> got_object_tree_close(tree);
> @@ -422,8 +416,9 @@ done:
>
> static const struct got_error *
> diff_modified_tree(struct got_object_id *id1, struct got_object_id *id2,
> - const char *label1, const char *label2, struct got_repository *repo,
> - got_diff_blob_cb cb, void *cb_arg, int diff_content)
> + FILE *f1, FILE *f2, const char *label1, const char *label2,
> + struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> + int diff_content)
> {
> const struct got_error *err;
> struct got_object *treeobj1 = NULL;
> @@ -457,8 +452,8 @@ diff_modified_tree(struct got_object_id *id1, struct g
> if (err)
> goto done;
>
> - err = got_diff_tree(tree1, tree2, label1, label2, repo, cb, cb_arg,
> - diff_content);
> + err = got_diff_tree(tree1, tree2, f1, f2, label1, label2,
> + repo, cb, cb_arg, diff_content);
>
> done:
> if (tree1)
> @@ -473,7 +468,7 @@ done:
> }
>
> static const struct got_error *
> -diff_deleted_tree(struct got_object_id *id, const char *label,
> +diff_deleted_tree(struct got_object_id *id, FILE *f, const char *label,
> struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> int diff_content)
> {
> @@ -494,8 +489,8 @@ diff_deleted_tree(struct got_object_id *id, const char
> if (err)
> goto done;
>
> - err = got_diff_tree(tree, NULL, label, NULL, repo, cb, cb_arg,
> - diff_content);
> + err = got_diff_tree(tree, NULL, f, NULL, label, NULL,
> + repo, cb, cb_arg, diff_content);
> done:
> if (tree)
> got_object_tree_close(tree);
> @@ -514,8 +509,8 @@ diff_kind_mismatch(struct got_object_id *id1, struct g
> }
>
> static const struct got_error *
> -diff_entry_old_new(struct got_tree_entry *te1,
> - struct got_tree_entry *te2, const char *label1, const char *label2,
> +diff_entry_old_new(struct got_tree_entry *te1, struct got_tree_entry *te2,
> + FILE *f1, FILE *f2, const char *label1, const char *label2,
> struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> int diff_content)
> {
> @@ -527,15 +522,16 @@ diff_entry_old_new(struct got_tree_entry *te1,
>
> if (te2 == NULL) {
> if (S_ISDIR(te1->mode))
> - err = diff_deleted_tree(&te1->id, label1, repo,
> + err = diff_deleted_tree(&te1->id, f1, label1, repo,
> cb, cb_arg, diff_content);
> else {
> if (diff_content)
> - err = diff_deleted_blob(&te1->id, label1,
> + err = diff_deleted_blob(&te1->id, f1, label1,
> te1->mode, repo, cb, cb_arg);
> else
> - err = cb(cb_arg, NULL, NULL, &te1->id, NULL,
> - label1, NULL, te1->mode, 0, repo);
> + err = cb(cb_arg, NULL, NULL, NULL, NULL,
> + &te1->id, NULL, label1, NULL,
> + te1->mode, 0, repo);
> }
> return err;
> } else if (got_object_tree_entry_is_submodule(te2))
> @@ -544,7 +540,7 @@ diff_entry_old_new(struct got_tree_entry *te1,
> id_match = (got_object_id_cmp(&te1->id, &te2->id) == 0);
> if (S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) {
> if (!id_match)
> - return diff_modified_tree(&te1->id, &te2->id,
> + return diff_modified_tree(&te1->id, &te2->id, f1, f2,
> label1, label2, repo, cb, cb_arg, diff_content);
> } else if ((S_ISREG(te1->mode) || S_ISLNK(te1->mode)) &&
> (S_ISREG(te2->mode) || S_ISLNK(te2->mode))) {
> @@ -553,12 +549,12 @@ diff_entry_old_new(struct got_tree_entry *te1,
> (te2->mode & (S_IFLNK | S_IXUSR))) {
> if (diff_content)
> return diff_modified_blob(&te1->id, &te2->id,
> - label1, label2, te1->mode, te2->mode,
> - repo, cb, cb_arg);
> + f1, f2, label1, label2, te1->mode,
> + te2->mode, repo, cb, cb_arg);
> else
> - return cb(cb_arg, NULL, NULL, &te1->id,
> - &te2->id, label1, label2, te1->mode,
> - te2->mode, repo);
> + return cb(cb_arg, NULL, NULL, NULL, NULL,
> + &te1->id, &te2->id, label1, label2,
> + te1->mode, te2->mode, repo);
> }
> }
>
> @@ -571,7 +567,7 @@ diff_entry_old_new(struct got_tree_entry *te1,
>
> static const struct got_error *
> diff_entry_new_old(struct got_tree_entry *te2,
> - struct got_tree_entry *te1, const char *label2,
> + struct got_tree_entry *te1, FILE *f2, const char *label2,
> struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> int diff_content)
> {
> @@ -582,21 +578,22 @@ diff_entry_new_old(struct got_tree_entry *te2,
> return NULL;
>
> if (S_ISDIR(te2->mode))
> - return diff_added_tree(&te2->id, label2, repo, cb, cb_arg,
> - diff_content);
> + return diff_added_tree(&te2->id, f2, label2,
> + repo, cb, cb_arg, diff_content);
>
> if (diff_content)
> - return diff_added_blob(&te2->id, label2, te2->mode, repo, cb,
> - cb_arg);
> + return diff_added_blob(&te2->id, f2, label2, te2->mode,
> + repo, cb, cb_arg);
>
> - return cb(cb_arg, NULL, NULL, NULL, &te2->id, NULL, label2, 0,
> - te2->mode, repo);
> + return cb(cb_arg, NULL, NULL, NULL, NULL, NULL, &te2->id,
> + NULL, label2, 0, te2->mode, repo);
> }
>
> const struct got_error *
> got_diff_tree_collect_changed_paths(void *arg, struct got_blob_object *blob1,
> - struct got_blob_object *blob2, struct got_object_id *id1,
> - struct got_object_id *id2, const char *label1, const char *label2,
> + struct got_blob_object *blob2, FILE *f1, FILE *f2,
> + struct got_object_id *id1, struct got_object_id *id2,
> + const char *label1, const char *label2,
> mode_t mode1, mode_t mode2, struct got_repository *repo)
> {
> const struct got_error *err = NULL;
> @@ -637,8 +634,9 @@ done:
>
> const struct got_error *
> got_diff_tree(struct got_tree_object *tree1, struct got_tree_object *tree2,
> - const char *label1, const char *label2, struct got_repository *repo,
> - got_diff_blob_cb cb, void *cb_arg, int diff_content)
> + FILE *f1, FILE *f2, const char *label1, const char *label2,
> + struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg,
> + int diff_content)
> {
> const struct got_error *err = NULL;
> struct got_tree_entry *te1 = NULL;
> @@ -673,8 +671,8 @@ got_diff_tree(struct got_tree_object *tree1, struct go
> return
> got_error_from_errno("asprintf");
> }
> - err = diff_entry_old_new(te1, te, l1, l2, repo, cb,
> - cb_arg, diff_content);
> + err = diff_entry_old_new(te1, te, f1, f2, l1, l2,
> + repo, cb, cb_arg, diff_content);
> if (err)
> break;
> }
> @@ -696,7 +694,7 @@ got_diff_tree(struct got_tree_object *tree1, struct go
> return
> got_error_from_errno("asprintf");
> }
> - err = diff_entry_new_old(te2, te, l2, repo,
> + err = diff_entry_new_old(te2, te, f2, l2, repo,
> cb, cb_arg, diff_content);
> if (err)
> break;
> @@ -729,7 +727,7 @@ got_diff_tree(struct got_tree_object *tree1, struct go
>
> 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,
> + FILE *f1, FILE *f2, struct got_object_id *id1, struct got_object_id *id2,
> const char *label1, const char *label2, int diff_context,
> int ignore_whitespace, int force_text_diff,
> struct got_repository *repo, FILE *outfile)
> @@ -750,7 +748,7 @@ got_diff_objects_as_blobs(off_t **line_offsets, size_t
> if (err)
> goto done;
> }
> - err = got_diff_blob(line_offsets, nlines, blob1, blob2,
> + err = got_diff_blob(line_offsets, nlines, blob1, blob2, f1, f2,
> label1, label2, diff_context, ignore_whitespace, force_text_diff,
> outfile);
> done:
> @@ -763,8 +761,8 @@ done:
>
> static const struct got_error *
> diff_paths(struct got_tree_object *tree1, struct got_tree_object *tree2,
> - struct got_pathlist_head *paths, struct got_repository *repo,
> - got_diff_blob_cb cb, void *cb_arg)
> + FILE *f1, FILE *f2, struct got_pathlist_head *paths,
> + struct got_repository *repo, got_diff_blob_cb cb, void *cb_arg)
> {
> const struct got_error *err = NULL;
> struct got_pathlist_entry *pe;
> @@ -843,7 +841,7 @@ diff_paths(struct got_tree_object *tree1, struct got_t
> if (err)
> goto done;
> }
> - err = cb(cb_arg, blob1, blob2, id1, id2,
> + err = cb(cb_arg, blob1, blob2, f1, f2, id1, id2,
> id1 ? pe->path : "/dev/null",
> id2 ? pe->path : "/dev/null",
> mode1, mode2, repo);
> @@ -863,7 +861,7 @@ diff_paths(struct got_tree_object *tree1, struct got_t
> if (err)
> goto done;
> }
> - err = got_diff_tree(subtree1, subtree2,
> + err = got_diff_tree(subtree1, subtree2, f1, f2,
> id1 ? pe->path : "/dev/null",
> id2 ? pe->path : "/dev/null",
> repo, cb, cb_arg, 1);
> @@ -890,7 +888,7 @@ done:
>
> 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,
> + FILE *f1, FILE *f2, struct got_object_id *id1, struct got_object_id *id2,
> struct got_pathlist_head *paths,
> char *label1, char *label2, int diff_context, int ignore_whitespace,
> int force_text_diff, struct got_repository *repo, FILE *outfile)
> @@ -926,10 +924,10 @@ got_diff_objects_as_trees(off_t **line_offsets, size_t
> arg.nlines = 0;
> }
> if (paths == NULL || TAILQ_EMPTY(paths)) {
> - err = got_diff_tree(tree1, tree2, label1, label2, repo,
> - got_diff_blob_output_unidiff, &arg, 1);
> + err = got_diff_tree(tree1, tree2, f1, f2, label1, label2,
> + repo, got_diff_blob_output_unidiff, &arg, 1);
> } else {
> - err = diff_paths(tree1, tree2, paths, repo,
> + err = diff_paths(tree1, tree2, f1, f2, paths, repo,
> got_diff_blob_output_unidiff, &arg);
> }
> if (want_lineoffsets) {
> @@ -946,7 +944,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,
> + FILE *f1, FILE *f2, struct got_object_id *id1, struct got_object_id *id2,
> struct got_pathlist_head *paths,
> int diff_context, int ignore_whitespace, int force_text_diff,
> struct got_repository *repo, FILE *outfile)
> @@ -967,7 +965,7 @@ got_diff_objects_as_commits(off_t **line_offsets, size
> if (err)
> goto done;
>
> - err = got_diff_objects_as_trees(line_offsets, nlines,
> + err = got_diff_objects_as_trees(line_offsets, nlines, f1, f2,
> 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);
> blob - ca8e4d6a6ba63c5f3e16487196a7a3bf16fa888b
> blob + c8e98cc3b117b9e02d199a6a46a60f02d73c2b83
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -2749,8 +2749,9 @@ struct merge_file_cb_arg {
>
> static const struct got_error *
> merge_file_cb(void *arg, struct got_blob_object *blob1,
> - struct got_blob_object *blob2, struct got_object_id *id1,
> - struct got_object_id *id2, const char *path1, const char *path2,
> + struct got_blob_object *blob2, FILE *f1, FILE *f2,
> + struct got_object_id *id1, struct got_object_id *id2,
> + const char *path1, const char *path2,
> mode_t mode1, mode_t mode2, struct got_repository *repo)
> {
> static const struct got_error *err = NULL;
> @@ -3056,8 +3057,9 @@ struct check_merge_conflicts_arg {
>
> static const struct got_error *
> check_merge_conflicts(void *arg, struct got_blob_object *blob1,
> - struct got_blob_object *blob2, struct got_object_id *id1,
> - struct got_object_id *id2, const char *path1, const char *path2,
> + struct got_blob_object *blob2, FILE *f1, FILE *f2,
> + struct got_object_id *id1, struct got_object_id *id2,
> + const char *path1, const char *path2,
> mode_t mode1, mode_t mode2, struct got_repository *repo)
> {
> const struct got_error *err = NULL;
> @@ -3105,6 +3107,7 @@ merge_files(struct got_worktree *worktree, struct got_
> struct check_merge_conflicts_arg cmc_arg;
> struct merge_file_cb_arg arg;
> char *label_orig = NULL;
> + FILE *f1 = NULL, *f2 = NULL;
>
> if (commit_id1) {
> err = got_object_open_as_commit(&commit1, repo, commit_id1);
> @@ -3133,6 +3136,12 @@ merge_files(struct got_worktree *worktree, struct got_
> goto done;
> }
> free(id_str);
> +
> + f1 = got_opentemp();
> + if (f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> }
>
> err = got_object_open_as_commit(&commit2, repo, commit_id2);
> @@ -3148,10 +3157,16 @@ merge_files(struct got_worktree *worktree, struct got_
> if (err)
> goto done;
>
> + f2 = got_opentemp();
> + if (f2 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> cmc_arg.worktree = worktree;
> cmc_arg.fileindex = fileindex;
> cmc_arg.repo = repo;
> - err = got_diff_tree(tree1, tree2, "", "", repo,
> + err = got_diff_tree(tree1, tree2, f1, f2, "", "", repo,
> check_merge_conflicts, &cmc_arg, 0);
> if (err)
> goto done;
> @@ -3165,7 +3180,8 @@ merge_files(struct got_worktree *worktree, struct got_
> arg.label_orig = label_orig;
> arg.commit_id2 = commit_id2;
> arg.allow_bad_symlinks = 1; /* preserve bad symlinks across merges */
> - err = got_diff_tree(tree1, tree2, "", "", repo, merge_file_cb, &arg, 1);
> + err = got_diff_tree(tree1, tree2, f1, f2, "", "", repo,
> + merge_file_cb, &arg, 1);
> sync_err = sync_fileindex(fileindex, fileindex_path);
> if (sync_err && err == NULL)
> err = sync_err;
> @@ -3178,6 +3194,10 @@ done:
> got_object_tree_close(tree1);
> if (tree2)
> got_object_tree_close(tree2);
> + if (f1 && fclose(f1) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> + if (f2 && fclose(f2) == EOF && err == NULL)
> + err = got_error_from_errno("fclose");
> free(label_orig);
> return err;
> }
> blob - a4221a9f756b84c1412ef1f4983cccd6aa233c2d
> blob + 2e5a6b392b55da86649c73d7f8efeabff5ff6cab
> --- tog/tog.c
> +++ tog/tog.c
> @@ -308,7 +308,7 @@ get_color_value(const char *envvar)
> struct tog_diff_view_state {
> struct got_object_id *id1, *id2;
> const char *label1, *label2;
> - FILE *f;
> + FILE *f, *f1, *f2;
> int first_displayed_line;
> int last_displayed_line;
> int eof;
> @@ -3144,7 +3144,7 @@ get_changed_paths(struct got_pathlist_head *paths,
> if (err)
> goto done;
>
> - err = got_diff_tree(tree1, tree2, "", "", repo,
> + err = got_diff_tree(tree1, tree2, NULL, NULL, "", "", repo,
> got_diff_tree_collect_changed_paths, paths, 0);
> done:
> if (tree1)
> @@ -3364,12 +3364,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, s->label1, s->label2, s->diff_context,
> - s->ignore_whitespace, s->force_text_diff, s->repo, s->f);
> + s->f1, s->f2, 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, NULL, "", "", s->diff_context,
> + s->f1, s->f2, s->id1, s->id2, NULL, "", "", s->diff_context,
> s->ignore_whitespace, s->force_text_diff, s->repo, s->f);
> break;
> case GOT_OBJ_TYPE_COMMIT: {
> @@ -3404,8 +3405,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, NULL, s->diff_context, s->ignore_whitespace,
> - s->force_text_diff, s->repo, s->f);
> + s->f1, s->f2, s->id1, s->id2, NULL, s->diff_context,
> + s->ignore_whitespace, s->force_text_diff, s->repo, s->f);
> break;
> }
> default:
> @@ -3502,6 +3503,32 @@ search_next_diff_view(struct tog_view *view)
> }
>
> static const struct got_error *
> +close_diff_view(struct tog_view *view)
> +{
> + const struct got_error *err = NULL;
> + struct tog_diff_view_state *s = &view->state.diff;
> +
> + free(s->id1);
> + s->id1 = NULL;
> + free(s->id2);
> + s->id2 = NULL;
> + if (s->f && fclose(s->f) == EOF)
> + err = got_error_from_errno("fclose");
> + s->f = NULL;
> + if (s->f1 && fclose(s->f1) == EOF)
> + err = got_error_from_errno("fclose");
> + s->f1 = NULL;
> + if (s->f2 && fclose(s->f2) == EOF)
> + err = got_error_from_errno("fclose");
> + s->f2 = NULL;
> + free_colors(&s->colors);
> + free(s->line_offsets);
> + s->line_offsets = NULL;
> + s->nlines = 0;
> + return err;
> +}
> +
> +static const struct got_error *
> open_diff_view(struct tog_view *view, struct got_object_id *id1,
> struct got_object_id *id2, const char *label1, const char *label2,
> int diff_context, int ignore_whitespace, int force_text_diff,
> @@ -3510,6 +3537,8 @@ open_diff_view(struct tog_view *view, struct got_objec
> const struct got_error *err;
> struct tog_diff_view_state *s = &view->state.diff;
>
> + memset(s, 0, sizeof(*s));
> +
> if (id1 != NULL && id2 != NULL) {
> int type1, type2;
> err = got_object_get_type(&type1, repo, id1);
> @@ -3535,16 +3564,26 @@ open_diff_view(struct tog_view *view, struct got_objec
> s->id1 = got_object_id_dup(id1);
> if (s->id1 == NULL)
> return got_error_from_errno("got_object_id_dup");
> + s->f1 = got_opentemp();
> + if (s->f1 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> } else
> s->id1 = NULL;
>
> s->id2 = got_object_id_dup(id2);
> if (s->id2 == NULL) {
> - free(s->id1);
> - s->id1 = NULL;
> - return got_error_from_errno("got_object_id_dup");
> + err = got_error_from_errno("got_object_id_dup");
> + goto done;
> }
> - s->f = NULL;
> +
> + s->f2 = got_opentemp();
> + if (s->f2 == NULL) {
> + err = got_error_from_errno("got_opentemp");
> + goto done;
> + }
> +
> s->first_displayed_line = 1;
> s->last_displayed_line = view->nlines;
> s->diff_context = diff_context;
> @@ -3559,89 +3598,52 @@ open_diff_view(struct tog_view *view, struct got_objec
> "^-", TOG_COLOR_DIFF_MINUS,
> get_color_value("TOG_COLOR_DIFF_MINUS"));
> if (err)
> - return err;
> + goto done;
> err = add_color(&s->colors, "^\\+",
> TOG_COLOR_DIFF_PLUS,
> get_color_value("TOG_COLOR_DIFF_PLUS"));
> - if (err) {
> - free_colors(&s->colors);
> - return err;
> - }
> + if (err)
> + goto done;
> err = add_color(&s->colors,
> "^@@", TOG_COLOR_DIFF_CHUNK_HEADER,
> get_color_value("TOG_COLOR_DIFF_CHUNK_HEADER"));
> - if (err) {
> - free_colors(&s->colors);
> - return err;
> - }
> + if (err)
> + goto done;
>
> err = add_color(&s->colors,
> "^(commit [0-9a-f]|parent [0-9]|(blob|file) [-+] |"
> "[MDmA] [^ ])", TOG_COLOR_DIFF_META,
> get_color_value("TOG_COLOR_DIFF_META"));
> - if (err) {
> - free_colors(&s->colors);
> - return err;
> - }
> + if (err)
> + goto done;
>
> err = add_color(&s->colors,
> "^(from|via): ", TOG_COLOR_AUTHOR,
> get_color_value("TOG_COLOR_AUTHOR"));
> - if (err) {
> - free_colors(&s->colors);
> - return err;
> - }
> + if (err)
> + goto done;
>
> err = add_color(&s->colors,
> "^date: ", TOG_COLOR_DATE,
> get_color_value("TOG_COLOR_DATE"));
> - if (err) {
> - free_colors(&s->colors);
> - return err;
> - }
> + if (err)
> + goto done;
> }
>
> if (log_view && view_is_splitscreen(view))
> show_log_view(log_view); /* draw vborder */
> diff_view_indicate_progress(view);
>
> - s->line_offsets = NULL;
> - s->nlines = 0;
> err = create_diff(s);
> - if (err) {
> - free(s->id1);
> - s->id1 = NULL;
> - free(s->id2);
> - s->id2 = NULL;
> - free_colors(&s->colors);
> - return err;
> - }
>
> view->show = show_diff_view;
> view->input = input_diff_view;
> view->close = close_diff_view;
> view->search_start = search_start_diff_view;
> view->search_next = search_next_diff_view;
> -
> - return NULL;
> -}
> -
> -static const struct got_error *
> -close_diff_view(struct tog_view *view)
> -{
> - const struct got_error *err = NULL;
> - struct tog_diff_view_state *s = &view->state.diff;
> -
> - free(s->id1);
> - s->id1 = NULL;
> - free(s->id2);
> - s->id2 = NULL;
> - if (s->f && fclose(s->f) == EOF)
> - err = got_error_from_errno("fclose");
> - free_colors(&s->colors);
> - free(s->line_offsets);
> - s->line_offsets = NULL;
> - s->nlines = 0;
> +done:
> + if (err)
> + close_diff_view(view);
> return err;
> }
>
>
--
Tracey Emery
move creation of tempfiles out of lib/diff.c