Commit Diff


commit - a5d43cac4cfa1a87141f03a15f8da1c09b856e74
commit + 9117a7b739232ec6280c90ef3366a0578a9a5b68
blob - 7b44ace527a04030b552586446d99d5a123db1e9
blob + 1dcf9111e8fdf66faee509a8e66280070c771349
--- got/got.c
+++ got/got.c
@@ -5359,12 +5359,13 @@ cmd_blame(int argc, char *argv[])
 	struct got_blob_object *blob = NULL;
 	char *commit_id_str = NULL;
 	struct blame_cb_args bca;
-	int ch, obj_type, i, fd = -1, fd1 = -1;
+	int ch, obj_type, i, fd1 = -1, fd2 = -1, fd3 = -1;
 	off_t filesize;
 	int *pack_fds = NULL;
+	FILE *f1 = NULL, *f2 = NULL;
 
-	fd = got_opentempfd();
-	if (fd == -1)
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
 		return got_error_from_errno("got_opentempfd");
 
 	memset(&bca, 0, sizeof(bca));
@@ -5517,7 +5518,7 @@ cmd_blame(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd);
+	error = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd1);
 	if (error)
 		goto done;
 	bca.f = got_opentemp();
@@ -5548,13 +5549,28 @@ cmd_blame(int argc, char *argv[])
 	}
 	bca.repo = repo;
 
-	fd1 = got_opentempfd();
-	if (fd1 == -1) {
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
 		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	fd3 = got_opentempfd();
+	if (fd3 == -1) {
+		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	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;
 	}
 	error = got_blame(link_target ? link_target : in_repo_path, commit_id,
-	    repo, blame_cb, &bca, check_cancelled, NULL, fd1);
+	    repo, blame_cb, &bca, check_cancelled, NULL, fd2, fd3, f1, f2);
 done:
 	free(in_repo_path);
 	free(link_target);
@@ -5564,10 +5580,18 @@ done:
 	free(obj_id);
 	if (commit)
 		got_object_commit_close(commit);
-	if (fd != -1 && close(fd) == -1 && error == NULL)
-		error = got_error_from_errno("close");
+
 	if (fd1 != -1 && close(fd1) == -1 && error == NULL)
 		error = got_error_from_errno("close");
+	if (fd2 != -1 && close(fd2) == -1 && error == NULL)
+		error = got_error_from_errno("close");
+	if (fd3 != -1 && close(fd3) == -1 && error == NULL)
+		error = got_error_from_errno("close");
+	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");
+
 	if (blob)
 		got_object_blob_close(blob);
 	if (worktree)
blob - 8f7c1c052c0b2cef36b1de075bd3e3a7481b706e
blob + d78a8e24af24a50a05a321bfbe66a8ffc0cbee5d
--- gotweb/gotweb.c
+++ gotweb/gotweb.c
@@ -4082,12 +4082,23 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
 	struct got_blob_object *blob = NULL;
 	char *path = NULL, *in_repo_path = NULL;
 	struct gw_blame_cb_args bca;
-	int i, obj_type, fd = -1, fd1 = -1;
+	int i, obj_type, fd1 = -1, fd2 = -1, fd3 = -1;
 	off_t filesize;
+	FILE *f1 = NULL, *f2 = NULL;
 
-	fd = got_opentempfd();
-	if (fd == -1)
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
 		return got_error_from_errno("got_opentempfd");
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+	fd3 = got_opentempfd();
+	if (fd3 == -1) {
+		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
 	memset(&bca, 0, sizeof(bca));
 
@@ -4132,7 +4143,7 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
 	}
 
 	error = got_object_open_as_blob(&blob, gw_trans->repo, obj_id, 8192,
-	    fd);
+	    fd1);
 	if (error)
 		goto done;
 
