diff options
-rw-r--r-- | src/attr_file.c | 12 | ||||
-rw-r--r-- | src/buffer.c | 4 | ||||
-rw-r--r-- | src/buffer.h | 3 | ||||
-rw-r--r-- | src/util.c | 18 | ||||
-rw-r--r-- | src/util.h | 9 | ||||
-rw-r--r-- | tests-clar/core/buffer.c | 20 |
6 files changed, 55 insertions, 11 deletions
diff --git a/src/attr_file.c b/src/attr_file.c index 0dad09727..837c42d8e 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -426,17 +426,7 @@ int git_attr_fnmatch__parse( return -1; } else { /* strip '\' that might have be used for internal whitespace */ - char *to = spec->pattern; - for (scan = spec->pattern; *scan; to++, scan++) { - if (*scan == '\\') - scan++; /* skip '\' but include next char */ - if (to != scan) - *to = *scan; - } - if (to != scan) { - *to = '\0'; - spec->length = (to - spec->pattern); - } + spec->length = git__unescape(spec->pattern); } return 0; diff --git a/src/buffer.c b/src/buffer.c index 5d54ee1a5..b57998e1b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -496,3 +496,7 @@ bool git_buf_is_binary(const git_buf *buf) return ((printable >> 7) < nonprintable); } +void git_buf_unescape(git_buf *buf) +{ + buf->size = git__unescape(buf->ptr); +} diff --git a/src/buffer.h b/src/buffer.h index 75f3b0e4f..17922e408 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -151,4 +151,7 @@ int git_buf_common_prefix(git_buf *buf, const git_strarray *strings); /* Check if buffer looks like it contains binary data */ bool git_buf_is_binary(const git_buf *buf); +/* Unescape all characters in a buffer */ +void git_buf_unescape(git_buf *buf); + #endif diff --git a/src/util.c b/src/util.c index 3093cd767..90bb3d02a 100644 --- a/src/util.c +++ b/src/util.c @@ -435,3 +435,21 @@ int git__parse_bool(int *out, const char *value) return -1; } + +size_t git__unescape(char *str) +{ + char *scan, *pos = str; + + for (scan = str; *scan; pos++, scan++) { + if (*scan == '\\' && *(scan + 1) != '\0') + scan++; /* skip '\' but include next char */ + if (pos != scan) + *pos = *scan; + } + + if (pos != scan) { + *pos = '\0'; + } + + return (pos - str); +} diff --git a/src/util.h b/src/util.h index a84dcab1e..905fc927f 100644 --- a/src/util.h +++ b/src/util.h @@ -238,4 +238,13 @@ extern int git__parse_bool(int *out, const char *value); */ int git__date_parse(git_time_t *out, const char *date); +/* + * Unescapes a string in-place. + * + * Edge cases behavior: + * - "jackie\" -> "jacky\" + * - "chan\\" -> "chan\" + */ +extern size_t git__unescape(char *str); + #endif /* INCLUDE_util_h__ */ diff --git a/tests-clar/core/buffer.c b/tests-clar/core/buffer.c index 21aaaed7e..b6274b012 100644 --- a/tests-clar/core/buffer.c +++ b/tests-clar/core/buffer.c @@ -658,3 +658,23 @@ void test_core_buffer__puts_escaped(void) git_buf_free(&a); } + +static void assert_unescape(char *expected, char *to_unescape) { + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_sets(&buf, to_unescape)); + git_buf_unescape(&buf); + cl_assert_equal_s(expected, buf.ptr); + cl_assert_equal_i(strlen(expected), buf.size); + + git_buf_free(&buf); +} + +void test_core_buffer__unescape(void) +{ + assert_unescape("Escaped\\", "Es\\ca\\ped\\"); + assert_unescape("Es\\caped\\", "Es\\\\ca\\ped\\\\"); + assert_unescape("\\", "\\"); + assert_unescape("\\", "\\\\"); + assert_unescape("", ""); +} |