From 20034ae472f247bb377249af007ae54c50bd3cbb Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 26 Jun 2024 14:28:29 -0500 Subject: [PATCH] Rename to `receipt.toml` --- crates/uv-tool/src/lib.rs | 52 +++++++++--------- crates/uv-tool/src/receipt.rs | 51 ++++++++++++++++++ crates/uv-tool/src/tool.rs | 25 +++++++++ crates/uv-tool/src/tools_toml.rs | 73 -------------------------- crates/uv/src/commands/tool/install.rs | 4 +- crates/uv/tests/tool_install.rs | 30 +++++------ 6 files changed, 120 insertions(+), 115 deletions(-) create mode 100644 crates/uv-tool/src/receipt.rs create mode 100644 crates/uv-tool/src/tool.rs delete mode 100644 crates/uv-tool/src/tools_toml.rs diff --git a/crates/uv-tool/src/lib.rs b/crates/uv-tool/src/lib.rs index 7517e494ec44..255d6b1d9e9d 100644 --- a/crates/uv-tool/src/lib.rs +++ b/crates/uv-tool/src/lib.rs @@ -11,19 +11,21 @@ use tracing::debug; use uv_fs::{LockedFile, Simplified}; use uv_toolchain::{Interpreter, PythonEnvironment}; -pub use tools_toml::{Tool, ToolToml}; +pub use receipt::ToolReceipt; +pub use tool::Tool; use uv_state::{StateBucket, StateStore}; -mod tools_toml; +mod receipt; +mod tool; #[derive(Error, Debug)] pub enum Error { #[error(transparent)] IO(#[from] io::Error), - #[error("Failed to update `tool.toml` at {0}")] - TomlWrite(PathBuf, #[source] Box), - #[error("Failed to read `tool.toml` at {0}")] - TomlRead(PathBuf, #[source] Box), + #[error("Failed to update `uv-receipt.toml` at {0}")] + ReceiptWrite(PathBuf, #[source] Box), + #[error("Failed to read `uv-receipt.toml` at {0}")] + ReceiptRead(PathBuf, #[source] Box), #[error(transparent)] VirtualEnvError(#[from] uv_virtualenv::Error), #[error("Failed to read package entry points {0}")] @@ -32,8 +34,8 @@ pub enum Error { DistInfoMissing(String, PathBuf), #[error("Failed to find a directory for executables")] NoExecutableDirectory, - #[error("Failed to find a metadata for tool `{0}` at {1}")] - MissingToolMetadata(String, PathBuf), + #[error("Failed to find a receipt for tool `{0}` at {1}")] + MissingToolReceipt(String, PathBuf), } /// A collection of uv-managed tools installed on the current system. @@ -72,27 +74,27 @@ impl InstalledTools { let mut tools = Vec::new(); for directory in uv_fs::directories(self.root()) { let name = directory.file_name().unwrap().to_string_lossy().to_string(); - let path = directory.join("tool.toml"); + let path = directory.join("uv-receipt.toml"); let contents = match fs_err::read_to_string(&path) { Ok(contents) => contents, // TODO(zanieb): Consider warning on malformed tools instead Err(err) if err.kind() == io::ErrorKind::NotFound => { - return Err(Error::MissingToolMetadata(name.clone(), path.clone())) + return Err(Error::MissingToolReceipt(name.clone(), path.clone())) } Err(err) => return Err(err.into()), }; - let tool_toml = ToolToml::from_string(contents) - .map_err(|err| Error::TomlRead(path, Box::new(err)))?; - tools.push((name, tool_toml.tool)); + let tool_receipt = ToolReceipt::from_string(contents) + .map_err(|err| Error::ReceiptRead(path, Box::new(err)))?; + tools.push((name, tool_receipt.tool)); } Ok(tools) } - /// Get the tool metadata for the given tool - pub fn tool_metadata(&self, name: &str) -> Result, Error> { - let path = self.root.join(name).join("tool.toml"); - match ToolToml::from_path(&path) { - Ok(tool_toml) => Ok(Some(tool_toml.tool)), + /// Get the receipt for the given tool. + pub fn get_tool_receipt(&self, name: &str) -> Result, Error> { + let path = self.root.join(name).join("uv-receipt.toml"); + match ToolReceipt::from_path(&path) { + Ok(tool_receipt) => Ok(Some(tool_receipt.tool)), Err(Error::IO(err)) if err.kind() == io::ErrorKind::NotFound => Ok(None), Err(err) => Err(err), } @@ -115,22 +117,22 @@ impl InstalledTools { )?) } - /// Add metadata for a tool. + /// Add a receipt for a tool. /// - /// Existing metadata will be replaced. - pub fn add_tool_metadata(&self, name: &str, tool: Tool) -> Result<(), Error> { + /// Any existing receipt will be replaced. + pub fn add_tool_receipt(&self, name: &str, tool: Tool) -> Result<(), Error> { let _lock = self.acquire_tool_lock(name); - let tool_toml = ToolToml::from(tool); - let path = self.root.join(name).join("tool.toml"); + let tool_receipt = ToolReceipt::from(tool); + let path = self.root.join(name).join("uv-receipt.toml"); debug!( "Adding metadata entry for tool `{name}` at {}", path.user_display() ); - let doc = toml::to_string(&tool_toml) - .map_err(|err| Error::TomlWrite(path.clone(), Box::new(err)))?; + let doc = toml::to_string(&tool_receipt) + .map_err(|err| Error::ReceiptWrite(path.clone(), Box::new(err)))?; // Save the modified `tools.toml`. fs_err::write(&path, doc)?; diff --git a/crates/uv-tool/src/receipt.rs b/crates/uv-tool/src/receipt.rs new file mode 100644 index 000000000000..abf130a09f69 --- /dev/null +++ b/crates/uv-tool/src/receipt.rs @@ -0,0 +1,51 @@ +use std::path::Path; + +use serde::{Deserialize, Serialize}; + +use crate::Tool; + +/// A `uv-receipt.toml` file tracking the installation of a tool. +#[allow(dead_code)] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ToolReceipt { + pub(crate) tool: Tool, + + /// The raw unserialized document. + #[serde(skip)] + pub(crate) raw: String, +} + +impl ToolReceipt { + /// Parse a [`ToolReceipt`] from a raw TOML string. + pub(crate) fn from_string(raw: String) -> Result { + let tool = toml::from_str(&raw)?; + Ok(ToolReceipt { raw, ..tool }) + } + + /// Read a [`ToolReceipt`] from the given path. + pub(crate) fn from_path(path: &Path) -> Result { + match fs_err::read_to_string(path) { + Ok(contents) => Ok(ToolReceipt::from_string(contents) + .map_err(|err| crate::Error::ReceiptRead(path.to_owned(), Box::new(err)))?), + Err(err) => Err(err.into()), + } + } +} + +// Ignore raw document in comparison. +impl PartialEq for ToolReceipt { + fn eq(&self, other: &Self) -> bool { + self.tool.eq(&other.tool) + } +} + +impl Eq for ToolReceipt {} + +impl From for ToolReceipt { + fn from(tool: Tool) -> Self { + ToolReceipt { + tool, + raw: String::new(), + } + } +} diff --git a/crates/uv-tool/src/tool.rs b/crates/uv-tool/src/tool.rs new file mode 100644 index 000000000000..f5d4e98dbbf2 --- /dev/null +++ b/crates/uv-tool/src/tool.rs @@ -0,0 +1,25 @@ +use pypi_types::VerbatimParsedUrl; +use serde::{Deserialize, Serialize}; + +/// A tool entry. +#[allow(dead_code)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Deserialize)] +#[serde(rename_all = "kebab-case")] +#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] +pub struct Tool { + requirements: Vec>, + python: Option, +} + +impl Tool { + /// Create a new `Tool`. + pub fn new( + requirements: Vec>, + python: Option, + ) -> Self { + Self { + requirements, + python, + } + } +} diff --git a/crates/uv-tool/src/tools_toml.rs b/crates/uv-tool/src/tools_toml.rs deleted file mode 100644 index 98db4f593a9b..000000000000 --- a/crates/uv-tool/src/tools_toml.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::path::Path; - -use pypi_types::VerbatimParsedUrl; -use serde::{Deserialize, Serialize}; - -/// A `tool.toml` file with a `[tool]` entry. -#[allow(dead_code)] -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ToolToml { - pub(crate) tool: Tool, - - /// The raw unserialized document. - #[serde(skip)] - pub(crate) raw: String, -} - -impl ToolToml { - /// Parse a `ToolToml` from a raw TOML string. - pub(crate) fn from_string(raw: String) -> Result { - let tool = toml::from_str(&raw)?; - Ok(ToolToml { raw, ..tool }) - } - - /// Parse a `ToolToml` from the given path TOML string. - pub(crate) fn from_path(path: &Path) -> Result { - match fs_err::read_to_string(path) { - Ok(contents) => Ok(ToolToml::from_string(contents) - .map_err(|err| crate::Error::TomlRead(path.to_owned(), Box::new(err)))?), - Err(err) => Err(err.into()), - } - } -} - -// Ignore raw document in comparison. -impl PartialEq for ToolToml { - fn eq(&self, other: &Self) -> bool { - self.tool.eq(&other.tool) - } -} - -impl Eq for ToolToml {} - -/// A tool entry. -#[allow(dead_code)] -#[derive(Debug, Clone, Serialize, PartialEq, Eq, Deserialize)] -#[serde(rename_all = "kebab-case")] -#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] -pub struct Tool { - requirements: Vec>, - python: Option, -} - -impl Tool { - /// Create a new `Tool`. - pub fn new( - requirements: Vec>, - python: Option, - ) -> Self { - Self { - requirements, - python, - } - } -} - -impl From for ToolToml { - fn from(tool: Tool) -> Self { - ToolToml { - tool, - raw: String::new(), - } - } -} diff --git a/crates/uv/src/commands/tool/install.rs b/crates/uv/src/commands/tool/install.rs index ee2f1589e130..26566516537c 100644 --- a/crates/uv/src/commands/tool/install.rs +++ b/crates/uv/src/commands/tool/install.rs @@ -51,7 +51,7 @@ pub(crate) async fn install( let installed_tools = InstalledTools::from_settings()?; // TODO(zanieb): Automatically replace an existing tool if the request differs - if installed_tools.tool_metadata(&name)?.is_some() { + if installed_tools.get_tool_receipt(&name)?.is_some() { if force { debug!("Replacing existing tool due to `--force` flag."); } else { @@ -180,7 +180,7 @@ pub(crate) async fn install( } let installed_tools = installed_tools.init()?; - installed_tools.add_tool_metadata(&name, tool)?; + installed_tools.add_tool_receipt(&name, tool)?; Ok(ExitStatus::Success) } diff --git a/crates/uv/tests/tool_install.rs b/crates/uv/tests/tool_install.rs index 6ca7fef9918c..f5b1880f0eee 100644 --- a/crates/uv/tests/tool_install.rs +++ b/crates/uv/tests/tool_install.rs @@ -44,7 +44,7 @@ fn tool_install() { tool_dir.child("black").assert(predicate::path::is_dir()); tool_dir .child("black") - .child("tool.toml") + .child("uv-receipt.toml") .assert(predicate::path::exists()); let executable = bin_dir.child(format!("black{}", std::env::consts::EXE_SUFFIX)); @@ -72,8 +72,8 @@ fn tool_install() { insta::with_settings!({ filters => context.filters(), }, { - // We should have a tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("tool.toml")).unwrap(), @r###" + // We should have a tool receipt + assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = ["black"] "###); @@ -148,8 +148,8 @@ fn tool_install() { insta::with_settings!({ filters => context.filters(), }, { - // We should have a new tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("flask").join("tool.toml")).unwrap(), @r###" + // 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 = ["flask"] "###); @@ -188,7 +188,7 @@ fn tool_install_twice() { tool_dir.child("black").assert(predicate::path::is_dir()); tool_dir .child("black") - .child("tool.toml") + .child("uv-receipt.toml") .assert(predicate::path::exists()); let executable = bin_dir.child(format!("black{}", std::env::consts::EXE_SUFFIX)); @@ -216,8 +216,8 @@ fn tool_install_twice() { insta::with_settings!({ filters => context.filters(), }, { - // We should have a tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("tool.toml")).unwrap(), @r###" + // We should have a tool receipt + assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = ["black"] "###); @@ -245,8 +245,8 @@ fn tool_install_twice() { insta::with_settings!({ filters => context.filters(), }, { - // We should not have an additional tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("tool.toml")).unwrap(), @r###" + // We should not have an additional tool receipt + assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = ["black"] "###); @@ -297,7 +297,7 @@ fn tool_install_entry_point_exists() { assert!(!tool_dir.child("black").exists()); // We should not write a tools entry - assert!(!tool_dir.join("black").join("tool.toml").exists()); + assert!(!tool_dir.join("black").join("uv-receipt.toml").exists()); insta::with_settings!({ filters => context.filters(), @@ -360,8 +360,8 @@ fn tool_install_entry_point_exists() { insta::with_settings!({ filters => context.filters(), }, { - // We write a tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("tool.toml")).unwrap(), @r###" + // We write a tool receipt + assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = ["black"] "###); @@ -392,8 +392,8 @@ fn tool_install_entry_point_exists() { insta::with_settings!({ filters => context.filters(), }, { - // We should have a tool entry - assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("tool.toml")).unwrap(), @r###" + // We should have a tool receipt + assert_snapshot!(fs_err::read_to_string(tool_dir.join("black").join("uv-receipt.toml")).unwrap(), @r###" [tool] requirements = ["black"] "###);