@@ -55,7 +55,9 @@ typedef struct {
5555
5656enum {
5757 COMPLETED_STEPS_MUTEX_INITIALIZED = 1 ,
58- PERFDATA_MUTEX_INITIALIZED = 2
58+ INDEX_MUTEX_INITIALIZED = 2 ,
59+ MKPATH_MUTEX_INITIALIZED = 4 ,
60+ PERFDATA_MUTEX_INITIALIZED = 8
5961};
6062
6163typedef struct {
@@ -83,6 +85,8 @@ typedef struct {
8385 git_strmap * mkdir_map ;
8486 git_attr_session attr_session ;
8587 git_mutex completed_steps_mutex ;
88+ git_mutex index_mutex ;
89+ git_mutex mkpath_mutex ;
8690 git_mutex perfdata_mutex ;
8791 unsigned int mutexes_initialized ;
8892} checkout_data ;
@@ -1451,15 +1455,20 @@ static int mkpath2file(
14511455 checkout_data * data , const char * path , unsigned int mode )
14521456{
14531457 struct stat st ;
1454- bool remove_existing = should_remove_existing (data );
1455- unsigned int flags =
1458+ bool remove_existing ;
1459+ unsigned int flags ;
1460+ int error ;
1461+
1462+ git_mutex_lock (& data -> mkpath_mutex );
1463+
1464+ remove_existing = should_remove_existing (data );
1465+ flags =
14561466 (remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL ) |
14571467 GIT_MKDIR_SKIP_LAST ;
1458- int error ;
14591468
14601469 if ((error = checkout_mkdir (
14611470 data , path , data -> opts .target_directory , mode , flags )) < 0 )
1462- return error ;
1471+ goto cleanup ;
14631472
14641473 if (remove_existing ) {
14651474 git_mutex_lock (& data -> perfdata_mutex );
@@ -1476,12 +1485,14 @@ static int mkpath2file(
14761485 error = git_futils_rmdir_r (path , NULL , GIT_RMDIR_REMOVE_FILES );
14771486 } else if (errno != ENOENT ) {
14781487 git_error_set (GIT_ERROR_OS , "failed to stat '%s'" , path );
1479- return GIT_EEXISTS ;
1488+ error = GIT_EEXISTS ;
14801489 } else {
14811490 git_error_clear ();
14821491 }
14831492 }
14841493
1494+ cleanup :
1495+ git_mutex_unlock (& data -> mkpath_mutex );
14851496 return error ;
14861497}
14871498
@@ -1557,12 +1568,19 @@ static int blob_content_to_file(
15571568 filter_session .attr_session = & data -> attr_session ;
15581569 filter_session .temp_buf = & buffers -> tmp ;
15591570
1560- if (!data -> opts .disable_filters &&
1561- (error = git_filter_list__load (
1571+ if (!data -> opts .disable_filters ) {
1572+ git_mutex_lock (& data -> index_mutex );
1573+
1574+ error = git_filter_list__load (
15621575 & fl , data -> repo , blob , hint_path ,
1563- GIT_FILTER_TO_WORKTREE , & filter_session ))) {
1564- p_close (fd );
1565- return error ;
1576+ GIT_FILTER_TO_WORKTREE , & filter_session );
1577+
1578+ git_mutex_unlock (& data -> index_mutex );
1579+
1580+ if (error ) {
1581+ p_close (fd );
1582+ return error ;
1583+ }
15661584 }
15671585
15681586 /* setup the writer */
@@ -1818,8 +1836,11 @@ static int checkout_blob(
18181836 data , & file -> id , fullpath -> ptr , file -> path , file -> mode , & st );
18191837
18201838 /* update the index unless prevented */
1821- if (!error && (data -> strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX ) == 0 )
1839+ if (!error && (data -> strategy & GIT_CHECKOUT_DONT_UPDATE_INDEX ) == 0 ) {
1840+ git_mutex_lock (& data -> index_mutex );
18221841 error = checkout_update_index (data , file , & st );
1842+ git_mutex_unlock (& data -> index_mutex );
1843+ }
18231844
18241845 /* update the submodule data if this was a new .gitmodules file */
18251846 if (!error && strcmp (file -> path , ".gitmodules" ) == 0 )
@@ -2412,6 +2433,12 @@ static void checkout_data_clear(checkout_data *data)
24122433 if (data -> mutexes_initialized & COMPLETED_STEPS_MUTEX_INITIALIZED )
24132434 git_mutex_free (& data -> completed_steps_mutex );
24142435
2436+ if (data -> mutexes_initialized & INDEX_MUTEX_INITIALIZED )
2437+ git_mutex_free (& data -> index_mutex );
2438+
2439+ if (data -> mutexes_initialized & MKPATH_MUTEX_INITIALIZED )
2440+ git_mutex_free (& data -> mkpath_mutex );
2441+
24152442 if (data -> mutexes_initialized & PERFDATA_MUTEX_INITIALIZED )
24162443 git_mutex_free (& data -> perfdata_mutex );
24172444}
@@ -2460,6 +2487,16 @@ static int checkout_data_init(
24602487
24612488 data -> mutexes_initialized |= COMPLETED_STEPS_MUTEX_INITIALIZED ;
24622489
2490+ if ((error = git_mutex_init (& data -> index_mutex )) < 0 )
2491+ goto cleanup ;
2492+
2493+ data -> mutexes_initialized |= INDEX_MUTEX_INITIALIZED ;
2494+
2495+ if ((error = git_mutex_init (& data -> mkpath_mutex )) < 0 )
2496+ goto cleanup ;
2497+
2498+ data -> mutexes_initialized |= MKPATH_MUTEX_INITIALIZED ;
2499+
24632500 if ((error = git_mutex_init (& data -> perfdata_mutex )) < 0 )
24642501 goto cleanup ;
24652502
0 commit comments