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

From:
Tracey Emery <tracey@traceyemery.net>
Subject:
Re: Move got_opentempfd out of got_repo_open
To:
Stefan Sperling <stsp@stsp.name>
Cc:
gameoftrees@openbsd.org
Date:
Mon, 13 Jun 2022 14:41:28 -0600

Download raw body.

Thread
On Sat, Jun 11, 2022 at 09:54:18PM +0200, Stefan Sperling wrote:
> On Tue, Jun 07, 2022 at 10:22:10AM -0600, Tracey Emery wrote:
> > +	for (i = 0; i < GOT_PACK_NUM_TEMPFILES; i++) {
> > +		pack_fds_tmp[i] = got_opentempfd();
> > +		if (pack_fds_tmp[i] == -1)
> > +			return got_error_from_errno("got_opentempfd");
> 
> If this fails during the loop then we leak files which
> were already opened in earlier loop iterations. This does
> not seem intentional since got_repo_pack_fds_close() cannot
> handle a partially initialized array, but assumes that every
> file descriptor is valid. We should probably close on error,
> and let got_repo_pack_fds_close() ignore fds which are initialized
> to -1 such that it can be called on a partial array of open fds.
>

See fixes for this in the diff below.

> > +	}
> > +	memcpy(*pack_fds, pack_fds_tmp, sizeof(pack_fds_tmp));
> > +	return err;
> > +}
> > +
> > +const struct got_error *
> > +got_repo_pack_fds_copy(int **pack_fds, struct got_repository *repo)
> > +{
> 
> I see this was added for tog. Can you explain why it is needed?
> 

Here, got_repo_open accepts a single array of fds to work with. This
function copies the opened fds from repo->packs into a single array for
run_blame, since we need to use our existing fds here, which are split
up between accumfd and basefd. This cannot be inlined, since we can't
work directly on the repo struct in tog or got.

Perhaps you can think of a better way to do this for tog? I'm open to
suggestions. :)

> > @@ -2370,9 +2372,16 @@ open_log_view(struct tog_view *view, struct got_object
> >  	view->search_start = search_start_log_view;
> >  	view->search_next = search_next_log_view;
> >  
> > -	err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL);
> > +	err = got_repo_pack_fds_open(&pack_fds);
> >  	if (err)
> >  		goto done;
> > +	err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL,
> > +	    pack_fds);
> > +	if (err)
> > +		goto done;
> > +	err = got_repo_pack_fds_close(pack_fds);
> > +	if (err)
> > +		goto done;
> 
> This looks very strange. Should the temp fds ever be closed before
> the repository instance which uses them is closed?
> 

Sorry, this is fixed in the new diff. It was an oversight.

> Something else I noticed while reviewing this patch is that some
> commands in got.c seem to forget about calling got_repo_close()
> on repositories they have opened... that needs to be fixed but
> can be done in a separate patch.
> 

-- 

Tracey Emery

diff 9f4f302a43f7e186910d59f9dbe0f839b6f2d565 1e1e2ca8cd14181c82d4d693f3842b106e2f681b
blob - d88f23ce5b63a9d80862b5fac05c212d054a0b74
blob + d1f9d2af6460b1ef39239ce66df3e219af7d5875
--- got/got.c
+++ got/got.c
@@ -715,6 +715,7 @@ cmd_import(int argc, char *argv[])
 	struct got_pathlist_head ignores;
 	struct got_pathlist_entry *pe;
 	int preserve_logmsg = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&ignores);
 
@@ -773,10 +774,12 @@ cmd_import(int argc, char *argv[])
 	error = get_gitconfig_path(&gitconfig_path);
 	if (error)
 		goto done;
-	error = got_repo_open(&repo, repo_path, gitconfig_path);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, repo_path, gitconfig_path, pack_fds);
 	if (error)
 		goto done;
-
 	error = get_author(&author, repo, NULL);
 	if (error)
 		return error;
@@ -900,6 +903,12 @@ cmd_import(int argc, char *argv[])
 	printf("Created branch %s with commit %s\n",
 	    got_ref_get_name(branch_ref), id_str);
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (preserve_logmsg) {
 		fprintf(stderr, "%s: log message preserved in %s\n",
 		    getprogname(), logmsg_path);
@@ -1484,6 +1493,7 @@ cmd_clone(int argc, char *argv[])
 	char *git_url = NULL;
 	int verbosity = 0, fetch_all_branches = 0, mirror_references = 0;
 	int list_refs_only = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&refs);
 	TAILQ_INIT(&symrefs);
@@ -1628,7 +1638,10 @@ cmd_clone(int argc, char *argv[])
 		error = got_repo_init(repo_path);
 		if (error)
 			goto done;
-		error = got_repo_open(&repo, repo_path, NULL);
+		error = got_repo_pack_fds_open(&pack_fds);
+		if (error != NULL)
+			goto done;
+		error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 		if (error)
 			goto done;
 	}
@@ -1806,6 +1819,12 @@ cmd_clone(int argc, char *argv[])
 		printf("Created %s repository '%s'\n",
 		    mirror_references ? "mirrored" : "cloned", repo_path);
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (fetchpid > 0) {
 		if (kill(fetchpid, SIGTERM) == -1)
 			error = got_error_from_errno("kill");
@@ -2212,6 +2231,7 @@ cmd_fetch(int argc, char *argv[])
 	struct got_fetch_progress_arg fpa;
 	int verbosity = 0, fetch_all_branches = 0, list_refs_only = 0;
 	int delete_refs = 0, replace_tags = 0, delete_remote = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&refs);
 	TAILQ_INIT(&symrefs);
