mirror of https://github.com/astral-sh/uv
Add a version backwards incompatibility scheme for the JSON Python download list
If the JSON does not deserialize, check to see if any key is named "version" and print a different error message hinting at upgrading uv. The intention is that we will add this field on backwards-incompatible changes (and set it to an integer or string or something else that does not deserialize into a JsonPythonDownload).
This commit is contained in:
parent
ecebc914a6
commit
25dd584a27
|
|
@ -98,8 +98,10 @@ pub enum Error {
|
||||||
Mirror(&'static str, &'static str),
|
Mirror(&'static str, &'static str),
|
||||||
#[error("Failed to determine the libc used on the current platform")]
|
#[error("Failed to determine the libc used on the current platform")]
|
||||||
LibcDetection(#[from] LibcDetectionError),
|
LibcDetection(#[from] LibcDetectionError),
|
||||||
#[error("The JSON of the python downloads is invalid: {0}")]
|
#[error("Unable to parse the JSON Python download list at {0}")]
|
||||||
InvalidPythonDownloadsJSON(String, #[source] serde_json::Error),
|
InvalidPythonDownloadsJSON(String, #[source] serde_json::Error),
|
||||||
|
#[error("This version of uv is too old to support the JSON Python download list at {0}")]
|
||||||
|
UnsupportedPythonDownloadsJSON(String),
|
||||||
#[error("An offline Python installation was requested, but {file} (from {url}) is missing in {}", python_builds_dir.user_display())]
|
#[error("An offline Python installation was requested, but {file} (from {url}) is missing in {}", python_builds_dir.user_display())]
|
||||||
OfflinePythonMissing {
|
OfflinePythonMissing {
|
||||||
file: Box<PythonInstallationKey>,
|
file: Box<PythonInstallationKey>,
|
||||||
|
|
@ -701,16 +703,30 @@ impl ManagedPythonDownloadList {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let json_downloads: HashMap<String, JsonPythonDownload> = serde_json::from_slice(&buf)
|
let json_downloads: HashMap<String, JsonPythonDownload> = serde_json::from_slice(&buf)
|
||||||
.map_err(|e| {
|
.map_err(
|
||||||
Error::InvalidPythonDownloadsJSON(
|
// As an explicit compatibility mechanism, if there's a top-level "version" key, it
|
||||||
match json_source {
|
// means it's a newer format than we know how to deal with. Before reporting a
|
||||||
|
// parse error about the format of JsonPythonDownload, check for that key. We can do
|
||||||
|
// this by parsing into a Map<String, IgnoredAny> which allows any valid JSON on the
|
||||||
|
// value side. (Because it's zero-sized, Clippy suggests Set<String>, but that won't
|
||||||
|
// have the same parsing effect.)
|
||||||
|
#[allow(clippy::zero_sized_map_values)]
|
||||||
|
|e| {
|
||||||
|
let source = match json_source {
|
||||||
Source::BuiltIn => "EMBEDDED IN THE BINARY".to_owned(),
|
Source::BuiltIn => "EMBEDDED IN THE BINARY".to_owned(),
|
||||||
Source::Path(path) => path.to_string_lossy().to_string(),
|
Source::Path(path) => path.to_string_lossy().to_string(),
|
||||||
Source::Http(url) => url.to_string(),
|
Source::Http(url) => url.to_string(),
|
||||||
},
|
};
|
||||||
e,
|
if let Ok(keys) =
|
||||||
)
|
serde_json::from_slice::<HashMap<String, serde::de::IgnoredAny>>(&buf)
|
||||||
})?;
|
&& keys.contains_key("version")
|
||||||
|
{
|
||||||
|
Error::UnsupportedPythonDownloadsJSON(source)
|
||||||
|
} else {
|
||||||
|
Error::InvalidPythonDownloadsJSON(source, e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
let result = parse_json_downloads(json_downloads);
|
let result = parse_json_downloads(json_downloads);
|
||||||
Ok(Self { downloads: result })
|
Ok(Self { downloads: result })
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue