@@ -70,6 +70,7 @@ typedef struct {
70
70
git_buf tmp ;
71
71
unsigned int strategy ;
72
72
int can_symlink ;
73
+ int respect_filemode ;
73
74
bool reload_submodules ;
74
75
size_t total_steps ;
75
76
size_t completed_steps ;
@@ -159,17 +160,20 @@ GIT_INLINE(bool) is_workdir_base_or_new(
159
160
git_oid__cmp (& newitem -> id , workdir_id ) == 0 );
160
161
}
161
162
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 )
163
164
{
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 );
173
177
}
174
178
175
179
static bool checkout_is_workdir_modified (
@@ -217,11 +221,11 @@ static bool checkout_is_workdir_modified(
217
221
if (ie != NULL &&
218
222
git_index_time_eq (& wditem -> mtime , & ie -> mtime ) &&
219
223
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 )) {
221
225
222
226
/* The workdir is modified iff the index entry is modified */
223
227
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 );
225
229
}
226
230
227
231
/* depending on where base is coming from, we may or may not know
@@ -234,7 +238,7 @@ static bool checkout_is_workdir_modified(
234
238
if (S_ISDIR (wditem -> mode ))
235
239
return false;
236
240
237
- if (is_file_mode_changed (baseitem -> mode , wditem -> mode ))
241
+ if (is_filemode_changed (baseitem -> mode , wditem -> mode , data -> respect_filemode ))
238
242
return true;
239
243
240
244
if (git_diff__oid_for_entry (& oid , data -> diff , wditem , wditem -> mode , NULL ) < 0 )
@@ -2454,6 +2458,10 @@ static int checkout_data_init(
2454
2458
& data -> can_symlink , repo , GIT_CVAR_SYMLINKS )) < 0 )
2455
2459
goto cleanup ;
2456
2460
2461
+ if ((error = git_repository__cvar (
2462
+ & data -> respect_filemode , repo , GIT_CVAR_FILEMODE )) < 0 )
2463
+ goto cleanup ;
2464
+
2457
2465
if (!data -> opts .baseline && !data -> opts .baseline_index ) {
2458
2466
data -> opts_free_baseline = true;
2459
2467
error = 0 ;
0 commit comments