Download raw body.
move creation of tempfiles out of lib/diff.c
This patch moves got_opentemp() calls from lib/diff.c into callers. ok? diff 83bd17334fecebef56255e68a393bcd22320124a 855f5e21bbf18bb3deec03872d80488d7e267eaa 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 - 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; }
move creation of tempfiles out of lib/diff.c