diff options
author | Edward Thomson <ethomson@github.com> | 2016-06-15 02:00:35 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@github.com> | 2016-06-25 18:05:44 -0400 |
commit | d2b6a63fd243e1de8e6f8c12faf99ff7185ac2da (patch) | |
tree | a0adf3e891a6fbc8532abdbf4ea867ca455156d2 | |
parent | d53e99f584648884ce0e972e6422c3c3e4c1901f (diff) | |
download | libgit2-d2b6a63fd243e1de8e6f8c12faf99ff7185ac2da.tar.gz |
checkout: treat files as modified if mode differs
When performing a forced checkout, treat files as modified when the
workdir or the index is identical except for the mode. This ensures
that force checkout will update the mode to the target. (Apply this
check for regular files only, if one of the items was a file and the
other was another type of item then this would be a typechange and
handled independently.)
-rw-r--r-- | src/checkout.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/src/checkout.c b/src/checkout.c index b4e5e3d86..08a555d55 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -160,6 +160,11 @@ GIT_INLINE(bool) is_workdir_base_or_new( git_oid__cmp(&newitem->id, workdir_id) == 0); } +GIT_INLINE(bool) is_file_mode_changed(git_filemode_t a, git_filemode_t b) +{ + return (S_ISREG(a) && S_ISREG(b) && a != b); +} + static bool is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, @@ -201,7 +206,8 @@ static bool is_workdir_modified( */ if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) { 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); } @@ -211,6 +217,9 @@ static bool is_workdir_modified( if (baseitem->size && wditem->file_size != baseitem->size) return true; + 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) return false; |