diff --git a/src/refs.c b/src/refs.c index cca3f3ec8..113cadad5 100644 --- a/src/refs.c +++ b/src/refs.c @@ -1599,7 +1599,8 @@ static int ensure_segment_validity(const char *name) { const char *current = name; char prev = '\0'; - int lock_len = strlen(GIT_FILELOCK_EXTENSION); + const int lock_len = (int)strlen(GIT_FILELOCK_EXTENSION); + int segment_len; if (*current == '.') return -1; /* Refname starts with "." */ @@ -1620,12 +1621,14 @@ static int ensure_segment_validity(const char *name) prev = *current; } + segment_len = (int)(current - name); + /* A refname component can not end with ".lock" */ - if (current - name >= lock_len && + if (segment_len >= lock_len && !memcmp(current - lock_len, GIT_FILELOCK_EXTENSION, lock_len)) return -1; - return (int)(current - name); + return segment_len; } static bool is_all_caps_and_underscore(const char *name, size_t len) @@ -1700,7 +1703,7 @@ int git_reference__normalize_name( /* No empty segment is allowed when not normalizing */ if (segment_len == 0 && !normalize) goto cleanup; - + if (current[segment_len] == '\0') break; diff --git a/src/repository.c b/src/repository.c index 5279d8f63..e120c5836 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1043,8 +1043,11 @@ static int repo_init_structure( static int mkdir_parent(git_buf *buf, uint32_t mode, bool skip2) { + /* When making parent directories during repository initialization + * don't try to set gid or grant world write access + */ return git_futils_mkdir( - buf->ptr, NULL, mode & ~(S_ISGID | S_IWOTH), + buf->ptr, NULL, mode & ~(S_ISGID | 0002), GIT_MKDIR_PATH | GIT_MKDIR_VERIFY_DIR | (skip2 ? GIT_MKDIR_SKIP_LAST2 : GIT_MKDIR_SKIP_LAST)); } diff --git a/tests-clar/refs/branches/remote.c b/tests-clar/refs/branches/remote.c index 145c3182f..5272d1236 100644 --- a/tests-clar/refs/branches/remote.c +++ b/tests-clar/refs/branches/remote.c @@ -11,7 +11,7 @@ void test_refs_branches_remote__initialize(void) { g_repo = cl_git_sandbox_init("testrepo"); - expected_remote_name_length = strlen(expected_remote_name) + 1; + expected_remote_name_length = (int)strlen(expected_remote_name) + 1; } void test_refs_branches_remote__cleanup(void) diff --git a/tests-clar/repo/init.c b/tests-clar/repo/init.c index c69ea76ca..085d65f86 100644 --- a/tests-clar/repo/init.c +++ b/tests-clar/repo/init.c @@ -363,10 +363,23 @@ void test_repo_init__extended_1(void) cl_fixture_cleanup("root"); } +static uint32_t normalize_filemode(uint32_t mode, bool core_filemode) +{ + /* if no filemode support, strip SETGID, exec, and low-order bits */ + + /* cannot use constants because on platform without SETGID, that + * will have been defined to zero - must use hardcoded value to + * clear it effectively from the expected value + */ + + return core_filemode ? mode : (mode & ~02177); +} + static void assert_hooks_match( const char *template_dir, const char *repo_dir, const char *hook_path, + bool core_filemode, uint32_t expected_mode) { git_buf expected = GIT_BUF_INIT; @@ -384,6 +397,8 @@ static void assert_hooks_match( if (!expected_mode) expected_mode = (uint32_t)expected_st.st_mode; + expected_mode = normalize_filemode(expected_mode, core_filemode); + cl_assert_equal_i((int)expected_mode, (int)st.st_mode); git_buf_free(&expected); @@ -391,7 +406,7 @@ static void assert_hooks_match( } static void assert_has_mode( - const char *base, const char *path, uint32_t expected) + const char *base, const char *path, bool core_filemode, uint32_t expected) { git_buf full = GIT_BUF_INIT; struct stat st; @@ -400,6 +415,8 @@ static void assert_has_mode( cl_git_pass(git_path_lstat(full.ptr, &st)); git_buf_free(&full); + expected = normalize_filemode(expected, core_filemode); + cl_assert_equal_i((int)expected, (int)st.st_mode); } @@ -433,11 +450,11 @@ void test_repo_init__extended_with_template(void) assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/update.sample", 0); + "hooks/update.sample", true, 0); assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/link.sample", 0); + "hooks/link.sample", true, 0); } void test_repo_init__extended_with_template_and_shared_mode(void) @@ -445,6 +462,8 @@ void test_repo_init__extended_with_template_and_shared_mode(void) git_buf expected = GIT_BUF_INIT; git_buf actual = GIT_BUF_INIT; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; + git_config *config; + int filemode = true; cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl"); @@ -458,6 +477,10 @@ void test_repo_init__extended_with_template_and_shared_mode(void) cl_assert(!git_repository_is_bare(_repo)); cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/")); + cl_git_pass(git_repository_config(&config, _repo)); + cl_git_pass(git_config_get_bool(&filemode, config, "core.filemode")); + git_config_free(config); + cl_git_pass(git_futils_readbuffer( &expected, cl_fixture("template/description"))); cl_git_pass(git_futils_readbuffer( @@ -468,17 +491,17 @@ void test_repo_init__extended_with_template_and_shared_mode(void) git_buf_free(&expected); git_buf_free(&actual); - assert_has_mode(git_repository_path(_repo), "hooks", + assert_has_mode(git_repository_path(_repo), "hooks", filemode, GIT_REPOSITORY_INIT_SHARED_GROUP | S_IFDIR); - assert_has_mode(git_repository_path(_repo), "info", + assert_has_mode(git_repository_path(_repo), "info", filemode, GIT_REPOSITORY_INIT_SHARED_GROUP | S_IFDIR); - assert_has_mode(git_repository_path(_repo), "description", + assert_has_mode(git_repository_path(_repo), "description", filemode, (GIT_REPOSITORY_INIT_SHARED_GROUP | S_IFREG) & ~(S_ISGID | 0111)); /* for a non-symlinked hook, it should have shared permissions now */ assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/update.sample", + "hooks/update.sample", filemode, (GIT_REPOSITORY_INIT_SHARED_GROUP | S_IFREG) & ~S_ISGID); /* for a symlinked hook, the permissions still should match the @@ -486,7 +509,7 @@ void test_repo_init__extended_with_template_and_shared_mode(void) */ assert_hooks_match( cl_fixture("template"), git_repository_path(_repo), - "hooks/link.sample", 0); + "hooks/link.sample", filemode, 0); } void test_repo_init__can_reinit_an_initialized_repository(void)