summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2019-05-22 11:45:45 +0200
committerGitHub <noreply@github.com>2019-05-22 11:45:45 +0200
commitd97afb9368ab0d78d5286ec7e1d34b4144a1495b (patch)
treefb74c7dcaf4846447ce8e894737c9822f059034c /src
parent3d9e82fdd5619985b56ca25fb1f89de3dfabc029 (diff)
parent0c71e4cbd646a62fcbe534532178e841107d232d (diff)
downloadlibgit2-d97afb9368ab0d78d5286ec7e1d34b4144a1495b.tar.gz
Merge pull request #5060 from pks-t/pks/refspec-nested-globs
Loosen restriction on wildcard "*" refspecs
Diffstat (limited to 'src')
-rw-r--r--src/refs.c32
-rw-r--r--src/refspec.c17
2 files changed, 24 insertions, 25 deletions
diff --git a/src/refs.c b/src/refs.c
index a031842bf..4604d4c4c 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -897,14 +897,13 @@ static int is_valid_ref_char(char ch)
case '\\':
case '?':
case '[':
- case '*':
return 0;
default:
return 1;
}
}
-static int ensure_segment_validity(const char *name)
+static int ensure_segment_validity(const char *name, char may_contain_glob)
{
const char *current = name;
char prev = '\0';
@@ -927,6 +926,12 @@ static int ensure_segment_validity(const char *name)
if (prev == '@' && *current == '{')
return -1; /* Refname contains "@{" */
+ if (*current == '*') {
+ if (!may_contain_glob)
+ return -1;
+ may_contain_glob = 0;
+ }
+
prev = *current;
}
@@ -1005,19 +1010,20 @@ int git_reference__normalize_name(
}
while (true) {
- segment_len = ensure_segment_validity(current);
- if (segment_len < 0) {
- if ((process_flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN) &&
- current[0] == '*' &&
- (current[1] == '\0' || current[1] == '/')) {
- /* Accept one wildcard as a full refname component. */
- process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN;
- segment_len = 1;
- } else
- goto cleanup;
- }
+ char may_contain_glob = process_flags & GIT_REFERENCE_FORMAT_REFSPEC_PATTERN;
+
+ segment_len = ensure_segment_validity(current, may_contain_glob);
+ if (segment_len < 0)
+ goto cleanup;
if (segment_len > 0) {
+ /*
+ * There may only be one glob in a pattern, thus we reset
+ * the pattern-flag in case the current segment has one.
+ */
+ if (memchr(current, '*', segment_len))
+ process_flags &= ~GIT_REFERENCE_FORMAT_REFSPEC_PATTERN;
+
if (normalize) {
size_t cur_len = git_buf_len(buf);
diff --git a/src/refspec.c b/src/refspec.c
index eaf0c2c83..dab053634 100644
--- a/src/refspec.c
+++ b/src/refspec.c
@@ -228,7 +228,6 @@ static int refspec_transform(
git_buf *out, const char *from, const char *to, const char *name)
{
const char *from_star, *to_star;
- const char *name_slash, *from_slash;
size_t replacement_len, star_offset;
git_buf_sanitize(out);
@@ -251,17 +250,11 @@ static int refspec_transform(
/* the first half is copied over */
git_buf_put(out, to, to_star - to);
- /* then we copy over the replacement, from the star's offset to the next slash in 'name' */
- name_slash = strchr(name + star_offset, '/');
- if (!name_slash)
- name_slash = strrchr(name, '\0');
-
- /* if there is no slash after the star in 'from', we want to copy everything over */
- from_slash = strchr(from + star_offset, '/');
- if (!from_slash)
- name_slash = strrchr(name, '\0');
-
- replacement_len = (name_slash - name) - star_offset;
+ /*
+ * Copy over the name, but exclude the trailing part in "from" starting
+ * after the glob
+ */
+ replacement_len = strlen(name + star_offset) - strlen(from_star + 1);
git_buf_put(out, name + star_offset, replacement_len);
return git_buf_puts(out, to_star + 1);