@@ -2311,8 +2331,12 @@ cmd_fetch(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -2333,7 +2357,7 @@ cmd_fetch(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
 
@@ -2606,6 +2630,12 @@ cmd_fetch(int argc, char *argv[])
 		}
 	}
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (fetchpid > 0) {
 		if (kill(fetchpid, SIGTERM) == -1)
 			error = got_error_from_errno("kill");
@@ -2848,6 +2878,7 @@ cmd_checkout(int argc, char *argv[])
 	int ch, same_path_prefix, allow_nonempty = 0, verbosity = 0;
 	struct got_pathlist_head paths;
 	struct got_checkout_progress_arg cpa;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -2936,10 +2967,14 @@ cmd_checkout(int argc, char *argv[])
 	got_path_strip_trailing_slashes(repo_path);
 	got_path_strip_trailing_slashes(worktree_path);
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
 	if (error != NULL)
 		goto done;
 
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
+	if (error != NULL)
+		goto done;
+
 	/* Pre-create work tree path for unveil(2) */
 	error = got_path_mkdir(worktree_path);
 	if (error) {
@@ -2966,7 +3001,7 @@ cmd_checkout(int argc, char *argv[])
 	if (error != NULL && !(error->code == GOT_ERR_ERRNO && errno == EEXIST))
 		goto done;
 
-	error = got_worktree_open(&worktree, worktree_path);
+	error = got_worktree_open(&worktree, worktree_path, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -3052,6 +3087,12 @@ cmd_checkout(int argc, char *argv[])
 	if (cpa.had_base_commit_ref_error)
 		show_worktree_base_ref_warning();
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (head_ref)
 		got_ref_close(head_ref);
 	if (ref)
@@ -3281,9 +3322,14 @@ wrap_not_worktree_error(const struct got_error *orig_e
 	const struct got_error *err;
 	struct got_repository *repo;
 	static char msg[512];
+	int *pack_fds = NULL;
 
-	err = got_repo_open(&repo, path, NULL);
+	err = got_repo_pack_fds_open(&pack_fds);
 	if (err)
+		return err;
+
+	err = got_repo_open(&repo, path, NULL, pack_fds);
+	if (err)
 		return orig_err;
 
 	snprintf(msg, sizeof(msg),
@@ -3293,6 +3339,12 @@ wrap_not_worktree_error(const struct got_error *orig_e
 	    "The got(1) manual page contains more information.", cmdname);
 	err = got_error_msg(GOT_ERR_NOT_WORKTREE, msg);
 	got_repo_close(repo);
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (err == NULL)
+			err = pack_err;
+	}
 	return err;
 }
 
@@ -3311,6 +3363,7 @@ cmd_update(int argc, char *argv[])
 	struct got_pathlist_entry *pe;
 	int ch, verbosity = 0;
 	struct got_update_progress_arg upa;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -3346,7 +3399,12 @@ cmd_update(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, worktree_path);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, worktree_path, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "update",
@@ -3359,7 +3417,7 @@ cmd_update(int argc, char *argv[])
 		goto done;
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -3463,8 +3521,15 @@ cmd_update(int argc, char *argv[])
 		    got_worktree_get_head_ref_name(worktree), commit_id_str);
 	} else
 		printf("Already up-to-date\n");
+
 	print_update_progress_stats(&upa);
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	free(worktree_path);
 	TAILQ_FOREACH(pe, &paths, entry)
 		free((char *)pe->path);
@@ -4120,6 +4185,7 @@ cmd_log(int argc, char *argv[])
 	const char *errstr;
 	struct got_reflist_head refs;
 	struct got_reflist_object_id_map *refs_idmap = NULL;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&refs);
 
@@ -4195,8 +4261,12 @@ cmd_log(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		error = NULL;
@@ -4227,7 +4297,7 @@ cmd_log(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -4309,6 +4379,12 @@ cmd_log(int argc, char *argv[])
 	    show_changed_paths, show_patch, search_pattern, diff_context,
 	    limit, log_branches, reverse_display_order, refs_idmap);
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	free(path);
 	free(repo_path);
 	free(cwd);
@@ -4579,6 +4655,7 @@ cmd_diff(int argc, char *argv[])
 	struct got_pathlist_head paths;
 	struct got_pathlist_entry *pe;
 	FILE *f1 = NULL, *f2 = NULL;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&refs);
 	TAILQ_INIT(&paths);
