]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'jc/format-patch-name-max'
authorJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2020 23:14:38 +0000 (15:14 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sat, 21 Nov 2020 23:14:38 +0000 (15:14 -0800)
The maximum length of output filenames "git format-patch" creates
has become configurable (used to be capped at 64).

* jc/format-patch-name-max:
  format-patch: make output filename configurable

Documentation/config/format.txt
Documentation/git-format-patch.txt
builtin/log.c
log-tree.c
log-tree.h
revision.h
t/t4014-format-patch.sh

index 851bf410a3bba8ff41e78993b9642d7a23d1652a..fdbc06a4d2a837f768a213fd5ffdf28ad5a48315 100644 (file)
@@ -94,6 +94,11 @@ format.outputDirectory::
        Set a custom directory to store the resulting files instead of the
        current working directory. All directory components will be created.
 
+format.filenameMaxLength::
+       The maximum length of the output filenames generated by the
+       `format-patch` command; defaults to 64.  Can be overridden
+       by the `--filename-max-length=<n>` command line option.
+
 format.useAutoBase::
        A boolean value which lets you enable the `--base=auto` option of
        format-patch by default. Can also be set to "whenAble" to allow
index bf1bb40f6303fab2a8362af493b1839af21471f2..3e49bf221087c06c7850e66cdc833b92d7dcb9bc 100644 (file)
@@ -28,6 +28,7 @@ SYNOPSIS
                   [--no-notes | --notes[=<ref>]]
                   [--interdiff=<previous>]
                   [--range-diff=<previous> [--creation-factor=<percent>]]
+                  [--filename-max-length=<n>]
                   [--progress]
                   [<common diff options>]
                   [ <since> | <revision range> ]
@@ -200,6 +201,13 @@ populated with placeholder text.
        allows for useful naming of a patch series, and can be
        combined with the `--numbered` option.
 
+--filename-max-length=<n>::
+       Instead of the standard 64 bytes, chomp the generated output
+       filenames at around '<n>' bytes (too short a value will be
+       silently raised to a reasonable length).  Defaults to the
+       value of the `format.filenameMaxLength` configuration
+       variable, or 64 if unconfigured.
+
 --rfc::
        Alias for `--subject-prefix="RFC PATCH"`. RFC means "Request For
        Comments"; use this when sending an experimental patch for
index 49eb8f6431b198d8942d48c77c1cc96e95fd3a0e..08204e3196418217b233387fdf1880af70447ec9 100644 (file)
@@ -37,6 +37,7 @@
 
 #define MAIL_DEFAULT_WRAP 72
 #define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
+#define FORMAT_PATCH_NAME_MAX_DEFAULT 64
 
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
@@ -50,6 +51,7 @@ static int decoration_style;
 static int decoration_given;
 static int use_mailmap_config = 1;
 static const char *fmt_patch_subject_prefix = "PATCH";
+static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
 static const char *fmt_pretty;
 
 static const char * const builtin_log_usage[] = {
@@ -150,6 +152,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)
        rev->abbrev_commit = default_abbrev_commit;
        rev->show_root_diff = default_show_root;
        rev->subject_prefix = fmt_patch_subject_prefix;
+       rev->patch_name_max = fmt_patch_name_max;
        rev->show_signature = default_show_signature;
        rev->encode_email_headers = default_encode_email_headers;
        rev->diffopt.flags.allow_textconv = 1;
@@ -457,6 +460,10 @@ static int git_log_config(const char *var, const char *value, void *cb)
                return git_config_string(&fmt_pretty, var, value);
        if (!strcmp(var, "format.subjectprefix"))
                return git_config_string(&fmt_patch_subject_prefix, var, value);
+       if (!strcmp(var, "format.filenamemaxlength")) {
+               fmt_patch_name_max = git_config_int(var, value);
+               return 0;
+       }
        if (!strcmp(var, "format.encodeemailheaders")) {
                default_encode_email_headers = git_config_bool(var, value);
                return 0;
@@ -958,15 +965,9 @@ static int open_next_file(struct commit *commit, const char *subject,
                         struct rev_info *rev, int quiet)
 {
        struct strbuf filename = STRBUF_INIT;
-       int suffix_len = strlen(rev->patch_suffix) + 1;
 
        if (output_directory) {
                strbuf_addstr(&filename, output_directory);
-               if (filename.len >=
-                   PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
-                       strbuf_release(&filename);
-                       return error(_("name of output directory is too long"));
-               }
                strbuf_complete(&filename, '/');
        }
 
@@ -1754,6 +1755,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                            N_("start numbering patches at <n> instead of 1")),
                OPT_INTEGER('v', "reroll-count", &reroll_count,
                            N_("mark the series as Nth re-roll")),
+               OPT_INTEGER(0, "filename-max-length", &fmt_patch_name_max,
+                           N_("max length of output filename")),
                OPT_CALLBACK_F(0, "rfc", &rev, NULL,
                            N_("Use [RFC PATCH] instead of [PATCH]"),
                            PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback),
@@ -1854,6 +1857,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                             PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
                             PARSE_OPT_KEEP_DASHDASH);
 
+       /* Make sure "0000-$sub.patch" gives non-negative length for $sub */
+       if (fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
+               fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
+
        if (cover_from_description_arg)
                cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
 
@@ -1938,6 +1945,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
 
        rev.zero_commit = zero_commit;
+       rev.patch_name_max = fmt_patch_name_max;
 
        if (!rev.diffopt.flags.text && !no_binary_diff)
                rev.diffopt.flags.binary = 1;
index 1927f917ce94ce2ec95c889754d6a86177fa2cac..fd0dde97ec324ff6611fa5a7685d4b2831350b3c 100644 (file)
@@ -367,7 +367,7 @@ void fmt_output_subject(struct strbuf *filename,
        const char *suffix = info->patch_suffix;
        int nr = info->nr;
        int start_len = filename->len;
-       int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1);
+       int max_len = start_len + info->patch_name_max - (strlen(suffix) + 1);
 
        if (0 < info->reroll_count)
                strbuf_addf(filename, "v%d-", info->reroll_count);
index 8fa79289ec6b6cb27e68534845d345caf40137ea..1e8c91dbf21f365efcb2b4e966ba6e1cff23ad95 100644 (file)
@@ -33,7 +33,6 @@ void log_write_email_headers(struct rev_info *opt, struct commit *commit,
                             int maybe_multipart);
 void load_ref_decorations(struct decoration_filter *filter, int flags);
 
-#define FORMAT_PATCH_NAME_MAX 64
 void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *);
 void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *);
 void fmt_output_email_subject(struct strbuf *, struct rev_info *);
index f6bf860d19e5a2997193c25873a5ba82e030f68b..086ff10280db586f2c714f989b10e4e8b082cf03 100644 (file)
@@ -238,6 +238,7 @@ struct rev_info {
        const char      *extra_headers;
        const char      *log_reencode;
        const char      *subject_prefix;
+       int             patch_name_max;
        int             no_inline;
        int             show_log_size;
        struct string_list *mailmap;
index 42588bf6e11fd5ff0aee94e0cffeab3a62f963c8..c5e5e0da3feef439415dbf9cfd235140eba7d0d9 100755 (executable)
@@ -313,6 +313,60 @@ test_expect_success 'multiple files' '
        ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
 '
 
+test_expect_success 'filename length limit' '
+       test_when_finished "rm -f 000*" &&
+       rm -rf 000[1-9]-*.patch &&
+       for len in 15 25 35
+       do
+               git format-patch --filename-max-length=$len -3 side &&
+               max=$(
+                       for patch in 000[1-9]-*.patch
+                       do
+                               echo "$patch" | wc -c
+                       done |
+                       sort -nr |
+                       head -n 1
+               ) &&
+               test $max -le $len || return 1
+       done
+'
+
+test_expect_success 'filename length limit from config' '
+       test_when_finished "rm -f 000*" &&
+       rm -rf 000[1-9]-*.patch &&
+       for len in 15 25 35
+       do
+               git -c format.filenameMaxLength=$len format-patch -3 side &&
+               max=$(
+                       for patch in 000[1-9]-*.patch
+                       do
+                               echo "$patch" | wc -c
+                       done |
+                       sort -nr |
+                       head -n 1
+               ) &&
+               test $max -le $len || return 1
+       done
+'
+
+test_expect_success 'filename limit applies only to basename' '
+       test_when_finished "rm -rf patches/" &&
+       rm -rf patches/ &&
+       for len in 15 25 35
+       do
+               git format-patch -o patches --filename-max-length=$len -3 side &&
+               max=$(
+                       for patch in patches/000[1-9]-*.patch
+                       do
+                               echo "${patch#patches/}" | wc -c
+                       done |
+                       sort -nr |
+                       head -n 1
+               ) &&
+               test $max -le $len || return 1
+       done
+'
+
 test_expect_success 'reroll count' '
        rm -fr patches &&
        git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&