From b7fb0b445f3698dd1dfc90361b9bea0ab1edee52 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 14 Jun 2024 06:05:14 -0700 Subject: [PATCH] Use portable slash paths in lockfile (#4324) ## Summary This would be a lightweight solution to https://github.com/astral-sh/uv/issues/4307 that doesn't fully engage with all the possibilities in the design space (but would unblock cross-platform for now). --- Cargo.lock | 1 + crates/uv-resolver/Cargo.toml | 1 + crates/uv-resolver/src/lock.rs | 6 +++++- crates/uv/tests/lock.rs | 19 +------------------ 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8bab8f264..995cd4cce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4864,6 +4864,7 @@ dependencies = [ "itertools 0.13.0", "once-map", "owo-colors", + "path-slash", "pep440_rs", "pep508_rs", "petgraph", diff --git a/crates/uv-resolver/Cargo.toml b/crates/uv-resolver/Cargo.toml index d54a4532c..8ce45cac2 100644 --- a/crates/uv-resolver/Cargo.toml +++ b/crates/uv-resolver/Cargo.toml @@ -42,6 +42,7 @@ futures = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } owo-colors = { workspace = true } +path-slash = { workspace = true } petgraph = { workspace = true } pubgrub = { workspace = true } rkyv = { workspace = true } diff --git a/crates/uv-resolver/src/lock.rs b/crates/uv-resolver/src/lock.rs index 02d961006..3b5e0e5cd 100644 --- a/crates/uv-resolver/src/lock.rs +++ b/crates/uv-resolver/src/lock.rs @@ -9,6 +9,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use either::Either; +use path_slash::PathExt; use petgraph::visit::EdgeRef; use rustc_hash::FxHashMap; use serde::{Deserialize, Deserializer}; @@ -851,8 +852,11 @@ enum Source { } /// A [`PathBuf`], but we show `.` instead of an empty path. +/// +/// We also normalize backslashes to forward slashes on Windows, to ensure +/// that the lock file contains portable paths. fn serialize_path_with_dot(path: &Path) -> Cow { - let path = path.to_string_lossy(); + let path = path.to_slash_lossy(); if path.is_empty() { Cow::Borrowed(".") } else { diff --git a/crates/uv/tests/lock.rs b/crates/uv/tests/lock.rs index 27358440e..bc0378dcf 100644 --- a/crates/uv/tests/lock.rs +++ b/crates/uv/tests/lock.rs @@ -2478,25 +2478,8 @@ fn relative_and_absolute_paths() -> Result<()> { let lock = fs_err::read_to_string(context.temp_dir.join("uv.lock"))?; - // In this particular test, Windows paths with \ are written to the TOML - // lock file, but because the \ starts an escape sequence in TOML strings, - // this causes the TOML serializer to use single quoted strings. But - // everywhere else, / is used and thus double quoted strings are used. - // - // Making matters more confusing, we have filters that normalize Windows - // paths to Unix paths, which makes it *look* like the TOML in the snapshot - // is needlessly using single quoted strings. - // - // So we add a filter here (that runs after all other filters) that - // replaces single quoted strings with double quoted strings. This isn't - // correct in general, but works for this specific test. - let filters = context - .filters() - .into_iter() - .chain(vec![(r"'([^']+)'", r#""$1""#)]) - .collect::>(); insta::with_settings!({ - filters => filters, + filters => context.filters(), }, { assert_snapshot!( lock, @r###"