{"thread":{"id":"66016","subject":"[PATCH] copy: drop dependency on `the_repository`","startedAt":"2026-07-16T09:56:26Z","lastAt":"2026-07-17T17:09:04Z","messageCount":6,"participants":["Patrick Steinhardt","Phillip Wood","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"548392","messageId":"20260716-pks-copy-wo-the-repository-v1-1-8f1e078bb82f@pks.im","threadId":"66016","inReplyTo":null,"subject":"[PATCH] copy: drop dependency on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-16T09:56:13Z","receivedAt":"2026-07-16T09:56:26Z","isPatch":true,"body":"When copying a file we need to potentially adapt permissions of the new\nfile based on whether or not \"core.shared\" is enabled. Parsing this\nconfiguration makes us implicitly depend on `the_repository`.\n\nRefactor the code to instead require the caller to pass in a repository\nso that we can remove `USE_THE_REPOSITORY_VARIABLE`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\nHi,\n\nI guess the title says it all: this small patch removes the dependency\non `the_repository` in \"copy.c\". Thanks!\n\nPatrick\n---\n builtin/clone.c      |  2 +-\n builtin/difftool.c   |  4 ++--\n builtin/worktree.c   |  4 ++--\n bundle-uri.c         |  2 +-\n copy.c               | 12 ++++++------\n copy.h               |  8 ++++++--\n refs/files-backend.c |  2 +-\n rerere.c             |  2 +-\n sequencer.c          |  6 +++---\n setup.c              |  2 +-\n 10 files changed, 24 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex d60d1b60bc..18603dd4ce 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -335,7 +335,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,\n \t\t\t\tdie_errno(_(\"failed to create link '%s'\"), dest->buf);\n \t\t\toption_no_hardlinks = 1;\n \t\t}\n-\t\tif (copy_file_with_time(dest->buf, src->buf, 0666))\n+\t\tif (copy_file_with_time(the_repository, dest->buf, src->buf, 0666))\n \t\t\tdie_errno(_(\"failed to copy file to '%s'\"), dest->buf);\n \t}\n \ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex 26778f8515..5e7777fbe4 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -552,7 +552,7 @@ static int run_dir_diff(struct repository *repo,\n \t\t\t\t\tstruct stat st;\n \t\t\t\t\tif (stat(wtdir.buf, &st))\n \t\t\t\t\t\tst.st_mode = 0644;\n-\t\t\t\t\tif (copy_file(rdir.buf, wtdir.buf,\n+\t\t\t\t\tif (copy_file(repo, rdir.buf, wtdir.buf,\n \t\t\t\t\t\t      st.st_mode)) {\n \t\t\t\t\t\tret = error(\"could not copy '%s' to '%s'\", wtdir.buf, rdir.buf);\n \t\t\t\t\t\tgoto finish;\n@@ -658,7 +658,7 @@ static int run_dir_diff(struct repository *repo,\n \t\t\t\twarning(\"%s\", \"\");\n \t\t\t\terr = 1;\n \t\t\t} else if (unlink(wtdir.buf) ||\n-\t\t\t\t   copy_file(wtdir.buf, rdir.buf, st.st_mode))\n+\t\t\t\t   copy_file(repo, wtdir.buf, rdir.buf, st.st_mode))\n \t\t\t\twarning_errno(_(\"could not copy '%s' to '%s'\"),\n \t\t\t\t\t      rdir.buf, wtdir.buf);\n \t\t}\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d21c43fde3..84b01960fb 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -349,7 +349,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)\n \n \tif (file_exists(from_file)) {\n \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n-\t\t\tcopy_file(to_file, from_file, 0666))\n+\t\t\tcopy_file(the_repository, to_file, from_file, 0666))\n \t\t\terror(_(\"failed to copy '%s' to '%s'; sparse-checkout may not work correctly\"),\n \t\t\t\tfrom_file, to_file);\n \t}\n@@ -368,7 +368,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)\n \t\tint bare;\n \n \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n-\t\t\tcopy_file(to_file, from_file, 0666)) {\n+\t\t\tcopy_file(the_repository, to_file, from_file, 0666)) {\n \t\t\terror(_(\"failed to copy worktree config from '%s' to '%s'\"),\n \t\t\t\tfrom_file, to_file);\n \t\t\tgoto worktree_copy_cleanup;\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 3b2e347288..ef37aebf30 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -396,7 +396,7 @@ static int copy_uri_to_file(const char *filename, const char *uri)\n \t\turi = out;\n \n \t/* Copy as a file */\n-\treturn copy_file(filename, uri, 0);\n+\treturn copy_file(the_repository, filename, uri, 0);\n }\n \n static int unbundle_from_file(struct repository *r, const char *file)\ndiff --git a/copy.c b/copy.c\nindex b668209b6c..6074132050 100644\n--- a/copy.c\n+++ b/copy.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"copy.h\"\n #include \"path.h\"\n@@ -35,7 +33,8 @@ static int copy_times(const char *dst, const char *src)\n \treturn 0;\n }\n \n-int copy_file(const char *dst, const char *src, int mode)\n+int copy_file(struct repository *repo,\n+\t      const char *dst, const char *src, int mode)\n {\n \tint fdi, fdo, status;\n \n@@ -59,15 +58,16 @@ int copy_file(const char *dst, const char *src, int mode)\n \tif (close(fdo) != 0)\n \t\treturn error_errno(\"%s: close error\", dst);\n \n-\tif (!status && adjust_shared_perm(the_repository, dst))\n+\tif (!status && adjust_shared_perm(repo, dst))\n \t\treturn -1;\n \n \treturn status;\n }\n \n-int copy_file_with_time(const char *dst, const char *src, int mode)\n+int copy_file_with_time(struct repository *repo,\n+\t\t\tconst char *dst, const char *src, int mode)\n {\n-\tint status = copy_file(dst, src, mode);\n+\tint status = copy_file(repo, dst, src, mode);\n \tif (!status)\n \t\treturn copy_times(dst, src);\n \treturn status;\ndiff --git a/copy.h b/copy.h\nindex 2af77cba86..1059b118d6 100644\n--- a/copy.h\n+++ b/copy.h\n@@ -1,10 +1,14 @@\n #ifndef COPY_H\n #define COPY_H\n \n+struct repository;\n+\n #define COPY_READ_ERROR (-2)\n #define COPY_WRITE_ERROR (-3)\n int copy_fd(int ifd, int ofd);\n-int copy_file(const char *dst, const char *src, int mode);\n-int copy_file_with_time(const char *dst, const char *src, int mode);\n+int copy_file(struct repository *repo,\n+\t      const char *dst, const char *src, int mode);\n+int copy_file_with_time(struct repository *repo,\n+\t\t\tconst char *dst, const char *src, int mode);\n \n #endif /* COPY_H */\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 3df56c25c8..442c98414e 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1736,7 +1736,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \t\tgoto out;\n \t}\n \n-\tif (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n+\tif (copy && log && copy_file(refs->base.repo, tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n \t\tret = error(\"unable to copy logfile logs/%s to logs/\"TMP_RENAMED_LOG\": %s\",\n \t\t\t    oldrefname, strerror(errno));\n \t\tgoto out;\ndiff --git a/rerere.c b/rerere.c\nindex 8232542585..bf5cfc6e51 100644\n--- a/rerere.c\n+++ b/rerere.c\n@@ -756,7 +756,7 @@ static void do_rerere_one_path(struct index_state *istate,\n \t/* Has the user resolved it already? */\n \tif (variant >= 0) {\n \t\tif (!handle_file(istate, path, NULL, NULL)) {\n-\t\t\tcopy_file(rerere_path(&buf, id, \"postimage\"), path, 0666);\n+\t\t\tcopy_file(the_repository, rerere_path(&buf, id, \"postimage\"), path, 0666);\n \t\t\tid->collection->status[variant] |= RR_HAS_POSTIMAGE;\n \t\t\tfprintf_ln(stderr, _(\"Recorded resolution for '%s'.\"), path);\n \t\t\tfree_rerere_id(rr_item);\ndiff --git a/sequencer.c b/sequencer.c\nindex 1355a99a09..c9ede9c02d 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -2419,7 +2419,7 @@ static int do_pick_commit(struct repository *r,\n \t\t} else {\n \t\t\tconst char *dest = git_path_squash_msg(r);\n \t\t\tunlink(dest);\n-\t\t\tif (copy_file(dest, rebase_path_squash_msg(), 0666)) {\n+\t\t\tif (copy_file(the_repository, dest, rebase_path_squash_msg(), 0666)) {\n \t\t\t\tres = error(_(\"could not copy '%s' to '%s'\"),\n \t\t\t\t\t    rebase_path_squash_msg(), dest);\n \t\t\t\tgoto leave;\n@@ -3864,11 +3864,11 @@ static int error_failed_squash(struct repository *r,\n \t\t\t       int subject_len,\n \t\t\t       const char *subject)\n {\n-\tif (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))\n+\tif (copy_file(the_repository, rebase_path_message(), rebase_path_squash_msg(), 0666))\n \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n \t\t\trebase_path_squash_msg(), rebase_path_message());\n \tunlink(git_path_merge_msg(r));\n-\tif (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))\n+\tif (copy_file(the_repository, git_path_merge_msg(r), rebase_path_message(), 0666))\n \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n \t\t\t     rebase_path_message(),\n \t\t\t     git_path_merge_msg(r));\ndiff --git a/setup.c b/setup.c\nindex 0de56a074f..91d61a5939 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2331,7 +2331,7 @@ static void copy_templates_1(struct repository *repo,\n \t\t\tstrbuf_release(&lnk);\n \t\t}\n \t\telse if (S_ISREG(st_template.st_mode)) {\n-\t\t\tif (copy_file(path->buf, template_path->buf, st_template.st_mode))\n+\t\t\tif (copy_file(repo, path->buf, template_path->buf, st_template.st_mode))\n \t\t\t\tdie_errno(_(\"cannot copy '%s' to '%s'\"),\n \t\t\t\t\t  template_path->buf, path->buf);\n \t\t}\n\n---\nbase-commit: d35c5399e3e54ac277bb391fc2f6be3e816d312b\nchange-id: 20260716-pks-copy-wo-the-repository-aa01ccdbed76\n\n"},{"id":"548412","messageId":"27d4d72f-1ab5-4dc3-8cf6-1a9b6883a631@gmail.com","threadId":"66016","inReplyTo":"20260716-pks-copy-wo-the-repository-v1-1-8f1e078bb82f@pks.im","subject":"Re: [PATCH] copy: drop dependency on `the_repository`","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-07-16T13:41:44Z","receivedAt":"2026-07-16T13:41:49Z","isPatch":true,"body":"Hi Patrick\n\nOn 16/07/2026 10:56, Patrick Steinhardt wrote:\n> When copying a file we need to potentially adapt permissions of the new\n> file based on whether or not \"core.shared\" is enabled. Parsing this\n> configuration makes us implicitly depend on `the_repository`.\n> \n> Refactor the code to instead require the caller to pass in a repository\n> so that we can remove `USE_THE_REPOSITORY_VARIABLE`.\n\nSounds sensible\n> diff --git a/sequencer.c b/sequencer.c\n> index 1355a99a09..c9ede9c02d 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -2419,7 +2419,7 @@ static int do_pick_commit(struct repository *r,\n>   \t\t} else {\n>   \t\t\tconst char *dest = git_path_squash_msg(r);\n>   \t\t\tunlink(dest);\n> -\t\t\tif (copy_file(dest, rebase_path_squash_msg(), 0666)) {\n> +\t\t\tif (copy_file(the_repository, dest, rebase_path_squash_msg(), 0666)) {\n\nThe path for \"dest\" is obtained using a local repository instance \"r\", \nbut we're using \"the_repository\" to set the permissions on that path. \nWhile that matches the current behavior it is clearly better to use the \nsame repository instance to obtain both the path and and permissions for \nthat path. In the hunk below we even have \"the_repository\" and \"r\" on \nthe same line which seems confusing. This patch uses a local repository \ninstance in refs/files-backend.c and setup.c, lets do the same here.\n\nThanks\n\nPhillip\n\n>   \t\t\t\tres = error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\t\t\t    rebase_path_squash_msg(), dest);\n>   \t\t\t\tgoto leave;\n> @@ -3864,11 +3864,11 @@ static int error_failed_squash(struct repository *r,\n>   \t\t\t       int subject_len,\n>   \t\t\t       const char *subject)\n>   {\n> -\tif (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))\n> +\tif (copy_file(the_repository, rebase_path_message(), rebase_path_squash_msg(), 0666))\n>   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\trebase_path_squash_msg(), rebase_path_message());\n>   \tunlink(git_path_merge_msg(r));\n> -\tif (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))\n> +\tif (copy_file(the_repository, git_path_merge_msg(r), rebase_path_message(), 0666))\n>   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\t     rebase_path_message(),\n>   \t\t\t     git_path_merge_msg(r));\n> diff --git a/setup.c b/setup.c\n> index 0de56a074f..91d61a5939 100644\n> --- a/setup.c\n> +++ b/setup.c\n> @@ -2331,7 +2331,7 @@ static void copy_templates_1(struct repository *repo,\n>   \t\t\tstrbuf_release(&lnk);\n>   \t\t}\n>   \t\telse if (S_ISREG(st_template.st_mode)) {\n> -\t\t\tif (copy_file(path->buf, template_path->buf, st_template.st_mode))\n> +\t\t\tif (copy_file(repo, path->buf, template_path->buf, st_template.st_mode))\n>   \t\t\t\tdie_errno(_(\"cannot copy '%s' to '%s'\"),\n>   \t\t\t\t\t  template_path->buf, path->buf);\n>   \t\t}\n> \n> ---\n> base-commit: d35c5399e3e54ac277bb391fc2f6be3e816d312b\n> change-id: 20260716-pks-copy-wo-the-repository-aa01ccdbed76\n> \n> \n\n"},{"id":"548422","messageId":"aljzZar4sG6IE4-h@pks.im","threadId":"66016","inReplyTo":"27d4d72f-1ab5-4dc3-8cf6-1a9b6883a631@gmail.com","subject":"Re: [PATCH] copy: drop dependency on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-16T15:06:13Z","receivedAt":"2026-07-16T15:06:21Z","isPatch":true,"body":"On Thu, Jul 16, 2026 at 02:41:44PM +0100, Phillip Wood wrote:\n> > diff --git a/sequencer.c b/sequencer.c\n> > index 1355a99a09..c9ede9c02d 100644\n> > --- a/sequencer.c\n> > +++ b/sequencer.c\n> > @@ -2419,7 +2419,7 @@ static int do_pick_commit(struct repository *r,\n> >   \t\t} else {\n> >   \t\t\tconst char *dest = git_path_squash_msg(r);\n> >   \t\t\tunlink(dest);\n> > -\t\t\tif (copy_file(dest, rebase_path_squash_msg(), 0666)) {\n> > +\t\t\tif (copy_file(the_repository, dest, rebase_path_squash_msg(), 0666)) {\n> \n> The path for \"dest\" is obtained using a local repository instance \"r\", but\n> we're using \"the_repository\" to set the permissions on that path. While that\n> matches the current behavior it is clearly better to use the same repository\n> instance to obtain both the path and and permissions for that path. In the\n> hunk below we even have \"the_repository\" and \"r\" on the same line which\n> seems confusing. This patch uses a local repository instance in\n> refs/files-backend.c and setup.c, lets do the same here.\n\nMakes sense. In that case though I'll also adapt the two uses of\n`the_repository` below. Thanks!\n\nPatrick\n\n> > @@ -3864,11 +3864,11 @@ static int error_failed_squash(struct repository *r,\n> >   \t\t\t       int subject_len,\n> >   \t\t\t       const char *subject)\n> >   {\n> > -\tif (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))\n> > +\tif (copy_file(the_repository, rebase_path_message(), rebase_path_squash_msg(), 0666))\n> >   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n> >   \t\t\trebase_path_squash_msg(), rebase_path_message());\n> >   \tunlink(git_path_merge_msg(r));\n> > -\tif (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))\n> > +\tif (copy_file(the_repository, git_path_merge_msg(r), rebase_path_message(), 0666))\n> >   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n> >   \t\t\t     rebase_path_message(),\n> >   \t\t\t     git_path_merge_msg(r));\n"},{"id":"548423","messageId":"20260716-pks-copy-wo-the-repository-v2-1-8f5e32942929@pks.im","threadId":"66016","inReplyTo":"20260716-pks-copy-wo-the-repository-v1-1-8f1e078bb82f@pks.im","subject":"[PATCH v2] copy: drop dependency on `the_repository`","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-16T15:28:23Z","receivedAt":"2026-07-16T15:28:35Z","isPatch":true,"body":"When copying a file we need to potentially adapt permissions of the new\nfile based on whether or not \"core.shared\" is enabled. Parsing this\nconfiguration makes us implicitly depend on `the_repository`.\n\nRefactor the code to instead require the caller to pass in a repository\nso that we can remove `USE_THE_REPOSITORY_VARIABLE`.\n\nSigned-off-by: Patrick Steinhardt <ps@pks.im>\n---\nHi,\n\nI guess the title says it all: this small patch removes the dependency\non `the_repository` in \"copy.c\". Thanks!\n\nChanges in v2:\n  - Adapt a couple more sites to use a repository from the context.\n  - Link to v1: https://patch.msgid.link/20260716-pks-copy-wo-the-repository-v1-1-8f1e078bb82f@pks.im\n\nPatrick\n---\n builtin/clone.c      |  2 +-\n builtin/difftool.c   |  4 ++--\n builtin/worktree.c   |  4 ++--\n bundle-uri.c         |  2 +-\n copy.c               | 12 ++++++------\n copy.h               |  8 ++++++--\n refs/files-backend.c |  2 +-\n rerere.c             |  2 +-\n sequencer.c          |  6 +++---\n setup.c              |  2 +-\n 10 files changed, 24 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/clone.c b/builtin/clone.c\nindex d60d1b60bc..18603dd4ce 100644\n--- a/builtin/clone.c\n+++ b/builtin/clone.c\n@@ -335,7 +335,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,\n \t\t\t\tdie_errno(_(\"failed to create link '%s'\"), dest->buf);\n \t\t\toption_no_hardlinks = 1;\n \t\t}\n-\t\tif (copy_file_with_time(dest->buf, src->buf, 0666))\n+\t\tif (copy_file_with_time(the_repository, dest->buf, src->buf, 0666))\n \t\t\tdie_errno(_(\"failed to copy file to '%s'\"), dest->buf);\n \t}\n \ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex 26778f8515..5e7777fbe4 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -552,7 +552,7 @@ static int run_dir_diff(struct repository *repo,\n \t\t\t\t\tstruct stat st;\n \t\t\t\t\tif (stat(wtdir.buf, &st))\n \t\t\t\t\t\tst.st_mode = 0644;\n-\t\t\t\t\tif (copy_file(rdir.buf, wtdir.buf,\n+\t\t\t\t\tif (copy_file(repo, rdir.buf, wtdir.buf,\n \t\t\t\t\t\t      st.st_mode)) {\n \t\t\t\t\t\tret = error(\"could not copy '%s' to '%s'\", wtdir.buf, rdir.buf);\n \t\t\t\t\t\tgoto finish;\n@@ -658,7 +658,7 @@ static int run_dir_diff(struct repository *repo,\n \t\t\t\twarning(\"%s\", \"\");\n \t\t\t\terr = 1;\n \t\t\t} else if (unlink(wtdir.buf) ||\n-\t\t\t\t   copy_file(wtdir.buf, rdir.buf, st.st_mode))\n+\t\t\t\t   copy_file(repo, wtdir.buf, rdir.buf, st.st_mode))\n \t\t\t\twarning_errno(_(\"could not copy '%s' to '%s'\"),\n \t\t\t\t\t      rdir.buf, wtdir.buf);\n \t\t}\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex d21c43fde3..84b01960fb 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -349,7 +349,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)\n \n \tif (file_exists(from_file)) {\n \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n-\t\t\tcopy_file(to_file, from_file, 0666))\n+\t\t\tcopy_file(the_repository, to_file, from_file, 0666))\n \t\t\terror(_(\"failed to copy '%s' to '%s'; sparse-checkout may not work correctly\"),\n \t\t\t\tfrom_file, to_file);\n \t}\n@@ -368,7 +368,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)\n \t\tint bare;\n \n \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n-\t\t\tcopy_file(to_file, from_file, 0666)) {\n+\t\t\tcopy_file(the_repository, to_file, from_file, 0666)) {\n \t\t\terror(_(\"failed to copy worktree config from '%s' to '%s'\"),\n \t\t\t\tfrom_file, to_file);\n \t\t\tgoto worktree_copy_cleanup;\ndiff --git a/bundle-uri.c b/bundle-uri.c\nindex 3b2e347288..ef37aebf30 100644\n--- a/bundle-uri.c\n+++ b/bundle-uri.c\n@@ -396,7 +396,7 @@ static int copy_uri_to_file(const char *filename, const char *uri)\n \t\turi = out;\n \n \t/* Copy as a file */\n-\treturn copy_file(filename, uri, 0);\n+\treturn copy_file(the_repository, filename, uri, 0);\n }\n \n static int unbundle_from_file(struct repository *r, const char *file)\ndiff --git a/copy.c b/copy.c\nindex b668209b6c..6074132050 100644\n--- a/copy.c\n+++ b/copy.c\n@@ -1,5 +1,3 @@\n-#define USE_THE_REPOSITORY_VARIABLE\n-\n #include \"git-compat-util.h\"\n #include \"copy.h\"\n #include \"path.h\"\n@@ -35,7 +33,8 @@ static int copy_times(const char *dst, const char *src)\n \treturn 0;\n }\n \n-int copy_file(const char *dst, const char *src, int mode)\n+int copy_file(struct repository *repo,\n+\t      const char *dst, const char *src, int mode)\n {\n \tint fdi, fdo, status;\n \n@@ -59,15 +58,16 @@ int copy_file(const char *dst, const char *src, int mode)\n \tif (close(fdo) != 0)\n \t\treturn error_errno(\"%s: close error\", dst);\n \n-\tif (!status && adjust_shared_perm(the_repository, dst))\n+\tif (!status && adjust_shared_perm(repo, dst))\n \t\treturn -1;\n \n \treturn status;\n }\n \n-int copy_file_with_time(const char *dst, const char *src, int mode)\n+int copy_file_with_time(struct repository *repo,\n+\t\t\tconst char *dst, const char *src, int mode)\n {\n-\tint status = copy_file(dst, src, mode);\n+\tint status = copy_file(repo, dst, src, mode);\n \tif (!status)\n \t\treturn copy_times(dst, src);\n \treturn status;\ndiff --git a/copy.h b/copy.h\nindex 2af77cba86..1059b118d6 100644\n--- a/copy.h\n+++ b/copy.h\n@@ -1,10 +1,14 @@\n #ifndef COPY_H\n #define COPY_H\n \n+struct repository;\n+\n #define COPY_READ_ERROR (-2)\n #define COPY_WRITE_ERROR (-3)\n int copy_fd(int ifd, int ofd);\n-int copy_file(const char *dst, const char *src, int mode);\n-int copy_file_with_time(const char *dst, const char *src, int mode);\n+int copy_file(struct repository *repo,\n+\t      const char *dst, const char *src, int mode);\n+int copy_file_with_time(struct repository *repo,\n+\t\t\tconst char *dst, const char *src, int mode);\n \n #endif /* COPY_H */\ndiff --git a/refs/files-backend.c b/refs/files-backend.c\nindex 3df56c25c8..442c98414e 100644\n--- a/refs/files-backend.c\n+++ b/refs/files-backend.c\n@@ -1736,7 +1736,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n \t\tgoto out;\n \t}\n \n-\tif (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n+\tif (copy && log && copy_file(refs->base.repo, tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n \t\tret = error(\"unable to copy logfile logs/%s to logs/\"TMP_RENAMED_LOG\": %s\",\n \t\t\t    oldrefname, strerror(errno));\n \t\tgoto out;\ndiff --git a/rerere.c b/rerere.c\nindex 8232542585..bf5cfc6e51 100644\n--- a/rerere.c\n+++ b/rerere.c\n@@ -756,7 +756,7 @@ static void do_rerere_one_path(struct index_state *istate,\n \t/* Has the user resolved it already? */\n \tif (variant >= 0) {\n \t\tif (!handle_file(istate, path, NULL, NULL)) {\n-\t\t\tcopy_file(rerere_path(&buf, id, \"postimage\"), path, 0666);\n+\t\t\tcopy_file(the_repository, rerere_path(&buf, id, \"postimage\"), path, 0666);\n \t\t\tid->collection->status[variant] |= RR_HAS_POSTIMAGE;\n \t\t\tfprintf_ln(stderr, _(\"Recorded resolution for '%s'.\"), path);\n \t\t\tfree_rerere_id(rr_item);\ndiff --git a/sequencer.c b/sequencer.c\nindex 1355a99a09..63bc1ef215 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -2419,7 +2419,7 @@ static int do_pick_commit(struct repository *r,\n \t\t} else {\n \t\t\tconst char *dest = git_path_squash_msg(r);\n \t\t\tunlink(dest);\n-\t\t\tif (copy_file(dest, rebase_path_squash_msg(), 0666)) {\n+\t\t\tif (copy_file(r, dest, rebase_path_squash_msg(), 0666)) {\n \t\t\t\tres = error(_(\"could not copy '%s' to '%s'\"),\n \t\t\t\t\t    rebase_path_squash_msg(), dest);\n \t\t\t\tgoto leave;\n@@ -3864,11 +3864,11 @@ static int error_failed_squash(struct repository *r,\n \t\t\t       int subject_len,\n \t\t\t       const char *subject)\n {\n-\tif (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))\n+\tif (copy_file(r, rebase_path_message(), rebase_path_squash_msg(), 0666))\n \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n \t\t\trebase_path_squash_msg(), rebase_path_message());\n \tunlink(git_path_merge_msg(r));\n-\tif (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))\n+\tif (copy_file(r, git_path_merge_msg(r), rebase_path_message(), 0666))\n \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n \t\t\t     rebase_path_message(),\n \t\t\t     git_path_merge_msg(r));\ndiff --git a/setup.c b/setup.c\nindex 0de56a074f..91d61a5939 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -2331,7 +2331,7 @@ static void copy_templates_1(struct repository *repo,\n \t\t\tstrbuf_release(&lnk);\n \t\t}\n \t\telse if (S_ISREG(st_template.st_mode)) {\n-\t\t\tif (copy_file(path->buf, template_path->buf, st_template.st_mode))\n+\t\t\tif (copy_file(repo, path->buf, template_path->buf, st_template.st_mode))\n \t\t\t\tdie_errno(_(\"cannot copy '%s' to '%s'\"),\n \t\t\t\t\t  template_path->buf, path->buf);\n \t\t}\n\n---\nbase-commit: d35c5399e3e54ac277bb391fc2f6be3e816d312b\nchange-id: 20260716-pks-copy-wo-the-repository-aa01ccdbed76\n\n"},{"id":"548518","messageId":"b0df688a-3b26-48f6-8b1c-98530483885e@gmail.com","threadId":"66016","inReplyTo":"20260716-pks-copy-wo-the-repository-v2-1-8f5e32942929@pks.im","subject":"Re: [PATCH v2] copy: drop dependency on `the_repository`","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-07-17T15:00:15Z","receivedAt":"2026-07-17T15:00:22Z","isPatch":true,"body":"Hi Patrick\n\nThis version looks good to me\n\nThanks\n\nPhillip\n\nOn 16/07/2026 16:28, Patrick Steinhardt wrote:\n> When copying a file we need to potentially adapt permissions of the new\n> file based on whether or not \"core.shared\" is enabled. Parsing this\n> configuration makes us implicitly depend on `the_repository`.\n> \n> Refactor the code to instead require the caller to pass in a repository\n> so that we can remove `USE_THE_REPOSITORY_VARIABLE`.\n> \n> Signed-off-by: Patrick Steinhardt <ps@pks.im>\n> ---\n> Hi,\n> \n> I guess the title says it all: this small patch removes the dependency\n> on `the_repository` in \"copy.c\". Thanks!\n> \n> Changes in v2:\n>    - Adapt a couple more sites to use a repository from the context.\n>    - Link to v1: https://patch.msgid.link/20260716-pks-copy-wo-the-repository-v1-1-8f1e078bb82f@pks.im\n> \n> Patrick\n> ---\n>   builtin/clone.c      |  2 +-\n>   builtin/difftool.c   |  4 ++--\n>   builtin/worktree.c   |  4 ++--\n>   bundle-uri.c         |  2 +-\n>   copy.c               | 12 ++++++------\n>   copy.h               |  8 ++++++--\n>   refs/files-backend.c |  2 +-\n>   rerere.c             |  2 +-\n>   sequencer.c          |  6 +++---\n>   setup.c              |  2 +-\n>   10 files changed, 24 insertions(+), 20 deletions(-)\n> \n> diff --git a/builtin/clone.c b/builtin/clone.c\n> index d60d1b60bc..18603dd4ce 100644\n> --- a/builtin/clone.c\n> +++ b/builtin/clone.c\n> @@ -335,7 +335,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,\n>   \t\t\t\tdie_errno(_(\"failed to create link '%s'\"), dest->buf);\n>   \t\t\toption_no_hardlinks = 1;\n>   \t\t}\n> -\t\tif (copy_file_with_time(dest->buf, src->buf, 0666))\n> +\t\tif (copy_file_with_time(the_repository, dest->buf, src->buf, 0666))\n>   \t\t\tdie_errno(_(\"failed to copy file to '%s'\"), dest->buf);\n>   \t}\n>   \n> diff --git a/builtin/difftool.c b/builtin/difftool.c\n> index 26778f8515..5e7777fbe4 100644\n> --- a/builtin/difftool.c\n> +++ b/builtin/difftool.c\n> @@ -552,7 +552,7 @@ static int run_dir_diff(struct repository *repo,\n>   \t\t\t\t\tstruct stat st;\n>   \t\t\t\t\tif (stat(wtdir.buf, &st))\n>   \t\t\t\t\t\tst.st_mode = 0644;\n> -\t\t\t\t\tif (copy_file(rdir.buf, wtdir.buf,\n> +\t\t\t\t\tif (copy_file(repo, rdir.buf, wtdir.buf,\n>   \t\t\t\t\t\t      st.st_mode)) {\n>   \t\t\t\t\t\tret = error(\"could not copy '%s' to '%s'\", wtdir.buf, rdir.buf);\n>   \t\t\t\t\t\tgoto finish;\n> @@ -658,7 +658,7 @@ static int run_dir_diff(struct repository *repo,\n>   \t\t\t\twarning(\"%s\", \"\");\n>   \t\t\t\terr = 1;\n>   \t\t\t} else if (unlink(wtdir.buf) ||\n> -\t\t\t\t   copy_file(wtdir.buf, rdir.buf, st.st_mode))\n> +\t\t\t\t   copy_file(repo, wtdir.buf, rdir.buf, st.st_mode))\n>   \t\t\t\twarning_errno(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\t\t\t      rdir.buf, wtdir.buf);\n>   \t\t}\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> index d21c43fde3..84b01960fb 100644\n> --- a/builtin/worktree.c\n> +++ b/builtin/worktree.c\n> @@ -349,7 +349,7 @@ static void copy_sparse_checkout(const char *worktree_git_dir)\n>   \n>   \tif (file_exists(from_file)) {\n>   \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n> -\t\t\tcopy_file(to_file, from_file, 0666))\n> +\t\t\tcopy_file(the_repository, to_file, from_file, 0666))\n>   \t\t\terror(_(\"failed to copy '%s' to '%s'; sparse-checkout may not work correctly\"),\n>   \t\t\t\tfrom_file, to_file);\n>   \t}\n> @@ -368,7 +368,7 @@ static void copy_filtered_worktree_config(const char *worktree_git_dir)\n>   \t\tint bare;\n>   \n>   \t\tif (safe_create_leading_directories(the_repository, to_file) ||\n> -\t\t\tcopy_file(to_file, from_file, 0666)) {\n> +\t\t\tcopy_file(the_repository, to_file, from_file, 0666)) {\n>   \t\t\terror(_(\"failed to copy worktree config from '%s' to '%s'\"),\n>   \t\t\t\tfrom_file, to_file);\n>   \t\t\tgoto worktree_copy_cleanup;\n> diff --git a/bundle-uri.c b/bundle-uri.c\n> index 3b2e347288..ef37aebf30 100644\n> --- a/bundle-uri.c\n> +++ b/bundle-uri.c\n> @@ -396,7 +396,7 @@ static int copy_uri_to_file(const char *filename, const char *uri)\n>   \t\turi = out;\n>   \n>   \t/* Copy as a file */\n> -\treturn copy_file(filename, uri, 0);\n> +\treturn copy_file(the_repository, filename, uri, 0);\n>   }\n>   \n>   static int unbundle_from_file(struct repository *r, const char *file)\n> diff --git a/copy.c b/copy.c\n> index b668209b6c..6074132050 100644\n> --- a/copy.c\n> +++ b/copy.c\n> @@ -1,5 +1,3 @@\n> -#define USE_THE_REPOSITORY_VARIABLE\n> -\n>   #include \"git-compat-util.h\"\n>   #include \"copy.h\"\n>   #include \"path.h\"\n> @@ -35,7 +33,8 @@ static int copy_times(const char *dst, const char *src)\n>   \treturn 0;\n>   }\n>   \n> -int copy_file(const char *dst, const char *src, int mode)\n> +int copy_file(struct repository *repo,\n> +\t      const char *dst, const char *src, int mode)\n>   {\n>   \tint fdi, fdo, status;\n>   \n> @@ -59,15 +58,16 @@ int copy_file(const char *dst, const char *src, int mode)\n>   \tif (close(fdo) != 0)\n>   \t\treturn error_errno(\"%s: close error\", dst);\n>   \n> -\tif (!status && adjust_shared_perm(the_repository, dst))\n> +\tif (!status && adjust_shared_perm(repo, dst))\n>   \t\treturn -1;\n>   \n>   \treturn status;\n>   }\n>   \n> -int copy_file_with_time(const char *dst, const char *src, int mode)\n> +int copy_file_with_time(struct repository *repo,\n> +\t\t\tconst char *dst, const char *src, int mode)\n>   {\n> -\tint status = copy_file(dst, src, mode);\n> +\tint status = copy_file(repo, dst, src, mode);\n>   \tif (!status)\n>   \t\treturn copy_times(dst, src);\n>   \treturn status;\n> diff --git a/copy.h b/copy.h\n> index 2af77cba86..1059b118d6 100644\n> --- a/copy.h\n> +++ b/copy.h\n> @@ -1,10 +1,14 @@\n>   #ifndef COPY_H\n>   #define COPY_H\n>   \n> +struct repository;\n> +\n>   #define COPY_READ_ERROR (-2)\n>   #define COPY_WRITE_ERROR (-3)\n>   int copy_fd(int ifd, int ofd);\n> -int copy_file(const char *dst, const char *src, int mode);\n> -int copy_file_with_time(const char *dst, const char *src, int mode);\n> +int copy_file(struct repository *repo,\n> +\t      const char *dst, const char *src, int mode);\n> +int copy_file_with_time(struct repository *repo,\n> +\t\t\tconst char *dst, const char *src, int mode);\n>   \n>   #endif /* COPY_H */\n> diff --git a/refs/files-backend.c b/refs/files-backend.c\n> index 3df56c25c8..442c98414e 100644\n> --- a/refs/files-backend.c\n> +++ b/refs/files-backend.c\n> @@ -1736,7 +1736,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store,\n>   \t\tgoto out;\n>   \t}\n>   \n> -\tif (copy && log && copy_file(tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n> +\tif (copy && log && copy_file(refs->base.repo, tmp_renamed_log.buf, sb_oldref.buf, 0644)) {\n>   \t\tret = error(\"unable to copy logfile logs/%s to logs/\"TMP_RENAMED_LOG\": %s\",\n>   \t\t\t    oldrefname, strerror(errno));\n>   \t\tgoto out;\n> diff --git a/rerere.c b/rerere.c\n> index 8232542585..bf5cfc6e51 100644\n> --- a/rerere.c\n> +++ b/rerere.c\n> @@ -756,7 +756,7 @@ static void do_rerere_one_path(struct index_state *istate,\n>   \t/* Has the user resolved it already? */\n>   \tif (variant >= 0) {\n>   \t\tif (!handle_file(istate, path, NULL, NULL)) {\n> -\t\t\tcopy_file(rerere_path(&buf, id, \"postimage\"), path, 0666);\n> +\t\t\tcopy_file(the_repository, rerere_path(&buf, id, \"postimage\"), path, 0666);\n>   \t\t\tid->collection->status[variant] |= RR_HAS_POSTIMAGE;\n>   \t\t\tfprintf_ln(stderr, _(\"Recorded resolution for '%s'.\"), path);\n>   \t\t\tfree_rerere_id(rr_item);\n> diff --git a/sequencer.c b/sequencer.c\n> index 1355a99a09..63bc1ef215 100644\n> --- a/sequencer.c\n> +++ b/sequencer.c\n> @@ -2419,7 +2419,7 @@ static int do_pick_commit(struct repository *r,\n>   \t\t} else {\n>   \t\t\tconst char *dest = git_path_squash_msg(r);\n>   \t\t\tunlink(dest);\n> -\t\t\tif (copy_file(dest, rebase_path_squash_msg(), 0666)) {\n> +\t\t\tif (copy_file(r, dest, rebase_path_squash_msg(), 0666)) {\n>   \t\t\t\tres = error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\t\t\t    rebase_path_squash_msg(), dest);\n>   \t\t\t\tgoto leave;\n> @@ -3864,11 +3864,11 @@ static int error_failed_squash(struct repository *r,\n>   \t\t\t       int subject_len,\n>   \t\t\t       const char *subject)\n>   {\n> -\tif (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))\n> +\tif (copy_file(r, rebase_path_message(), rebase_path_squash_msg(), 0666))\n>   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\trebase_path_squash_msg(), rebase_path_message());\n>   \tunlink(git_path_merge_msg(r));\n> -\tif (copy_file(git_path_merge_msg(r), rebase_path_message(), 0666))\n> +\tif (copy_file(r, git_path_merge_msg(r), rebase_path_message(), 0666))\n>   \t\treturn error(_(\"could not copy '%s' to '%s'\"),\n>   \t\t\t     rebase_path_message(),\n>   \t\t\t     git_path_merge_msg(r));\n> diff --git a/setup.c b/setup.c\n> index 0de56a074f..91d61a5939 100644\n> --- a/setup.c\n> +++ b/setup.c\n> @@ -2331,7 +2331,7 @@ static void copy_templates_1(struct repository *repo,\n>   \t\t\tstrbuf_release(&lnk);\n>   \t\t}\n>   \t\telse if (S_ISREG(st_template.st_mode)) {\n> -\t\t\tif (copy_file(path->buf, template_path->buf, st_template.st_mode))\n> +\t\t\tif (copy_file(repo, path->buf, template_path->buf, st_template.st_mode))\n>   \t\t\t\tdie_errno(_(\"cannot copy '%s' to '%s'\"),\n>   \t\t\t\t\t  template_path->buf, path->buf);\n>   \t\t}\n> \n> ---\n> base-commit: d35c5399e3e54ac277bb391fc2f6be3e816d312b\n> change-id: 20260716-pks-copy-wo-the-repository-aa01ccdbed76\n> \n> \n\n"},{"id":"548549","messageId":"xmqqo6g54k7m.fsf@gitster.g","threadId":"66016","inReplyTo":"b0df688a-3b26-48f6-8b1c-98530483885e@gmail.com","subject":"Re: [PATCH v2] copy: drop dependency on `the_repository`","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-17T17:09:01Z","receivedAt":"2026-07-17T17:09:04Z","isPatch":true,"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Patrick\n>\n> This version looks good to me\n>\n> Thanks\n>\n> Phillip\n\nThe changes to 'copy.c' are fairly straightforward and\ntrivially correct.  The resulting updates to the callers\nare also minor, as requiring them to pass 'the_repository'\nintroduces no change in behavior by definition.\n\nThanks.  Let's mark the topic for 'next'.\n\n"}]}