Re: [PATCH] format-patch: add --filename-prefix to prepend a prefix to output file names

4 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH] format-patch: add --filename-prefix to prepend a prefix to output file names

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:56

Nguyễn Thái Ngọc Duy  [off-list ref] writes:
I use git to manage patches in my Gentoo development. In Gentoo, all
ebuilds (another form of RPM spec) corresponding to different versions
of the same package are grouped into one directory. So patches for
each version usually have a prefix to separate them from ones for
other versions. With --filename-prefix it comes handy to produce such
patches, for example:

git format-patch --filename-prefix dbus-1.2.3- HEAD~5

will generate patches for dbus-1.2.3 for me, all starting with "dbus-1.2.3-".

This might be handy for RPM developers as well.
If this patch needs another round, I would prefer seeing the explanation
done in a different order.  When a busy person who is uninterested in
Gentoo starts reading the above paragraph, the patch will (incorrectly) be
dismissed with an "Ah, Gentoo specific feature?  Not interesting." after
reading the first two lines.  I.e. "Add X that does Y.  This is useful in
such and such situations because ...".
+--filename-prefix=.<pfx>::
+	Prepend specified prefix in front of generated filenames.
Hmm... ;-)

What happens when I feed a path with a slash in it with --filename-prefix?
We will fail in open/creat if the leading path does not exist?

I am not saying we must allow a slash in the prefix and create necessary
leading paths ourselves, nor we must check for a slash and fail in the
input validation phase, but I am wondering if we can have some clever way
to internally unify the handling of this new option with --outdir.
quoted hunk
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 8b33321..cf16c0a 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -246,6 +246,7 @@ format-patch --stdout initial..master
 format-patch --stdout --no-numbered initial..master
 format-patch --stdout --numbered initial..master
 format-patch --attach --stdout initial..side
+format-patch --attach --stdout --filename-prefix=foo- initial..side
Heh, clever.  I wondered what the point of testing with --stdout was
for a patch that affects the generated filename.  The magic of --attach ;-)

[PATCH] format-patch: add --filename-prefix to prepend a prefix to output file names

From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:46:57

In Linux packaging, patches are usually saved along with the "package
spec" (to suit distro specific needs or just to back port some
fixes). Those patches are usually prefixed with either the package
name, or package version for various reasons. With --filename-prefix
it comes handy to produce such patches, for example:

git format-patch --filename-prefix dbus-1.2.3- HEAD~5

will generate patches for dbus-1.2.3 for me, all starting with "dbus-1.2.3-".

Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
 On Wed, Jun 10, 2009 at 08:58:01AM -0700, Junio C Hamano wrote:
 > Nguyễn Thái Ngọc Duy  [off-list ref] writes:
 > 
 > > I use git to manage patches in my Gentoo development. In Gentoo, all
 > > ebuilds (another form of RPM spec) corresponding to different versions
 > > of the same package are grouped into one directory. So patches for
 > > each version usually have a prefix to separate them from ones for
 > > other versions. With --filename-prefix it comes handy to produce such
 > > patches, for example:
 > >
 > > git format-patch --filename-prefix dbus-1.2.3- HEAD~5
 > >
 > > will generate patches for dbus-1.2.3 for me, all starting with "dbus-1.2.3-".
 > >
 > > This might be handy for RPM developers as well.
 > 
 > If this patch needs another round, I would prefer seeing the explanation
 > done in a different order.  When a busy person who is uninterested in
 > Gentoo starts reading the above paragraph, the patch will (incorrectly) be
 > dismissed with an "Ah, Gentoo specific feature?  Not interesting." after
 > reading the first two lines.  I.e. "Add X that does Y.  This is useful in
 > such and such situations because ...".

 Done

 > 
 > > +--filename-prefix=.<pfx>::
 > > +	Prepend specified prefix in front of generated filenames.
 > 
 > Hmm... ;-)
 > 
 > What happens when I feed a path with a slash in it with --filename-prefix?
 > We will fail in open/creat if the leading path does not exist?
 > 
 > I am not saying we must allow a slash in the prefix and create necessary
 > leading paths ourselves, nor we must check for a slash and fail in the
 > input validation phase, but I am wondering if we can have some clever way
 > to internally unify the handling of this new option with --outdir.

 Hardly, the way it is handled now (chdir()ing to --outdir, then write patches)

 Documentation/git-format-patch.txt                 |    6 ++-
 builtin-log.c                                      |    9 ++-
 log-tree.c                                         |   10 ++-
 log-tree.h                                         |    4 +-
 revision.h                                         |    1 +
 t/t4013-diff-various.sh                            |    1 +
 ...h_--stdout_--filename-prefix=foo-_initial..side |   61 ++++++++++++++++++++
 7 files changed, 83 insertions(+), 9 deletions(-)
 create mode 100644 t/t4013/diff.format-patch_--attach_--stdout_--filename-prefix=foo-_initial..side
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 6f1fc80..052a3b8 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -15,7 +15,8 @@ SYNOPSIS
 		   [-s | --signoff]
 		   [-n | --numbered | -N | --no-numbered]
 		   [--start-number <n>] [--numbered-files]
