23
23
#include "transport.h"
24
24
#include "strbuf.h"
25
25
#include "dir.h"
26
+ #include "dir-iterator.h"
27
+ #include "iterator.h"
26
28
#include "sigchain.h"
27
29
#include "branch.h"
28
30
#include "remote.h"
@@ -394,58 +396,63 @@ static void copy_alternates(struct strbuf *src, const char *src_repo)
394
396
fclose (in );
395
397
}
396
398
399
+ static void mkdir_if_missing (const char * pathname , mode_t mode )
400
+ {
401
+ struct stat st ;
402
+
403
+ if (!mkdir (pathname , mode ))
404
+ return ;
405
+
406
+ if (errno != EEXIST )
407
+ die_errno (_ ("failed to create directory '%s'" ), pathname );
408
+ else if (stat (pathname , & st ))
409
+ die_errno (_ ("failed to stat '%s'" ), pathname );
410
+ else if (!S_ISDIR (st .st_mode ))
411
+ die (_ ("%s exists and is not a directory" ), pathname );
412
+ }
413
+
397
414
static void copy_or_link_directory (struct strbuf * src , struct strbuf * dest ,
398
- const char * src_repo , int src_baselen )
415
+ const char * src_repo )
399
416
{
400
- struct dirent * de ;
401
- struct stat buf ;
402
417
int src_len , dest_len ;
403
- DIR * dir ;
404
-
405
- dir = opendir (src -> buf );
406
- if (!dir )
407
- die_errno (_ ("failed to open '%s'" ), src -> buf );
408
-
409
- if (mkdir (dest -> buf , 0777 )) {
410
- if (errno != EEXIST )
411
- die_errno (_ ("failed to create directory '%s'" ), dest -> buf );
412
- else if (stat (dest -> buf , & buf ))
413
- die_errno (_ ("failed to stat '%s'" ), dest -> buf );
414
- else if (!S_ISDIR (buf .st_mode ))
415
- die (_ ("%s exists and is not a directory" ), dest -> buf );
416
- }
418
+ struct dir_iterator * iter ;
419
+ int iter_status ;
420
+ unsigned int flags ;
421
+
422
+ mkdir_if_missing (dest -> buf , 0777 );
423
+
424
+ flags = DIR_ITERATOR_PEDANTIC | DIR_ITERATOR_FOLLOW_SYMLINKS ;
425
+ iter = dir_iterator_begin (src -> buf , flags );
426
+
427
+ if (!iter )
428
+ die_errno (_ ("failed to start iterator over '%s'" ), src -> buf );
417
429
418
430
strbuf_addch (src , '/' );
419
431
src_len = src -> len ;
420
432
strbuf_addch (dest , '/' );
421
433
dest_len = dest -> len ;
422
434
423
- while ((de = readdir ( dir )) != NULL ) {
435
+ while ((iter_status = dir_iterator_advance ( iter )) == ITER_OK ) {
424
436
strbuf_setlen (src , src_len );
425
- strbuf_addstr (src , de -> d_name );
437
+ strbuf_addstr (src , iter -> relative_path );
426
438
strbuf_setlen (dest , dest_len );
427
- strbuf_addstr (dest , de -> d_name );
428
- if (stat (src -> buf , & buf )) {
429
- warning (_ ("failed to stat %s\n" ), src -> buf );
430
- continue ;
431
- }
432
- if (S_ISDIR (buf .st_mode )) {
433
- if (de -> d_name [0 ] != '.' )
434
- copy_or_link_directory (src , dest ,
435
- src_repo , src_baselen );
439
+ strbuf_addstr (dest , iter -> relative_path );
440
+
441
+ if (S_ISDIR (iter -> st .st_mode )) {
442
+ mkdir_if_missing (dest -> buf , 0777 );
436
443
continue ;
437
444
}
438
445
439
446
/* Files that cannot be copied bit-for-bit... */
440
- if (!strcmp ( src -> buf + src_baselen , "/ info/alternates" )) {
447
+ if (!fspathcmp ( iter -> relative_path , "info/alternates" )) {
441
448
copy_alternates (src , src_repo );
442
449
continue ;
443
450
}
444
451
445
452
if (unlink (dest -> buf ) && errno != ENOENT )
446
453
die_errno (_ ("failed to unlink '%s'" ), dest -> buf );
447
454
if (!option_no_hardlinks ) {
448
- if (!link (src -> buf , dest -> buf ))
455
+ if (!link (real_path ( src -> buf ) , dest -> buf ))
449
456
continue ;
450
457
if (option_local > 0 )
451
458
die_errno (_ ("failed to create link '%s'" ), dest -> buf );
@@ -454,7 +461,11 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
454
461
if (copy_file_with_time (dest -> buf , src -> buf , 0666 ))
455
462
die_errno (_ ("failed to copy file to '%s'" ), dest -> buf );
456
463
}
457
- closedir (dir );
464
+
465
+ if (iter_status != ITER_DONE ) {
466
+ strbuf_setlen (src , src_len );
467
+ die (_ ("failed to iterate over '%s'" ), src -> buf );
468
+ }
458
469
}
459
470
460
471
static void clone_local (const char * src_repo , const char * dest_repo )
@@ -472,7 +483,7 @@ static void clone_local(const char *src_repo, const char *dest_repo)
472
483
get_common_dir (& dest , dest_repo );
473
484
strbuf_addstr (& src , "/objects" );
474
485
strbuf_addstr (& dest , "/objects" );
475
- copy_or_link_directory (& src , & dest , src_repo , src . len );
486
+ copy_or_link_directory (& src , & dest , src_repo );
476
487
strbuf_release (& src );
477
488
strbuf_release (& dest );
478
489
}
0 commit comments