@@ -70,6 +70,7 @@ typedef struct {
7070 git_buf tmp ;
7171 unsigned int strategy ;
7272 int can_symlink ;
73+ int respect_filemode ;
7374 bool reload_submodules ;
7475 size_t total_steps ;
7576 size_t completed_steps ;
@@ -159,17 +160,20 @@ GIT_INLINE(bool) is_workdir_base_or_new(
159160 git_oid__cmp (& newitem -> id , workdir_id ) == 0 );
160161}
161162
162- GIT_INLINE (bool ) is_file_mode_changed (git_filemode_t a , git_filemode_t b )
163+ GIT_INLINE (bool ) is_filemode_changed (git_filemode_t a , git_filemode_t b , int respect_filemode )
163164{
164- #ifdef GIT_WIN32
165- /*
166- * On Win32 we do not support the executable bit; the file will
167- * always be 0100644 on disk, don't bother doing a test.
168- */
169- return false;
170- #else
171- return (S_ISREG (a ) && S_ISREG (b ) && a != b );
172- #endif
165+ /* If core.filemode = false, ignore links in the repository and executable bit changes */
166+ if (!respect_filemode ) {
167+ if (a == S_IFLNK )
168+ a = GIT_FILEMODE_BLOB ;
169+ if (b == S_IFLNK )
170+ b = GIT_FILEMODE_BLOB ;
171+
172+ a &= ~0111 ;
173+ b &= ~0111 ;
174+ }
175+
176+ return (a != b );
173177}
174178
175179static bool checkout_is_workdir_modified (
@@ -217,11 +221,11 @@ static bool checkout_is_workdir_modified(
217221 if (ie != NULL &&
218222 git_index_time_eq (& wditem -> mtime , & ie -> mtime ) &&
219223 wditem -> file_size == ie -> file_size &&
220- !is_file_mode_changed (wditem -> mode , ie -> mode )) {
224+ !is_filemode_changed (wditem -> mode , ie -> mode , data -> respect_filemode )) {
221225
222226 /* The workdir is modified iff the index entry is modified */
223227 return !is_workdir_base_or_new (& ie -> id , baseitem , newitem ) ||
224- is_file_mode_changed (baseitem -> mode , ie -> mode );
228+ is_filemode_changed (baseitem -> mode , ie -> mode , data -> respect_filemode );
225229 }
226230
227231 /* depending on where base is coming from, we may or may not know
@@ -234,7 +238,7 @@ static bool checkout_is_workdir_modified(
234238 if (S_ISDIR (wditem -> mode ))
235239 return false;
236240
237- if (is_file_mode_changed (baseitem -> mode , wditem -> mode ))
241+ if (is_filemode_changed (baseitem -> mode , wditem -> mode , data -> respect_filemode ))
238242 return true;
239243
240244 if (git_diff__oid_for_entry (& oid , data -> diff , wditem , wditem -> mode , NULL ) < 0 )
@@ -2454,6 +2458,10 @@ static int checkout_data_init(
24542458 & data -> can_symlink , repo , GIT_CVAR_SYMLINKS )) < 0 )
24552459 goto cleanup ;
24562460
2461+ if ((error = git_repository__cvar (
2462+ & data -> respect_filemode , repo , GIT_CVAR_FILEMODE )) < 0 )
2463+ goto cleanup ;
2464+
24572465 if (!data -> opts .baseline && !data -> opts .baseline_index ) {
24582466 data -> opts_free_baseline = true;
24592467 error = 0 ;
0 commit comments