2323#include "transport.h"
2424#include "strbuf.h"
2525#include "dir.h"
26+ #include "dir-iterator.h"
27+ #include "iterator.h"
2628#include "sigchain.h"
2729#include "branch.h"
2830#include "remote.h"
@@ -394,58 +396,63 @@ static void copy_alternates(struct strbuf *src, const char *src_repo)
394396 fclose (in );
395397}
396398
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+
397414static void copy_or_link_directory (struct strbuf * src , struct strbuf * dest ,
398- const char * src_repo , int src_baselen )
415+ const char * src_repo )
399416{
400- struct dirent * de ;
401- struct stat buf ;
402417 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 );
417429
418430 strbuf_addch (src , '/' );
419431 src_len = src -> len ;
420432 strbuf_addch (dest , '/' );
421433 dest_len = dest -> len ;
422434
423- while ((de = readdir ( dir )) != NULL ) {
435+ while ((iter_status = dir_iterator_advance ( iter )) == ITER_OK ) {
424436 strbuf_setlen (src , src_len );
425- strbuf_addstr (src , de -> d_name );
437+ strbuf_addstr (src , iter -> relative_path );
426438 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 );
436443 continue ;
437444 }
438445
439446 /* 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" )) {
441448 copy_alternates (src , src_repo );
442449 continue ;
443450 }
444451
445452 if (unlink (dest -> buf ) && errno != ENOENT )
446453 die_errno (_ ("failed to unlink '%s'" ), dest -> buf );
447454 if (!option_no_hardlinks ) {
448- if (!link (src -> buf , dest -> buf ))
455+ if (!link (real_path ( src -> buf ) , dest -> buf ))
449456 continue ;
450457 if (option_local > 0 )
451458 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,
454461 if (copy_file_with_time (dest -> buf , src -> buf , 0666 ))
455462 die_errno (_ ("failed to copy file to '%s'" ), dest -> buf );
456463 }
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+ }
458469}
459470
460471static 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)
472483 get_common_dir (& dest , dest_repo );
473484 strbuf_addstr (& src , "/objects" );
474485 strbuf_addstr (& dest , "/objects" );
475- copy_or_link_directory (& src , & dest , src_repo , src . len );
486+ copy_or_link_directory (& src , & dest , src_repo );
476487 strbuf_release (& src );
477488 strbuf_release (& dest );
478489 }
0 commit comments