static void check_stat_data(git_index *index, const char *path, bool match) { const git_index_entry *entry; struct stat st; cl_must_pass(p_lstat(path, &st)); /* skip repo base dir name */ while (*path != '/') ++path; ++path; entry = git_index_get_bypath(index, path, 0); cl_assert(entry); if (match) { cl_assert(st.st_ctime == entry->ctime.seconds); cl_assert(st.st_mtime == entry->mtime.seconds); cl_assert(st.st_size == entry->file_size); cl_assert(st.st_uid == entry->uid); cl_assert(st.st_gid == entry->gid); cl_assert_equal_i_fmt( GIT_MODE_TYPE(st.st_mode), GIT_MODE_TYPE(entry->mode), "%07o"); 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); /* would check mtime, but with second resolution it won't work :( */ } }
static void assert_mode_seems_okay( const char *base, const char *path, git_filemode_t expect_mode, bool expect_setgid, bool core_filemode) { git_buf full = GIT_BUF_INIT; struct stat st; cl_git_pass(git_buf_joinpath(&full, base, path)); cl_git_pass(git_path_lstat(full.ptr, &st)); git_buf_free(&full); if (!core_filemode) { CLEAR_FOR_CORE_FILEMODE(expect_mode); CLEAR_FOR_CORE_FILEMODE(st.st_mode); expect_setgid = false; } if (S_ISGID != 0) cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0); cl_assert_equal_b( GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode)); cl_assert_equal_i_fmt( GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o"); }
void test_checkout_tree__filemode_preserved_in_index(void) { git_oid executable_oid; git_commit *commit; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; git_index *index; const git_index_entry *entry; opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_repository_index(&index, g_repo)); /* test a freshly added executable */ cl_git_pass(git_oid_fromstr(&executable_oid, "afe4393b2b2a965f06acf2ca9658eaa01e0cd6b6")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(entry = git_index_get_bypath(index, "executable.txt", 0)); cl_assert(GIT_PERMS_IS_EXEC(entry->mode)); git_commit_free(commit); /* Now start with a commit which has a text file */ cl_git_pass(git_oid_fromstr(&executable_oid, "cf80f8de9f1185bf3a05f993f6121880dd0cfbc9")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(entry = git_index_get_bypath(index, "a/b.txt", 0)); cl_assert(!GIT_PERMS_IS_EXEC(entry->mode)); git_commit_free(commit); /* And then check out to a commit which converts the text file to an executable */ cl_git_pass(git_oid_fromstr(&executable_oid, "144344043ba4d4a405da03de3844aa829ae8be0e")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(entry = git_index_get_bypath(index, "a/b.txt", 0)); cl_assert(GIT_PERMS_IS_EXEC(entry->mode)); git_commit_free(commit); /* Finally, check out the text file again and check that the exec bit is cleared */ cl_git_pass(git_oid_fromstr(&executable_oid, "cf80f8de9f1185bf3a05f993f6121880dd0cfbc9")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(entry = git_index_get_bypath(index, "a/b.txt", 0)); cl_assert(!GIT_PERMS_IS_EXEC(entry->mode)); git_commit_free(commit); git_index_free(index); }
void test_checkout_tree__filemode_preserved_in_workdir(void) { #ifndef GIT_WIN32 git_oid executable_oid; git_commit *commit; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; opts.checkout_strategy = GIT_CHECKOUT_FORCE; /* test a freshly added executable */ cl_git_pass(git_oid_fromstr(&executable_oid, "afe4393b2b2a965f06acf2ca9658eaa01e0cd6b6")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(GIT_PERMS_IS_EXEC(read_filemode("executable.txt"))); git_commit_free(commit); /* Now start with a commit which has a text file */ cl_git_pass(git_oid_fromstr(&executable_oid, "cf80f8de9f1185bf3a05f993f6121880dd0cfbc9")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(!GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); /* And then check out to a commit which converts the text file to an executable */ cl_git_pass(git_oid_fromstr(&executable_oid, "144344043ba4d4a405da03de3844aa829ae8be0e")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); /* Finally, check out the text file again and check that the exec bit is cleared */ cl_git_pass(git_oid_fromstr(&executable_oid, "cf80f8de9f1185bf3a05f993f6121880dd0cfbc9")); cl_git_pass(git_commit_lookup(&commit, g_repo, &executable_oid)); cl_git_pass(git_checkout_tree(g_repo, (const git_object *)commit, &opts)); cl_assert(!GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); #endif }
static char diff_pick_suffix(int mode) { if (S_ISDIR(mode)) return '/'; else if (GIT_PERMS_IS_EXEC(mode)) return '*'; else return ' '; }
static char diff_pick_suffix(int mode) { if (S_ISDIR(mode)) return '/'; else if (GIT_PERMS_IS_EXEC(mode)) /* -V536 */ /* in git, modes are very regular, so we must have 0100755 mode */ return '*'; else return ' '; }
mode_t read_filemode(const char *path) { git_buf fullpath = GIT_BUF_INIT; struct stat st; mode_t result; git_buf_joinpath(&fullpath, "testrepo", path); cl_must_pass(p_stat(fullpath.ptr, &st)); result = GIT_PERMS_IS_EXEC(st.st_mode) ? GIT_FILEMODE_BLOB_EXECUTABLE : GIT_FILEMODE_BLOB; git_buf_free(&fullpath); return result; }