@@ -88,6 +88,106 @@ void main() {
8888 expect (sourceMemoryFs.directory (sourcePath).listSync ().length, 3 );
8989 });
9090
91+ testWithoutContext ('test directory copy with followLinks: true' , () async {
92+ final Signals signals = Signals .test ();
93+ final LocalFileSystem fileSystem = LocalFileSystem .test (
94+ signals: signals,
95+ );
96+ final Directory tempDir = fileSystem.systemTempDirectory.createTempSync ('flutter_copy_directory.' );
97+ try {
98+ final String sourcePath = io.Platform .isWindows ? r'some\origin' : 'some/origin' ;
99+ final Directory sourceDirectory = tempDir.childDirectory (sourcePath)..createSync (recursive: true );
100+ final File sourceFile1 = sourceDirectory.childFile ('some_file.txt' )..writeAsStringSync ('file 1' );
101+ sourceDirectory.childLink ('absolute_linked.txt' ).createSync (sourceFile1.absolute.path);
102+ final DateTime writeTime = sourceFile1.lastModifiedSync ();
103+ final Directory sourceSubDirectory = sourceDirectory.childDirectory ('dir1' ).childDirectory ('dir2' )..createSync (recursive: true );
104+ sourceSubDirectory.childFile ('another_file.txt' ).writeAsStringSync ('file 2' );
105+ final String subdirectorySourcePath = io.Platform .isWindows ? r'dir1\dir2' : 'dir1/dir2' ;
106+ sourceDirectory.childLink ('relative_linked_sub_dir' ).createSync (subdirectorySourcePath);
107+ sourceDirectory.childDirectory ('empty_directory' ).createSync (recursive: true );
108+
109+ final String targetPath = io.Platform .isWindows ? r'some\non-existent\target' : 'some/non-existent/target' ;
110+ final Directory targetDirectory = tempDir.childDirectory (targetPath);
111+
112+ copyDirectory (sourceDirectory, targetDirectory);
113+
114+ expect (targetDirectory.existsSync (), true );
115+ expect (targetDirectory.childFile ('some_file.txt' ).existsSync (), true );
116+ expect (targetDirectory.childFile ('some_file.txt' ).readAsStringSync (), 'file 1' );
117+ expect (targetDirectory.childFile ('absolute_linked.txt' ).readAsStringSync (), 'file 1' );
118+ expect (targetDirectory.childLink ('absolute_linked.txt' ).existsSync (), false );
119+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).existsSync (), true );
120+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).childFile ('another_file.txt' ).existsSync (), true );
121+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).childFile ('another_file.txt' ).readAsStringSync (), 'file 2' );
122+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).existsSync (), true );
123+ expect (targetDirectory.childLink ('relative_linked_sub_dir' ).existsSync (), false );
124+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).childFile ('another_file.txt' ).existsSync (), true );
125+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).childFile ('another_file.txt' ).readAsStringSync (), 'file 2' );
126+ expect (targetDirectory.childDirectory ('empty_directory' ).existsSync (), true );
127+
128+ // Assert that the copy operation hasn't modified the original file in some way.
129+ expect (sourceDirectory.childFile ('some_file.txt' ).lastModifiedSync (), writeTime);
130+ // There's still 5 things in the original directory as there were initially.
131+ expect (sourceDirectory.listSync ().length, 5 );
132+ } finally {
133+ tryToDelete (tempDir);
134+ }
135+ });
136+
137+ testWithoutContext ('test directory copy with followLinks: false' , () async {
138+ final Signals signals = Signals .test ();
139+ final LocalFileSystem fileSystem = LocalFileSystem .test (
140+ signals: signals,
141+ );
142+ final Directory tempDir = fileSystem.systemTempDirectory.createTempSync ('flutter_copy_directory.' );
143+ try {
144+ final String sourcePath = io.Platform .isWindows ? r'some\origin' : 'some/origin' ;
145+ final Directory sourceDirectory = tempDir.childDirectory (sourcePath)..createSync (recursive: true );
146+ final File sourceFile1 = sourceDirectory.childFile ('some_file.txt' )..writeAsStringSync ('file 1' );
147+ sourceDirectory.childLink ('absolute_linked.txt' ).createSync (sourceFile1.absolute.path);
148+ final DateTime writeTime = sourceFile1.lastModifiedSync ();
149+ final Directory sourceSubDirectory = sourceDirectory.childDirectory ('dir1' ).childDirectory ('dir2' )..createSync (recursive: true );
150+ sourceSubDirectory.childFile ('another_file.txt' ).writeAsStringSync ('file 2' );
151+ final String subdirectorySourcePath = io.Platform .isWindows ? r'dir1\dir2' : 'dir1/dir2' ;
152+ sourceDirectory.childLink ('relative_linked_sub_dir' ).createSync (subdirectorySourcePath);
153+ sourceDirectory.childDirectory ('empty_directory' ).createSync (recursive: true );
154+
155+ final String targetPath = io.Platform .isWindows ? r'some\non-existent\target' : 'some/non-existent/target' ;
156+ final Directory targetDirectory = tempDir.childDirectory (targetPath);
157+
158+ copyDirectory (sourceDirectory, targetDirectory, followLinks: false );
159+
160+ expect (targetDirectory.existsSync (), true );
161+ expect (targetDirectory.childFile ('some_file.txt' ).existsSync (), true );
162+ expect (targetDirectory.childFile ('some_file.txt' ).readAsStringSync (), 'file 1' );
163+ expect (targetDirectory.childFile ('absolute_linked.txt' ).readAsStringSync (), 'file 1' );
164+ expect (targetDirectory.childLink ('absolute_linked.txt' ).existsSync (), true );
165+ expect (
166+ targetDirectory.childLink ('absolute_linked.txt' ).targetSync (),
167+ sourceFile1.absolute.path,
168+ );
169+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).existsSync (), true );
170+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).childFile ('another_file.txt' ).existsSync (), true );
171+ expect (targetDirectory.childDirectory ('dir1' ).childDirectory ('dir2' ).childFile ('another_file.txt' ).readAsStringSync (), 'file 2' );
172+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).existsSync (), true );
173+ expect (targetDirectory.childLink ('relative_linked_sub_dir' ).existsSync (), true );
174+ expect (
175+ targetDirectory.childLink ('relative_linked_sub_dir' ).targetSync (),
176+ subdirectorySourcePath,
177+ );
178+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).childFile ('another_file.txt' ).existsSync (), true );
179+ expect (targetDirectory.childDirectory ('relative_linked_sub_dir' ).childFile ('another_file.txt' ).readAsStringSync (), 'file 2' );
180+ expect (targetDirectory.childDirectory ('empty_directory' ).existsSync (), true );
181+
182+ // Assert that the copy operation hasn't modified the original file in some way.
183+ expect (sourceDirectory.childFile ('some_file.txt' ).lastModifiedSync (), writeTime);
184+ // There's still 5 things in the original directory as there were initially.
185+ expect (sourceDirectory.listSync ().length, 5 );
186+ } finally {
187+ tryToDelete (tempDir);
188+ }
189+ });
190+
91191 testWithoutContext ('Skip files if shouldCopyFile returns false' , () {
92192 final MemoryFileSystem fileSystem = MemoryFileSystem .test ();
93193 final Directory origin = fileSystem.directory ('/origin' );
0 commit comments