2016-10-05 10:04:51 +02:00
|
|
|
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
|
|
|
// MIT-style license that can be found in the LICENSE file or at
|
|
|
|
// https://opensource.org/licenses/MIT.
|
|
|
|
|
2019-01-04 20:17:18 +01:00
|
|
|
import 'package:path/path.dart' as p;
|
|
|
|
|
|
|
|
import 'io/interface.dart'
|
|
|
|
if (dart.library.io) 'io/vm.dart'
|
|
|
|
if (dart.library.js) 'io/node.dart';
|
|
|
|
import 'utils.dart';
|
|
|
|
|
2016-10-05 10:04:51 +02:00
|
|
|
export 'io/interface.dart'
|
|
|
|
if (dart.library.io) 'io/vm.dart'
|
2018-03-23 23:57:03 +01:00
|
|
|
if (dart.library.js) 'io/node.dart';
|
2019-01-04 20:17:18 +01:00
|
|
|
|
|
|
|
/// Returns whether the current operating system might be case-insensitive.
|
|
|
|
///
|
|
|
|
/// We can't know for sure because different Mac OS systems are configured
|
|
|
|
/// differently.
|
2020-12-24 03:07:20 +01:00
|
|
|
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);
|
2019-01-04 20:17:18 +01:00
|
|
|
|
|
|
|
/// 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
|
2020-12-24 03:07:20 +01:00
|
|
|
/// operating systems other than Windows or Mac OS, since they almost never use
|
2019-01-04 20:17:18 +01:00
|
|
|
/// case-insensitive filesystems.
|
2020-12-24 03:07:20 +01:00
|
|
|
String _realCasePath(String path) {
|
2019-01-04 20:17:18 +01:00
|
|
|
// TODO(nweiz): Use an SDK function for this when dart-lang/sdk#35370 and/or
|
2020-12-24 03:07:20 +01:00
|
|
|
// nodejs/node#24942 are fixed, or at least use FFI functions.
|
|
|
|
|
|
|
|
if (!_couldBeCaseInsensitive) return path;
|
2019-01-04 20:17:18 +01:00
|
|
|
|
2020-12-24 03:07:20 +01:00
|
|
|
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();
|
2019-01-04 20:17:18 +01:00
|
|
|
|
2020-12-24 03:07:20 +01:00
|
|
|
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];
|
|
|
|
}
|
2019-01-04 20:17:18 +01:00
|
|
|
|
2020-12-24 03:07:20 +01:00
|
|
|
return realCasePath;
|
2019-01-04 20:17:18 +01:00
|
|
|
}
|