From 035afc2c25796de5d2f4e88bbc4ee2340e51d66c Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Wed, 21 Sep 2016 11:24:29 -0700 Subject: [PATCH] Properly handle symlinked source files in hot mode (#5978) --- packages/flutter_tools/lib/src/devfs.dart | 31 ++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart index 4c515d014d9..6874461ad37 100644 --- a/packages/flutter_tools/lib/src/devfs.dart +++ b/packages/flutter_tools/lib/src/devfs.dart @@ -30,7 +30,7 @@ class DevFSEntry { final AssetBundleEntry bundleEntry; String get assetPath => bundleEntry.archivePath; - final File file; + final FileSystemEntity file; FileStat _fileStat; // When we scanned for files, did this still exist? bool _exists = false; @@ -69,15 +69,29 @@ class DevFSEntry { if (_isSourceEntry) return; _fileStat = file.statSync(); + if (_fileStat.type == FileSystemEntityType.LINK) { + // Stat the link target. + String resolved = file.resolveSymbolicLinksSync(); + _fileStat = FileStat.statSync(resolved); + } } bool get _isSourceEntry => file == null; bool get _isAssetEntry => bundleEntry != null; + File _getFile() { + if (file is Link) { + // The link target. + return new File(file.resolveSymbolicLinksSync()); + } + return file; + } + Future> contentsAsBytes() async { if (_isSourceEntry) return bundleEntry.contentsAsBytes(); + final File file = _getFile(); return file.readAsBytes(); } @@ -86,6 +100,7 @@ class DevFSEntry { return new Stream>.fromIterable( >[bundleEntry.contentsAsBytes()]); } + final File file = _getFile(); return file.openRead(); } @@ -417,7 +432,7 @@ class DevFS { logger.flush(); } - void _scanFile(String devicePath, File file) { + void _scanFile(String devicePath, FileSystemEntity file) { DevFSEntry entry = _entries[devicePath]; if (entry == null) { // New file. @@ -485,10 +500,20 @@ class DevFS { Stream files = directory.list(recursive: recursive, followLinks: false); await for (FileSystemEntity file in files) { - if (file is! File) { + if (file is Link) { + final String linkPath = file.resolveSymbolicLinksSync(); + final FileSystemEntityType linkType = + FileStat.statSync(linkPath).type; + if (linkType == FileSystemEntityType.DIRECTORY) { + // Skip links to directories. + continue; + } + } + if (file is Directory) { // Skip non-files. continue; } + assert((file is Link) || (file is File)); if (ignoreDotFiles && path.basename(file.path).startsWith('.')) { // Skip dot files. continue;