summaryrefslogtreecommitdiff
path: root/src/refs.c
diff options
context:
space:
mode:
authornulltoken <emeric.fermas@gmail.com>2012-09-17 07:11:32 +0200
committernulltoken <emeric.fermas@gmail.com>2012-09-25 07:49:15 +0200
commit77e06d7e8547e82336489b7cdeb04294ed3d6015 (patch)
treec1715edc9ba6ae7ac17a23d4f4f46b36da7ac8ba /src/refs.c
parentc030ada7ff7f9c93a2287ca2f57173d66fbff88a (diff)
downloadlibgit2-77e06d7e8547e82336489b7cdeb04294ed3d6015.tar.gz
refs: introduce git_reference_is_valid_name()
Diffstat (limited to 'src/refs.c')
-rw-r--r--src/refs.c95
1 files changed, 59 insertions, 36 deletions
diff --git a/src/refs.c b/src/refs.c
index ef8300aba..e71d8c60e 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1239,7 +1239,7 @@ int git_reference_create_oid(
git_reference *ref = NULL;
char normalized[GIT_REFNAME_MAX];
- if (git_reference__normalize_name_oid(
+ if (git_reference__normalize_name_lax(
normalized,
sizeof(normalized),
name) < 0)
@@ -1611,6 +1611,26 @@ static int ensure_segment_validity(const char *name)
return current - name;
}
+static bool is_all_caps_and_underscore(const char *name, int len)
+{
+ int i;
+ char c;
+
+ assert(name && len > 0);
+
+ for (i = 0; i < len; i++)
+ {
+ c = name[i];
+ if ((c < 'A' || c > 'Z') && c != '_')
+ return false;
+ }
+
+ if (*name == '_' || name[len - 1] == '_')
+ return false;
+
+ return true;
+}
+
int git_reference__normalize_name(
git_buf *buf,
const char *name,
@@ -1620,37 +1640,42 @@ int git_reference__normalize_name(
char *current;
int segment_len, segments_count = 0, error = -1;
-
- assert(name && buf);
+ unsigned int process_flags;
+ bool normalize = (buf != NULL);
+ assert(name);
+ process_flags = flags;
current = (char *)name;
- git_buf_clear(buf);
+ if (normalize)
+ git_buf_clear(buf);
while (true) {
segment_len = ensure_segment_validity(current);
if (segment_len < 0) {
- if ((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) &&
+ if ((process_flags & GIT_REF_FORMAT_REFSPEC_PATTERN) &&
current[0] == '*' &&
(current[1] == '\0' || current[1] == '/')) {
/* Accept one wildcard as a full refname component. */
- flags &= ~GIT_REF_FORMAT_REFSPEC_PATTERN;
+ process_flags &= ~GIT_REF_FORMAT_REFSPEC_PATTERN;
segment_len = 1;
} else
goto cleanup;
}
if (segment_len > 0) {
- int cur_len = git_buf_len(buf);
+ if (normalize) {
+ int cur_len = git_buf_len(buf);
- git_buf_joinpath(buf, git_buf_cstr(buf), current);
- git_buf_truncate(buf,
- cur_len + segment_len + (segments_count ? 1 : 0));
+ git_buf_joinpath(buf, git_buf_cstr(buf), current);
+ git_buf_truncate(buf,
+ cur_len + segment_len + (segments_count ? 1 : 0));
- segments_count++;
+ if (git_buf_oom(buf))
+ goto cleanup;
+ }
- if (git_buf_oom(buf))
- goto cleanup;
+ segments_count++;
}
if (current[segment_len] == '\0')
@@ -1660,7 +1685,7 @@ int git_reference__normalize_name(
}
/* A refname can not be empty */
- if (git_buf_len(buf) == 0)
+ if (segment_len == 0 && segments_count == 0)
goto cleanup;
/* A refname can not end with "." */
@@ -1675,15 +1700,17 @@ int git_reference__normalize_name(
if (!git__suffixcmp(name, GIT_FILELOCK_EXTENSION))
goto cleanup;
- /* Object id refname have to contain at least one slash, except
- * for HEAD in a detached state or MERGE_HEAD if we're in the
- * middle of a merge */
- if (!(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL) &&
- segments_count < 2 &&
- strcmp(name, GIT_HEAD_FILE) != 0 &&
- strcmp(name, GIT_MERGE_HEAD_FILE) != 0 &&
- strcmp(name, GIT_FETCH_HEAD_FILE) != 0)
- return -1;
+ if ((segments_count == 1 ) && !(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL))
+ goto cleanup;
+
+ if ((segments_count == 1 ) &&
+ !(is_all_caps_and_underscore(name, segment_len) ||
+ ((flags & GIT_REF_FORMAT_REFSPEC_PATTERN) && !strcmp("*", name))))
+ goto cleanup;
+
+ if ((segments_count > 1)
+ && (is_all_caps_and_underscore(name, strchr(name, '/') - name)))
+ goto cleanup;
error = 0;
@@ -1736,19 +1763,6 @@ int git_reference__normalize_name_lax(
name,
GIT_REF_FORMAT_ALLOW_ONELEVEL);
}
-
-int git_reference__normalize_name_oid(
- char *buffer_out,
- size_t out_size,
- const char *name)
-{
- return git_reference_normalize_name(
- buffer_out,
- out_size,
- name,
- GIT_REF_FORMAT_NORMAL);
-}
-
#define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC)
int git_reference_cmp(git_reference *ref1, git_reference *ref2)
@@ -1937,3 +1951,12 @@ cleanup:
git_reference_free(resolved);
return error;
}
+
+int git_reference_is_valid_name(
+ const char *refname)
+{
+ return git_reference__normalize_name(
+ NULL,
+ refname,
+ GIT_REF_FORMAT_ALLOW_ONELEVEL) == 0;
+}