Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 87 additions & 1 deletion crates/uv-distribution-types/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl IndexCacheControl {
}
}

#[derive(Debug, Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[serde(rename_all = "kebab-case")]
pub struct Index {
Expand Down Expand Up @@ -156,6 +156,92 @@ pub struct Index {
pub cache_control: Option<IndexCacheControl>,
}

impl PartialEq for Index {
fn eq(&self, other: &Self) -> bool {
let Self {
name,
url,
explicit,
default,
origin: _,
format,
publish_url,
authenticate,
ignore_error_codes,
cache_control,
} = self;
*url == other.url
&& *name == other.name
&& *explicit == other.explicit
&& *default == other.default
&& *format == other.format
&& *publish_url == other.publish_url
&& *authenticate == other.authenticate
&& *ignore_error_codes == other.ignore_error_codes
&& *cache_control == other.cache_control
}
}

impl Eq for Index {}

impl PartialOrd for Index {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Index {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let Self {
name,
url,
explicit,
default,
origin: _,
format,
publish_url,
authenticate,
ignore_error_codes,
cache_control,
} = self;
url.cmp(&other.url)
.then_with(|| name.cmp(&other.name))
.then_with(|| explicit.cmp(&other.explicit))
.then_with(|| default.cmp(&other.default))
.then_with(|| format.cmp(&other.format))
.then_with(|| publish_url.cmp(&other.publish_url))
.then_with(|| authenticate.cmp(&other.authenticate))
.then_with(|| ignore_error_codes.cmp(&other.ignore_error_codes))
.then_with(|| cache_control.cmp(&other.cache_control))
}
}

impl std::hash::Hash for Index {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let Self {
name,
url,
explicit,
default,
origin: _,
format,
publish_url,
authenticate,
ignore_error_codes,
cache_control,
} = self;
url.hash(state);
name.hash(state);
explicit.hash(state);
default.hash(state);
format.hash(state);
publish_url.hash(state);
authenticate.hash(state);
ignore_error_codes.hash(state);
cache_control.hash(state);
}
}

#[derive(
Default,
Debug,
Expand Down
111 changes: 110 additions & 1 deletion crates/uv/tests/it/tool_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3906,7 +3906,6 @@ fn tool_install_default_credentials() -> Result<()> {
sys.argv[0] = sys.argv[0][:-4]
sys.exit(main())
"###);

});

insta::with_settings!({
Expand Down Expand Up @@ -4094,6 +4093,116 @@ fn tool_install_with_executables_from_no_entrypoints() {
"###);
}

#[test]
fn tool_install_find_links() {
let context = TestContext::new("3.13").with_filtered_exe_suffix();
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");

// Run with `--find-links`.
uv_snapshot!(context.filters(), context.tool_run()
.arg("--find-links")
.arg(context.workspace_root.join("scripts/links/"))
.arg("basic-app")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
Hello from basic-app!

----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ basic-app==0.1.0
");

// Install with `--find-links`.
uv_snapshot!(context.filters(), context.tool_install()
.arg("--find-links")
.arg(context.workspace_root.join("scripts/links/"))
.arg("basic-app")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
.env(EnvVars::PATH, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----

----- stderr -----
Resolved 1 package in [TIME]
Installed 1 package in [TIME]
+ basic-app==0.1.0
Installed 1 executable: basic-app
");

tool_dir
.child("basic-app")
.assert(predicate::path::is_dir());
tool_dir
.child("basic-app")
.child("uv-receipt.toml")
.assert(predicate::path::exists());

let executable = bin_dir.child(format!("basic-app{}", std::env::consts::EXE_SUFFIX));
assert!(executable.exists());

// On Windows, we can't snapshot an executable file.
#[cfg(not(windows))]
insta::with_settings!({
filters => context.filters(),
}, {
// Should run basic-app in the virtual environment
assert_snapshot!(fs_err::read_to_string(executable).unwrap(), @r#"
#![TEMP_DIR]/tools/basic-app/bin/python
# -*- coding: utf-8 -*-
import sys
from basic_app import main
if __name__ == "__main__":
if sys.argv[0].endswith("-script.pyw"):
sys.argv[0] = sys.argv[0][:-11]
elif sys.argv[0].endswith(".exe"):
sys.argv[0] = sys.argv[0][:-4]
sys.exit(main())
"#);
});

// Run the installed version with `--find-links` on the CLI again.
uv_snapshot!(context.filters(), context.tool_run()
.arg("--offline")
.arg("--find-links")
.arg(context.workspace_root.join("scripts/links/"))
.arg("basic-app")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
success: true
exit_code: 0
----- stdout -----
Hello from basic-app!

----- stderr -----
");

// Run the installed version without `--find-links`.
uv_snapshot!(context.filters(), context.tool_run()
.arg("--offline")
.arg("basic-app")
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r"
success: false
exit_code: 1
----- stdout -----

----- stderr -----
× No solution found when resolving tool dependencies:
╰─▶ Because only basic-app==0.1 is available and basic-app==0.1 needs to be downloaded from a registry, we can conclude that all versions of basic-app cannot be used.
And because you require basic-app, we can conclude that your requirements are unsatisfiable.

hint: Packages were unavailable because the network was disabled. When the network is disabled, registry packages may only be read from the cache.
");
}

#[test]
fn tool_install_python_platform() {
let context = TestContext::new("3.12")
Expand Down
Binary file added scripts/links/basic_app-0.1.0-py3-none-any.whl
Binary file not shown.
Loading