Commit 38e769cb by Patrick Steinhardt Committed by GitHub

Merge pull request #4369 from libgit2/ethomson/checkout_typechange

Checkout typechange-only deltas
parents 21e6a11a 19e8faba
...@@ -159,6 +159,19 @@ GIT_INLINE(bool) is_workdir_base_or_new( ...@@ -159,6 +159,19 @@ GIT_INLINE(bool) is_workdir_base_or_new(
git_oid__cmp(&newitem->id, workdir_id) == 0); git_oid__cmp(&newitem->id, workdir_id) == 0);
} }
GIT_INLINE(bool) is_file_mode_changed(git_filemode_t a, git_filemode_t b)
{
#ifdef GIT_WIN32
/*
* On Win32 we do not support the executable bit; the file will
* always be 0100644 on disk, don't bother doing a test.
*/
return false;
#else
return (S_ISREG(a) && S_ISREG(b) && a != b);
#endif
}
static bool checkout_is_workdir_modified( static bool checkout_is_workdir_modified(
checkout_data *data, checkout_data *data,
const git_diff_file *baseitem, const git_diff_file *baseitem,
...@@ -200,7 +213,8 @@ static bool checkout_is_workdir_modified( ...@@ -200,7 +213,8 @@ static bool checkout_is_workdir_modified(
*/ */
if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) { if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
if (git_index_time_eq(&wditem->mtime, &ie->mtime) && if (git_index_time_eq(&wditem->mtime, &ie->mtime) &&
wditem->file_size == ie->file_size) wditem->file_size == ie->file_size &&
!is_file_mode_changed(wditem->mode, ie->mode))
return !is_workdir_base_or_new(&ie->id, baseitem, newitem); return !is_workdir_base_or_new(&ie->id, baseitem, newitem);
} }
...@@ -214,6 +228,9 @@ static bool checkout_is_workdir_modified( ...@@ -214,6 +228,9 @@ static bool checkout_is_workdir_modified(
if (S_ISDIR(wditem->mode)) if (S_ISDIR(wditem->mode))
return false; return false;
if (is_file_mode_changed(baseitem->mode, wditem->mode))
return true;
if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0) if (git_diff__oid_for_entry(&oid, data->diff, wditem, wditem->mode, NULL) < 0)
return false; return false;
......
...@@ -1514,6 +1514,51 @@ void test_checkout_tree__baseline_is_empty_when_no_index(void) ...@@ -1514,6 +1514,51 @@ void test_checkout_tree__baseline_is_empty_when_no_index(void)
git_reference_free(head); git_reference_free(head);
} }
void test_checkout_tree__mode_change_is_force_updated(void)
{
git_index *index;
git_reference *head;
git_object *obj;
git_status_list *status;
if (!cl_is_chmod_supported())
clar__skip();
assert_on_branch(g_repo, "master");
cl_git_pass(git_repository_index(&index, g_repo));
cl_git_pass(git_repository_head(&head, g_repo));
cl_git_pass(git_reference_peel(&obj, head, GIT_OBJ_COMMIT));
cl_git_pass(git_reset(g_repo, obj, GIT_RESET_HARD, NULL));
cl_git_pass(git_status_list_new(&status, g_repo, NULL));
cl_assert_equal_i(0, git_status_list_entrycount(status));
git_status_list_free(status);
/* update the mode on-disk */
cl_must_pass(p_chmod("testrepo/README", 0755));
cl_git_pass(git_checkout_tree(g_repo, obj, &g_opts));
cl_git_pass(git_status_list_new(&status, g_repo, NULL));
cl_assert_equal_i(0, git_status_list_entrycount(status));
git_status_list_free(status);
/* update the mode on-disk and in the index */
cl_must_pass(p_chmod("testrepo/README", 0755));
cl_must_pass(git_index_add_bypath(index, "README"));
cl_git_pass(git_checkout_tree(g_repo, obj, &g_opts));
cl_git_pass(git_status_list_new(&status, g_repo, NULL));
cl_assert_equal_i(0, git_status_list_entrycount(status));
git_status_list_free(status);
git_object_free(obj);
git_reference_free(head);
git_index_free(index);
}
void test_checkout_tree__nullopts(void) void test_checkout_tree__nullopts(void)
{ {
cl_git_pass(git_checkout_tree(g_repo, NULL, NULL)); cl_git_pass(git_checkout_tree(g_repo, NULL, NULL));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment