diff --git a/include/git2/repository.h b/include/git2/repository.h index 74ab65bf7..28d8400f2 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -299,10 +299,12 @@ GIT_EXTERN(int) git_repository_init_ext( * properties to compensate for the current filesystem of the repo. * * @param repo A repository object + * @param recurse_submodules Should submodules be reset recursively * @returrn 0 on success, < 0 on error */ GIT_EXTERN(int) git_repository_reset_filesystem( - git_repository *repo); + git_repository *repo, + int recurse_submodules); /** * Retrieve and resolve the reference pointed at by HEAD. diff --git a/src/checkout.c b/src/checkout.c index 5d741d393..d3f673d40 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -783,7 +783,8 @@ static int checkout_update_index( memset(&entry, 0, sizeof(entry)); entry.path = (char *)file->path; /* cast to prevent warning */ - git_index_entry__init_from_stat(&entry, st); + git_index_entry__init_from_stat( + &entry, st, !(git_index_caps(data->index) & GIT_INDEXCAP_NO_FILEMODE)); git_oid_cpy(&entry.oid, &file->oid); return git_index_add(data->index, &entry); diff --git a/src/errors.c b/src/errors.c index e2629f69e..c9d9e4e37 100644 --- a/src/errors.c +++ b/src/errors.c @@ -116,4 +116,3 @@ const git_error *giterr_last(void) { return GIT_GLOBAL->last_error; } - diff --git a/src/fileops.c b/src/fileops.c index be2e53ca8..63aedc6d0 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -78,11 +78,8 @@ int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, con int git_futils_open_ro(const char *path) { int fd = p_open(path, O_RDONLY); - if (fd < 0) { - if (errno == ENOENT || errno == ENOTDIR) - fd = GIT_ENOTFOUND; - giterr_set(GITERR_OS, "Failed to open '%s'", path); - } + if (fd < 0) + return git_path_set_error(errno, path, "open"); return fd; } @@ -138,7 +135,6 @@ int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) int git_futils_readbuffer_updated( git_buf *buf, const char *path, time_t *mtime, size_t *size, int *updated) { - int error = 0; git_file fd; struct stat st; bool changed = false; @@ -148,13 +144,8 @@ int git_futils_readbuffer_updated( if (updated != NULL) *updated = 0; - if (p_stat(path, &st) < 0) { - error = errno; - giterr_set(GITERR_OS, "Failed to stat '%s'", path); - if (error == ENOENT || error == ENOTDIR) - return GIT_ENOTFOUND; - return -1; - } + if (p_stat(path, &st) < 0) + return git_path_set_error(errno, path, "stat"); if (S_ISDIR(st.st_mode) || !git__is_sizet(st.st_size+1)) { giterr_set(GITERR_OS, "Invalid regular file stat for '%s'", path); @@ -441,66 +432,60 @@ static int futils__rm_first_parent(git_buf *path, const char *ceiling) static int futils__rmdir_recurs_foreach(void *opaque, git_buf *path) { - struct stat st; futils__rmdir_data *data = opaque; + int error = data->error; + struct stat st; - if (data->depth > FUTILS_MAX_DEPTH) { - data->error = - futils__error_cannot_rmdir(path->ptr, "directory nesting too deep"); - } + if (data->depth > FUTILS_MAX_DEPTH) + error = futils__error_cannot_rmdir( + path->ptr, "directory nesting too deep"); - else if ((data->error = p_lstat_posixly(path->ptr, &st)) < 0) { + else if ((error = p_lstat_posixly(path->ptr, &st)) < 0) { if (errno == ENOENT) - data->error = 0; + error = 0; else if (errno == ENOTDIR) { /* asked to remove a/b/c/d/e and a/b is a normal file */ if ((data->flags & GIT_RMDIR_REMOVE_BLOCKERS) != 0) - data->error = futils__rm_first_parent(path, data->base); + error = futils__rm_first_parent(path, data->base); else futils__error_cannot_rmdir( path->ptr, "parent is not directory"); } else - futils__error_cannot_rmdir(path->ptr, "cannot access"); + error = git_path_set_error(errno, path->ptr, "rmdir"); } else if (S_ISDIR(st.st_mode)) { data->depth++; - { - int error = - git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); - if (error < 0) - return (error == GIT_EUSER) ? data->error : error; - } + error = git_path_direach(path, 0, futils__rmdir_recurs_foreach, data); + if (error < 0) + return (error == GIT_EUSER) ? data->error : error; data->depth--; if (data->depth == 0 && (data->flags & GIT_RMDIR_SKIP_ROOT) != 0) return data->error; - data->error = p_rmdir(path->ptr); - - if (data->error < 0) { + if ((error = p_rmdir(path->ptr)) < 0) { if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) != 0 && (errno == ENOTEMPTY || errno == EEXIST || errno == EBUSY)) - data->error = 0; + error = 0; else - futils__error_cannot_rmdir(path->ptr, NULL); + error = git_path_set_error(errno, path->ptr, "rmdir"); } } else if ((data->flags & GIT_RMDIR_REMOVE_FILES) != 0) { - data->error = p_unlink(path->ptr); - - if (data->error < 0) - futils__error_cannot_rmdir(path->ptr, "cannot be removed"); + if (p_unlink(path->ptr) < 0) + error = git_path_set_error(errno, path->ptr, "remove"); } else if ((data->flags & GIT_RMDIR_SKIP_NONEMPTY) == 0) - data->error = futils__error_cannot_rmdir(path->ptr, "still present"); + error = futils__error_cannot_rmdir(path->ptr, "still present"); - return data->error; + data->error = error; + return error; } static int futils__rmdir_empty_parent(void *opaque, git_buf *path) @@ -523,7 +508,7 @@ static int futils__rmdir_empty_parent(void *opaque, git_buf *path) giterr_clear(); error = GIT_ITEROVER; } else { - futils__error_cannot_rmdir(git_buf_cstr(path), NULL); + error = git_path_set_error(errno, git_buf_cstr(path), "rmdir"); } } @@ -818,11 +803,8 @@ int git_futils_cp(const char *from, const char *to, mode_t filemode) return ifd; if ((ofd = p_open(to, O_WRONLY | O_CREAT | O_EXCL, filemode)) < 0) { - if (errno == ENOENT || errno == ENOTDIR) - ofd = GIT_ENOTFOUND; - giterr_set(GITERR_OS, "Failed to open '%s' for writing", to); p_close(ifd); - return ofd; + return git_path_set_error(errno, to, "open for writing"); } return cp_by_fd(ifd, ofd, true); @@ -905,15 +887,14 @@ static int _cp_r_callback(void *ref, git_buf *from) goto exit; } - if (p_lstat(info->to.ptr, &to_st) < 0) { - if (errno != ENOENT && errno != ENOTDIR) { - giterr_set(GITERR_OS, - "Could not access %s while copying files", info->to.ptr); - error = -1; - goto exit; - } - } else + if (!(error = git_path_lstat(info->to.ptr, &to_st))) exists = true; + else if (error != GIT_ENOTFOUND) + goto exit; + else { + giterr_clear(); + error = 0; + } if ((error = git_path_lstat(from->ptr, &from_st)) < 0) goto exit; diff --git a/src/index.c b/src/index.c index 21a8d31d1..06394e6db 100644 --- a/src/index.c +++ b/src/index.c @@ -579,7 +579,8 @@ const git_index_entry *git_index_get_bypath( return git_index_get_byindex(index, pos); } -void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st) +void git_index_entry__init_from_stat( + git_index_entry *entry, struct stat *st, bool trust_mode) { entry->ctime.seconds = (git_time_t)st->st_ctime; entry->mtime.seconds = (git_time_t)st->st_mtime; @@ -587,7 +588,8 @@ void git_index_entry__init_from_stat(git_index_entry *entry, struct stat *st) /* entry->ctime.nanoseconds = st->st_ctimensec; */ entry->dev = st->st_rdev; entry->ino = st->st_ino; - entry->mode = index_create_mode(st->st_mode); + entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ? + index_create_mode(0666) : index_create_mode(st->st_mode); entry->uid = st->st_uid; entry->gid = st->st_gid; entry->file_size = st->st_size; @@ -631,7 +633,7 @@ static int index_entry_init( entry = git__calloc(1, sizeof(git_index_entry)); GITERR_CHECK_ALLOC(entry); - git_index_entry__init_from_stat(entry, &st); + git_index_entry__init_from_stat(entry, &st, !index->distrust_filemode); entry->oid = oid; entry->path = git__strdup(rel_path); diff --git a/src/index.h b/src/index.h index 40577e105..4c448fabf 100644 --- a/src/index.h +++ b/src/index.h @@ -48,7 +48,7 @@ struct git_index_conflict_iterator { }; extern void git_index_entry__init_from_stat( - git_index_entry *entry, struct stat *st); + git_index_entry *entry, struct stat *st, bool trust_mode); extern size_t git_index__prefix_position(git_index *index, const char *path); diff --git a/src/iterator.c b/src/iterator.c index ea6b45e88..c0d7862ff 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1175,7 +1175,7 @@ static int fs_iterator__update_entry(fs_iterator *fi) return GIT_ITEROVER; fi->entry.path = ps->path; - git_index_entry__init_from_stat(&fi->entry, &ps->st); + git_index_entry__init_from_stat(&fi->entry, &ps->st, true); /* need different mode here to keep directories during iteration */ fi->entry.mode = git_futils_canonical_mode(ps->st.st_mode); diff --git a/src/path.c b/src/path.c index 27abd062b..d45751cd1 100644 --- a/src/path.c +++ b/src/path.c @@ -538,16 +538,35 @@ bool git_path_is_empty_dir(const char *path) #endif +int git_path_set_error(int errno_value, const char *path, const char *action) +{ + switch (errno_value) { + case ENOENT: + case ENOTDIR: + giterr_set(GITERR_OS, "Could not find '%s' to %s", path, action); + return GIT_ENOTFOUND; + + case EINVAL: + case ENAMETOOLONG: + giterr_set(GITERR_OS, "Invalid path for filesystem '%s'", path); + return GIT_EINVALIDSPEC; + + case EEXIST: + giterr_set(GITERR_OS, "Failed %s - '%s' already exists", action, path); + return GIT_EEXISTS; + + default: + giterr_set(GITERR_OS, "Could not %s '%s'", action, path); + return -1; + } +} + int git_path_lstat(const char *path, struct stat *st) { - int err = 0; + if (p_lstat(path, st) == 0) + return 0; - if (p_lstat(path, st) < 0) { - err = (errno == ENOENT) ? GIT_ENOTFOUND : -1; - giterr_set(GITERR_OS, "Failed to stat file '%s'", path); - } - - return err; + return git_path_set_error(errno, path, "stat"); } static bool _check_dir_contents( diff --git a/src/path.h b/src/path.h index 2cfd714cd..175756938 100644 --- a/src/path.h +++ b/src/path.h @@ -358,6 +358,10 @@ extern int git_path_dirload_with_stat( const char *end_stat, git_vector *contents); +/* translate errno to libgit2 error code and set error message */ +extern int git_path_set_error( + int errno_value, const char *path, const char *action); + /* check if non-ascii characters are present in filename */ extern bool git_path_has_non_ascii(const char *path, size_t pathlen); diff --git a/src/repository.c b/src/repository.c index 52509ffc1..23cafe05a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -961,80 +961,121 @@ static int create_empty_file(const char *path, mode_t mode) return 0; } +static int repo_local_config( + git_config **out, + git_buf *config_dir, + git_repository *repo, + const char *repo_dir) +{ + int error = 0; + git_config *parent; + const char *cfg_path; + + if (git_buf_joinpath(config_dir, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) + return -1; + cfg_path = git_buf_cstr(config_dir); + + /* make LOCAL config if missing */ + if (!git_path_isfile(cfg_path) && + (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0) + return error; + + /* if no repo, just open that file directly */ + if (!repo) + return git_config_open_ondisk(out, cfg_path); + + /* otherwise, open parent config and get that level */ + if ((error = git_repository_config__weakptr(&parent, repo)) < 0) + return error; + + if (git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL) < 0) { + giterr_clear(); + + if (!(error = git_config_add_file_ondisk( + parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false))) + error = git_config_open_level(out, parent, GIT_CONFIG_LEVEL_LOCAL); + } + + git_config_free(parent); + + return error; +} + +static int repo_init_fs_configs( + git_config *cfg, + const char *cfg_path, + const char *repo_dir, + const char *work_dir, + bool update_ignorecase) +{ + int error = 0; + + if (!work_dir) + work_dir = repo_dir; + + if ((error = git_config_set_bool( + cfg, "core.filemode", is_chmod_supported(cfg_path))) < 0) + return error; + + if (!are_symlinks_supported(work_dir)) { + if ((error = git_config_set_bool(cfg, "core.symlinks", false)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.symlinks") < 0) + giterr_clear(); + + if (update_ignorecase) { + if (is_filesystem_case_insensitive(repo_dir)) { + if ((error = git_config_set_bool(cfg, "core.ignorecase", true)) < 0) + return error; + } else if (git_config_delete_entry(cfg, "core.ignorecase") < 0) + giterr_clear(); + } + +#ifdef GIT_USE_ICONV + if ((error = git_config_set_bool( + cfg, "core.precomposeunicode", + does_fs_decompose_unicode_paths(work_dir))) < 0) + return error; +#endif + + return 0; +} + static int repo_init_config( - git_config *parent, const char *repo_dir, const char *work_dir, uint32_t flags, uint32_t mode) { int error = 0; - git_buf buf = GIT_BUF_INIT; - const char *cfg_path = NULL; + git_buf cfg_path = GIT_BUF_INIT; git_config *config = NULL; bool is_bare = ((flags & GIT_REPOSITORY_INIT_BARE) != 0); + bool is_reinit = ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0); -#define SET_REPO_CONFIG(TYPE, NAME, VAL) do {\ + if ((error = repo_local_config(&config, &cfg_path, NULL, repo_dir)) < 0) + goto cleanup; + + if (is_reinit && (error = check_repositoryformatversion(config)) < 0) + goto cleanup; + +#define SET_REPO_CONFIG(TYPE, NAME, VAL) do { \ if ((error = git_config_set_##TYPE(config, NAME, VAL)) < 0) \ goto cleanup; } while (0) - if (git_buf_joinpath(&buf, repo_dir, GIT_CONFIG_FILENAME_INREPO) < 0) - return -1; - cfg_path = git_buf_cstr(&buf); + SET_REPO_CONFIG(bool, "core.bare", is_bare); + SET_REPO_CONFIG(int32, "core.repositoryformatversion", GIT_REPO_VERSION); - if (!git_path_isfile(cfg_path) && - (error = create_empty_file(cfg_path, GIT_CONFIG_FILE_MODE)) < 0) + if ((error = repo_init_fs_configs( + config, cfg_path.ptr, repo_dir, work_dir, !is_reinit)) < 0) goto cleanup; - if (!parent) - error = git_config_open_ondisk(&config, cfg_path); - else if ((error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL)) < 0) - { - giterr_clear(); - - if (!(error = git_config_add_file_ondisk( - parent, cfg_path, GIT_CONFIG_LEVEL_LOCAL, false))) - error = git_config_open_level( - &config, parent, GIT_CONFIG_LEVEL_LOCAL); - } - if (error < 0) - goto cleanup; - - if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0 && - (error = check_repositoryformatversion(config)) < 0) - goto cleanup; - - SET_REPO_CONFIG( - bool, "core.bare", is_bare); - SET_REPO_CONFIG( - int32, "core.repositoryformatversion", GIT_REPO_VERSION); - SET_REPO_CONFIG( - bool, "core.filemode", is_chmod_supported(cfg_path)); - -#ifdef GIT_USE_ICONV - SET_REPO_CONFIG( - bool, "core.precomposeunicode", - does_fs_decompose_unicode_paths(is_bare ? repo_dir : work_dir)); -#endif - - if (!are_symlinks_supported(is_bare ? repo_dir : work_dir)) - SET_REPO_CONFIG(bool, "core.symlinks", false); - - /* core git does not do this on a reinit, but it is a property of - * the filesystem, so I think we should... - */ - if (!(flags & GIT_REPOSITORY_INIT__IS_REINIT) && - is_filesystem_case_insensitive(repo_dir)) - SET_REPO_CONFIG(bool, "core.ignorecase", true); - if (!is_bare) { SET_REPO_CONFIG(bool, "core.logallrefupdates", true); - if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) { + if (!(flags & GIT_REPOSITORY_INIT__NATURAL_WD)) SET_REPO_CONFIG(string, "core.worktree", work_dir); - } - else if ((flags & GIT_REPOSITORY_INIT__IS_REINIT) != 0) { + else if (is_reinit) { if (git_config_delete_entry(config, "core.worktree") < 0) giterr_clear(); } @@ -1050,38 +1091,44 @@ static int repo_init_config( } cleanup: - git_buf_free(&buf); + git_buf_free(&cfg_path); git_config_free(config); return error; } -int git_repository_reset_filesystem(git_repository *repo) +static int repo_reset_submodule_fs(git_submodule *sm, const char *n, void *p) +{ + git_repository *smrepo = NULL; + GIT_UNUSED(n); GIT_UNUSED(p); + + if (git_submodule_open(&smrepo, sm) < 0 || + git_repository_reset_filesystem(smrepo, true) < 0) + giterr_clear(); + git_repository_free(smrepo); + + return 0; +} + +int git_repository_reset_filesystem(git_repository *repo, int recurse) { int error = 0; - uint32_t flags = 0; - const char *repo_dir, *work_dir; - git_config *cfg; + git_buf path = GIT_BUF_INIT; + git_config *config = NULL; + const char *repo_dir = git_repository_path(repo); - assert(repo); + if (!(error = repo_local_config(&config, &path, repo, repo_dir))) + error = repo_init_fs_configs( + config, path.ptr, repo_dir, git_repository_workdir(repo), true); - repo_dir = git_repository_path(repo); - work_dir = git_repository_workdir(repo); + git_config_free(config); + git_buf_free(&path); - if (git_repository_is_bare(repo)) - flags |= GIT_REPOSITORY_INIT_BARE; - else if (!git__prefixcmp(repo_dir, work_dir) && - !strcmp(repo_dir + strlen(work_dir), DOT_GIT "/")) - flags |= GIT_REPOSITORY_INIT__NATURAL_WD; - - if ((error = git_repository_config(&cfg, repo)) < 0) - return error; - - error = repo_init_config(cfg, repo_dir, work_dir, flags, 0); - - git_config_free(cfg); git_repository__cvar_cache_clear(repo); + if (!repo->is_bare && recurse) + (void)git_submodule_foreach(repo, repo_reset_submodule_fs, NULL); + return error; } @@ -1473,7 +1520,7 @@ int git_repository_init_ext( opts->flags |= GIT_REPOSITORY_INIT__IS_REINIT; error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode); /* TODO: reinitialize the templates */ } @@ -1481,7 +1528,7 @@ int git_repository_init_ext( if (!(error = repo_init_structure( repo_path.ptr, wd_path.ptr, opts)) && !(error = repo_init_config( - NULL, repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) + repo_path.ptr, wd_path.ptr, opts->flags, opts->mode))) error = repo_init_create_head( repo_path.ptr, opts->initial_head); } diff --git a/src/submodule.c b/src/submodule.c index 121383b9c..12ade83fe 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -372,7 +372,8 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index) memset(&entry, 0, sizeof(entry)); entry.path = sm->path; - git_index_entry__init_from_stat(&entry, &st); + git_index_entry__init_from_stat( + &entry, &st, !(git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE)); /* calling git_submodule_open will have set sm->wd_oid if possible */ if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) { diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 2f490529c..18f717b0f 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -125,8 +125,8 @@ static int do_lstat( errno = ENOENT; - /* We need POSIX behavior, then ENOTDIR must set when any of the folders in the - * file path is a regular file,otherwise ENOENT must be set. + /* To match POSIX behavior, set ENOTDIR when any of the folders in the + * file path is a regular file, otherwise set ENOENT. */ if (posix_enotdir) { /* scan up path until we find an existing item */ diff --git a/tests-clar/clar_libgit2.c b/tests-clar/clar_libgit2.c index c3abc1f95..82ec5c065 100644 --- a/tests-clar/clar_libgit2.c +++ b/tests-clar/clar_libgit2.c @@ -191,7 +191,7 @@ git_repository *cl_git_sandbox_init(const char *sandbox) cl_git_pass(git_repository_open(&_cl_repo, sandbox)); /* Adjust configs after copying to new filesystem */ - cl_git_pass(git_repository_reset_filesystem(_cl_repo)); + cl_git_pass(git_repository_reset_filesystem(_cl_repo, 0)); return _cl_repo; } diff --git a/tests-clar/diff/patch.c b/tests-clar/diff/patch.c index 7aab8f409..1dbfc9ac5 100644 --- a/tests-clar/diff/patch.c +++ b/tests-clar/diff/patch.c @@ -240,7 +240,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo); + git_repository_reset_filesystem(g_repo, false); cl_git_pass( git_futils_readbuffer(&old_content, "renames/songof7cities.txt")); @@ -524,7 +524,7 @@ void test_diff_patch__line_counts_with_eofnl(void) git_repository_set_config(g_repo, cfg); git_config_free(cfg); - git_repository_reset_filesystem(g_repo); + git_repository_reset_filesystem(g_repo, false); cl_git_pass(git_futils_readbuffer(&content, "renames/songof7cities.txt")); diff --git a/tests-clar/diff/workdir.c b/tests-clar/diff/workdir.c index 6c17b41c6..aeef7b963 100644 --- a/tests-clar/diff/workdir.c +++ b/tests-clar/diff/workdir.c @@ -761,16 +761,7 @@ void test_diff_workdir__submodules(void) git_diff_list *diff = NULL; diff_expects exp; - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); - p_rename("submod2/not/.gitted", "submod2/not/.git"); - - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); a = resolve_commit_oid_to_tree(g_repo, a_commit); diff --git a/tests-clar/index/addall.c b/tests-clar/index/addall.c index f46a1e16c..3b5f5f22d 100644 --- a/tests-clar/index/addall.c +++ b/tests-clar/index/addall.c @@ -111,8 +111,9 @@ static void check_stat_data(git_index *index, const char *path, bool match) cl_assert(st.st_gid == entry->gid); cl_assert_equal_i_fmt( GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); - cl_assert_equal_b( - GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); + if (cl_is_chmod_supported()) + cl_assert_equal_b( + GIT_PERMS_IS_EXEC(st.st_mode), GIT_PERMS_IS_EXEC(entry->mode)); } else { /* most things will still match */ cl_assert(st.st_size != entry->file_size); diff --git a/tests-clar/index/filemodes.c b/tests-clar/index/filemodes.c index 8cbd6ff3a..013932696 100644 --- a/tests-clar/index/filemodes.c +++ b/tests-clar/index/filemodes.c @@ -74,7 +74,6 @@ static void add_and_check_mode_( void test_index_filemodes__untrusted(void) { git_index *index; - bool can_filemode = cl_is_chmod_supported(); cl_repo_set_bool(g_repo, "core.filemode", false); @@ -97,20 +96,15 @@ void test_index_filemodes__untrusted(void) replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); - /* these tests of newly added files won't give predictable results on - * filesystems without actual filemode support, so skip them. - */ - if (can_filemode) { - /* 5 - add new 0644 -> expect 0644 */ - cl_git_write2file("filemodes/new_off", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0644); - add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); + /* 5 - add new 0644 -> expect 0644 */ + cl_git_write2file("filemodes/new_off", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0644); + add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); - /* 6 - add new 0755 -> expect 0755 */ - cl_git_write2file("filemodes/new_on", "blah", 0, - O_WRONLY | O_CREAT | O_TRUNC, 0755); - add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); - } + /* 6 - add new 0755 -> expect 0644 if core.filemode == false */ + cl_git_write2file("filemodes/new_on", "blah", 0, + O_WRONLY | O_CREAT | O_TRUNC, 0755); + add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB); git_index_free(index); } diff --git a/tests-clar/refs/unicode.c b/tests-clar/refs/unicode.c index 2ec103275..b29c63e2b 100644 --- a/tests-clar/refs/unicode.c +++ b/tests-clar/refs/unicode.c @@ -22,23 +22,38 @@ void test_refs_unicode__create_and_lookup(void) git_reference *ref0, *ref1, *ref2; git_repository *repo2; - const char *REFNAME = "refs/heads/" "\305" "ngstr" "\366" "m"; + const char *REFNAME = "refs/heads/" "\303\205" "ngstr" "\303\266" "m"; + const char *REFNAME_DECOMPOSED = + "refs/heads/" "A" "\314\212" "ngstro" "\314\210" "m"; const char *master = "refs/heads/master"; /* Create the reference */ cl_git_pass(git_reference_lookup(&ref0, repo, master)); cl_git_pass(git_reference_create(&ref1, repo, REFNAME, git_reference_target(ref0), 0)); cl_assert_equal_s(REFNAME, git_reference_name(ref1)); + git_reference_free(ref0); /* Lookup the reference in a different instance of the repository */ cl_git_pass(git_repository_open(&repo2, "testrepo.git")); + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME)); - - cl_assert(git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2)) == 0); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); cl_assert_equal_s(REFNAME, git_reference_name(ref2)); - - git_reference_free(ref0); - git_reference_free(ref1); git_reference_free(ref2); + +#if GIT_USE_ICONV + /* Lookup reference by decomposed unicode name */ + + cl_git_pass(git_reference_lookup(&ref2, repo2, REFNAME_DECOMPOSED)); + cl_assert_equal_i( + 0, git_oid_cmp(git_reference_target(ref1), git_reference_target(ref2))); + cl_assert_equal_s(REFNAME, git_reference_name(ref2)); + git_reference_free(ref2); +#endif + + /* Cleanup */ + + git_reference_free(ref1); git_repository_free(repo2); } diff --git a/tests-clar/submodule/lookup.c b/tests-clar/submodule/lookup.c index b626cdf04..5f320e702 100644 --- a/tests-clar/submodule/lookup.c +++ b/tests-clar/submodule/lookup.c @@ -7,20 +7,7 @@ static git_repository *g_repo = NULL; void test_submodule_lookup__initialize(void) { - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - /* must create submod2_target before rewrite so prettify will work */ - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); -} - -void test_submodule_lookup__cleanup(void) -{ - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); } void test_submodule_lookup__simple_lookup(void) diff --git a/tests-clar/submodule/modify.c b/tests-clar/submodule/modify.c index c0498ce6e..e326287a6 100644 --- a/tests-clar/submodule/modify.c +++ b/tests-clar/submodule/modify.c @@ -11,20 +11,7 @@ static git_repository *g_repo = NULL; void test_submodule_modify__initialize(void) { - g_repo = cl_git_sandbox_init("submod2"); - - cl_fixture_sandbox("submod2_target"); - p_rename("submod2_target/.gitted", "submod2_target/.git"); - - /* must create submod2_target before rewrite so prettify will work */ - rewrite_gitmodules(git_repository_workdir(g_repo)); - p_rename("submod2/not-submodule/.gitted", "submod2/not-submodule/.git"); -} - -void test_submodule_modify__cleanup(void) -{ - cl_git_sandbox_cleanup(); - cl_fixture_cleanup("submod2_target"); + g_repo = setup_fixture_submod2(); } void test_submodule_modify__add(void) diff --git a/tests-clar/submodule/submodule_helpers.c b/tests-clar/submodule/submodule_helpers.c index 3e79c77fd..cc3b7a2e3 100644 --- a/tests-clar/submodule/submodule_helpers.c +++ b/tests-clar/submodule/submodule_helpers.c @@ -102,6 +102,8 @@ git_repository *setup_fixture_submodules(void) cl_set_cleanup(cleanup_fixture_submodules, "testrepo.git"); + cl_git_pass(git_repository_reset_filesystem(repo, 1)); + return repo; } @@ -118,5 +120,7 @@ git_repository *setup_fixture_submod2(void) cl_set_cleanup(cleanup_fixture_submodules, "submod2_target"); + cl_git_pass(git_repository_reset_filesystem(repo, 1)); + return repo; }