Skip to content

Preserve absolute paths in uv add for local dependencies#17316

Open
nooscraft wants to merge 4 commits intoastral-sh:mainfrom
nooscraft:bugfix/17307
Open

Preserve absolute paths in uv add for local dependencies#17316
nooscraft wants to merge 4 commits intoastral-sh:mainfrom
nooscraft:bugfix/17307

Conversation

@nooscraft
Copy link
Contributor

When adding a local package with an absolute path like uv add /path/to/package, keep it absolute instead of converting to relative. Relative paths stay relative.

Fixes #17307

When adding a local package with an absolute path like
`uv add /path/to/package`, keep it absolute instead of converting
to relative. Relative paths stay relative.

Fixes astral-sh#17307
Keep the path format as provided by the user instead of always
converting to relative paths. Workspace members remain relative
for portability.
Copy link
Contributor

@EliteTK EliteTK left a comment

Choose a reason for hiding this comment

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

I've had a look around / and manually tested some corner cases and it seems like this approach should work for the forward path. But...

There's places where we make up a PathBuiltDist on the spot e.g.:

let path_dist = PathBuiltDist {
filename,
url: verbatim_url(&install_path, &self.id)?,
install_path: absolute_path(workspace_root, path)?.into_boxed_path(),
};

And it seems like this change might end up with us getting absolute paths in places where previously we would want relative ones.

I haven't found a case like that yet, but it may be worth changing the tests where the snapshots have changed to using relative paths instead, just to see if it shakes out a case like this.

Overall, I'm not experienced enough in this area of the code to be sure if this is the best approach for this. I'll let others comment though.

Comment on lines 3640 to 3652
/// Check if the user originally provided an absolute path by inspecting the VerbatimUrl.
fn was_absolute_path(url: &VerbatimUrl) -> bool {
// Check the original user-provided string if available
if let Some(given) = url.given() {
// Check if the given string starts with "/" (Unix) or contains ":" (Windows drive)
let path_str = given.strip_prefix("file://").unwrap_or(given);
Path::new(path_str).is_absolute()
} else {
// Fallback: assume file:// URLs with absolute paths were originally absolute
url.scheme() == "file"
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Given that we now have 4 places where we are doing this, I think it's may be a candidate for just having a function. Something which also incorporates this logic:

if was_absolute_path(&url) {
    std::path::absolute(&install_path)
} else {
    relative_to(&install_path, root)
        .or_else(|_| std::path::absolute(&install_path))
}

So the call sites can just become absolute_or_relative_to(instal_path, root, url).map_err(...)?.

Not sure about the name or location, will get back to you on that.

Copy link
Contributor 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 comments and I have addressed the suggestion.

Updated the path resolution methods to maintain the original absolute or relative nature of paths provided by the user. Introduced a new function, `absolute_or_relative_to`, to streamline the handling of paths in various contexts, ensuring that workspace members remain relative while external dependencies respect the user's original input.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

uv add results in relative path for a local package

2 participants