Change file system copy folder to copy directory (#7624)

* Change file_system’s copy folder to copy director which takes into account the file system

* Address review comments.
Test with 2 different instances of file systems.
diff --git a/packages/flutter_tools/lib/src/base/file_system.dart b/packages/flutter_tools/lib/src/base/file_system.dart
index 5fd2ed8..66a5639 100644
--- a/packages/flutter_tools/lib/src/base/file_system.dart
+++ b/packages/flutter_tools/lib/src/base/file_system.dart
@@ -29,23 +29,24 @@
   fs.directory(dirPath).createSync(recursive: true);
 }
 
-/// Recursively copies a folder from `srcPath` to `destPath`
-void copyFolderSync(String srcPath, String destPath) {
-  Directory srcDir = fs.directory(srcPath);
+/// Recursively copies `srcDir` to `destDir`.
+///
+/// Creates `destDir` if needed.
+void copyDirectorySync(Directory srcDir, Directory destDir) {
   if (!srcDir.existsSync())
     throw new Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
 
-  Directory destDir = fs.directory(destPath);
   if (!destDir.existsSync())
     destDir.createSync(recursive: true);
 
   srcDir.listSync().forEach((FileSystemEntity entity) {
     String newPath = path.join(destDir.path, path.basename(entity.path));
     if (entity is File) {
-      File newFile = fs.file(newPath);
+      File newFile = destDir.fileSystem.file(newPath);
       newFile.writeAsBytesSync(entity.readAsBytesSync());
     } else if (entity is Directory) {
-      copyFolderSync(entity.path, newPath);
+      copyDirectorySync(
+        entity, destDir.fileSystem.directory(newPath));
     } else {
       throw new Exception('${entity.path} is neither File nor Directory');
     }
diff --git a/packages/flutter_tools/test/src/base/file_system_test.dart b/packages/flutter_tools/test/src/base/file_system_test.dart
new file mode 100644
index 0000000..0b513e1
--- /dev/null
+++ b/packages/flutter_tools/test/src/base/file_system_test.dart
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('file_system', () {
+    /// Test file_systems.copyDirectorySync() using MemoryFileSystem.
+    /// Copies between 2 instances of file systems which is also supported by copyDirectorySync().
+    test('test directory copy', () async {
+      MemoryFileSystem sourceMemoryFs = new MemoryFileSystem();
+      String sourcePath = '/some/origin';
+      Directory sourceDirectory = await sourceMemoryFs.directory(sourcePath).create(recursive: true);
+      sourceMemoryFs.currentDirectory = sourcePath;
+      File sourceFile1 = sourceMemoryFs.file('some_file.txt')..writeAsStringSync('bleh');
+      DateTime writeTime = sourceFile1.lastModifiedSync();
+      sourceMemoryFs.file('sub_dir/another_file.txt').createSync(recursive: true);
+      sourceMemoryFs.directory('empty_directory').createSync();
+
+      // Copy to another memory file system instance.
+      MemoryFileSystem targetMemoryFs = new MemoryFileSystem();
+      String targetPath = '/some/non-existent/target';
+      Directory targetDirectory = targetMemoryFs.directory(targetPath);
+      copyDirectorySync(sourceDirectory, targetDirectory);
+      
+      expect(targetDirectory.existsSync(), true);
+      targetMemoryFs.currentDirectory = targetPath;
+      expect(targetMemoryFs.directory('empty_directory').existsSync(), true);
+      expect(targetMemoryFs.file('sub_dir/another_file.txt').existsSync(), true);
+      expect(targetMemoryFs.file('some_file.txt').readAsStringSync(), 'bleh');
+
+      // Assert that the copy operation hasn't modified the original file in some way.
+      expect(sourceMemoryFs.file('some_file.txt').lastModifiedSync(), writeTime);
+      // There's still 3 things in the original directory as there were initially.
+      expect(sourceMemoryFs.directory(sourcePath).listSync().length, 3);
+    });
+  });
+}