@@ -838,6 +838,48 @@ test('cp -p should preserve mode, ownership, and timestamp (regular file)', t =>
838838 t . is ( stat . gid , statOfResult . gid ) ;
839839} ) ;
840840
841+ test ( 'cp -p should preserve mode, ownership, and timestamp (directory)' , t => {
842+ // Setup: copy to srcFile and modify mode and timestamp
843+ const srcDir = `${ t . context . tmp } /srcDir` ;
844+ const srcFile = `${ srcDir } /srcFile` ;
845+ shell . mkdir ( srcDir ) ;
846+ shell . cp ( 'test/resources/cp/file1' , srcFile ) ;
847+ // Make this a round number of seconds, since the underlying system may not
848+ // have millisecond precision.
849+ const newModifyTimeMs = 12345000 ;
850+ const newAccessTimeMs = 67890000 ;
851+ shell . touch ( { '-d' : new Date ( newModifyTimeMs ) , '-m' : true } , srcFile ) ;
852+ shell . touch ( { '-d' : new Date ( newAccessTimeMs ) , '-a' : true } , srcFile ) ;
853+ fs . utimesSync ( srcDir , new Date ( newAccessTimeMs ) , new Date ( newModifyTimeMs ) ) ;
854+ const mode = '444' ;
855+ shell . chmod ( mode , srcFile ) ;
856+
857+ // Now re-copy (the whole dir) with '-p' and verify metadata of file contents.
858+ const result = shell . cp ( '-pr' , srcDir , `${ t . context . tmp } /preservedDir` ) ;
859+ const stat = common . statFollowLinks ( srcFile ) ;
860+ const statDir = common . statFollowLinks ( srcDir ) ;
861+ const statOfResult = common . statFollowLinks ( `${ t . context . tmp } /preservedDir/srcFile` ) ;
862+ const statOfResultDir = common . statFollowLinks ( `${ t . context . tmp } /preservedDir` ) ;
863+
864+ t . is ( result . code , 0 ) ;
865+
866+ // Both original file and original dir should be unchanged:
867+ t . is ( statDir . mtime . getTime ( ) , newModifyTimeMs ) ;
868+ t . is ( stat . mtime . getTime ( ) , newModifyTimeMs ) ;
869+ // cp appears to update the atime, but only of the srcFile & srcDir
870+ t . is ( stat . mode . toString ( 8 ) , '100' + mode ) ;
871+
872+ // Both new file and new dir should keep same attributes
873+ t . is ( statOfResultDir . mtime . getTime ( ) , newModifyTimeMs ) ;
874+ t . is ( statOfResultDir . atime . getTime ( ) , newAccessTimeMs ) ;
875+ t . is ( statOfResult . mtime . getTime ( ) , newModifyTimeMs ) ;
876+ t . is ( statOfResult . atime . getTime ( ) , newAccessTimeMs ) ;
877+ t . is ( statOfResult . mode . toString ( 8 ) , '100' + mode ) ;
878+
879+ t . is ( stat . uid , statOfResult . uid ) ;
880+ t . is ( stat . gid , statOfResult . gid ) ;
881+ } ) ;
882+
841883test ( 'cp -p should preserve mode, ownership, and timestamp (symlink)' , t => {
842884 // Skip in Windows because symlinks require elevated permissions.
843885 utils . skipOnWin ( t , ( ) => {
0 commit comments