Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paths are treated as case sensitive on windows for packageOf #1545

Open
jakemac53 opened this issue Jun 5, 2023 · 2 comments
Open

Paths are treated as case sensitive on windows for packageOf #1545

jakemac53 opened this issue Jun 5, 2023 · 2 comments

Comments

@jakemac53
Copy link
Contributor

Paths are not case sensitive on windows, but this package treats them as if they are in the packageOf function.

In particular, this is annoying because:

  • Pub will put paths with upper case in the package config
  • The canonicalize function from package:path will lower case everything on windows.

These are essentially incompatible - a package config created from pub will not be able to find the containing package for any file URI whose path has been canonicalized.

@jakemac53
Copy link
Contributor Author

Fwiw here is an example test that would fail:

    test('packageOf, windows paths capitalization', () {
      var configBytes = utf8.encode(json.encode({
        'configVersion': 2,
        'packages': [
          {'name': 'foo', 'rootUri': 'file:///C:/Foo/', 'packageUri': 'lib/'},
        ]
      }));
      var config = parsePackageConfigBytes(configBytes as Uint8List,
          Uri.parse('file:///C:/tmp/.dart_tool/file.dart'), throwError);
      expect(config.version, 2);
      expect(config.packageOf(Uri.parse('file:///C:/foo/lala/lala.dart'))!.name,
          'foo');
    });

jakemac53 referenced this issue in dart-lang/package_config Jan 10, 2024
…137)

- validates the behavior of https://github.com/dart-lang/package_config/issues/136 today (but does not change it)
- removes build_runner deps for testing, there is no need to use it for such a small package
- fixes a bug in discovery_test.dart that was probably landed due to inability to run tests
@lrhn
Copy link
Member

lrhn commented Feb 12, 2024

This is a tricky issue.
At the root, the code doesn't actually care what kind of URI it has, and therefore don't treat file URIs specially.
It converts between "some URI" and package:-URI by doing URI text manipulation.

If we start treating file: URIs as case-insensitive in some operations, we need to figure out which operations.
And we should figure out how to be case insensitive, because there isn't just one way to do that.
And whether, because if this is for Windows file paths, then the real authority is the actual file system, which may or may not be case sensitive. On a per-directory basis.

The package_config works by reading a package_config.json file, then resolving everything from that. It doesn't ask the file system about whether a file exists. That's actually counter-productive when resolving package: uris, because you can ask for locations that don't exist yet within the lib/ directory, fx. in order to create them.
Which means that the package has no real way to know whether to be case sensitive or not.

Let's assume we bite the bullet and ask the operation system. If a path exists, we can ask the directory whether it's case sensitive (somehow) and use that information to to determine whether the following path segments are equivalent.

That requires knowing the case normalization algorithm. Which is non-trivial.
Again, the only safe answer is to ask the file system/Windows kernel whether two paths are indeed the same.
I don't know if that can work if the paths do not exist yet. Maybe we can assume that's not the case - if someone asks if file:///c:/foo/bar/baz is the same as file:///c:/foo/bar/BAZ, and c:/foo/bar does not even exist (yet), then we just say "no".
If c:/foo/bar exists, then we ask the file system whether c:/foo/bar/baz and c:/foo/bar/BAZ would be the same. If that is possible without one of them existing.

Doing any of this would make package:package_config need a dependency on something like dart:ffi or package:win32, assuming that it's even possible.

And then we still need to figure out which functions are affected by this.
It's the ones that compare two paths against each other, or that read actual files.

Reading actual files is not an issue. We try to read files like .dart_tool/package_config.json or .packages, and if the filesystem is case insensitive, we'll also match other names, which is fine. If it's not, we find only what we are looking for.
In either case, it's not a problem.

The packageOf function takes a file URI and tries to find a matching package root. Then it returns the Package for that. It compares two different URIs for "equality", which means it should be affected by case sensitivity.
The isInside functionality is basically the same as packageOf.

The resolve converts a package URI to a file URI. It doesn't compare two paths at all. It should not be affected. We don't care whether the result is case sensitive or not, it's what you asked for.

I don't think we ever need to compare two package: URIs, so whether package:foo/bar.dart and package foo/BAR.dart` would resolve to the same filesystem file isn't important.

Maybe that is it. The packageOf functionality is really the only one that matters.
if the root and package URI root directories for a package exists, then maybe we can figure out whether they are case sensitive. Maybe we can figure out whether two paths up to there would be case-folded to the same thing, probably by doing a per-segment path comparison, if the OS provides the primitives.

And then we remember that MacOS is also not case sensitive by default. Maybe all our Mac developers have chosen to mount their source file systems as case-sensitive.

(Should dart create on Windows mark the directory as case sensitive? Won't help with the path until there, but might avoid some other issues.)

All in all, I don't think it's reasonable to fix this properly. A more hacky approach (ASCII-only case insensitivity perhaps) may be viable, but not necessarily sufficient.

mosuem referenced this issue Dec 9, 2024
…art-lang/package_config#137)

- validates the behavior of https://github.com/dart-lang/package_config/issues/136 today (but does not change it)
- removes build_runner deps for testing, there is no need to use it for such a small package
- fixes a bug in discovery_test.dart that was probably landed due to inability to run tests
@mosuem mosuem transferred this issue from dart-lang/package_config Dec 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants