diff options
author | Edward Thomson <ethomson@github.com> | 2016-06-15 02:00:35 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2017-10-06 23:53:34 +0100 |
commit | 752b7c792d7e2aad7be43a88114552233c230780 (patch) | |
tree | 8977e6715f0fc4853892c32e8979c86e037fcdaa | |
parent | 62ac39314c11ec43e34e2930f990c3d4ad13153b (diff) | |
download | libgit2-752b7c792d7e2aad7be43a88114552233c230780.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 6c7a94441..61c85ceae 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -159,6 +159,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 checkout_is_workdir_modified( checkout_data *data, const git_diff_file *baseitem, @@ -200,7 +205,8 @@ static bool checkout_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); } @@ -214,6 +220,9 @@ static bool checkout_is_workdir_modified( if (S_ISDIR(wditem->mode)) 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) return false; |