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