mirror of https://github.com/astral-sh/uv
Ignore origin when comparing installed tools (#16055)
## Summary This field gets dropped when you serialize and deserialize, so we should ignore it when comparing indexes. Closes https://github.com/astral-sh/uv/issues/16051.
This commit is contained in:
parent
fd908aa439
commit
170ab1cd7f
|
|
@ -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))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct Index {
|
pub struct Index {
|
||||||
|
|
@ -156,6 +156,92 @@ pub struct Index {
|
||||||
pub cache_control: Option<IndexCacheControl>,
|
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(
|
#[derive(
|
||||||
Default,
|
Default,
|
||||||
Debug,
|
Debug,
|
||||||
|
|
|
||||||
|
|
@ -3906,7 +3906,6 @@ fn tool_install_default_credentials() -> Result<()> {
|
||||||
sys.argv[0] = sys.argv[0][:-4]
|
sys.argv[0] = sys.argv[0][:-4]
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
insta::with_settings!({
|
insta::with_settings!({
|
||||||
|
|
@ -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]
|
#[test]
|
||||||
fn tool_install_python_platform() {
|
fn tool_install_python_platform() {
|
||||||
let context = TestContext::new("3.12")
|
let context = TestContext::new("3.12")
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue