Avoid always downcasing file paths on Windows (#1172)

Closes #1169
This commit is contained in:
Natalie Weizenbaum 2020-12-23 18:07:20 -08:00 committed by GitHub
parent 40f16bf7af
commit bf623752fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 39 additions and 29 deletions

View File

@ -1,3 +1,8 @@
## 1.30.1
* Properly load files in case-sensitive Windows directories with upper-case
names.
## 1.30.0
* Fix a bug where `@at-root (without: all)` wouldn't properly remove a

View File

@ -44,7 +44,7 @@ Future<CompileResult> compileAsync(String path,
(syntax == null || syntax == Syntax.forPath(path))) {
importCache ??= AsyncImportCache.none(logger: logger);
stylesheet = await importCache.importCanonical(
FilesystemImporter('.'), p.toUri(p.canonicalize(path)), p.toUri(path));
FilesystemImporter('.'), p.toUri(canonicalize(path)), p.toUri(path));
} else {
stylesheet = Stylesheet.parse(
readFile(path), syntax ?? Syntax.forPath(path),

View File

@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_compile.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: bca3a79dd4a5c3905b07003b123172f3c876d2de
// Checksum: b2cd6037efa37e300daa45ebed20cb4b61526161
//
// ignore_for_file: unused_import
@ -54,7 +54,7 @@ CompileResult compile(String path,
(syntax == null || syntax == Syntax.forPath(path))) {
importCache ??= ImportCache.none(logger: logger);
stylesheet = importCache.importCanonical(
FilesystemImporter('.'), p.toUri(p.canonicalize(path)), p.toUri(path));
FilesystemImporter('.'), p.toUri(canonicalize(path)), p.toUri(path));
} else {
stylesheet = Stylesheet.parse(
readFile(path), syntax ?? Syntax.forPath(path),

View File

@ -41,8 +41,8 @@ Future<void> watch(ExecutableOptions options, StylesheetGraph graph) async {
var watcher = _Watcher(options, graph);
for (var source in options.sourcesToDestinations.keys) {
var destination = options.sourcesToDestinations[source];
graph.addCanonical(FilesystemImporter('.'), p.toUri(p.canonicalize(source)),
p.toUri(source),
graph.addCanonical(
FilesystemImporter('.'), p.toUri(canonicalize(source)), p.toUri(source),
recanonicalize: false);
var success = await watcher.compile(source, destination, ifModified: true);
if (!success && options.stopOnError) {
@ -188,7 +188,7 @@ class _Watcher {
}
/// Returns the canonical URL for the stylesheet path [path].
Uri _canonicalize(String path) => p.toUri(p.canonicalize(path));
Uri _canonicalize(String path) => p.toUri(canonicalize(path));
/// Combine [WatchEvent]s that happen in quick succession.
///

View File

@ -23,18 +23,13 @@ class FilesystemImporter extends Importer {
Uri canonicalize(Uri url) {
if (url.scheme != 'file' && url.scheme != '') return null;
var resolved = resolveImportPath(p.join(_loadPath, p.fromUri(url)));
return resolved == null ? null : p.toUri(p.canonicalize(resolved));
return resolved == null ? null : p.toUri(io.canonicalize(resolved));
}
ImporterResult load(Uri url) {
var path = p.fromUri(url);
return ImporterResult(io.readFile(path),
sourceMapUrl:
// [io.realCasePath] will short-circuit on case-sensitive
// filesystems anyway, but we still avoid calling it here so we
// don't have to re-parse the URL.
io.couldBeCaseInsensitive ? p.toUri(io.realCasePath(path)) : url,
syntax: Syntax.forPath(path));
sourceMapUrl: url, syntax: Syntax.forPath(path));
}
DateTime modificationTime(Uri url) => io.modificationTime(p.fromUri(url));

View File

@ -17,26 +17,36 @@ export 'io/interface.dart'
///
/// We can't know for sure because different Mac OS systems are configured
/// differently.
bool get couldBeCaseInsensitive => isWindows || isMacOS;
bool get _couldBeCaseInsensitive => isWindows || isMacOS;
/// Returns the canonical form of `path` on disk.
String canonicalize(String path) => _couldBeCaseInsensitive
? _realCasePath(p.absolute(p.normalize(path)))
: p.canonicalize(path);
/// Returns `path` with the case updated to match the path's case on disk.
///
/// This only updates `path`'s basename. It always returns `path` as-is on
/// operating systems other than Windows or Mac OS, since they almost never uses
/// operating systems other than Windows or Mac OS, since they almost never use
/// case-insensitive filesystems.
String realCasePath(String path) {
String _realCasePath(String path) {
// TODO(nweiz): Use an SDK function for this when dart-lang/sdk#35370 and/or
// nodejs/node#24942 are fixed.
// nodejs/node#24942 are fixed, or at least use FFI functions.
if (!couldBeCaseInsensitive) return path;
if (!_couldBeCaseInsensitive) return path;
var basename = p.basename(path);
var matches = listDir(p.dirname(path))
.where((realPath) => equalsIgnoreCase(p.basename(realPath), basename))
var realCasePath = p.rootPrefix(path);
for (var component in p.split(path.substring(realCasePath.length))) {
var matches = listDir(realCasePath)
.where((realPath) => equalsIgnoreCase(p.basename(realPath), component))
.toList();
// If the file doesn't exist, or if there are multiple options (meaning the
// filesystem isn't actually case-insensitive), return `path` as-is.
if (matches.length != 1) return path;
return matches.first;
realCasePath = matches.length != 1
// If the file doesn't exist, or if there are multiple options (meaning
// the filesystem isn't actually case-insensitive), use `component` as-is.
? p.join(realCasePath, component)
: matches[0];
}
return realCasePath;
}

View File

@ -1,5 +1,5 @@
name: sass
version: 1.30.0
version: 1.30.1-dev
description: A Sass implementation in Dart.
author: Sass Team
homepage: https://github.com/sass/dart-sass

View File

@ -73,8 +73,8 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
expect(
_readJson("out.css.map"),
containsPair("sources", [
p.toUri(p.canonicalize(d.path("dir/other.scss"))).toString(),
p.toUri(p.canonicalize(d.path("test.scss"))).toString()
p.toUri(canonicalize(d.path("dir/other.scss"))).toString(),
p.toUri(canonicalize(d.path("test.scss"))).toString()
]));
});