Commit 8e4aae1ae5f9f023641ab4046dfee6c744e58e13

Ben Straub 2012-07-31T10:44:42

Checkout: handle file modes properly. Global file mode override now works properly with the file mode stored in the tree node.

diff --git a/src/checkout.c b/src/checkout.c
index 41acf1c..e8fba79 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -61,11 +61,13 @@ static int blob_contents_to_link(tree_walk_data *data, git_buf *fnbuf,
 
 
 static int blob_contents_to_file(git_repository *repo, git_buf *fnbuf,
-											const git_oid *id, tree_walk_data *data)
+											const git_tree_entry *entry, tree_walk_data *data)
 {
 	int retcode = GIT_ERROR;
 	int fd = -1;
 	git_buf contents = GIT_BUF_INIT;
+	const git_oid *id = git_tree_entry_id(entry);
+	int file_mode = data->opts->file_mode;
 
 	/* Deal with pre-existing files */
 	if (git_path_exists(git_buf_cstr(fnbuf)) &&
@@ -84,10 +86,14 @@ static int blob_contents_to_file(git_repository *repo, git_buf *fnbuf,
 	}
 	if (retcode < 0) goto bctf_cleanup;
 
+	/* Allow overriding of file mode */
+	if (!file_mode)
+		file_mode = git_tree_entry_attributes(entry);
+
 	if ((retcode = git_futils_mkpath2file(git_buf_cstr(fnbuf), data->opts->dir_mode)) < 0)
 		goto bctf_cleanup;
 
-	fd = p_open(git_buf_cstr(fnbuf), data->opts->file_open_flags, data->opts->file_mode);
+	fd = p_open(git_buf_cstr(fnbuf), data->opts->file_open_flags, file_mode);
 	if (fd < 0) goto bctf_cleanup;
 
 	if (!p_write(fd, git_buf_cstr(&contents), git_buf_len(&contents)))
@@ -129,8 +135,7 @@ static int checkout_walker(const char *path, const git_tree_entry *entry, void *
 			retcode = blob_contents_to_link(data, &fnbuf,
 													  git_tree_entry_id(entry));
 		} else {
-			retcode = blob_contents_to_file(data->repo, &fnbuf,
-													  git_tree_entry_id(entry), data);
+			retcode = blob_contents_to_file(data->repo, &fnbuf, entry, data);
 		}
 		break;
 
@@ -163,8 +168,6 @@ int git_checkout_head(git_repository *repo, git_checkout_opts *opts, git_indexer
 		opts->existing_file_action = GIT_CHECKOUT_OVERWRITE_EXISTING;
 	/* opts->disable_filters is false by default */
 	if (!opts->dir_mode) opts->dir_mode = GIT_DIR_MODE;
-	if (!opts->file_mode)
-		opts->file_mode = 0644; 
 	if (!opts->file_open_flags)
 		opts->file_open_flags = O_CREAT | O_TRUNC | O_WRONLY;
 
diff --git a/tests-clar/checkout/checkout.c b/tests-clar/checkout/checkout.c
index 1e777e0..5099c4e 100644
--- a/tests-clar/checkout/checkout.c
+++ b/tests-clar/checkout/checkout.c
@@ -145,14 +145,18 @@ void test_checkout_checkout__dir_modes(void)
 
 	cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/dir"));
 
-	opts.dir_mode = 0600;
+	opts.dir_mode = 0701;
 	cl_git_pass(git_checkout_reference(ref, &opts, NULL));
 	cl_git_pass(p_stat("./testrepo/a", &st));
-	cl_assert_equal_i(st.st_mode & 0777, 0600);
+	cl_assert_equal_i(st.st_mode & 0777, 0701);
+
+	/* File-mode test, since we're on the 'dir' branch */
+	cl_git_pass(p_stat("./testrepo/a/b.txt", &st));
+	cl_assert_equal_i(st.st_mode & 0777, 0755);
 #endif
 }
 
-void test_checkout_checkout__file_modes(void)
+void test_checkout_checkout__override_file_modes(void)
 {
 #ifndef GIT_WIN32
 	git_checkout_opts opts = {0};
diff --git a/tests-clar/resources/testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e b/tests-clar/resources/testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e
new file mode 100644
index 0000000..b7d944f
Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/14/4344043ba4d4a405da03de3844aa829ae8be0e differ
diff --git a/tests-clar/resources/testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 b/tests-clar/resources/testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63
new file mode 100644
index 0000000..e915021
Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/4e/0883eeeeebc1fb1735161cea82f7cb5fab7e63 differ
diff --git a/tests-clar/resources/testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 b/tests-clar/resources/testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83
new file mode 100644
index 0000000..00940f0
Binary files /dev/null and b/tests-clar/resources/testrepo/.gitted/objects/d5/2a8fe84ceedf260afe4f0287bbfca04a117e83 differ
diff --git a/tests-clar/resources/testrepo/.gitted/refs/heads/dir b/tests-clar/resources/testrepo/.gitted/refs/heads/dir
index e140e85..4567d37 100644
--- a/tests-clar/resources/testrepo/.gitted/refs/heads/dir
+++ b/tests-clar/resources/testrepo/.gitted/refs/heads/dir
@@ -1 +1 @@
-cf80f8de9f1185bf3a05f993f6121880dd0cfbc9
+144344043ba4d4a405da03de3844aa829ae8be0e