347
strbuf_release(&trace);
348
}
349
350
+static int check_roundtrip(const char *enc_name)
351
+{
352
+ /*
353
+ * check_roundtrip_encoding contains a string of comma and/or
354
+ * space separated encodings (eg. "UTF-16, ASCII, CP1125").
355
+ * Search for the given encoding in that string.
356
+ */
357
+ const char *found = strcasestr(check_roundtrip_encoding, enc_name);
358
+ const char *next;
359
+ int len;
360
+ if (!found)
361
+ return 0;
362
+ next = found + strlen(enc_name);
363
+ len = strlen(check_roundtrip_encoding);
364
+ return (found && (
365
+ /*
366
+ * check that the found encoding is at the
367
+ * beginning of check_roundtrip_encoding or
368
+ * that it is prefixed with a space or comma
369
+ */
370
+ found == check_roundtrip_encoding || (
371
+ (isspace(found[-1]) || found[-1] == ',')
372
+ )
373
+ ) && (
374
+ /*
375
+ * check that the found encoding is at the
376
+ * end of check_roundtrip_encoding or
377
+ * that it is suffixed with a space or comma
378
+ */
379
+ next == check_roundtrip_encoding + len || (
380
+ next < check_roundtrip_encoding + len &&
381
+ (isspace(next[0]) || next[0] == ',')
382
+ )
383
+ ));
384
+}
385
+
386
static const char *default_encoding = "UTF-8";
387
388
static int encode_to_git(const char *path, const char *src, size_t src_len,
431
}
432
trace_encoding("destination", path, default_encoding, dst, dst_len);
433
434
+ /*
435
+ * UTF supports lossless conversion round tripping [1] and conversions
436
+ * between UTF and other encodings are mostly round trip safe as
437
+ * Unicode aims to be a superset of all other character encodings.
438
+ * However, certain encodings (e.g. SHIFT-JIS) are known to have round
439
+ * trip issues [2]. Check the round trip conversion for all encodings
440
+ * listed in core.checkRoundtripEncoding.
441
+ *
442
+ * The round trip check is only performed if content is written to Git.
443
+ * This ensures that no information is lost during conversion to/from
444
+ * the internal UTF-8 representation.
445
+ *
446
+ * Please note, the code below is not tested because I was not able to
447
+ * generate a faulty round trip without an iconv error. Iconv errors
448
+ * are already caught above.
449
+ *
450
+ * [1] http://unicode.org/faq/utf_bom.html#gen2
451
+ * [2] https://support.microsoft.com/en-us/help/170559/prb-conversion-problem-between-shift-jis-and-unicode
452
+ */
453
+ if (die_on_error && check_roundtrip(enc)) {
454
+ char *re_src;
455
+ int re_src_len;
456
+
457
+ re_src = reencode_string_len(dst, dst_len,
458
+ enc, default_encoding,
459
+ &re_src_len);
460
+
461
+ trace_printf("Checking roundtrip encoding for %s...\n", enc);
462
+ trace_encoding("reencoded source", path, enc,
463
+ re_src, re_src_len);
464
+
465
+ if (!re_src || src_len != re_src_len ||
466
+ memcmp(src, re_src, src_len)) {
467
+ const char* msg = _("encoding '%s' from %s to %s and "
468
+ "back is not the same");
469
+ die(msg, path, enc, default_encoding);
470
+ }
471
+
472
+ free(re_src);
473
+ }
474
+
475
strbuf_attach(buf, dst, dst_len, dst_len + 1);
476
return 1;
477
}