Skip to content

[hooks] Handle absolute paths in UserDefines.path() - #3526

Open
cornpip wants to merge 2 commits into
dart-lang:mainfrom
cornpip:userdefines-absolute-path
Open

[hooks] Handle absolute paths in UserDefines.path()#3526
cornpip wants to merge 2 commits into
dart-lang:mainfrom
cornpip:userdefines-absolute-path

Conversation

@cornpip

@cornpip cornpip commented Aug 6, 2026

Copy link
Copy Markdown

Description

UserDefines.path() passed every value through basePath.resolve(). A Windows drive letter is a valid URI scheme, so an absolute Windows path was parsed as an already-absolute URI: D:\a\b.dll became a URI with scheme d, and toFilePath() on the result throws.

path() now returns absolute paths as-is and keeps the existing resolve() behavior for relative paths. Absolute paths are detected with File(path).isAbsolute, which uses the platform's native path semantics, so no OS-specific branching is needed. The doc comment states this contract.

Tests cover the two separator cases raised in the issue, both on Windows: backslashes with an absolute path, and forward slashes with a relative path. They also cover UNC paths, POSIX paths, and the null cases.

Related Issues

Fixes #3518

PR Checklist

  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
  • I've run dart tool/ci.dart --all locally and resolved all issues identified. This ensures the PR is formatted, has no lint errors, and ran all code generators. This applies to the packages part of the toplevel pubspec.yaml workspace.
  • All existing and new tests are passing. I added new tests to check the change I am making.
  • The PR is actually solving the issue. PRs that don't solve the issue will be closed. Please be respectful of the maintainers' time. If it's not clear what the issue is, feel free to ask questions on the GitHub issue before submitting a PR.
  • I have updated CHANGELOG.md for the relevant packages. (Not needed for small changes such as doc typos).
  • I have updated the pubspec package version if necessary.

UserDefines.path() passed every value through basePath.resolve(). A
Windows drive letter is a valid URI scheme, so an absolute Windows path
was parsed as an already-absolute URI and toFilePath() on the result
throws. Absolute paths (File(path).isAbsolute) are now converted with
Uri.file without resolution; relative paths keep the existing behavior.

Fixes dart-lang#3518

@dcharkes dcharkes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @cornpip 🙏

expect(uri, Uri.parse('file://server/share/lib.dll'));
expect(uri.toFilePath(), r'\\server\share\lib.dll');
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also test that relative path with windows separators works? Or maybe it shouldn't work and we should document on the path methods that relative paths should use linux path separators.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!
It works. Dart's Uri parser treats backslashes as path separators, so some\dir\model.bin resolves against the base path as expected. Added a test.

Uri.parse('file:///home/user/proj/example/some/dir/model.bin'),
);
expect(uri.toFilePath(), '/home/user/proj/example/some/dir/model.bin');
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably also test what happens with relative paths with Windows path separators.

If we don't support it, then we should document this clearly on on the path method.

(What happens with File.isAbsolute and Uri.resolve if you pass in Windows relative paths on linux? If it does the right thing we could support it. If. Not we should clearly document that on the path method.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does the right thing on Linux too: File.isAbsolute is false there, and the Uri parser normalizes backslashes to path separators independently of the platform, so it resolves the same as with forward slashes. Added a test as well.

Requested in review: Dart's Uri parser treats backslashes as path
separators on all platforms, so relative paths with Windows separators
resolve against basePath the same way forward-slash paths do. Adds the
case to both the Windows and POSIX test groups.
@dcharkes

dcharkes commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

@liamappelbe any chance the zizmor changes are preventing running the health check commenting?

@liamappelbe

Copy link
Copy Markdown
Contributor

@liamappelbe any chance the zizmor changes are preventing running the health check commenting?

Definitely possible. I'm not a workflow expert. I probably removed an important permission. I'm about to head out for the weekend, so if you want it fixed before Monday you might need to take a look at it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[hooks] UserDefines.path() breaks on Windows absolute paths

3 participants