]> git.ipfire.org Git - thirdparty/git.git/commitdiff
rebase -r: let `label` generate safer labels
authorMatthew Rogers <mattr94@gmail.com>
Sun, 17 Nov 2019 23:16:10 +0000 (23:16 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 18 Nov 2019 03:49:17 +0000 (12:49 +0900)
The `label` todo command in interactive rebases creates temporary refs
in the `refs/rewritten/` namespace. These refs are stored as loose refs,
i.e. as files in `.git/refs/rewritten/`, therefore they have to conform
with file name limitations on the current filesystem in addition to the
accepted ref format.

This poses a problem in particular on NTFS/FAT, where e.g. the colon,
double-quote and pipe characters are disallowed as part of a file name.

Let's safeguard against this by replacing not only white-space
characters by dashes, but all non-alpha-numeric ones.

However, we exempt non-ASCII UTF-8 characters from that, as it should be
quite possible to reflect branch names such as `↯↯↯` in refs/file names.

Signed-off-by: Matthew Rogers <mattr94@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sequencer.c
t/t3430-rebase-merges.sh

index 85c66f489ff10f586652cc2767f4bd56f431b92f..fece07b680f2c913047c9d32dcaee9a175fa27d5 100644 (file)
@@ -4471,8 +4471,26 @@ static const char *label_oid(struct object_id *oid, const char *label,
        } else {
                struct strbuf *buf = &state->buf;
 
+               /*
+                * Sanitize labels by replacing non-alpha-numeric characters
+                * (including white-space ones) by dashes, as they might be
+                * illegal in file names (and hence in ref names).
+                *
+                * Note that we retain non-ASCII UTF-8 characters (identified
+                * via the most significant bit). They should be all acceptable
+                * in file names. We do not validate the UTF-8 here, that's not
+                * the job of this function.
+                */
                for (; *label; label++)
-                       strbuf_addch(buf, isspace(*label) ? '-' : *label);
+                       if ((*label & 0x80) || isalnum(*label))
+                               strbuf_addch(buf, *label);
+                       /* avoid leading dash and double-dashes */
+                       else if (buf->len && buf->buf[buf->len - 1] != '-')
+                               strbuf_addch(buf, '-');
+               if (!buf->len) {
+                       strbuf_addstr(buf, "rev-");
+                       strbuf_add_unique_abbrev(buf, oid, default_abbrev);
+               }
                label = buf->buf;
 
                if ((buf->len == the_hash_algo->hexsz &&
index 9efcf4808ac92f13272e279fe4d7b660fccf8da3..f728aba995b2fdc85e9c899372f00e3504d99184 100755 (executable)
@@ -468,4 +468,10 @@ test_expect_success '--rebase-merges with strategies' '
        test_cmp expect G.t
 '
 
+test_expect_success '--rebase-merges with commit that can generate bad characters for filename' '
+       git checkout -b colon-in-label E &&
+       git merge -m "colon: this should work" G &&
+       git rebase --rebase-merges --force-rebase E
+'
+
 test_done