Skip to contentSkip to conversation

format-patch: teach format.notes config option

PATCH In review Denton Liu 2 participants 5 messages May 16, 2019 – Dec 9, 2019 Documentation

lore
Share & tools
lore

Denton Liu

author
#0 lore raw

v4 cover format-patch: teach format.notes config option

Hi Junio,

I've changed format.notes so that it can accept a boolean as well. Hopefully, my last email has addressed the remainder of your comments.

Changes since v3:

* Made format.notes accept a boolean instead of "standard" to get default notes

Changes since v2:

* Fixed if-else code style
* Fixed typoed errors in 2/2 log message

Changes since v1:

* Made format.notes accept a notes ref instead of a boolean

Denton Liu (2):
git-format-patch.txt: document --no-notes option
format-patch: teach format.notes config option

 Documentation/config/format.txt    | 15 +++++++
 Documentation/git-format-patch.txt |  7 ++-
 builtin/log.c                      | 20 ++++++++-
 t/t4014-format-patch.sh            | 70 ++++++++++++++++++++++++++++++
 4 files changed, 110 insertions(+), 2 deletions(-)

Range-diff against v3:

1:  4c3535f25b = 1:  4c3535f25b git-format-patch.txt: document --no-notes option
2:  df864c4adf ! 2:  7cb770e190 format-patch: teach format.notes config option
    @@ -25,14 +25,16 @@
      	format-patch by default.
     +
     +format.notes::
    -+	A ref which specifies where to get the notes (see
    -+	linkgit:git-notes[1]) that are appended for the commit after the
    -+	three-dash line.
    ++	Provides the default value for the `--notes` option to
    ++	format-patch. Accepts a boolean value, or a ref which specifies
    ++	where to get notes. If false, format-patch defaults to
    ++	`--no-notes`. If true, format-patch defaults to `--notes`. If
    ++	set to a non-boolean value, format-patch defaults to
    ++	`--notes=<ref>`, where `ref` is the non-boolean value. Defaults
    ++	to false.
     ++
    -+If the special value of "standard" is specified, then the standard notes
    -+ref is used (i.e. the notes ref used by `git notes` when no `--ref`
    -+argument is specified). If one wishes to use the ref
    -+`ref/notes/standard`, please use that literal instead.
    ++If one wishes to use the ref `ref/notes/true`, please use that literal
    ++instead.
     ++
     +This configuration can be specified multiple times in order to allow
     +multiple notes refs to be included.
    @@ -69,15 +71,17 @@
      	}
     +	if (!strcmp(var, "format.notes")) {
     +		struct strbuf buf = STRBUF_INIT;
    -+
    ++		int b = git_parse_maybe_bool(value);
    ++		if (!b)
    ++			return 0;
     +		rev->show_notes = 1;
    -+		if (!strcmp(value, "standard")) {
    -+			rev->notes_opt.use_default_notes = 1;
    -+		} else {
    ++		if (b < 0) {
     +			strbuf_addstr(&buf, value);
     +			expand_notes_ref(&buf);
     +			string_list_append(&rev->notes_opt.extra_notes_refs,
     +					strbuf_detach(&buf, NULL));
    ++		} else {
    ++			rev->notes_opt.use_default_notes = 1;
     +		}
     +		return 0;
     +	}
    @@ -117,7 +121,7 @@
     +	git format-patch -1 --stdout --no-notes --notes >out &&
     +	grep "notes config message" out &&
     +
    -+	test_config format.notes standard &&
    ++	test_config format.notes true &&
     +	git format-patch -1 --stdout >out &&
     +	grep "notes config message" out &&
     +	git format-patch -1 --stdout --notes >out &&
Signature · 1 line
2.21.0.1049.geb646f7864
author
#1 lore raw

PATCH v4 1/2 git-format-patch.txt: document --no-notes option

Internally, git-format-patch uses the handle_revision_opt parser. The parser handles the --no-notes option to negate an earlier --notes option, but it isn't documented. Document this option so that users are aware of it.

---
 Documentation/git-format-patch.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Documentation/git-format-patch.txt +3 -1
index 1af85d404f..2c3971390e 100644
@@ -22,7 +22,8 @@ SYNOPSIS
 		   [--rfc] [--subject-prefix=Subject-Prefix]
 		   [(--reroll-count|-v) <n>]
 		   [--to=<email>] [--cc=<email>]
-		   [--[no-]cover-letter] [--quiet] [--notes[=<ref>]]
+		   [--[no-]cover-letter] [--quiet]
+		   [--no-notes | --notes[=<ref>]]
 		   [--interdiff=<previous>]
 		   [--range-diff=<previous> [--creation-factor=<percent>]]
 		   [--progress]
@@ -263,6 +264,7 @@ material (this may change in the future).
 	for details.
 
 --notes[=<ref>]::
+--no-notes::
 	Append the notes (see linkgit:git-notes[1]) for the commit
 	after the three-dash line.
 +
Signature · 1 line
2.21.0.1049.geb646f7864
author
#2 lore raw

PATCH v4 2/2 format-patch: teach format.notes config option

In reply to Denton Liu

In git-format-patch, notes can be appended with the --notes option. However, this must be specified by the user on an invocation-by-invocation basis. If a user is not careful, it's possible that they may forget to include it and generate a patch series without notes.

Teach git-format-patch the format.notes config option. Its value is a notes ref that will be automatically appended. The special value of "standard" can be used to specify the standard notes. This option is overridable with the --no-notes option in case a user wishes not to append notes.

---
 Documentation/config/format.txt    | 15 +++++++
 Documentation/git-format-patch.txt |  3 ++
 builtin/log.c                      | 20 ++++++++-
 t/t4014-format-patch.sh            | 70 ++++++++++++++++++++++++++++++
 4 files changed, 107 insertions(+), 1 deletion(-)
Documentation/config/format.txt +15 -0
index dc77941c48..414a5a8a9d 100644
@@ -85,3 +85,18 @@ format.outputDirectory::
 format.useAutoBase::
 	A boolean value which lets you enable the `--base=auto` option of
 	format-patch by default.
+
+format.notes::
+	Provides the default value for the `--notes` option to
+	format-patch. Accepts a boolean value, or a ref which specifies
+	where to get notes. If false, format-patch defaults to
+	`--no-notes`. If true, format-patch defaults to `--notes`. If
+	set to a non-boolean value, format-patch defaults to
+	`--notes=<ref>`, where `ref` is the non-boolean value. Defaults
+	to false.
++
+If one wishes to use the ref `ref/notes/true`, please use that literal
+instead.
++
+This configuration can be specified multiple times in order to allow
+multiple notes refs to be included.
Documentation/git-format-patch.txt +3 -0
index 2c3971390e..9ce5b8aaee 100644
@@ -275,6 +275,9 @@ these explanations after `format-patch` has run but before sending,
 keeping them as Git notes allows them to be maintained between versions
 of the patch series (but see the discussion of the `notes.rewrite`
 configuration options in linkgit:git-notes[1] to use this workflow).
++
+The default is `--no-notes`, unless the `format.notes` configuration is
+set.
 
 --[no-]signature=<signature>::
 	Add a signature to each message produced. Per RFC 3676 the signature
builtin/log.c +19 -1
index e43ee12fb1..dad63cffc6 100644
@@ -779,6 +779,8 @@ enum {
 
 static int git_format_config(const char *var, const char *value, void *cb)
 {
+	struct rev_info *rev = cb;
+
 	if (!strcmp(var, "format.headers")) {
 		if (!value)
 			die(_("format.headers without value"));
@@ -864,6 +866,22 @@ static int git_format_config(const char *var, const char *value, void *cb)
 			from = NULL;
 		return 0;
 	}
+	if (!strcmp(var, "format.notes")) {
+		struct strbuf buf = STRBUF_INIT;
+		int b = git_parse_maybe_bool(value);
+		if (!b)
+			return 0;
+		rev->show_notes = 1;
+		if (b < 0) {
+			strbuf_addstr(&buf, value);
+			expand_notes_ref(&buf);
+			string_list_append(&rev->notes_opt.extra_notes_refs,
+					strbuf_detach(&buf, NULL));
+		} else {
+			rev->notes_opt.use_default_notes = 1;
+		}
+		return 0;
+	}
 
 	return git_log_config(var, value, cb);
 }
@@ -1617,8 +1635,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 	extra_to.strdup_strings = 1;
 	extra_cc.strdup_strings = 1;
 	init_log_defaults();
-	git_config(git_format_config, NULL);
 	repo_init_revisions(the_repository, &rev, prefix);
+	git_config(git_format_config, &rev);
 	rev.commit_format = CMIT_FMT_EMAIL;
 	rev.expand_tabs_in_log_default = 0;
 	rev.verbose_header = 1;
t/t4014-format-patch.sh +70 -0

76 lines not on this page · raw message

Signature · 1 line
2.21.0.1049.geb646f7864
#3 lore raw

Hi Denton,

I was recently digging in this area (due to the recent rebase-applies-patches-incorrectly bug report) and found a couple bugs from this old commit:

Quoted 81 lines · Denton Liu

In git-format-patch, notes can be appended with the --notes option. However, this must be specified by the user on an invocation-by-invocation basis. If a user is not careful, it's possible that they may forget to include it and generate a patch series without notes.

Teach git-format-patch the format.notes config option. Its value is a notes ref that will be automatically appended. The special value of "standard" can be used to specify the standard notes. This option is overridable with the --no-notes option in case a user wishes not to append notes.

---
 Documentation/config/format.txt    | 15 +++++++
 Documentation/git-format-patch.txt |  3 ++
 builtin/log.c                      | 20 ++++++++-
 t/t4014-format-patch.sh            | 70 ++++++++++++++++++++++++++++++
 4 files changed, 107 insertions(+), 1 deletion(-)
Documentation/config/format.txt +15 -0
index dc77941c48..414a5a8a9d 100644
@@ -85,3 +85,18 @@ format.outputDirectory::
 format.useAutoBase::
        A boolean value which lets you enable the `--base=auto` option of
        format-patch by default.
+
+format.notes::
+       Provides the default value for the `--notes` option to
+       format-patch. Accepts a boolean value, or a ref which specifies
+       where to get notes. If false, format-patch defaults to
+       `--no-notes`. If true, format-patch defaults to `--notes`. If
+       set to a non-boolean value, format-patch defaults to
+       `--notes=<ref>`, where `ref` is the non-boolean value. Defaults
+       to false.
++
+If one wishes to use the ref `ref/notes/true`, please use that literal
+instead.
++
+This configuration can be specified multiple times in order to allow
+multiple notes refs to be included.
Documentation/git-format-patch.txt +3 -0
index 2c3971390e..9ce5b8aaee 100644
@@ -275,6 +275,9 @@ these explanations after `format-patch` has run but before sending,
 keeping them as Git notes allows them to be maintained between versions
 of the patch series (but see the discussion of the `notes.rewrite`
 configuration options in linkgit:git-notes[1] to use this workflow).
++
+The default is `--no-notes`, unless the `format.notes` configuration is
+set.
 
 --[no-]signature=<signature>::
        Add a signature to each message produced. Per RFC 3676 the signature
builtin/log.c +8 -0
index e43ee12fb1..dad63cffc6 100644
@@ -779,6 +779,8 @@ enum {
 
 static int git_format_config(const char *var, const char *value, void *cb)
 {
+       struct rev_info *rev = cb;
+
        if (!strcmp(var, "format.headers")) {
                if (!value)
                        die(_("format.headers without value"));
@@ -864,6 +866,22 @@ static int git_format_config(const char *var, const char *value, void *cb)
                        from = NULL;
                return 0;
        }
+       if (!strcmp(var, "format.notes")) {
+               struct strbuf buf = STRBUF_INIT;
+               int b = git_parse_maybe_bool(value);
+               if (!b)
+                       return 0;
+               rev->show_notes = 1;

builtin/log.c static int git_format_config(const char *var, const char *value, void *cb) · line 884

Quoted 10 lines
builtin/log.c +10 -0
+               if (b < 0) {
+                       strbuf_addstr(&buf, value);
+                       expand_notes_ref(&buf);
+                       string_list_append(&rev->notes_opt.extra_notes_refs,
+                                       strbuf_detach(&buf, NULL));
+               } else {
+                       rev->notes_opt.use_default_notes = 1;
+               }
+               return 0;
+       }

What if someone has multiple format.notes entries in their config file, but the last entry is "false" -- shouldn't that disable notes? Also, what if they specify both "true" and e.g. "refs/notes/my-cool-notes"? In that case, should it show refs/notes/my-cool-notes because that's obviously showing some notes so it satisfies true as well as the specific request about which note, or should it treat "true" the same as the-default-notes-ref and then add the two refs together and show them both?

builtin/log.c int cmd_format_patch(int argc, const char **argv, const char *prefix) · line 1639

Quoted 10 lines
builtin/log.c +1 -1
        return git_log_config(var, value, cb);
 }
@@ -1617,8 +1635,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        extra_to.strdup_strings = 1;
        extra_cc.strdup_strings = 1;
        init_log_defaults();
-       git_config(git_format_config, NULL);
        repo_init_revisions(the_repository, &rev, prefix);
+       git_config(git_format_config, &rev);

Calling git_config() after repo_init_revisions() breaks things; generally git_config() should always be called first. Here, git_format_config() can set up parameters used by repo_init_revisions(), and by reversing the order of the two you end up ignoring settings specified by the user (e.g. diff.context having a value of 5). This came up due to the bug report at
https://lore.kernel.org/git/[email protected]/T/#mb6a09958ff10acde295b37a9136bc3791fd4a2c2
(though fixing the issue there _also_ requires fixing git_am_config() to call git_diff_ui_config()). To break the circular dependency here, we'd need to store the information that git_format_config() discovers in some data structure besides rev, and then after the repo_init_revisions() call has finished then update rev.

I was just going to do that, but then ran into the questions above about multiple format.notes entries in the config file, and am not as sure about what should be done about that stuff (and I don't want to try to translate the current behavior as-is while tweaking where the stuff is stored, both because I'm not sure of the right behavior and because I don't want future folks to blame the code to me when they hit bugs in this area), so I'm firing off this email instead.

So, um...help?

Thanks,
Elijah

author
#4 lore raw

Hi Elijah,

Quoted 21 lines · Elijah Newren
Quoted 10 lines
builtin/log.c +6 -0
@@ -864,6 +866,22 @@ static int git_format_config(const char *var, const char *value, void *cb)
                        from = NULL;
                return 0;
        }
+       if (!strcmp(var, "format.notes")) {
+               struct strbuf buf = STRBUF_INIT;
+               int b = git_parse_maybe_bool(value);
+               if (!b)
+                       return 0;
+               rev->show_notes = 1;

builtin/log.c static int git_format_config(const char *var, const char *value, void *cb) · line 884

Quoted 10 lines
builtin/log.c +10 -0
+               if (b < 0) {
+                       strbuf_addstr(&buf, value);
+                       expand_notes_ref(&buf);
+                       string_list_append(&rev->notes_opt.extra_notes_refs,
+                                       strbuf_detach(&buf, NULL));
+               } else {
+                       rev->notes_opt.use_default_notes = 1;
+               }
+               return 0;
+       }
Quoted 8 lines

What if someone has multiple format.notes entries in their config file, but the last entry is "false" -- shouldn't that disable notes? Also, what if they specify both "true" and e.g. "refs/notes/my-cool-notes"? In that case, should it show refs/notes/my-cool-notes because that's obviously showing some notes so it satisfies true as well as the specific request about which note, or should it treat "true" the same as the-default-notes-ref and then add the two refs together and show them both?

I think I'll just copy the existing logic of --notes, --notes=<ref> and --no-notes from revision.c to format.notes = true, format.notes = <ref> and format.notes = false respectively. IOW, with format.notes = true, we'll unconditionally use the default notes, with format.notes = <ref>, we'll append <ref> to the reflist and with format.notes = false, we'll clear and unset the notes refs.

It seems like that logic has been around for almost a decade and I don't think anyone's complained about it so I think it should be safe to duplicate.

Quoted 16 lines

builtin/log.c int cmd_format_patch(int argc, const char **argv, const char *prefix) · line 1639

Quoted 11 lines
builtin/log.c +1 -1
        return git_log_config(var, value, cb);
 }
@@ -1617,8 +1635,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        extra_to.strdup_strings = 1;
        extra_cc.strdup_strings = 1;
        init_log_defaults();
-       git_config(git_format_config, NULL);
        repo_init_revisions(the_repository, &rev, prefix);
+       git_config(git_format_config, &rev);

Calling git_config() after repo_init_revisions() breaks things; generally git_config() should always be called first. Here, git_format_config() can set up parameters used by repo_init_revisions(), and by reversing the order of the two you end

Quoted 8 lines

up ignoring settings specified by the user (e.g. diff.context having a value of 5). This came up due to the bug report at
https://lore.kernel.org/git/[email protected]/T/#mb6a09958ff10acde295b37a9136bc3791fd4a2c2
(though fixing the issue there _also_ requires fixing git_am_config() to call git_diff_ui_config()). To break the circular dependency here, we'd need to store the information that git_format_config() discovers in some data structure besides rev, and then after the repo_init_revisions() call has finished then update rev.

I see, I'll move the git_config() back up while I'm at it.

Quoted 8 lines

I was just going to do that, but then ran into the questions above about multiple format.notes entries in the config file, and am not as sure about what should be done about that stuff (and I don't want to try to translate the current behavior as-is while tweaking where the stuff is stored, both because I'm not sure of the right behavior and because I don't want future folks to blame the code to me when they hit bugs in this area), so I'm firing off this email instead.

Sounds good, I don't want my bugs blamed on anyone else either ;)

I'll try to get a patchset out soon and hopefully you'll be able to base your work off of that.

Thanks,

Denton

Quoted 5 lines

So, um...help?

Thanks,
Elijah