diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/refs.c | 108 |
1 files changed, 70 insertions, 38 deletions
diff --git a/src/refs.c b/src/refs.c index cf55a6fd5..9fc194cb6 100644 --- a/src/refs.c +++ b/src/refs.c @@ -68,11 +68,6 @@ static int reference_path_available(git_repository *repo, static int reference_delete(git_reference *ref); static int reference_lookup(git_reference *ref); -/* name normalization */ -static int normalize_name(char *buffer_out, size_t out_size, - const char *name, int is_oid_ref); - - void git_reference_free(git_reference *reference) { if (reference == NULL) @@ -1099,9 +1094,12 @@ int git_reference_lookup_resolved( scan->name = git__calloc(GIT_REFNAME_MAX + 1, sizeof(char)); GITERR_CHECK_ALLOC(scan->name); - if ((result = normalize_name(scan->name, GIT_REFNAME_MAX, name, 0)) < 0) { - git_reference_free(scan); - return result; + if ((result = git_reference__normalize_name( + scan->name, + GIT_REFNAME_MAX, + name)) < 0) { + git_reference_free(scan); + return result; } scan->target.symbolic = git__strdup(scan->name); @@ -1198,8 +1196,11 @@ int git_reference_create_symbolic( char normalized[GIT_REFNAME_MAX]; git_reference *ref = NULL; - if (normalize_name(normalized, sizeof(normalized), name, 0) < 0) - return -1; + if (git_reference__normalize_name( + normalized, + sizeof(normalized), + name) < 0) + return -1; if (reference_can_write(repo, normalized, NULL, force) < 0) return -1; @@ -1234,8 +1235,11 @@ int git_reference_create_oid( git_reference *ref = NULL; char normalized[GIT_REFNAME_MAX]; - if (normalize_name(normalized, sizeof(normalized), name, 1) < 0) - return -1; + if (git_reference__normalize_name_oid( + normalized, + sizeof(normalized), + name) < 0) + return -1; if (reference_can_write(repo, normalized, NULL, force) < 0) return -1; @@ -1314,8 +1318,11 @@ int git_reference_set_target(git_reference *ref, const char *target) return -1; } - if (normalize_name(normalized, sizeof(normalized), target, 0)) - return -1; + if (git_reference__normalize_name( + normalized, + sizeof(normalized), + target)) + return -1; git__free(ref->target.symbolic); ref->target.symbolic = git__strdup(normalized); @@ -1327,15 +1334,23 @@ int git_reference_set_target(git_reference *ref, const char *target) int git_reference_rename(git_reference *ref, const char *new_name, int force) { int result; + unsigned int normalization_flags; git_buf aux_path = GIT_BUF_INIT; char normalized[GIT_REFNAME_MAX]; const char *head_target = NULL; git_reference *head = NULL; - if (normalize_name(normalized, sizeof(normalized), - new_name, ref->flags & GIT_REF_OID) < 0) - return -1; + normalization_flags = ref->flags & GIT_REF_SYMBOLIC ? + GIT_REF_FORMAT_ALLOW_ONELEVEL + : GIT_REF_FORMAT_NORMAL; + + if (git_reference_normalize_name( + normalized, + sizeof(normalized), + new_name, + normalization_flags) < 0) + return -1; if (reference_can_write(ref->owner, normalized, ref->name, force) < 0) return -1; @@ -1565,11 +1580,11 @@ static int is_valid_ref_char(char ch) } } -static int normalize_name( +int git_reference_normalize_name( char *buffer_out, - size_t out_size, + size_t buffer_size, const char *name, - int is_oid_ref) + unsigned int flags) { const char *name_end, *buffer_out_start; const char *current; @@ -1577,12 +1592,17 @@ static int normalize_name( assert(name && buffer_out); + if (flags & GIT_REF_FORMAT_REFSPEC_PATTERN) { + giterr_set(GITERR_INVALID, "Unimplemented"); + return -1; + } + buffer_out_start = buffer_out; current = name; name_end = name + strlen(name); /* Terminating null byte */ - out_size--; + buffer_size--; /* A refname can not be empty */ if (name_end == name) @@ -1592,7 +1612,7 @@ static int normalize_name( if (*(name_end - 1) == '.' || *(name_end - 1) == '/') goto invalid_name; - while (current < name_end && out_size) { + while (current < name_end && buffer_size > 0) { if (!is_valid_ref_char(*current)) goto invalid_name; @@ -1615,19 +1635,29 @@ static int normalize_name( } if (*current == '/') - contains_a_slash = 1; + if (buffer_out > buffer_out_start) + contains_a_slash = 1; + else { + current++; + continue; + } + *buffer_out++ = *current++; - out_size--; + buffer_size--; } - if (!out_size) - goto invalid_name; + if (current < name_end) { + giterr_set( + GITERR_REFERENCE, + "The provided buffer is too short to hold the normalization of '%s'", name); + return GIT_EBUFS; + } /* 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 (is_oid_ref && + if (!(flags & GIT_REF_FORMAT_ALLOW_ONELEVEL) && !contains_a_slash && strcmp(name, GIT_HEAD_FILE) != 0 && strcmp(name, GIT_MERGE_HEAD_FILE) != 0 && @@ -1640,18 +1670,12 @@ static int normalize_name( *buffer_out = '\0'; - /* - * For object id references, name has to start with refs/. Again, - * we need to allow HEAD to be in a detached state. - */ - if (is_oid_ref && !(git__prefixcmp(buffer_out_start, GIT_REFS_DIR) || - strcmp(buffer_out_start, GIT_HEAD_FILE))) - goto invalid_name; - return 0; invalid_name: - giterr_set(GITERR_REFERENCE, "The given reference name is not valid"); + giterr_set( + GITERR_REFERENCE, + "The given reference name '%s' is not valid", name); return -1; } @@ -1660,7 +1684,11 @@ int git_reference__normalize_name( size_t out_size, const char *name) { - return normalize_name(buffer_out, out_size, name, 0); + return git_reference_normalize_name( + buffer_out, + out_size, + name, + GIT_REF_FORMAT_ALLOW_ONELEVEL); } int git_reference__normalize_name_oid( @@ -1668,7 +1696,11 @@ int git_reference__normalize_name_oid( size_t out_size, const char *name) { - return normalize_name(buffer_out, out_size, name, 1); + return git_reference_normalize_name( + buffer_out, + out_size, + name, + GIT_REF_FORMAT_NORMAL); } #define GIT_REF_TYPEMASK (GIT_REF_OID | GIT_REF_SYMBOLIC) |
