mirror of
https://github.com/flutter/flutter
synced 2024-08-25 11:07:06 +00:00
Update copyDirectory to allow links to not be followed (#144040)
In other words, copy links within a directory as links rather than copying them as files/directories. Fixes https://github.com/flutter/flutter/issues/144032.
This commit is contained in:
parent
d05eaf4a98
commit
45c8881eb2
|
@ -109,12 +109,19 @@ String getDisplayPath(String fullPath, FileSystem fileSystem) {
|
|||
///
|
||||
/// Skips files if [shouldCopyFile] returns `false`.
|
||||
/// Does not recurse over directories if [shouldCopyDirectory] returns `false`.
|
||||
///
|
||||
/// If [followLinks] is false, then any symbolic links found are reported as
|
||||
/// [Link] objects, rather than as directories or files, and are not recursed into.
|
||||
///
|
||||
/// If [followLinks] is true, then working links are reported as directories or
|
||||
/// files, depending on what they point to.
|
||||
void copyDirectory(
|
||||
Directory srcDir,
|
||||
Directory destDir, {
|
||||
bool Function(File srcFile, File destFile)? shouldCopyFile,
|
||||
bool Function(Directory)? shouldCopyDirectory,
|
||||
void Function(File srcFile, File destFile)? onFileCopied,
|
||||
bool followLinks = true,
|
||||
}) {
|
||||
if (!srcDir.existsSync()) {
|
||||
throw Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
|
||||
|
@ -124,7 +131,7 @@ void copyDirectory(
|
|||
destDir.createSync(recursive: true);
|
||||
}
|
||||
|
||||
for (final FileSystemEntity entity in srcDir.listSync()) {
|
||||
for (final FileSystemEntity entity in srcDir.listSync(followLinks: followLinks)) {
|
||||
final String newPath = destDir.fileSystem.path.join(destDir.path, entity.basename);
|
||||
if (entity is Link) {
|
||||
final Link newLink = destDir.fileSystem.link(newPath);
|
||||
|
@ -145,6 +152,7 @@ void copyDirectory(
|
|||
destDir.fileSystem.directory(newPath),
|
||||
shouldCopyFile: shouldCopyFile,
|
||||
onFileCopied: onFileCopied,
|
||||
followLinks: followLinks,
|
||||
);
|
||||
} else {
|
||||
throw Exception('${entity.path} is neither File nor Directory, was ${entity.runtimeType}');
|
||||
|
|
|
@ -88,6 +88,106 @@ void main() {
|
|||
expect(sourceMemoryFs.directory(sourcePath).listSync().length, 3);
|
||||
});
|
||||
|
||||
testWithoutContext('test directory copy with followLinks: true', () async {
|
||||
final Signals signals = Signals.test();
|
||||
final LocalFileSystem fileSystem = LocalFileSystem.test(
|
||||
signals: signals,
|
||||
);
|
||||
final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_copy_directory.');
|
||||
try {
|
||||
final String sourcePath = io.Platform.isWindows ? r'some\origin' : 'some/origin';
|
||||
final Directory sourceDirectory = tempDir.childDirectory(sourcePath)..createSync(recursive: true);
|
||||
final File sourceFile1 = sourceDirectory.childFile('some_file.txt')..writeAsStringSync('file 1');
|
||||
sourceDirectory.childLink('absolute_linked.txt').createSync(sourceFile1.absolute.path);
|
||||
final DateTime writeTime = sourceFile1.lastModifiedSync();
|
||||
final Directory sourceSubDirectory = sourceDirectory.childDirectory('dir1').childDirectory('dir2')..createSync(recursive: true);
|
||||
sourceSubDirectory.childFile('another_file.txt').writeAsStringSync('file 2');
|
||||
final String subdirectorySourcePath = io.Platform.isWindows ? r'dir1\dir2' : 'dir1/dir2';
|
||||
sourceDirectory.childLink('relative_linked_sub_dir').createSync(subdirectorySourcePath);
|
||||
sourceDirectory.childDirectory('empty_directory').createSync(recursive: true);
|
||||
|
||||
final String targetPath = io.Platform.isWindows ? r'some\non-existent\target' : 'some/non-existent/target';
|
||||
final Directory targetDirectory = tempDir.childDirectory(targetPath);
|
||||
|
||||
copyDirectory(sourceDirectory, targetDirectory);
|
||||
|
||||
expect(targetDirectory.existsSync(), true);
|
||||
expect(targetDirectory.childFile('some_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childFile('some_file.txt').readAsStringSync(), 'file 1');
|
||||
expect(targetDirectory.childFile('absolute_linked.txt').readAsStringSync(), 'file 1');
|
||||
expect(targetDirectory.childLink('absolute_linked.txt').existsSync(), false);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').childFile('another_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').childFile('another_file.txt').readAsStringSync(), 'file 2');
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').existsSync(), true);
|
||||
expect(targetDirectory.childLink('relative_linked_sub_dir').existsSync(), false);
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').childFile('another_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').childFile('another_file.txt').readAsStringSync(), 'file 2');
|
||||
expect(targetDirectory.childDirectory('empty_directory').existsSync(), true);
|
||||
|
||||
// Assert that the copy operation hasn't modified the original file in some way.
|
||||
expect(sourceDirectory.childFile('some_file.txt').lastModifiedSync(), writeTime);
|
||||
// There's still 5 things in the original directory as there were initially.
|
||||
expect(sourceDirectory.listSync().length, 5);
|
||||
} finally {
|
||||
tryToDelete(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
testWithoutContext('test directory copy with followLinks: false', () async {
|
||||
final Signals signals = Signals.test();
|
||||
final LocalFileSystem fileSystem = LocalFileSystem.test(
|
||||
signals: signals,
|
||||
);
|
||||
final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('flutter_copy_directory.');
|
||||
try {
|
||||
final String sourcePath = io.Platform.isWindows ? r'some\origin' : 'some/origin';
|
||||
final Directory sourceDirectory = tempDir.childDirectory(sourcePath)..createSync(recursive: true);
|
||||
final File sourceFile1 = sourceDirectory.childFile('some_file.txt')..writeAsStringSync('file 1');
|
||||
sourceDirectory.childLink('absolute_linked.txt').createSync(sourceFile1.absolute.path);
|
||||
final DateTime writeTime = sourceFile1.lastModifiedSync();
|
||||
final Directory sourceSubDirectory = sourceDirectory.childDirectory('dir1').childDirectory('dir2')..createSync(recursive: true);
|
||||
sourceSubDirectory.childFile('another_file.txt').writeAsStringSync('file 2');
|
||||
final String subdirectorySourcePath = io.Platform.isWindows ? r'dir1\dir2' : 'dir1/dir2';
|
||||
sourceDirectory.childLink('relative_linked_sub_dir').createSync(subdirectorySourcePath);
|
||||
sourceDirectory.childDirectory('empty_directory').createSync(recursive: true);
|
||||
|
||||
final String targetPath = io.Platform.isWindows ? r'some\non-existent\target' : 'some/non-existent/target';
|
||||
final Directory targetDirectory = tempDir.childDirectory(targetPath);
|
||||
|
||||
copyDirectory(sourceDirectory, targetDirectory, followLinks: false);
|
||||
|
||||
expect(targetDirectory.existsSync(), true);
|
||||
expect(targetDirectory.childFile('some_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childFile('some_file.txt').readAsStringSync(), 'file 1');
|
||||
expect(targetDirectory.childFile('absolute_linked.txt').readAsStringSync(), 'file 1');
|
||||
expect(targetDirectory.childLink('absolute_linked.txt').existsSync(), true);
|
||||
expect(
|
||||
targetDirectory.childLink('absolute_linked.txt').targetSync(),
|
||||
sourceFile1.absolute.path,
|
||||
);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').childFile('another_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('dir1').childDirectory('dir2').childFile('another_file.txt').readAsStringSync(), 'file 2');
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').existsSync(), true);
|
||||
expect(targetDirectory.childLink('relative_linked_sub_dir').existsSync(), true);
|
||||
expect(
|
||||
targetDirectory.childLink('relative_linked_sub_dir').targetSync(),
|
||||
subdirectorySourcePath,
|
||||
);
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').childFile('another_file.txt').existsSync(), true);
|
||||
expect(targetDirectory.childDirectory('relative_linked_sub_dir').childFile('another_file.txt').readAsStringSync(), 'file 2');
|
||||
expect(targetDirectory.childDirectory('empty_directory').existsSync(), true);
|
||||
|
||||
// Assert that the copy operation hasn't modified the original file in some way.
|
||||
expect(sourceDirectory.childFile('some_file.txt').lastModifiedSync(), writeTime);
|
||||
// There's still 5 things in the original directory as there were initially.
|
||||
expect(sourceDirectory.listSync().length, 5);
|
||||
} finally {
|
||||
tryToDelete(tempDir);
|
||||
}
|
||||
});
|
||||
|
||||
testWithoutContext('Skip files if shouldCopyFile returns false', () {
|
||||
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
|
||||
final Directory origin = fileSystem.directory('/origin');
|
||||
|
|
Loading…
Reference in a new issue