mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 22:01:26 +00:00
Merge pull request #3429 from ethomson/checkout_chmod
Checkout: handle mode changes
This commit is contained in:
commit
add0378d8e
@ -243,6 +243,12 @@ static int checkout_action_common(
|
||||
if (delta->new_file.mode == GIT_FILEMODE_LINK && wd != NULL)
|
||||
*action |= CHECKOUT_ACTION__REMOVE;
|
||||
|
||||
/* if the file is on disk and doesn't match our mode, force update */
|
||||
if (wd &&
|
||||
GIT_PERMS_IS_EXEC(wd->mode) !=
|
||||
GIT_PERMS_IS_EXEC(delta->new_file.mode))
|
||||
*action |= CHECKOUT_ACTION__REMOVE;
|
||||
|
||||
notify = GIT_CHECKOUT_NOTIFY_UPDATED;
|
||||
}
|
||||
|
||||
@ -1500,15 +1506,6 @@ static int blob_content_to_file(
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
if (GIT_PERMS_IS_EXEC(mode)) {
|
||||
data->perfdata.chmod_calls++;
|
||||
|
||||
if ((error = p_chmod(path, mode)) < 0) {
|
||||
giterr_set(GITERR_OS, "Failed to set permissions on '%s'", path);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (st) {
|
||||
data->perfdata.stat_calls++;
|
||||
|
||||
|
@ -946,7 +946,7 @@ void test_checkout_tree__filemode_preserved_in_index(void)
|
||||
|
||||
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_equal_i(0100755, entry->mode);
|
||||
cl_assert(GIT_PERMS_IS_EXEC(entry->mode));
|
||||
|
||||
git_commit_free(commit);
|
||||
|
||||
@ -957,7 +957,7 @@ void test_checkout_tree__filemode_preserved_in_index(void)
|
||||
|
||||
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_equal_i(0100644, entry->mode);
|
||||
cl_assert(!GIT_PERMS_IS_EXEC(entry->mode));
|
||||
|
||||
git_commit_free(commit);
|
||||
|
||||
@ -968,7 +968,18 @@ void test_checkout_tree__filemode_preserved_in_index(void)
|
||||
|
||||
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_equal_i(0100755, entry->mode);
|
||||
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);
|
||||
|
||||
@ -976,6 +987,73 @@ void test_checkout_tree__filemode_preserved_in_index(void)
|
||||
git_index_free(index);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
void test_checkout_tree__removes_conflicts(void)
|
||||
{
|
||||
git_oid commit_id;
|
||||
|
Loading…
Reference in New Issue
Block a user