diff --git a/crates/uv-tool/src/lib.rs b/crates/uv-tool/src/lib.rs index c330fd3bd..603c24a38 100644 --- a/crates/uv-tool/src/lib.rs +++ b/crates/uv-tool/src/lib.rs @@ -52,6 +52,8 @@ pub enum Error { EnvironmentRead(PathBuf, String), #[error("Failed find tool package `{0}` at `{1}`")] MissingToolPackage(PackageName, PathBuf), + #[error(transparent)] + Serialization(#[from] toml_edit::ser::Error), } /// A collection of uv-managed tools installed on the current system. @@ -159,7 +161,7 @@ impl InstalledTools { path.user_display() ); - let doc = tool_receipt.to_toml(); + let doc = tool_receipt.to_toml()?; // Save the modified `uv-receipt.toml`. fs_err::write(&path, doc)?; diff --git a/crates/uv-tool/src/receipt.rs b/crates/uv-tool/src/receipt.rs index 4b3d8318e..537ea482f 100644 --- a/crates/uv-tool/src/receipt.rs +++ b/crates/uv-tool/src/receipt.rs @@ -32,13 +32,13 @@ impl ToolReceipt { } /// Returns the TOML representation of this receipt. - pub(crate) fn to_toml(&self) -> String { + pub(crate) fn to_toml(&self) -> Result { // We construct a TOML document manually instead of going through Serde to enable // the use of inline tables. let mut doc = toml_edit::DocumentMut::new(); - doc.insert("tool", toml_edit::Item::Table(self.tool.to_toml())); + doc.insert("tool", toml_edit::Item::Table(self.tool.to_toml()?)); - doc.to_string() + Ok(doc.to_string()) } } diff --git a/crates/uv-tool/src/tool.rs b/crates/uv-tool/src/tool.rs index f04a582b0..1e023e67e 100644 --- a/crates/uv-tool/src/tool.rs +++ b/crates/uv-tool/src/tool.rs @@ -73,26 +73,25 @@ impl Tool { } /// Returns the TOML table for this tool. - pub(crate) fn to_toml(&self) -> Table { + pub(crate) fn to_toml(&self) -> Result { let mut table = Table::new(); table.insert("requirements", { - let requirements = match self.requirements.as_slice() { + let requirements = self + .requirements + .iter() + .map(|requirement| { + serde::Serialize::serialize( + &requirement, + toml_edit::ser::ValueSerializer::new(), + ) + }) + .collect::, _>>()?; + + let requirements = match requirements.as_slice() { [] => Array::new(), - [requirement] => Array::from_iter([serde::Serialize::serialize( - &requirement, - toml_edit::ser::ValueSerializer::new(), - ) - .unwrap()]), - requirements => { - each_element_on_its_line_array(requirements.iter().map(|requirement| { - serde::Serialize::serialize( - &requirement, - toml_edit::ser::ValueSerializer::new(), - ) - .unwrap() - })) - } + [requirement] => Array::from_iter([requirement]), + requirements => each_element_on_its_line_array(requirements.iter()), }; value(requirements) }); @@ -111,7 +110,7 @@ impl Tool { value(entrypoints) }); - table + Ok(table) } pub fn entrypoints(&self) -> &[ToolEntrypoint] { diff --git a/crates/uv/tests/tool_install.rs b/crates/uv/tests/tool_install.rs index 4d70b9fb5..6a3754718 100644 --- a/crates/uv/tests/tool_install.rs +++ b/crates/uv/tests/tool_install.rs @@ -144,7 +144,6 @@ fn tool_install() { sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0]) sys.exit(main()) "###); - }); uv_snapshot!(context.filters(), Command::new("flask").arg("--version").env("PATH", bin_dir.as_os_str()), @r###" @@ -161,7 +160,6 @@ fn tool_install() { insta::with_settings!({ filters => context.filters(), }, { - // We should have a new tool receipt assert_snapshot!(fs_err::read_to_string(tool_dir.join("flask").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = [{ name = "flask" }]