From 6124d983b6970f99ec7c93e480896806a83e7198 Mon Sep 17 00:00:00 2001 From: Matti Virolainen Date: Mon, 1 Jun 2015 11:16:36 +0300 Subject: Check that an executable in index is not an executable after checkout. --- tests/checkout/tree.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index be4019822..577409511 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -973,6 +973,17 @@ void test_checkout_tree__filemode_preserved_in_index(void) 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_equal_i(0100644, entry->mode); + + git_commit_free(commit); + + git_index_free(index); } -- cgit v1.2.1 From 33cad995899c960c777b3545dd58fd342ffdc64a Mon Sep 17 00:00:00 2001 From: Matti Virolainen Date: Mon, 1 Jun 2015 14:31:49 +0300 Subject: Check that checkout preserves filemode in working directory. --- tests/checkout/tree.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 577409511..9217c12d9 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -987,6 +987,69 @@ void test_checkout_tree__filemode_preserved_in_index(void) git_index_free(index); } +mode_t read_filemode(const char *path) +{ + struct stat st; + char pathabs[256] = {0}; + + strcat(pathabs, clar_sandbox_path()); + strcat(pathabs, "/testrepo/"); + strcat(pathabs, path); + cl_must_pass(p_stat(pathabs, &st)); + + return st.st_mode; +} + +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_equal_i(0100755, 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_equal_i(0100644, 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_equal_i(0100755, 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_equal_i(0100644, read_filemode("a/b.txt")); + + git_commit_free(commit); +#endif +} + void test_checkout_tree__removes_conflicts(void) { git_oid commit_id; -- cgit v1.2.1 From b4d183a77aa01cac406aecdff8908f10cb3501cb Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Sep 2015 04:12:47 +0000 Subject: checkout::tree tests: don't use static buffer --- tests/checkout/tree.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 9217c12d9..3b84f43ce 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -989,15 +989,18 @@ void test_checkout_tree__filemode_preserved_in_index(void) mode_t read_filemode(const char *path) { + git_buf fullpath = GIT_BUF_INIT; struct stat st; - char pathabs[256] = {0}; + mode_t result; - strcat(pathabs, clar_sandbox_path()); - strcat(pathabs, "/testrepo/"); - strcat(pathabs, path); - cl_must_pass(p_stat(pathabs, &st)); + git_buf_joinpath(&fullpath, "testrepo", path); + cl_must_pass(p_stat(fullpath.ptr, &st)); - return st.st_mode; + result = GIT_PERMS_IS_EXEC(st.st_mode) ? 0100755 : 0100644; + + git_buf_free(&fullpath); + + return result; } void test_checkout_tree__filemode_preserved_in_workdir(void) -- cgit v1.2.1 From 6fe322843b98f0f9101258c88c820f230eec5f64 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Sep 2015 10:17:54 -0400 Subject: checkout::tree tests: don't use hardcoded mode --- tests/checkout/tree.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 3b84f43ce..5692e1f25 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -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,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(0100755, entry->mode); + cl_assert(GIT_PERMS_IS_EXEC(entry->mode)); git_commit_free(commit); @@ -979,7 +979,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); @@ -1017,7 +1017,7 @@ void test_checkout_tree__filemode_preserved_in_workdir(void) 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_equal_i(0100755, read_filemode("executable.txt")); + cl_assert(GIT_PERMS_IS_EXEC(read_filemode("executable.txt"))); git_commit_free(commit); @@ -1027,7 +1027,7 @@ void test_checkout_tree__filemode_preserved_in_workdir(void) 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_equal_i(0100644, read_filemode("a/b.txt")); + cl_assert(!GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); @@ -1037,7 +1037,7 @@ void test_checkout_tree__filemode_preserved_in_workdir(void) 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_equal_i(0100755, read_filemode("a/b.txt")); + cl_assert(GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); @@ -1047,7 +1047,7 @@ void test_checkout_tree__filemode_preserved_in_workdir(void) 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_equal_i(0100644, read_filemode("a/b.txt")); + cl_assert(!GIT_PERMS_IS_EXEC(read_filemode("a/b.txt"))); git_commit_free(commit); #endif -- cgit v1.2.1 From eea7c850248c04a6ac3aadbb13b2c72c2237013b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Wed, 16 Sep 2015 05:44:27 +0000 Subject: checkout: overwrite files with differing modes When a file exists on disk and we're checking out a file that differs in executableness, remove the old file. This allows us to recreate the new file with p_open, which will take the new mode into account and handle setting the umask properly. Remove any notion of chmod'ing existing files, since it is now handled by the aforementioned removal and was incorrect, as it did not take umask into account. --- src/checkout.c | 15 ++++++--------- tests/checkout/tree.c | 3 ++- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/checkout.c b/src/checkout.c index de48c9e01..8c06b3335 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -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++; diff --git a/tests/checkout/tree.c b/tests/checkout/tree.c index 5692e1f25..5680b86df 100644 --- a/tests/checkout/tree.c +++ b/tests/checkout/tree.c @@ -996,7 +996,8 @@ mode_t read_filemode(const char *path) git_buf_joinpath(&fullpath, "testrepo", path); cl_must_pass(p_stat(fullpath.ptr, &st)); - result = GIT_PERMS_IS_EXEC(st.st_mode) ? 0100755 : 0100644; + result = GIT_PERMS_IS_EXEC(st.st_mode) ? + GIT_FILEMODE_BLOB_EXECUTABLE : GIT_FILEMODE_BLOB; git_buf_free(&fullpath); -- cgit v1.2.1