50
51
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
52
53
+/*
54
+ * To accommodate common filesystem limitations, where the loose refs' file
55
+ * names must not exceed `NAME_MAX`, the labels generated by `git rebase
56
+ * --rebase-merges` need to be truncated if the corresponding commit subjects
57
+ * are too long.
58
+ * Add some margin to stay clear from reaching `NAME_MAX`.
59
+ */
60
+#define GIT_MAX_LABEL_LENGTH ((NAME_MAX) - (LOCK_SUFFIX_LEN) - 16)
61
+
62
static const char sign_off_header[] = "Signed-off-by: ";
63
static const char cherry_picked_prefix[] = "(cherry picked from commit ";
64
5395
}
5396
} else {
5397
struct strbuf *buf = &state->buf;
5398
+ int label_is_utf8 = 1; /* start with this assumption */
5399
+ size_t max_len = buf->len + GIT_MAX_LABEL_LENGTH;
5400
5401
/*
5402
* Sanitize labels by replacing non-alpha-numeric characters
5405
*
5406
* Note that we retain non-ASCII UTF-8 characters (identified
5407
* via the most significant bit). They should be all acceptable
5397
- * in file names. We do not validate the UTF-8 here, that's not
5398
- * the job of this function.
5408
+ * in file names.
5409
+ *
5410
+ * As we will use the labels as names of (loose) refs, it is
5411
+ * vital that the name not be longer than the maximum component
5412
+ * size of the file system (`NAME_MAX`). We are careful to
5413
+ * truncate the label accordingly, allowing for the `.lock`
5414
+ * suffix and for the label to be UTF-8 encoded (i.e. we avoid
5415
+ * truncating in the middle of a character).
5416
*/
5400
- for (; *label; label++)
5401
- if ((*label & 0x80) || isalnum(*label))
5417
+ for (; *label && buf->len + 1 < max_len; label++)
5418
+ if (isalnum(*label) ||
5419
+ (!label_is_utf8 && (*label & 0x80)))
5420
strbuf_addch(buf, *label);
5421
+ else if (*label & 0x80) {
5422
+ const char *p = label;
5423
+
5424
+ utf8_width(&p, NULL);
5425
+ if (p) {
5426
+ if (buf->len + (p - label) > max_len)
5427
+ break;
5428
+ strbuf_add(buf, label, p - label);
5429
+ label = p - 1;
5430
+ } else {
5431
+ label_is_utf8 = 0;
5432
+ strbuf_addch(buf, *label);
5433
+ }
5434
/* avoid leading dash and double-dashes */
5404
- else if (buf->len && buf->buf[buf->len - 1] != '-')
5435
+ } else if (buf->len && buf->buf[buf->len - 1] != '-')
5436
strbuf_addch(buf, '-');
5437
if (!buf->len) {
5438
strbuf_addstr(buf, "rev-");