-		   [--in-reply-to=Message-Id] [--suffix=.<sfx>]
+		   [--in-reply-to=Message-Id]
+		   [--filename-prefix=<pfx>] [--suffix=.<sfx>]
 		   [--ignore-if-in-upstream]
 		   [--subject-prefix=Subject-Prefix]
 		   [--cc=<email>]
@@ -168,6 +169,9 @@ if that is not set.
 	containing the shortlog and the overall diffstat.  You can
 	fill in a description in the file before sending it out.
 
+--filename-prefix=<pfx>::
+	Prepend specified prefix in front of generated filenames.
+
 --suffix=.<sfx>::
 	Instead of using `.patch` as the suffix for generated
 	filenames, use specified suffix.  A common alternative is
diff --git a/builtin-log.c b/builtin-log.c
index 0d34050..d458753 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -419,6 +419,7 @@ int cmd_log(int argc, const char **argv, const char *prefix)
 
 /* format-patch */
 
+static const char *fmt_patch_prefix = "";
 static const char *fmt_patch_suffix = ".patch";
 static int numbered = 0;
 static int auto_number = 1;
@@ -524,18 +525,19 @@ static int outdir_offset;
 static int reopen_stdout(struct commit *commit, struct rev_info *rev)
 {
 	struct strbuf filename = STRBUF_INIT;
+	int prefix_len = strlen(fmt_patch_prefix);
 	int suffix_len = strlen(fmt_patch_suffix) + 1;
 
 	if (output_directory) {
 		strbuf_addstr(&filename, output_directory);
 		if (filename.len >=
-		    PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
+		    PATH_MAX - FORMAT_PATCH_NAME_MAX - prefix_len - suffix_len)
 			return error("name of output directory is too long");
 		if (filename.buf[filename.len - 1] != '/')
 			strbuf_addch(&filename, '/');
 	}
 
-	get_patch_filename(commit, rev->nr, fmt_patch_suffix, &filename);
+	get_patch_filename(commit, rev->nr, fmt_patch_prefix, fmt_patch_suffix, &filename);
 
 	if (!DIFF_OPT_TST(&rev->diffopt, QUIET))
 		fprintf(realstdout, "%s\n", filename.buf + outdir_offset);
@@ -877,6 +879,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 			    "generate a cover letter"),
 		OPT_BOOLEAN(0, "numbered-files", &numbered_files,
 			    "use simple number sequence for output file names"),
+		OPT_STRING(0, "filename-prefix", &fmt_patch_prefix, "pfx",
+			    "prepend <pfx> to output file names"),
 		OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
 			    "use <sfx> instead of '.patch'"),
 		OPT_INTEGER(0, "start-number", &start_number,
@@ -1093,6 +1097,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 		string_list_append(msgid, rev.ref_message_ids);
 	}
 	rev.numbered_files = numbered_files;
+	rev.patch_prefix = fmt_patch_prefix;
 	rev.patch_suffix = fmt_patch_suffix;
 	if (cover_letter) {
 		if (thread)
diff --git a/log-tree.c b/log-tree.c
index 59d63eb..139c8b5 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -180,12 +180,13 @@ static int has_non_ascii(const char *s)
 	return 0;
 }
 
-void get_patch_filename(struct commit *commit, int nr, const char *suffix,
-			struct strbuf *buf)
+void get_patch_filename(struct commit *commit, int nr, const char *prefix,
+			const char *suffix, struct strbuf *buf)
 {
 	int suffix_len = strlen(suffix) + 1;
-	int start_len = buf->len;
+	int start_len = buf->len + strlen(prefix);
 
+	strbuf_addstr(buf, prefix);
 	strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
 	if (commit) {
 		int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
@@ -263,7 +264,8 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 		extra_headers = subject_buffer;
 
 		get_patch_filename(opt->numbered_files ? NULL : commit, opt->nr,
-				    opt->patch_suffix, &filename);
+				    opt->patch_prefix, opt->patch_suffix,
+				    &filename);
 		snprintf(buffer, sizeof(buffer) - 1,
 			 "\n--%s%s\n"
 			 "Content-Type: text/x-patch;"
diff --git a/log-tree.h b/log-tree.h
index 20b5caf..566c85d 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -20,7 +20,7 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
 void load_ref_decorations(void);
 
 #define FORMAT_PATCH_NAME_MAX 64
-void get_patch_filename(struct commit *commit, int nr, const char *suffix,
-			struct strbuf *buf);
+void get_patch_filename(struct commit *commit, int nr, const char *prefix,
+			const char *suffix, struct strbuf *buf);
 
 #endif
diff --git a/revision.h b/revision.h
index 227164c..b35c038 100644
--- a/revision.h
+++ b/revision.h
@@ -85,6 +85,7 @@ struct rev_info {
 	struct log_info *loginfo;
 	int		nr, total;
 	const char	*mime_boundary;
+	const char	*patch_prefix;
 	const char	*patch_suffix;
 	int		numbered_files;
 	char		*message_id;
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 8b33321..cf16c0a 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -246,6 +246,7 @@ format-patch --stdout initial..master
 format-patch --stdout --no-numbered initial..master
 format-patch --stdout --numbered initial..master
 format-patch --attach --stdout initial..side
+format-patch --attach --stdout --filename-prefix=foo- initial..side
 format-patch --attach --stdout --suffix=.diff initial..side
 format-patch --attach --stdout initial..master^
 format-patch --attach --stdout initial..master
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_--filename-prefix=foo-_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_--filename-prefix=foo-_initial..side
new file mode 100644
index 0000000..72127eb
--- /dev/null
+++ b/t/t4013/diff.format-patch_--attach_--stdout_--filename-prefix=foo-_initial..side
@@ -0,0 +1,61 @@
+$ git format-patch --attach --stdout --filename-prefix=foo- initial..side
+From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
+From: A U Thor <author@example.com>
+Date: Mon, 26 Jun 2006 00:03:00 +0000
+Subject: [PATCH] Side
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------g-i-t--v-e-r-s-i-o-n"
+
+This is a multi-part message in MIME format.
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+---
+ dir/sub |    2 ++
+ file0   |    3 +++
+ file3   |    4 ++++
+ 3 files changed, 9 insertions(+), 0 deletions(-)
+ create mode 100644 file3
+
+
+--------------g-i-t--v-e-r-s-i-o-n
+Content-Type: text/x-patch; name="foo-0001-Side.patch"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: attachment; filename="foo-0001-Side.patch"
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..7289e35 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++1
++2
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+--- /dev/null
++++ b/file3
+@@ -0,0 +1,4 @@
++A
++B
++1
++2
+
+--------------g-i-t--v-e-r-s-i-o-n--
+
+
+$
-- 
1.6.3.2.318.g2fd57

Re: [PATCH] format-patch: add --filename-prefix to prepend a prefix to output file names

From: Stephen Boyd <hidden>
Date: 2016-06-15 22:46:57

Nguyễn Thái Ngọc Duy wrote:
quoted hunk
diff --git a/log-tree.c b/log-tree.c
index 59d63eb..139c8b5 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -180,12 +180,13 @@ static int has_non_ascii(const char *s)
 	return 0;
 }
 
-void get_patch_filename(struct commit *commit, int nr, const char *suffix,
-			struct strbuf *buf)
+void get_patch_filename(struct commit *commit, int nr, const char *prefix,
+			const char *suffix, struct strbuf *buf)
 {
 	int suffix_len = strlen(suffix) + 1;
-	int start_len = buf->len;
+	int start_len = buf->len + strlen(prefix);
 
+	strbuf_addstr(buf, prefix);
 	strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
 	if (commit) {
 		int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
  
Why does the prefix length not count against the filename length? I
think you want to subtract a prefix_len.

Also, this doesn't replace the numbering (0001, 0002, etc.) which I
consider to be a prefix. Does anyone else feel the same way?

This is kind of a funny thought, but I'll throw it out there. Could you
just put the desired prefix in your patch subjects, and then add an
option for no-numbered-files? So in your case, you add "dbus 1.2.3" at
the start of each subject during git-commit and then format-patch with
--no-numbered-files. This way you get git to insert the dashes you want,
other people get files with no numbers, and you don't have to deal with
slashes and directory prefixes.

I'm kind of confused about this though. The patches you're generating
for Gentoo are not being read by humans; merely being applied by portage
correct? Are you going back and removing the mail headers and commit
messages from these patches? What I'm getting at is for your case
format-patch may be overkill.

Re: [PATCH] format-patch: add --filename-prefix to prepend a prefix to output file names

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:46:57

2009/6/14 Stephen Boyd [off-list ref]:
Nguyễn Thái Ngọc Duy wrote:
quoted
diff --git a/log-tree.c b/log-tree.c
index 59d63eb..139c8b5 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -180,12 +180,13 @@ static int has_non_ascii(const char *s)
      return 0;
 }

-void get_patch_filename(struct commit *commit, int nr, const char *suffix,
-                     struct strbuf *buf)
+void get_patch_filename(struct commit *commit, int nr, const char *prefix,
+                     const char *suffix, struct strbuf *buf)
 {
      int suffix_len = strlen(suffix) + 1;
-     int start_len = buf->len;
+     int start_len = buf->len + strlen(prefix);

+     strbuf_addstr(buf, prefix);
      strbuf_addf(buf, commit ? "%04d-" : "%d", nr);
      if (commit) {
              int max_len = start_len + FORMAT_PATCH_NAME_MAX - suffix_len;
Why does the prefix length not count against the filename length? I
think you want to subtract a prefix_len.

Also, this doesn't replace the numbering (0001, 0002, etc.) which I
consider to be a prefix. Does anyone else feel the same way?

This is kind of a funny thought, but I'll throw it out there. Could you
just put the desired prefix in your patch subjects, and then add an
option for no-numbered-files? So in your case, you add "dbus 1.2.3" at
the start of each subject during git-commit and then format-patch with
--no-numbered-files. This way you get git to insert the dashes you want,
other people get files with no numbers, and you don't have to deal with
slashes and directory prefixes.
Well, for true flexibility, I would implement something like printf
format. But that would be overkill.
I'm kind of confused about this though. The patches you're generating
for Gentoo are not being read by humans; merely being applied by portage
correct? Are you going back and removing the mail headers and commit
messages from these patches? What I'm getting at is for your case
format-patch may be overkill.
They are read by human, i.e. ebuild developers, and uptream developers
too when they are submitted upstream (which is great because if
upstream uses Git, you don't have to do anything else). Plain patches
are enough for portage, other information is for human ;-)
-- 
Duy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help