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))]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Index {
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -3906,7 +3906,6 @@ fn tool_install_default_credentials() -> Result<()> {
|
|||
sys.argv[0] = sys.argv[0][:-4]
|
||||
sys.exit(main())
|
||||
"###);
|
||||
|
||||
});
|
||||
|
||||
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]
|
||||
fn tool_install_python_platform() {
|
||||
let context = TestContext::new("3.12")
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue