threads / patch / 52515

patchformat-patch: make format.outputDirectory relative to worktree

Subject: [PATCH] format-patch: make format.outputDirectory relative to worktree

## tl;dr

4 messages between Dec 24, 2019 and Dec 25, 2019. Diffs are folded; open one to read it.

replies: 3people: 2as markdown or json

Denton Liu· Dec 24, 2019, 12:37 UTC · lore

Currently, when format-patch outputs patches to the path specified by the `format.outputDirectory` configuration variable, it is relative to the current working directory. However, it would make more sense for the path to be relative to the worktree if it exists so that patches will be placed in one location even if a user were to change directories.

Rewrite the output directory logic for format-patch so that it will be relative to the worktree of the directory. An escape hatch is provided for if the previous behaviour is desired by prepending "./" to the variable.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 Documentation/config/format.txt |  3 +++
 builtin/log.c                   | 20 ++++++++++++-----
 t/t4014-format-patch.sh         | 39 +++++++++++++++++++++++++++++++++
 3 files changed, 56 insertions(+), 6 deletions(-)
Show changes to 3 files +56 −6

Documentation/config/format.txt, builtin/log.c, t/t4014-format-patch.sh

diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 513fcd88d5..fc9d110d88 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -88,6 +88,9 @@ format.coverLetter::
 format.outputDirectory::
 	Set a custom directory to store the resulting files instead of the
 	current working directory. All directory components will be created.
+	The path specified will be relative to the worktree of the repository
+	unless the path begins with "./" or there is no worktree in which case
+	the path will be relative to current working directory.
 
 format.useAutoBase::
 	A boolean value which lets you enable the `--base=auto` option of
diff --git a/builtin/log.c b/builtin/log.c
index 8c664067ca..fe072c7309 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -885,7 +885,7 @@ static int git_format_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 	if (!strcmp(var, "format.outputdirectory"))
-		return git_config_string(&config_output_directory, var, value);
+		return git_config_pathname(&config_output_directory, var, value);
 	if (!strcmp(var, "format.useautobase")) {
 		base_auto = git_config_bool(var, value);
 		return 0;
@@ -1841,13 +1841,21 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	if (rev.show_notes)
 		init_display_notes(&rev.notes_opt);
 
-	if (!output_directory && !use_stdout)
-		output_directory = config_output_directory;
+	if (!use_stdout) {
+		const char *outdir_prefix = NULL;
+		const char *outdir = config_output_directory;
 
-	if (!use_stdout)
-		output_directory = set_outdir(prefix, output_directory);
-	else
+		if (output_directory)
+			outdir = output_directory;
+
+		if (output_directory ||
+		    (config_output_directory && starts_with(config_output_directory, "./")))
+			outdir_prefix = prefix;
+
+		output_directory = set_outdir(outdir_prefix, outdir);
+	} else {
 		setup_pager();
+	}
 
 	if (output_directory) {
 		int saved;
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index a5b6302a1c..cc13cc4699 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -1813,6 +1813,45 @@ test_expect_success 'format-patch format.outputDirectory option' '
 	test_line_count = $count list
 '
 
+test_expect_success 'format-patch format.outputDirectory option relative to git dir' '
+	test_config format.outputDirectory patches &&
+	rm -fr patches &&
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git format-patch master..side
+	) &&
+	count=$(git rev-list --count master..side) &&
+	ls patches >list &&
+	test_line_count = $count list
+'
+
+test_expect_success 'format-patch format.outputDirectory option with relative path' '
+	test_config format.outputDirectory ./patches &&
+	mkdir -p sub &&
+	(
+		cd sub &&
+		rm -fr patches &&
+		git format-patch master..side &&
+		count=$(git rev-list --count master..side) &&
+		ls patches >list &&
+		test_line_count = $count list
+	)
+'
+
+test_expect_success 'format-patch format.outputDirectory option absolute path' '
+	test_config format.outputDirectory "$PWD/patches" &&
+	rm -fr patches &&
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git format-patch master..side
+	) &&
+	count=$(git rev-list --count master..side) &&
+	ls patches >list &&
+	test_line_count = $count list
+'
+
 test_expect_success 'format-patch -o overrides format.outputDirectory' '
 	test_config format.outputDirectory patches &&
 	rm -fr patches patchset &&
-- 
2.24.1.810.g65a2f617f4
Junio C Hamano· Dec 24, 2019, 19:25 UTC · re: Denton Liu · lore

Re: [PATCH] format-patch: make format.outputDirectory relative to worktree

Denton Liu <liu.denton@gmail.com> writes:
Show 5 quoted lines
> Currently, when format-patch outputs patches to the path specified by
> the `format.outputDirectory` configuration variable, it is relative to
> the current working directory. However, it would make more sense for the
> path to be relative to the worktree if it exists so that patches will be
> placed in one location even if a user were to change directories.

Would it make more sense? If a user is deep in the hierarchy, after running

	$ git format-patch master..

the next thing the user would want to do is to go to the directory and give them final review and edit the patches before sending out. That would involve going up some levels depending on where s/he is, in other words, the location the patches are found would be different and this change makes it a lot more cumbersome to go there with a relative path. The only people who benefit from the change is those who have their working trees at very shallow hierarchy so that it is not cumbersome for them to give the full path to the top of them.

So I think this cuts both ways, and "it would make more sense" is overselling. Besides, those who can easily give the full path to the top of the working tree (because they are short) can spell that short path to outputDirectory configuration variable just once and be done with it, no?

> Rewrite the output directory logic for format-patch so that it will be
> relative to the worktree of the directory. An escape hatch is provided
> for if the previous behaviour is desired by prepending "./" to the
> variable.

Anything that forces existing users to change their existing settings is not an escape hatch. It merely is a regression with a possible workaround.

So I dunno. I probably would have accepted a patch that *adds* outputDirectory configuration that behaves the way you are proposing in this patch if we did not have the variable yet in the system (i.e. three or four years ago), but I am not sure if it is a good idea to change it after these years.

Denton Liu· Dec 24, 2019, 22:05 UTC · re: Junio C Hamano · lore

Re: [PATCH] format-patch: make format.outputDirectory relative to worktree

Hi Junio,
On Tue, Dec 24, 2019 at 11:25:18AM -0800, Junio C Hamano wrote:
Show 15 quoted lines
> Denton Liu <liu.denton@gmail.com> writes:
> > Rewrite the output directory logic for format-patch so that it will be
> > relative to the worktree of the directory. An escape hatch is provided
> > for if the previous behaviour is desired by prepending "./" to the
> > variable.
> 
> Anything that forces existing users to change their existing
> settings is not an escape hatch.  It merely is a regression with a
> possible workaround.
> 
> So I dunno.  I probably would have accepted a patch that *adds*
> outputDirectory configuration that behaves the way you are proposing
> in this patch if we did not have the variable yet in the system
> (i.e. three or four years ago), but I am not sure if it is a good
> idea to change it after these years.

Perhaps instead of switching the default behaviour so that it's always relative to the top of the worktree, we can add some sort of prefix to indicate that we want this behaviour. Maybe `worktree:path/from/top` or `^path/from/top` or something like this?

Thanks,
Denton
Junio C Hamano· Dec 25, 2019, 02:26 UTC · re: Denton Liu · lore

Re: [PATCH] format-patch: make format.outputDirectory relative to worktree

Denton Liu <liu.denton@gmail.com> writes:
> ... Maybe `worktree:path/from/top` or
> `^path/from/top` or something like this?

I recall seeing a similar idea with a bit better syntax discussed when we talked about path-type values in the configuration system, where we use "~WORD~/" prefix to expand to Git specific special places in the filesystem, just like "~USER/" prefix expands to the home directory of the user. E.g. "~gitdir~/config" may expand to point at the per-repository configuration file in the current repository, and "~worktree~/Makefile" may be the top-level Makefile checked out in the current worktree. This depends on the fact that nobody sane has username ending with tilde (and if there is such a user, tough luck for that user). I'm tempted to credit Dscho for the idea but it could have been by J6t.

Does anybody have a pointer to the discussion thread?

← back to recent threads