@@ -67,6 +67,7 @@ typedef struct {
6767 bool reload_submodules ;
6868 size_t total_steps ;
6969 size_t completed_steps ;
70+ git_checkout_perfdata perfdata ;
7071} checkout_data ;
7172
7273typedef struct {
@@ -1289,50 +1290,86 @@ static int checkout_get_actions(
12891290 return error ;
12901291}
12911292
1293+ static int checkout_mkdir (
1294+ checkout_data * data ,
1295+ const char * path ,
1296+ const char * base ,
1297+ mode_t mode ,
1298+ unsigned int flags )
1299+ {
1300+ struct git_futils_mkdir_perfdata mkdir_perfdata = {0 };
1301+
1302+ int error = git_futils_mkdir_withperf (
1303+ path , base , mode , flags , & mkdir_perfdata );
1304+
1305+ data -> perfdata .mkdir_calls += mkdir_perfdata .mkdir_calls ;
1306+ data -> perfdata .stat_calls += mkdir_perfdata .stat_calls ;
1307+ data -> perfdata .chmod_calls += mkdir_perfdata .chmod_calls ;
1308+
1309+ return error ;
1310+ }
1311+
1312+ static int mkpath2file (
1313+ checkout_data * data , const char * path , unsigned int mode )
1314+ {
1315+ return checkout_mkdir (
1316+ data , path , git_repository_workdir (data -> repo ), mode ,
1317+ GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR );
1318+ }
1319+
12921320static int buffer_to_file (
1321+ checkout_data * data ,
12931322 struct stat * st ,
12941323 git_buf * buf ,
12951324 const char * path ,
1296- mode_t dir_mode ,
1297- int file_open_flags ,
12981325 mode_t file_mode )
12991326{
13001327 int error ;
13011328
1302- if ((error = git_futils_mkpath2file ( path , dir_mode )) < 0 )
1329+ if ((error = mkpath2file ( data , path , data -> opts . dir_mode )) < 0 )
13031330 return error ;
13041331
13051332 if ((error = git_futils_writebuffer (
1306- buf , path , file_open_flags , file_mode )) < 0 )
1333+ buf , path , data -> opts . file_open_flags , file_mode )) < 0 )
13071334 return error ;
13081335
1309- if (st != NULL && (error = p_stat (path , st )) < 0 )
1310- giterr_set (GITERR_OS , "Error statting '%s'" , path );
1336+ if (st ) {
1337+ data -> perfdata .stat_calls ++ ;
1338+
1339+ if ((error = p_stat (path , st )) < 0 ) {
1340+ giterr_set (GITERR_OS , "Error statting '%s'" , path );
1341+ return error ;
1342+ }
1343+ }
13111344
1312- else if (GIT_PERMS_IS_EXEC (file_mode ) &&
1313- (error = p_chmod (path , file_mode )) < 0 )
1314- giterr_set (GITERR_OS , "Failed to set permissions on '%s'" , path );
1345+ if (GIT_PERMS_IS_EXEC (file_mode )) {
1346+ data -> perfdata .chmod_calls ++ ;
1347+
1348+ if ((error = p_chmod (path , file_mode )) < 0 )
1349+ giterr_set (GITERR_OS , "Failed to set permissions on '%s'" , path );
1350+ }
13151351
13161352 return error ;
13171353}
13181354
13191355static int blob_content_to_file (
1356+ checkout_data * data ,
13201357 struct stat * st ,
13211358 git_blob * blob ,
13221359 const char * path ,
13231360 const char * hint_path ,
1324- mode_t entry_filemode ,
1325- git_checkout_options * opts )
1361+ mode_t entry_filemode )
13261362{
1327- int error = 0 ;
1328- mode_t file_mode = opts -> file_mode ? opts -> file_mode : entry_filemode ;
1363+ mode_t file_mode = data -> opts . file_mode ?
1364+ data -> opts . file_mode : entry_filemode ;
13291365 git_buf out = GIT_BUF_INIT ;
13301366 git_filter_list * fl = NULL ;
1367+ int error = 0 ;
13311368
13321369 if (hint_path == NULL )
13331370 hint_path = path ;
13341371
1335- if (!opts -> disable_filters )
1372+ if (!data -> opts . disable_filters )
13361373 error = git_filter_list_load (
13371374 & fl , git_blob_owner (blob ), blob , hint_path ,
13381375 GIT_FILTER_TO_WORKTREE , GIT_FILTER_OPT_DEFAULT );
@@ -1343,9 +1380,7 @@ static int blob_content_to_file(
13431380 git_filter_list_free (fl );
13441381
13451382 if (!error ) {
1346- error = buffer_to_file (
1347- st , & out , path , opts -> dir_mode , opts -> file_open_flags , file_mode );
1348-
1383+ error = buffer_to_file (data , st , & out , path , file_mode );
13491384 st -> st_mode = entry_filemode ;
13501385
13511386 git_buf_free (& out );
@@ -1355,29 +1390,30 @@ static int blob_content_to_file(
13551390}
13561391
13571392static int blob_content_to_link (
1393+ checkout_data * data ,
13581394 struct stat * st ,
13591395 git_blob * blob ,
1360- const char * path ,
1361- mode_t dir_mode ,
1362- int can_symlink )
1396+ const char * path )
13631397{
13641398 git_buf linktarget = GIT_BUF_INIT ;
13651399 int error ;
13661400
1367- if ((error = git_futils_mkpath2file ( path , dir_mode )) < 0 )
1401+ if ((error = mkpath2file ( data , path , data -> opts . dir_mode )) < 0 )
13681402 return error ;
13691403
13701404 if ((error = git_blob__getbuf (& linktarget , blob )) < 0 )
13711405 return error ;
13721406
1373- if (can_symlink ) {
1407+ if (data -> can_symlink ) {
13741408 if ((error = p_symlink (git_buf_cstr (& linktarget ), path )) < 0 )
13751409 giterr_set (GITERR_OS , "Could not create symlink %s\n" , path );
13761410 } else {
13771411 error = git_futils_fake_symlink (git_buf_cstr (& linktarget ), path );
13781412 }
13791413
13801414 if (!error ) {
1415+ data -> perfdata .stat_calls ++ ;
1416+
13811417 if ((error = p_lstat (path , st )) < 0 )
13821418 giterr_set (GITERR_CHECKOUT , "Could not stat symlink %s" , path );
13831419
@@ -1421,6 +1457,7 @@ static int checkout_submodule_update_index(
14211457 if (git_buf_puts (& data -> path , file -> path ) < 0 )
14221458 return -1 ;
14231459
1460+ data -> perfdata .stat_calls ++ ;
14241461 if (p_stat (git_buf_cstr (& data -> path ), & st ) < 0 ) {
14251462 giterr_set (
14261463 GITERR_CHECKOUT , "Could not stat submodule %s\n" , file -> path );
@@ -1442,7 +1479,8 @@ static int checkout_submodule(
14421479 if ((data -> strategy & GIT_CHECKOUT_UPDATE_ONLY ) != 0 )
14431480 return 0 ;
14441481
1445- if ((error = git_futils_mkdir (
1482+ if ((error = checkout_mkdir (
1483+ data ,
14461484 file -> path , data -> opts .target_directory ,
14471485 data -> opts .dir_mode , GIT_MKDIR_PATH )) < 0 )
14481486 return error ;
@@ -1481,10 +1519,13 @@ static void report_progress(
14811519 data -> opts .progress_payload );
14821520}
14831521
1484- static int checkout_safe_for_update_only (const char * path , mode_t expected_mode )
1522+ static int checkout_safe_for_update_only (
1523+ checkout_data * data , const char * path , mode_t expected_mode )
14851524{
14861525 struct stat st ;
14871526
1527+ data -> perfdata .stat_calls ++ ;
1528+
14881529 if (p_lstat (path , & st ) < 0 ) {
14891530 /* if doesn't exist, then no error and no update */
14901531 if (errno == ENOENT || errno == ENOTDIR )
@@ -1517,11 +1558,9 @@ static int checkout_write_content(
15171558 return error ;
15181559
15191560 if (S_ISLNK (mode ))
1520- error = blob_content_to_link (
1521- st , blob , full_path , data -> opts .dir_mode , data -> can_symlink );
1561+ error = blob_content_to_link (data , st , blob , full_path );
15221562 else
1523- error = blob_content_to_file (
1524- st , blob , full_path , hint_path , mode , & data -> opts );
1563+ error = blob_content_to_file (data , st , blob , full_path , hint_path , mode );
15251564
15261565 git_blob_free (blob );
15271566
@@ -1552,7 +1591,7 @@ static int checkout_blob(
15521591
15531592 if ((data -> strategy & GIT_CHECKOUT_UPDATE_ONLY ) != 0 ) {
15541593 int rval = checkout_safe_for_update_only (
1555- git_buf_cstr (& data -> path ), file -> mode );
1594+ data , git_buf_cstr (& data -> path ), file -> mode );
15561595 if (rval <= 0 )
15571596 return rval ;
15581597 }
@@ -1807,7 +1846,7 @@ static int checkout_write_entry(
18071846 }
18081847
18091848 if ((data -> strategy & GIT_CHECKOUT_UPDATE_ONLY ) != 0 &&
1810- (error = checkout_safe_for_update_only (git_buf_cstr (& data -> path ), side -> mode )) <= 0 )
1849+ (error = checkout_safe_for_update_only (data , git_buf_cstr (& data -> path ), side -> mode )) <= 0 )
18111850 return error ;
18121851
18131852 return checkout_write_content (data ,
@@ -1906,7 +1945,7 @@ static int checkout_write_merge(
19061945 goto done ;
19071946
19081947 if ((data -> strategy & GIT_CHECKOUT_UPDATE_ONLY ) != 0 &&
1909- (error = checkout_safe_for_update_only (git_buf_cstr (& path_workdir ), result .mode )) <= 0 )
1948+ (error = checkout_safe_for_update_only (data , git_buf_cstr (& path_workdir ), result .mode )) <= 0 )
19101949 goto done ;
19111950
19121951 if (!data -> opts .disable_filters ) {
@@ -1922,7 +1961,7 @@ static int checkout_write_merge(
19221961 out_data .size = result .len ;
19231962 }
19241963
1925- if ((error = git_futils_mkpath2file ( path_workdir .ptr , 0755 )) < 0 ||
1964+ if ((error = mkpath2file ( data , path_workdir .ptr , data -> opts . dir_mode )) < 0 ||
19261965 (error = git_filebuf_open (& output , git_buf_cstr (& path_workdir ), GIT_FILEBUF_DO_NOT_BUFFER , result .mode )) < 0 ||
19271966 (error = git_filebuf_write (& output , out_data .ptr , out_data .size )) < 0 ||
19281967 (error = git_filebuf_commit (& output )) < 0 )
@@ -2157,8 +2196,9 @@ static int checkout_data_init(
21572196 if (!data -> opts .target_directory )
21582197 data -> opts .target_directory = git_repository_workdir (repo );
21592198 else if (!git_path_isdir (data -> opts .target_directory ) &&
2160- (error = git_futils_mkdir (data -> opts .target_directory , NULL ,
2161- GIT_DIR_MODE , GIT_MKDIR_VERIFY_DIR )) < 0 )
2199+ (error = checkout_mkdir (data ,
2200+ data -> opts .target_directory , NULL ,
2201+ GIT_DIR_MODE , GIT_MKDIR_VERIFY_DIR )) < 0 )
21622202 goto cleanup ;
21632203
21642204 /* refresh config and index content unless NO_REFRESH is given */
0 commit comments