@@ -4638,8 +4715,12 @@ cmd_diff(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -4660,7 +4741,7 @@ cmd_diff(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	free(repo_path);
 	if (error != NULL)
 		goto done;
@@ -4915,6 +4996,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	TAILQ_FOREACH(pe, &paths, entry)
 		free((char *)pe->path);
 	got_pathlist_free(&paths);
@@ -5061,6 +5148,7 @@ cmd_blame(int argc, char *argv[])
 	struct blame_cb_args bca;
 	int ch, obj_type, i;
 	off_t filesize;
+	int *pack_fds = NULL;
 
 	memset(&bca, 0, sizeof(bca));
 
@@ -5101,8 +5189,13 @@ cmd_blame(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -5124,7 +5217,7 @@ cmd_blame(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -5258,6 +5351,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (bca.lines) {
 		for (i = 0; i < bca.nlines; i++) {
 			struct blame_line *bline = &bca.lines[i];
@@ -5402,6 +5501,7 @@ cmd_tree(int argc, char *argv[])
 	char *commit_id_str = NULL;
 	int show_ids = 0, recurse = 0;
 	int ch;
+	int *pack_fds = NULL;
 
 #ifndef PROFILE
 	if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
@@ -5448,8 +5548,13 @@ cmd_tree(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -5470,7 +5575,7 @@ cmd_tree(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -5558,6 +5663,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -5624,6 +5735,7 @@ cmd_status(int argc, char *argv[])
 	struct got_pathlist_head paths;
 	struct got_pathlist_entry *pe;
 	int ch, i, no_ignores = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -5683,7 +5795,11 @@ cmd_status(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "status", cwd);
@@ -5691,7 +5807,7 @@ cmd_status(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -5707,6 +5823,13 @@ cmd_status(int argc, char *argv[])
 	error = got_worktree_status(worktree, &paths, repo, no_ignores,
 	    print_status, &st, check_cancelled, NULL);
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
+
 	TAILQ_FOREACH(pe, &paths, entry)
 		free((char *)pe->path);
 	got_pathlist_free(&paths);
@@ -5848,6 +5971,7 @@ cmd_ref(int argc, char *argv[])
 	int ch, do_list = 0, do_delete = 0, sort_by_time = 0;
 	const char *obj_arg = NULL, *symref_target= NULL;
 	char *refname = NULL;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "c:dr:ls:t")) != -1) {
 		switch (ch) {
@@ -5931,8 +6055,12 @@ cmd_ref(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -5953,7 +6081,7 @@ cmd_ref(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -5989,6 +6117,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
@@ -6238,6 +6372,7 @@ cmd_branch(int argc, char *argv[])
 	struct got_pathlist_entry *pe;
 	struct got_object_id *commit_id = NULL;
 	char *commit_id_str = NULL;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -6302,8 +6437,12 @@ cmd_branch(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -6324,7 +6463,7 @@ cmd_branch(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -6417,6 +6556,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
@@ -6796,6 +6941,7 @@ cmd_tag(int argc, char *argv[])
 	char *gitconfig_path = NULL, *tagger = NULL;
 	const char *tag_name, *commit_id_arg = NULL, *tagmsg = NULL;
 	int ch, do_list = 0;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "c:m:r:l")) != -1) {
 		switch (ch) {
@@ -6848,8 +6994,12 @@ cmd_tag(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -6876,9 +7026,10 @@ cmd_tag(int argc, char *argv[])
 			got_worktree_close(worktree);
 			worktree = NULL;
 		}
-		error = got_repo_open(&repo, repo_path, NULL);
+		error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 		if (error != NULL)
 			goto done;
+
 #ifndef PROFILE
 		/* Remove "cpath" promise. */
 		if (pledge("stdio rpath wpath flock proc exec sendfd unveil",
@@ -6893,7 +7044,8 @@ cmd_tag(int argc, char *argv[])
 		error = get_gitconfig_path(&gitconfig_path);
 		if (error)
 			goto done;
-		error = got_repo_open(&repo, repo_path, gitconfig_path);
+		error = got_repo_open(&repo, repo_path, gitconfig_path,
+		    pack_fds);
 		if (error != NULL)
 			goto done;
 
@@ -6939,6 +7091,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
@@ -6976,6 +7134,7 @@ cmd_add(int argc, char *argv[])
 	struct got_pathlist_head paths;
 	struct got_pathlist_entry *pe;
 	int ch, can_recurse = 0, no_ignores = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -7010,7 +7169,11 @@ cmd_add(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "add", cwd);
@@ -7018,7 +7181,7 @@ cmd_add(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -7068,6 +7231,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	TAILQ_FOREACH(pe, &paths, entry)
@@ -7111,6 +7280,7 @@ cmd_remove(int argc, char *argv[])
 	struct got_pathlist_entry *pe;
 	int ch, delete_local_mods = 0, can_recurse = 0, keep_on_disk = 0, i;
 	int ignore_missing_paths = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -7164,7 +7334,12 @@ cmd_remove(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "remove", cwd);
@@ -7172,7 +7347,7 @@ cmd_remove(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error)
 		goto done;
 
@@ -7223,6 +7398,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	TAILQ_FOREACH(pe, &paths, entry)
@@ -7327,6 +7508,7 @@ cmd_patch(int argc, char *argv[])
 	char *cwd = NULL;
 	int ch, nop = 0, strip = -1, reverse = 0;
 	int patchfd;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "np:R")) != -1) {
 		switch (ch) {
@@ -7369,12 +7551,16 @@ cmd_patch(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
 	if (error != NULL)
 		goto done;
 
+	error = got_worktree_open(&worktree, cwd, pack_fds);
+	if (error != NULL)
+		goto done;
+
 	const char *repo_path = got_worktree_get_repo_path(worktree);
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -7398,6 +7584,12 @@ done:
 		if (error == NULL)
 			error = close_error;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree != NULL) {
 		close_error = got_worktree_close(worktree);
 		if (error == NULL)
@@ -7552,6 +7744,7 @@ cmd_revert(int argc, char *argv[])
 	FILE *patch_script_file = NULL;
 	const char *patch_script_path = NULL;
 	struct choose_patch_arg cpa;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -7590,7 +7783,12 @@ cmd_revert(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "revert", cwd);
@@ -7598,7 +7796,7 @@ cmd_revert(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -7661,6 +7859,13 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
+
 	if (worktree)
 		got_worktree_close(worktree);
 	free(path);
@@ -7836,6 +8041,7 @@ cmd_commit(int argc, char *argv[])
 	int ch, rebase_in_progress, histedit_in_progress, preserve_logmsg = 0;
 	int allow_bad_symlinks = 0, non_interactive = 0, merge_in_progress = 0;
 	struct got_pathlist_head paths;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 	cl_arg.logmsg_path = NULL;
@@ -7880,7 +8086,12 @@ cmd_commit(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "commit", cwd);
@@ -7904,7 +8115,7 @@ cmd_commit(int argc, char *argv[])
 	if (error)
 		goto done;
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    gitconfig_path);
+	    gitconfig_path, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -7977,6 +8188,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
@@ -8215,6 +8432,7 @@ cmd_send(int argc, char *argv[])
 	int verbosity = 0, overwrite_refs = 0;
 	int send_all_branches = 0, send_all_tags = 0;
 	struct got_reference *ref = NULL;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&branches);
 	TAILQ_INIT(&tags);
@@ -8294,8 +8512,12 @@ cmd_send(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		else
@@ -8316,7 +8538,7 @@ cmd_send(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
 
@@ -8520,6 +8742,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	if (ref)
@@ -8561,6 +8789,7 @@ cmd_cherrypick(int argc, char *argv[])
 	struct got_object_qid *pid;
 	int ch;
 	struct got_update_progress_arg upa;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -8586,7 +8815,12 @@ cmd_cherrypick(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "cherrypick",
@@ -8595,7 +8829,7 @@ cmd_cherrypick(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -8637,6 +8871,13 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
+
 	return error;
 }
 
@@ -8659,6 +8900,7 @@ cmd_backout(int argc, char *argv[])
 	struct got_object_qid *pid;
 	int ch;
 	struct got_update_progress_arg upa;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -8684,7 +8926,12 @@ cmd_backout(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "backout", cwd);
@@ -8692,7 +8939,7 @@ cmd_backout(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -8738,6 +8985,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -9322,6 +9575,7 @@ cmd_rebase(int argc, char *argv[])
 	const struct got_object_id_queue *parent_ids;
 	struct got_object_qid *qid, *pid;
 	struct got_update_progress_arg upa;
+	int *pack_fds = NULL;
 
 	STAILQ_INIT(&commits);
 	TAILQ_INIT(&merged_paths);
@@ -9388,7 +9642,12 @@ cmd_rebase(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (list_backups || delete_backups) {
 			if (error->code != GOT_ERR_NOT_WORKTREE)
@@ -9402,7 +9661,8 @@ cmd_rebase(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo,
-	    worktree ? got_worktree_get_repo_path(worktree) : cwd, NULL);
+	    worktree ? got_worktree_get_repo_path(worktree) : cwd, NULL,
+	    pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -9687,6 +9947,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -10541,6 +10807,7 @@ cmd_histedit(int argc, char *argv[])
 	struct got_object_qid *pid;
 	struct got_histedit_list histedit_cmds;
 	struct got_histedit_list_entry *hle;
+	int *pack_fds = NULL;
 
 	STAILQ_INIT(&commits);
 	TAILQ_INIT(&histedit_cmds);
@@ -10662,7 +10929,12 @@ cmd_histedit(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	error = got_worktree_open(&worktree, cwd);
+
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (list_backups || delete_backups) {
 			if (error->code != GOT_ERR_NOT_WORKTREE)
@@ -10678,7 +10950,7 @@ cmd_histedit(int argc, char *argv[])
 	if (list_backups || delete_backups) {
 		error = got_repo_open(&repo,
 		    worktree ? got_worktree_get_repo_path(worktree) : cwd,
-		    NULL);
+		    NULL, pack_fds);
 		if (error != NULL)
 			goto done;
 		error = apply_unveil(got_repo_get_path(repo), 0,
@@ -10692,7 +10964,7 @@ cmd_histedit(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -11062,6 +11334,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -11085,6 +11363,7 @@ cmd_integrate(int argc, char *argv[])
 	struct got_object_id *commit_id = NULL, *base_commit_id = NULL;
 	int ch;
 	struct got_update_progress_arg upa;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -11111,7 +11390,11 @@ cmd_integrate(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "integrate",
@@ -11124,7 +11407,7 @@ cmd_integrate(int argc, char *argv[])
 		goto done;
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -11202,6 +11485,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
@@ -11236,6 +11525,7 @@ cmd_merge(int argc, char *argv[])
 	struct got_update_progress_arg upa;
 	struct got_object_id *merge_commit_id = NULL;
 	char *branch_name = NULL;
+	int *pack_fds = NULL;
 
 	memset(&upa, 0, sizeof(upa));
 
@@ -11279,7 +11569,11 @@ cmd_merge(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error,
@@ -11288,7 +11582,8 @@ cmd_merge(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo,
-	    worktree ? got_worktree_get_repo_path(worktree) : cwd, NULL);
+	    worktree ? got_worktree_get_repo_path(worktree) : cwd, NULL,
+	    pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -11474,6 +11769,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -11526,6 +11827,7 @@ cmd_stage(int argc, char *argv[])
 	FILE *patch_script_file = NULL;
 	const char *patch_script_path = NULL;
 	struct choose_patch_arg cpa;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -11568,7 +11870,11 @@ cmd_stage(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "stage", cwd);
@@ -11576,7 +11882,7 @@ cmd_stage(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -11621,6 +11927,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	TAILQ_FOREACH(pe, &paths, entry)
@@ -11654,6 +11966,7 @@ cmd_unstage(int argc, char *argv[])
 	FILE *patch_script_file = NULL;
 	const char *patch_script_path = NULL;
 	struct choose_patch_arg cpa;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -11688,7 +12001,11 @@ cmd_unstage(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "unstage", cwd);
@@ -11696,7 +12013,7 @@ cmd_unstage(int argc, char *argv[])
 	}
 
 	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree),
-	    NULL);
+	    NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -11734,6 +12051,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	TAILQ_FOREACH(pe, &paths, entry)
@@ -11938,6 +12261,7 @@ cmd_cat(int argc, char *argv[])
 	struct got_commit_object *commit = NULL;
 	int ch, obj_type, i, force_path = 0;
 	struct got_reflist_head refs;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&refs);
 
@@ -11977,8 +12301,12 @@ cmd_cat(int argc, char *argv[])
 		goto done;
 	}
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree) {
@@ -12001,7 +12329,7 @@ cmd_cat(int argc, char *argv[])
 			return got_error_from_errno("strdup");
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	free(repo_path);
 	if (error != NULL)
 		goto done;
@@ -12087,6 +12415,13 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
+
 	got_ref_list_free(&refs);
 	return error;
 }
@@ -12177,6 +12512,7 @@ cmd_info(int argc, char *argv[])
 	struct got_pathlist_entry *pe;
 	char *uuidstr = NULL;
 	int ch, show_files = 0;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&paths);
 
@@ -12202,7 +12538,11 @@ cmd_info(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error) {
 		if (error->code == GOT_ERR_NOT_WORKTREE)
 			error = wrap_not_worktree_error(error, "info", cwd);
@@ -12269,6 +12609,12 @@ cmd_info(int argc, char *argv[])
 		}
 	}
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	TAILQ_FOREACH(pe, &paths, entry)
 		free((char *)pe->path);
 	got_pathlist_free(&paths);
blob - 59c11d1ab01684d8a2f16d934fb1d6870d7ac871
blob + 94aa122da416f31dd52c4f9839a25313a0da9cc2
--- gotadmin/gotadmin.c
+++ gotadmin/gotadmin.c
@@ -238,6 +238,7 @@ get_repo_path(char **repo_path)
 	const struct got_error *err = NULL;
 	struct got_worktree *worktree = NULL;
 	char *cwd;
+	int *pack_fds = NULL;
 
 	*repo_path = NULL;
 
@@ -245,7 +246,11 @@ get_repo_path(char **repo_path)
 	if (cwd == NULL)
 		return got_error_from_errno("getcwd");
 
-	err = got_worktree_open(&worktree, cwd);
+	err = got_repo_pack_fds_open(&pack_fds);
+	if (err != NULL)
+		goto done;
+
+	err = got_worktree_open(&worktree, cwd, pack_fds);
 	if (err) {
 		if (err->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
@@ -262,6 +267,7 @@ done:
 	if (worktree)
 		got_worktree_close(worktree);
 	free(cwd);
+	err = got_repo_pack_fds_close(pack_fds);
 	return err;
 }
 
@@ -275,6 +281,7 @@ cmd_info(int argc, char *argv[])
 	int ch, npackfiles, npackedobj, nobj;
 	off_t packsize, loose_size;
 	char scaled[FMT_SCALED_STRSIZE];
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "r:")) != -1) {
 		switch (ch) {
@@ -304,7 +311,10 @@ cmd_info(int argc, char *argv[])
 		if (error)
 			goto done;
 	}
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
 #ifndef PROFILE
@@ -371,6 +381,7 @@ cmd_info(int argc, char *argv[])
 done:
 	if (repo)
 		got_repo_close(repo);
+	error = got_repo_pack_fds_close(pack_fds);
 	free(repo_path);
 	return error;
 }
@@ -629,6 +640,7 @@ cmd_pack(int argc, char *argv[])
 	struct got_reflist_head exclude_refs;
 	struct got_reflist_head include_refs;
 	struct got_reflist_entry *re, *new;
+	int *pack_fds = NULL;
 
 	TAILQ_INIT(&exclude_args);
 	TAILQ_INIT(&exclude_refs);
@@ -675,7 +687,10 @@ cmd_pack(int argc, char *argv[])
 		if (error)
 			goto done;
 	}
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
 
@@ -731,6 +746,9 @@ cmd_pack(int argc, char *argv[])
 			printf("\n");
 		goto done;
 	}
+	error = got_repo_pack_fds_close(pack_fds);
+	if (error)
+		goto done;
 
 	error = got_object_id_str(&id_str, pack_hash);
 	if (error)
@@ -775,6 +793,7 @@ cmd_indexpack(int argc, char *argv[])
 	char *id_str = NULL;
 	struct got_pack_progress_arg ppa;
 	FILE *packfile = NULL;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "")) != -1) {
 		switch (ch) {
@@ -800,9 +819,15 @@ cmd_indexpack(int argc, char *argv[])
 		err(1, "pledge");
 #endif
 
-	error = got_repo_open(&repo, packfile_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, packfile_path, NULL, pack_fds);
 	if (error)
 		goto done;
+	error = got_repo_pack_fds_close(pack_fds);
+	if (error)
+		goto done;
 
 	error = apply_unveil(got_repo_get_path_git_dir(repo), 0);
 	if (error)
@@ -943,6 +968,7 @@ cmd_listpack(int argc, char *argv[])
 	struct gotadmin_list_pack_cb_args lpa;
 	FILE *packfile = NULL;
 	int show_stats = 0, human_readable = 0;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "hs")) != -1) {
 		switch (ch) {
@@ -972,9 +998,15 @@ cmd_listpack(int argc, char *argv[])
 	    NULL) == -1)
 		err(1, "pledge");
 #endif
-	error = got_repo_open(&repo, packfile_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, packfile_path, NULL, pack_fds);
 	if (error)
 		goto done;
+	error = got_repo_pack_fds_close(pack_fds);
+	if (error)
+		goto done;
 #ifndef PROFILE
 	/* Remove "cpath" promise. */
 	if (pledge("stdio rpath wpath flock proc exec sendfd unveil",
@@ -1120,6 +1152,7 @@ cmd_cleanup(int argc, char *argv[])
 	char scaled_diff[FMT_SCALED_STRSIZE];
 	char **extensions;
 	int nextensions, i;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "apr:nq")) != -1) {
 		switch (ch) {
@@ -1161,9 +1194,15 @@ cmd_cleanup(int argc, char *argv[])
 		if (error)
 			goto done;
 	}
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
+	error = got_repo_pack_fds_close(pack_fds);
+	if (error)
+		goto done;
 
 	error = apply_unveil(got_repo_get_path_git_dir(repo), 0);
 	if (error)
blob - 613976ee0e8a3f55e862ceb0aa730fd85f3e46e3
blob + 156fdc229cc2ed2c606d5aded919cc4fa7adeaad
--- gotweb/gotweb.c
+++ gotweb/gotweb.c
@@ -568,7 +568,7 @@ gw_index(struct gw_trans *gw_trans)
 	enum kcgi_err kerr = KCGI_OK;
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil",
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
 	    NULL) == -1) {
 		error = got_error_from_errno("pledge");
 		return error;
@@ -972,7 +972,7 @@ gw_commits(struct gw_trans *gw_trans)
 		return got_error_from_errno("malloc");
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil",
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
 	    NULL) == -1) {
 		error = got_error_from_errno("pledge");
 		goto done;
@@ -1199,7 +1199,7 @@ gw_briefs(struct gw_trans *gw_trans)
 		return got_error_from_errno("malloc");
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil",
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
 	    NULL) == -1) {
 		error = got_error_from_errno("pledge");
 		goto done;
@@ -1459,7 +1459,8 @@ gw_summary(struct gw_trans *gw_trans)
 	enum kcgi_err kerr = KCGI_OK;
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
+	    NULL) == -1)
 		return got_error_from_errno("pledge");
 #endif
 	error = gw_apply_unveil(gw_trans->gw_dir->path);
@@ -1622,7 +1623,8 @@ gw_tree(struct gw_trans *gw_trans)
 	enum kcgi_err kerr = KCGI_OK;
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
+	    NULL) == -1)
 		return got_error_from_errno("pledge");
 #endif
 	if ((header = gw_init_header()) == NULL)
@@ -1697,7 +1699,8 @@ gw_tags(struct gw_trans *gw_trans)
 	enum kcgi_err kerr = KCGI_OK;
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
+	    NULL) == -1)
 		return got_error_from_errno("pledge");
 #endif
 	if ((header = gw_init_header()) == NULL)
@@ -1813,7 +1816,7 @@ gw_tag(struct gw_trans *gw_trans)
 	enum kcgi_err kerr = KCGI_OK;
 
 #ifndef PROFILE
-	if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
+	if (pledge("stdio rpath wpath cpath proc exec sendfd unveil", NULL) == -1)
 		return got_error_from_errno("pledge");
 #endif
 	if ((header = gw_init_header()) == NULL)
@@ -2784,6 +2787,7 @@ gw_get_repo_age(char **repo_age, struct gw_trans *gw_t
 	struct got_reflist_head refs;
 	struct got_reflist_entry *re;
 	time_t committer_time = 0, cmp_time = 0;
+	int *pack_fds = NULL;
 
 	*repo_age = NULL;
 	TAILQ_INIT(&refs);
@@ -2794,7 +2798,10 @@ gw_get_repo_age(char **repo_age, struct gw_trans *gw_t
 	if (gw_trans->repo)
 		repo = gw_trans->repo;
 	else {
-		error = got_repo_open(&repo, dir, NULL);
+		error = got_repo_pack_fds_open(&pack_fds);
+		if (error != NULL)
+			goto done;
+		error = got_repo_open(&repo, dir, NULL, pack_fds);
 		if (error)
 			return error;
 	}
@@ -2844,6 +2851,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -2955,15 +2968,20 @@ gw_get_repo_owner(char **owner, struct gw_trans *gw_tr
 	const struct got_error *error = NULL, *close_err;
 	struct got_repository *repo;
 	const char *gitconfig_owner;
+	int *pack_fds = NULL;
 
 	*owner = NULL;
 
 	if (gw_trans->gw_conf->got_show_repo_owner == 0)
 		return NULL;
 
-	error = got_repo_open(&repo, dir, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		return error;
+	error = got_repo_open(&repo, dir, NULL, pack_fds);
 	if (error)
 		return error;
+
 	gitconfig_owner = got_repo_get_gitconfig_owner(repo);
 	if (gitconfig_owner) {
 		*owner = strdup(gitconfig_owner);
@@ -2973,6 +2991,12 @@ gw_get_repo_owner(char **owner, struct gw_trans *gw_tr
 	close_err = got_repo_close(repo);
 	if (error == NULL)
 		error = close_err;
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	return error;
 }
 
@@ -3772,8 +3796,13 @@ gw_get_header(struct gw_trans *gw_trans, struct gw_hea
 	char *in_repo_path = NULL;
 	struct got_object_id *id = NULL;
 	struct got_reference *ref;
+	int *pack_fds = NULL;
 
-	error = got_repo_open(&gw_trans->repo, gw_trans->repo_path, NULL);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+	error = got_repo_open(&gw_trans->repo, gw_trans->repo_path, NULL,
+	    pack_fds);
 	if (error)
 		return error;
 
@@ -3855,7 +3884,12 @@ gw_get_header(struct gw_trans *gw_trans, struct gw_hea
 
 	error = gw_get_commits(gw_trans, header, limit, id);
 done:
-	got_ref_list_free(&header->refs);
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	free(id);
 	free(in_repo_path);
 	return error;
@@ -4847,17 +4881,17 @@ main(int argc, char *argv[])
 	if (error)
 		goto done;
 
-	if (gw_trans->action == GW_BLOB)
-		error = gw_blob(gw_trans);
-	else
-		error = gw_display_index(gw_trans);
-done:
 	if (gw_trans->repo) {
 		const struct got_error *close_err;
 		close_err = got_repo_close(gw_trans->repo);
 		if (error == NULL)
 			error = close_err;
 	}
+	if (gw_trans->action == GW_BLOB)
+		error = gw_blob(gw_trans);
+	else
+		error = gw_display_index(gw_trans);
+done:
 	if (error) {
 		gw_trans->error = error;
 		gw_trans->action = GW_ERR;
blob - b6e44e8b40b8476a471c53fd10cffd4a7ff3b32d
blob + c6c3ae86c927f406085a265e15638706ec7fed6f
--- include/got_repository.h
+++ include/got_repository.h
@@ -20,7 +20,7 @@ struct got_tag_object;
 
 /* Open and close repositories. */
 const struct got_error *got_repo_open(struct got_repository**, const char *,
-    const char *);
+    const char *, int *);
 const struct got_error *got_repo_close(struct got_repository*);
 
 /* Obtain the on-disk path to the repository. */
@@ -177,3 +177,12 @@ const struct got_error *got_repo_get_loose_object_info
 /* Obtain the number and size of packed objects in the repository. */
 const struct got_error *got_repo_get_packfile_info(int *npackfiles,
     int *nobjects, off_t *total_packsize, struct got_repository *);
+
+/* Create an array of file descriptors to hand over to got_repo_open for pack */
+const struct got_error *got_repo_pack_fds_open(int **);
+
+/* Copy our pack file descriptors */
+const struct got_error *got_repo_pack_fds_copy(int **, struct got_repository *);
+
+/* Close the array of file descriptors handed over to got_repo_open for pack */
+const struct got_error *got_repo_pack_fds_close(int *);
blob - 610e03aa8788afbfcdcdc782c96c1c1965707674
blob + e193a6a07c0f85bab692aa00733a0b15e305e345
--- include/got_worktree.h
+++ include/got_worktree.h
@@ -54,7 +54,8 @@ const struct got_error *got_worktree_init(const char *
  * Attempt to open a worktree at or above the specified path.
  * The caller must dispose of it with got_worktree_close().
  */
-const struct got_error *got_worktree_open(struct got_worktree **, const char *);
+const struct got_error *got_worktree_open(struct got_worktree **, const char *,
+    int *);
 
 /* Dispose of an open work tree. */
 const struct got_error *got_worktree_close(struct got_worktree *);
blob - a35884552cf66d678f0db623e1dd92d976a7014e
blob + 414cf45f495487020f948b4b0c3e6a45ef730da9
--- lib/got_lib_worktree.h
+++ lib/got_lib_worktree.h
@@ -22,6 +22,7 @@ struct got_worktree {
 	struct got_object_id *base_commit_id;
 	char *head_ref_name;
 	uuid_t uuid;
+	int *pack_fds;
 
 	/*
 	 * File descriptor for the lock file, open while a work tree is open.
blob - fff58b083aa8eadb970ebd09ce593455d223fcc9
blob + c148b0c64ac4412a9bfc2da3e193337b4cc91238
--- lib/pack_create.c
+++ lib/pack_create.c
@@ -1520,21 +1520,13 @@ load_packed_tree_ids(void *arg, struct got_tree_object
 	if (tree == NULL) {
 		free(a->id);
 		a->id = got_object_id_dup(id);
-		if (a->id == NULL) {
-			err = got_error_from_errno("got_object_id_dup");
-			free(a->dpath);
-			a->dpath = NULL;
-			return err;
-		}
+		if (a->id == NULL)
+			return got_error_from_errno("got_object_id_dup");
 
 		free(a->dpath);
 		a->dpath = strdup(dpath);
-		if (a->dpath == NULL) {
-			err = got_error_from_errno("strdup");
-			free(a->id);
-			a->id = NULL;
-			return err;
-		}
+		if (a->dpath == NULL)
+			return got_error_from_errno("strdup");
 
 		a->mtime = mtime;
 		return NULL;
blob - 5be66db732b6a51d032ae835a233ef3cbcd3733b
blob + c44b00d3ffbd22e50b9baecf400fa49228fd37bf
--- lib/repository.c
+++ lib/repository.c
@@ -68,6 +68,8 @@
 #define nitems(_a) (sizeof(_a) / sizeof((_a)[0]))
 #endif
 
+#define GOT_PACK_NUM_TEMPFILES		GOT_PACK_CACHE_SIZE * 2
+
 RB_PROTOTYPE(got_packidx_bloom_filter_tree, got_packidx_bloom_filter, entry,
     got_packidx_bloom_filter_cmp);
 
@@ -247,6 +249,70 @@ done:
 }
 
 const struct got_error *
+got_repo_pack_fds_open(int **pack_fds)
+{
+	const struct got_error *err = NULL;
+	int i, pack_fds_tmp[GOT_PACK_NUM_TEMPFILES];
+
+	*pack_fds = calloc(GOT_PACK_NUM_TEMPFILES, sizeof(**pack_fds));
+	if (*pack_fds == NULL)
+		return got_error_from_errno("calloc");
+
+	for (i = 0; i < GOT_PACK_NUM_TEMPFILES; i++) {
+		pack_fds_tmp[i] = got_opentempfd();
+		if (pack_fds_tmp[i] == -1) {
+			err = got_repo_pack_fds_close(pack_fds_tmp);
+			if (err)
+				return err;
+			else
+				return got_error_from_errno("got_opentempfd");
+		}
+	}
+	memcpy(*pack_fds, pack_fds_tmp, sizeof(pack_fds_tmp));
+	return err;
+}
+
+const struct got_error *
+got_repo_pack_fds_copy(int **pack_fds, struct got_repository *repo)
+{
+	const struct got_error *err = NULL;
+	int i, pack_fds_tmp[GOT_PACK_NUM_TEMPFILES];
+
+	*pack_fds = calloc(GOT_PACK_NUM_TEMPFILES, sizeof(**pack_fds));
+	if (*pack_fds == NULL)
+		return got_error_from_errno("calloc");
+
+	for (i = 0; i < GOT_PACK_NUM_TEMPFILES / 2; i++)
+		pack_fds_tmp[i] = repo->packs[i].accumfd;
+
+	for (i = GOT_PACK_NUM_TEMPFILES / 2; i < GOT_PACK_NUM_TEMPFILES; i++)
+		pack_fds_tmp[i] = repo->packs[i -
+		    (GOT_PACK_NUM_TEMPFILES / 2)].basefd;
+
+	memcpy(*pack_fds, pack_fds_tmp, sizeof(pack_fds_tmp));
+	return err;
+}
+
+const struct got_error *
+got_repo_pack_fds_close(int *pack_fds)
+{
+	const struct got_error *err = NULL;
+	int i;
+
+	for (i = 0; i < GOT_PACK_NUM_TEMPFILES; i++) {
+		if (pack_fds[i] == -1)
+			continue;
+		if (close(pack_fds[i]) == -1) {
+			err = got_error_from_errno("close");
+			break;
+		}
+	}
+	free(pack_fds);
+	pack_fds = NULL;
+	return err;
+}
+
+const struct got_error *
 got_repo_cache_object(struct got_repository *repo, struct got_object_id *id,
     struct got_object *obj)
 {
@@ -651,12 +717,12 @@ static const char *const repo_extensions[] = {
 
 const struct got_error *
 got_repo_open(struct got_repository **repop, const char *path,
-    const char *global_gitconfig_path)
+    const char *global_gitconfig_path, int *pack_fds)
 {
 	struct got_repository *repo = NULL;
 	const struct got_error *err = NULL;
 	char *repo_path = NULL;
-	size_t i;
+	size_t i, j = 0;
 	struct rlimit rl;
 
 	*repop = NULL;
@@ -703,12 +769,8 @@ got_repo_open(struct got_repository **repop, const cha
 		repo->pack_cache_size = rl.rlim_cur / 8;
 	for (i = 0; i < nitems(repo->packs); i++) {
 		if (i < repo->pack_cache_size) {
-			repo->packs[i].basefd = got_opentempfd();
-			if (repo->packs[i].basefd == -1)
-				return got_error_from_errno("got_opentempfd");
-			repo->packs[i].accumfd = got_opentempfd();
-			if (repo->packs[i].accumfd == -1)
-				return got_error_from_errno("got_opentempfd");
+			repo->packs[i].basefd = pack_fds[j++];
+			repo->packs[i].accumfd = pack_fds[j++];
 		} else {
 			repo->packs[i].basefd = -1;
 			repo->packs[i].accumfd = -1;
@@ -796,20 +858,10 @@ got_repo_close(struct got_repository *repo)
 		free(bf);
 	}
 
-	for (i = 0; i < repo->pack_cache_size; i++) {
+	for (i = 0; i < repo->pack_cache_size; i++)
 		if (repo->packs[i].path_packfile)
-			got_pack_close(&repo->packs[i]);
-		if (repo->packs[i].basefd != -1) {
-			if (close(repo->packs[i].basefd) == -1 && err == NULL)
-				err = got_error_from_errno("close");
-			repo->packs[i].basefd = -1;
-		}
-		if (repo->packs[i].accumfd != -1) {
-			if (close(repo->packs[i].accumfd) == -1 && err == NULL)
-				err = got_error_from_errno("close");
-			repo->packs[i].accumfd = -1;
-		}
-	}
+			if (repo->packs[i].path_packfile)
+				got_pack_close(&repo->packs[i]);
 
 	free(repo->path);
 	free(repo->path_git_dir);
blob - 673cbeb89c705904097774881d38ef9d51751939
blob + b2c501c93b5b911eda66bb0c017747c3e1297121
--- lib/worktree_open.c
+++ lib/worktree_open.c
@@ -105,7 +105,7 @@ done:
 }
 
 static const struct got_error *
-open_worktree(struct got_worktree **worktree, const char *path)
+open_worktree(struct got_worktree **worktree, const char *path, int *pack_fds)
 {
 	const struct got_error *err = NULL;
 	char *path_got;
@@ -190,7 +190,7 @@ open_worktree(struct got_worktree **worktree, const ch
 		goto done;
 	}
 
-	err = got_repo_open(&repo, (*worktree)->repo_path, NULL);
+	err = got_repo_open(&repo, (*worktree)->repo_path, NULL, pack_fds);
 	if (err)
 		goto done;
 
@@ -244,7 +244,8 @@ done:
 }
 
 const struct got_error *
-got_worktree_open(struct got_worktree **worktree, const char *path)
+got_worktree_open(struct got_worktree **worktree, const char *path,
+    int *pack_fds)
 {
 	const struct got_error *err = NULL;
 	char *worktree_path;
@@ -256,7 +257,7 @@ got_worktree_open(struct got_worktree **worktree, cons
 	for (;;) {
 		char *parent_path;
 
-		err = open_worktree(worktree, worktree_path);
+		err = open_worktree(worktree, worktree_path, pack_fds);
 		if (err && !(err->code == GOT_ERR_ERRNO && errno == ENOENT)) {
 			free(worktree_path);
 			return err;
blob - b4efe82ad2000b743da8b7312623bf0fe3708969
blob + aa5e33d82c1134b4ee9c05ead7fbf9445e5341f0
--- tog/tog.c
+++ tog/tog.c
@@ -1125,7 +1125,7 @@ view_loop(struct tog_view *view)
 			}
 			TAILQ_INSERT_TAIL(&views, new_view, entry);
 			view = new_view;
-		} 
+		}
 		if (view) {
 			if (view_is_parent_view(view)) {
 				if (view->child && view->child->focussed)
@@ -2317,6 +2317,7 @@ open_log_view(struct tog_view *view, struct got_object
 	struct got_repository *thread_repo = NULL;
 	struct got_commit_graph *thread_graph = NULL;
 	int errcode;
+	int *pack_fds = NULL;
 
 	if (in_repo_path != s->in_repo_path) {
 		free(s->in_repo_path);
@@ -2370,9 +2371,13 @@ open_log_view(struct tog_view *view, struct got_object
 	view->search_start = search_start_log_view;
 	view->search_next = search_next_log_view;
 
-	err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL);
+	err = got_repo_pack_fds_open(&pack_fds);
 	if (err)
 		goto done;
+	err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL,
+	    pack_fds);
+	if (err)
+		goto done;
 	err = got_commit_graph_open(&thread_graph, s->in_repo_path,
 	    !s->log_branches);
 	if (err)
@@ -2407,6 +2412,12 @@ open_log_view(struct tog_view *view, struct got_object
 	s->thread_args.search_next_done = &view->search_next_done;
 	s->thread_args.regex = &view->regex;
 done:
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (err == NULL)
+			err = pack_err;
+	}
 	if (err)
 		close_log_view(view);
 	return err;
@@ -2442,6 +2453,7 @@ input_log_view(struct tog_view **new_view, struct tog_
 	struct tog_view *ref_view = NULL;
 	struct commit_queue_entry *entry;
 	int begin_x = 0, n;
+	int *pack_fds = NULL;
 
 	if (s->thread_args.load_all) {
 		if (ch == KEY_BACKSPACE)
@@ -2634,10 +2646,16 @@ input_log_view(struct tog_view **new_view, struct tog_
 		} else /* 'B' */
 			s->log_branches = !s->log_branches;
 
+		err = got_repo_pack_fds_open(&pack_fds);
+		if (err)
+			return err;
 		err = got_repo_open(&s->thread_args.repo,
-		    got_repo_get_path(s->repo), NULL);
+		    got_repo_get_path(s->repo), NULL, pack_fds);
 		if (err)
 			return err;
+		err = got_repo_pack_fds_close(pack_fds);
+		if (err)
+			return err;
 		tog_free_refs();
 		err = tog_load_refs(s->repo, 0);
 		if (err)
@@ -2791,6 +2809,7 @@ cmd_log(int argc, char *argv[])
 	const char *head_ref_name = NULL;
 	int ch, log_branches = 0;
 	struct tog_view *view;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "bc:r:")) != -1) {
 		switch (ch) {
@@ -2818,11 +2837,15 @@ cmd_log(int argc, char *argv[])
 	if (argc > 1)
 		usage_log();
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
 		cwd = getcwd(NULL, 0);
 		if (cwd == NULL)
 			return got_error_from_errno("getcwd");
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree)
@@ -2836,7 +2859,7 @@ cmd_log(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -2906,6 +2929,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	tog_free_refs();
@@ -3911,6 +3940,7 @@ cmd_diff(int argc, char *argv[])
 	int ch, force_text_diff = 0;
 	const char *errstr;
 	struct tog_view *view;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "aC:r:w")) != -1) {
 		switch (ch) {
@@ -3951,11 +3981,15 @@ cmd_diff(int argc, char *argv[])
 	} else
 		usage_diff();
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error)
+		goto done;
+
 	if (repo_path == NULL) {
 		cwd = getcwd(NULL, 0);
 		if (cwd == NULL)
 			return got_error_from_errno("getcwd");
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree)
@@ -3969,7 +4003,7 @@ cmd_diff(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error)
 		goto done;
 
@@ -4013,6 +4047,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (worktree)
 		got_worktree_close(worktree);
 	tog_free_refs();
@@ -4162,7 +4202,7 @@ draw_blame(struct tog_view *view)
 			width = 9;
 			wline = wcsdup(L"");
 			if (wline == NULL) {
-				err = got_error_from_errno("wcsdup");
+				err = got_error_from_errno("wcsup");
 				free(line);
 				return err;
 			}
@@ -4372,6 +4412,7 @@ run_blame(struct tog_view *view)
 	struct got_repository *thread_repo = NULL;
 	struct got_object_id *obj_id = NULL;
 	int obj_type;
+	int *pack_fds = NULL;
 
 	err = got_object_open_as_commit(&commit, s->repo,
 	    &s->blamed_commit->id);
@@ -4418,9 +4459,13 @@ run_blame(struct tog_view *view)
 		goto done;
 	}
 
-	err = got_repo_open(&thread_repo, got_repo_get_path(s->repo), NULL);
+	err = got_repo_pack_fds_copy(&pack_fds, s->repo);
 	if (err)
 		goto done;
+	err = got_repo_open(&thread_repo, got_repo_get_path(s->repo), NULL,
+	    pack_fds);
+	if (err)
+		goto done;
 
 	blame->cb_args.view = view;
 	blame->cb_args.lines = blame->lines;
@@ -4861,6 +4906,7 @@ cmd_blame(int argc, char *argv[])
 	char *commit_id_str = NULL;
 	int ch;
 	struct tog_view *view;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "c:r:")) != -1) {
 		switch (ch) {
@@ -4885,11 +4931,15 @@ cmd_blame(int argc, char *argv[])
 	if (argc != 1)
 		usage_blame();
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
 		cwd = getcwd(NULL, 0);
 		if (cwd == NULL)
 			return got_error_from_errno("getcwd");
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree)
@@ -4903,7 +4953,7 @@ cmd_blame(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -4977,6 +5027,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	tog_free_refs();
 	return error;
 }
@@ -5723,6 +5779,7 @@ cmd_tree(int argc, char *argv[])
 	const char *head_ref_name = NULL;
 	int ch;
 	struct tog_view *view;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "c:r:")) != -1) {
 		switch (ch) {
@@ -5747,11 +5804,15 @@ cmd_tree(int argc, char *argv[])
 	if (argc > 1)
 		usage_tree();
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
 		cwd = getcwd(NULL, 0);
 		if (cwd == NULL)
 			return got_error_from_errno("getcwd");
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree)
@@ -5765,7 +5826,7 @@ cmd_tree(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -5840,6 +5901,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	tog_free_refs();
 	return error;
 }
@@ -6476,6 +6543,7 @@ cmd_ref(int argc, char *argv[])
 	char *cwd = NULL, *repo_path = NULL;
 	int ch;
 	struct tog_view *view;
+	int *pack_fds = NULL;
 
 	while ((ch = getopt(argc, argv, "r:")) != -1) {
 		switch (ch) {
@@ -6497,11 +6565,15 @@ cmd_ref(int argc, char *argv[])
 	if (argc > 1)
 		usage_ref();
 
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
 	if (repo_path == NULL) {
 		cwd = getcwd(NULL, 0);
 		if (cwd == NULL)
 			return got_error_from_errno("getcwd");
-		error = got_worktree_open(&worktree, cwd);
+		error = got_worktree_open(&worktree, cwd, pack_fds);
 		if (error && error->code != GOT_ERR_NOT_WORKTREE)
 			goto done;
 		if (worktree)
@@ -6515,7 +6587,7 @@ cmd_ref(int argc, char *argv[])
 		}
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -6553,6 +6625,12 @@ done:
 		if (close_err)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	tog_free_refs();
 	return error;
 }
@@ -6624,12 +6702,17 @@ tog_log_with_path(int argc, char *argv[])
 	struct got_commit_object *commit = NULL;
 	char *cwd = NULL, *repo_path = NULL, *in_repo_path = NULL;
 	char *commit_id_str = NULL, **cmd_argv = NULL;
+	int *pack_fds = NULL;
 
 	cwd = getcwd(NULL, 0);
 	if (cwd == NULL)
 		return got_error_from_errno("getcwd");
 
-	error = got_worktree_open(&worktree, cwd);
+	error = got_repo_pack_fds_open(&pack_fds);
+	if (error != NULL)
+		goto done;
+
+	error = got_worktree_open(&worktree, cwd, pack_fds);
 	if (error && error->code != GOT_ERR_NOT_WORKTREE)
 		goto done;
 
@@ -6642,7 +6725,7 @@ tog_log_with_path(int argc, char *argv[])
 		goto done;
 	}
 
-	error = got_repo_open(&repo, repo_path, NULL);
+	error = got_repo_open(&repo, repo_path, NULL, pack_fds);
 	if (error != NULL)
 		goto done;
 
@@ -6698,6 +6781,12 @@ done:
 		if (error == NULL)
 			error = close_err;
 	}
+	if (pack_fds) {
+		const struct got_error *pack_err =
+		    got_repo_pack_fds_close(pack_fds);
+		if (error == NULL)
+			error = pack_err;
+	}
 	if (commit)
 		got_object_commit_close(commit);
 	if (worktree)
@@ -6806,4 +6895,5 @@ main(int argc, char *argv[])
 	if (error && error->code != GOT_ERR_CANCELLED)
 		fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
 	return 0;
+
 }