@@ -4167,22 +4178,39 @@ gw_output_file_blame(struct gw_trans *gw_trans, struct
 
 	fd1 = got_opentempfd();
 	if (fd1 == -1) {
+		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
+
+	f1 = got_opentemp();
+	if (f1 == NULL) {
 		error = got_error_from_errno("got_opentempfd");
 		goto done;
 	}
+	f2 = got_opentemp();
+	if (f2 == NULL) {
+		error = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
 	error = got_blame(in_repo_path, commit_id, gw_trans->repo, gw_blame_cb,
-	    &bca, NULL, NULL, fd1);
+	    &bca, NULL, NULL, fd2, fd3, f1, f2);
 done:
 	free(in_repo_path);
 	free(commit_id);
 	free(obj_id);
 	free(path);
 
-	if (fd != -1 && close(fd) == -1 && error == NULL)
-		error = got_error_from_errno("close");
 	if (fd1 != -1 && close(fd1) == -1 && error == NULL)
+		error = got_error_from_errno("close");
+	if (fd2 != -1 && close(fd2) == -1 && error == NULL)
+		error = got_error_from_errno("close");
+	if (fd3 != -1 && close(fd3) == -1 && error == NULL)
 		error = got_error_from_errno("close");
+	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");
 
 	if (blob) {
 		free(bca.line_offsets);
blob - 56e2d804dc17e77e5b5660bcd248453a942fcbb4
blob + 5d01c0034c2587d4dffbfd407a94631f1cfe7e7c
--- include/got_blame.h
+++ include/got_blame.h
@@ -36,4 +36,4 @@ typedef const struct got_error *(*got_blame_cb)(void *
  */
 const struct got_error *got_blame(const char *,
     struct got_object_id *, struct got_repository *,
-    got_blame_cb, void *, got_cancel_cb, void *, int);
+    got_blame_cb, void *, got_cancel_cb, void *, int, int, FILE *, FILE *);
blob - eb13ac75e0c336bec54b71046ba2a3d166afff3c
blob + c02f21892b132a039394e57b1553a9b1a8442a12
--- lib/blame.c
+++ lib/blame.c
@@ -64,6 +64,7 @@ struct got_blame {
 	 */
 	FILE *f1; /* older version from commit N-1. */
 	FILE *f2; /* newer version from commit N. */
+	int fd;
 	unsigned char *map1;
 	unsigned char *map2;
 	off_t size1;
@@ -203,7 +204,6 @@ blame_commit(struct got_blame *blame, struct got_objec
 	struct got_object_id *pblob_id = NULL;
 	struct got_blob_object *pblob = NULL;
 	struct diff_result *diff_result = NULL;
-	int fd = -1;
 
 	err = got_object_open_as_commit(&commit, repo, id);
 	if (err)
@@ -215,12 +215,6 @@ blame_commit(struct got_blame *blame, struct got_objec
 		return NULL;
 	}
 
-	fd = got_opentempfd();
-	if (fd == -1) {
-		err = got_error_from_errno("got_opentempfd");
-		goto done;
-	}
-
 	err = got_object_open_as_commit(&pcommit, repo, &pid->id);
 	if (err)
 		goto done;
@@ -232,16 +226,10 @@ blame_commit(struct got_blame *blame, struct got_objec
 		goto done;
 	}
 
-	err = got_object_open_as_blob(&pblob, repo, pblob_id, 8192, fd);
+	err = got_object_open_as_blob(&pblob, repo, pblob_id, 8192, blame->fd);
 	if (err)
 		goto done;
 
-	blame->f1 = got_opentemp();
-	if (blame->f1 == NULL) {
-		err = got_error_from_errno("got_opentemp");
-		goto done;
-	}
-
 	err = blame_prepare_file(blame->f1, &blame->map1, &blame->size1,
 	    &blame->nlines1, &blame->line_offsets1, blame->data1,
 	    blame->cfg, pblob);
@@ -279,8 +267,6 @@ done:
 	if (pcommit)
 		got_object_commit_close(pcommit);
 	free(pblob_id);
-	if (fd != -1 && close(fd) == -1 && err == NULL)
-		err = got_error_from_errno("close");
 	if (pblob)
 		got_object_blob_close(pblob);
 	return err;
@@ -303,10 +289,6 @@ blame_close(struct got_blame *blame)
 		if (munmap(blame->map2, blame->size2) == -1 && err == NULL)
 			err = got_error_from_errno("munmap");
 	}
-	if (blame->f1 && fclose(blame->f1) == EOF && err == NULL)
-		err = got_error_from_errno("fclose");
-	if (blame->f2 && fclose(blame->f2) == EOF && err == NULL)
-		err = got_error_from_errno("fclose");
 	free(blame->lines);
 	free(blame->line_offsets1);
 	free(blame->line_offsets2);
@@ -465,9 +447,11 @@ blame_atomize_file(void *arg, struct diff_data *d)
 }
 
 static const struct got_error *
-close_file2_and_reuse_file1(struct got_blame *blame)
+flip_files(struct got_blame *blame)
 {
+	const struct got_error *err = NULL;
 	struct diff_data *d;
+	FILE *tmp;
 
 	free(blame->line_offsets2);
 	blame->line_offsets2 = blame->line_offsets1;
@@ -482,15 +466,16 @@ close_file2_and_reuse_file1(struct got_blame *blame)
 			return got_error_from_errno("munmap");
 		blame->map2 = blame->map1;
 		blame->map1 = NULL;
-
 	}
 	blame->size2 = blame->size1;
-	blame->size1 = 0;
 
-	if (fclose(blame->f2) == EOF)
-		return got_error_from_errno("fclose");
+	err = got_opentemp_truncate(blame->f2);
+	if (err)
+		return err; 
+	tmp = blame->f2;
 	blame->f2 = blame->f1;
-	blame->f1 = NULL;
+	blame->f1 = tmp;
+	blame->size1 = 0;
 
 	blame->nlines2 = blame->nlines1;
 	blame->nlines1 = 0;
@@ -508,7 +493,7 @@ static const struct got_error *
 blame_open(struct got_blame **blamep, const char *path,
     struct got_object_id *start_commit_id, struct got_repository *repo,
     got_blame_cb cb, void *arg, got_cancel_cb cancel_cb, void *cancel_arg,
-    int fd)
+    int fd1, int fd2, FILE *f1, FILE *f2)
 {
 	const struct got_error *err = NULL;
 	struct got_commit_object *start_commit = NULL, *last_commit = NULL;
@@ -529,7 +514,7 @@ blame_open(struct got_blame **blamep, const char *path
 	if (err)
 		goto done;
 
-	err = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd);
+	err = got_object_open_as_blob(&blob, repo, obj_id, 8192, fd1);
 	if (err)
 		goto done;
 
@@ -550,11 +535,10 @@ blame_open(struct got_blame **blamep, const char *path
 		goto done;
 	}
 
-	blame->f2 = got_opentemp();
-	if (blame->f2 == NULL) {
-		err = got_error_from_errno("got_opentemp");
-		goto done;
-	}
+	blame->f1 = f1;
+	blame->f2 = f2;
+	blame->fd = fd2;
+
 	err = got_diff_get_config(&blame->cfg, GOT_DIFF_ALGORITHM_PATIENCE,
 	    blame_atomize_file, blame);
 	if (err)
@@ -618,7 +602,7 @@ blame_open(struct got_blame **blamep, const char *path
 			if (blame->nannotated == blame->nlines)
 				break;
 
-			err = close_file2_and_reuse_file1(blame);
+			err = flip_files(blame);
 			if (err)
 				goto done;
 		}
@@ -659,7 +643,8 @@ done:
 const struct got_error *
 got_blame(const char *path, struct got_object_id *commit_id,
     struct got_repository *repo, got_blame_cb cb, void *arg,
-    got_cancel_cb cancel_cb, void* cancel_arg, int fd)
+    got_cancel_cb cancel_cb, void* cancel_arg, int fd1, int fd2, FILE *f1,
+    FILE *f2)
 {
 	const struct got_error *err = NULL, *close_err = NULL;
 	struct got_blame *blame;
@@ -669,7 +654,7 @@ got_blame(const char *path, struct got_object_id *comm
 		return got_error_from_errno2("asprintf", path);
 
 	err = blame_open(&blame, abspath, commit_id, repo, cb, arg,
-	    cancel_cb, cancel_arg, fd);
+	    cancel_cb, cancel_arg, fd1, fd2, f1, f2);
 	free(abspath);
 	if (blame)
 		close_err = blame_close(blame);
blob - 8b04d0a40b8fa98b53f0bef334af77660f4ad741
blob + da849f2c7865ce55524ada6c7f156dc1f9a3f5cf
--- tog/tog.c
+++ tog/tog.c
@@ -4914,25 +4914,45 @@ blame_thread(void *arg)
 	const struct got_error *err, *close_err;
 	struct tog_blame_thread_args *ta = arg;
 	struct tog_blame_cb_args *a = ta->cb_args;
-	int errcode, fd = -1;
+	int errcode, fd1 = -1, fd2 = -1;
+	FILE *f1 = NULL, *f2 = NULL;
 
-	fd = got_opentempfd();
-	if (fd == -1)
+	fd1 = got_opentempfd();
+	if (fd1 == -1)
 		return (void *)got_error_from_errno("got_opentempfd");
+
+	fd2 = got_opentempfd();
+	if (fd2 == -1) {
+		err = got_error_from_errno("got_opentempfd");
+		goto done;
+	}
 
+	f1 = got_opentemp();
+	if (f1 == NULL) {
+		err = (void *)got_error_from_errno("got_opentemp");
+		goto done;
+	}
+	f2 = got_opentemp();
+	if (f2 == NULL) {
+		err = (void *)got_error_from_errno("got_opentemp");
+		goto done;
+	}
+
 	err = block_signals_used_by_main_thread();
 	if (err)
-		return (void *)err;
+		goto done;
 
 	err = got_blame(ta->path, a->commit_id, ta->repo,
-	    blame_cb, ta->cb_args, ta->cancel_cb, ta->cancel_arg, fd);
+	    blame_cb, ta->cb_args, ta->cancel_cb, ta->cancel_arg, fd1, fd2, f1,
+	    f2);
 	if (err && err->code == GOT_ERR_CANCELLED)
 		err = NULL;
 
 	errcode = pthread_mutex_lock(&tog_mutex);
-	if (errcode)
-		return (void *)got_error_set_errno(errcode,
-		    "pthread_mutex_lock");
+	if (errcode) {
+		err = got_error_set_errno(errcode, "pthread_mutex_lock");
+		goto done;
+	}
 
 	close_err = got_repo_close(ta->repo);
 	if (err == NULL)
@@ -4944,8 +4964,15 @@ blame_thread(void *arg)
 	if (errcode && err == NULL)
 		err = got_error_set_errno(errcode, "pthread_mutex_unlock");
 
-	if (fd != -1 && close(fd) == -1 && err == NULL)
+done:
+	if (fd1 != -1 && close(fd1) == -1 && err == NULL)
 		err = got_error_from_errno("close");
+	if (fd2 != -1 && close(fd2) == -1 && err == NULL)
+		err = got_error_from_errno("close");
+	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 (void *)err;
 }