diff --git a/include/git2/reflog.h b/include/git2/reflog.h index 45dff2165..418826d1d 100644 --- a/include/git2/reflog.h +++ b/include/git2/reflog.h @@ -63,9 +63,12 @@ GIT_EXTERN(int) git_reflog_append(git_reflog *reflog, const git_oid *id, const g * * The reflog to be renamed is expected to already exist * + * The new name will be checked for validity. + * See `git_reference_create_symbolic()` for rules about valid names. + * * @param ref the reference * @param name the new name of the reference - * @return 0 or an error code + * @return 0 on success, GIT_EINVALIDSPEC or an error code */ GIT_EXTERN(int) git_reflog_rename(git_reference *ref, const char *name); diff --git a/src/reflog.c b/src/reflog.c index ac481fb81..df799b113 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -340,21 +340,29 @@ cleanup: int git_reflog_rename(git_reference *ref, const char *new_name) { - int error = -1, fd; + int error, fd; git_buf old_path = GIT_BUF_INIT; git_buf new_path = GIT_BUF_INIT; git_buf temp_path = GIT_BUF_INIT; + git_buf normalized = GIT_BUF_INIT; assert(ref && new_name); + if ((error = git_reference__normalize_name( + &normalized, new_name, GIT_REF_FORMAT_ALLOW_ONELEVEL)) < 0) + goto cleanup; + + error = -1; + if (git_buf_joinpath(&temp_path, git_reference_owner(ref)->path_repository, GIT_REFLOG_DIR) < 0) return -1; if (git_buf_joinpath(&old_path, git_buf_cstr(&temp_path), ref->name) < 0) goto cleanup; - if (git_buf_joinpath(&new_path, git_buf_cstr(&temp_path), new_name) < 0) - goto cleanup; + if (git_buf_joinpath(&new_path, + git_buf_cstr(&temp_path), git_buf_cstr(&normalized)) < 0) + goto cleanup; /* * Move the reflog to a temporary place. This two-phase renaming is required @@ -386,6 +394,7 @@ cleanup: git_buf_free(&temp_path); git_buf_free(&old_path); git_buf_free(&new_path); + git_buf_free(&normalized); return error; } diff --git a/tests-clar/refs/reflog/reflog.c b/tests-clar/refs/reflog/reflog.c index 8743c8a76..19ee53567 100644 --- a/tests-clar/refs/reflog/reflog.c +++ b/tests-clar/refs/reflog/reflog.c @@ -170,3 +170,15 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) git_buf_free(&moved_log_path); git_buf_free(&master_log_path); } + +void test_refs_reflog_reflog__renaming_with_an_invalid_name_returns_EINVALIDSPEC(void) +{ + git_reference *master; + + cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); + + cl_assert_equal_i(GIT_EINVALIDSPEC, + git_reflog_rename(master, "refs/heads/Inv@{id")); + + git_reference_free(master); +}