From f3d2c68430475ef3d9eb6de5cdfb27f19cd7d57e Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 20 Jul 2017 22:18:56 +0200 Subject: [PATCH] test-helper: learn to act as a drop-in replacement for `iconv` It is convenient to assume that everybody who wants to build & test Git has access to a working `iconv` executable (after all, we already pretty much require libiconv) However, that limits esoteric test scenarios such as Git for Windows', where an end user installation has to ship with `iconv` for the sole purpose of being testable. That payload serves no other purpose. So let's just have a test helper (to be able to test Git, the test helpers have to be available, after all) to act as `iconv` replacement. Signed-off-by: Johannes Schindelin --- t/helper/test-helper.c | 46 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/t/helper/test-helper.c b/t/helper/test-helper.c index 1eaf8df925..c3b4e0bf93 100644 --- a/t/helper/test-helper.c +++ b/t/helper/test-helper.c @@ -2,6 +2,7 @@ #include "strbuf.h" #include "gettext.h" #include "parse-options.h" +#include "utf8.h" static const char * const test_helper_usage[] = { N_("test-helper []"), @@ -46,14 +47,55 @@ static int cmp(int argc, const char **argv) } } +static int iconv_(int argc, const char **argv) +{ + struct strbuf buf = STRBUF_INIT; + char *from = NULL, *to = NULL, *p; + int len, ret = 0; + const char * const iconv_usage[] = { + N_("test-helper --iconv []"), + NULL + }; + struct option options[] = { + OPT_STRING('f', "from-code", &from, "encoding", "from"), + OPT_STRING('t', "to-code", &to, "encoding", "to"), + OPT_END() + }; + + argc = parse_options(argc, argv, NULL, options, + iconv_usage, 0); + + if (argc > 1 || !from || !to) + usage_with_options(iconv_usage, options); + + if (!argc) { + if (strbuf_read(&buf, 0, 2048) < 0) + die_errno("Could not read from stdin"); + } else if (strbuf_read_file(&buf, argv[0], 2048) < 0) + die_errno("Could not read from '%s'", argv[0]); + + p = reencode_string_len(buf.buf, buf.len, to, from, &len); + if (!p) + die_errno("Could not reencode"); + if (write(1, p, len) < 0) + ret = !!error_errno("Could not write %d bytes", len); + + strbuf_release(&buf); + free(p); + + return ret; +} + int cmd_main(int argc, const char **argv) { enum mode { - CMP = 1 + CMP = 1, ICONV } command = 0; struct option options[] = { OPT_CMDMODE(0, "cmp", &command, N_("compare files (ignoring LF vs CR/LF)"), CMP), + OPT_CMDMODE(0, "iconv", &command, + N_("act as drop-in replacement for `iconv`"), ICONV), OPT_END() }; @@ -63,6 +105,8 @@ int cmd_main(int argc, const char **argv) if (command == CMP) return !!cmp(argc, argv); + if (command == ICONV) + return !!iconv_(argc, argv); die("unhandled mode"); }