mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Avoid UV_PRERELEASE=allow
It had some downsides: - the lockfile was discarded when switching between beta/non-beta - it could result in beta versions of transitory dependencies By adding 'anki' and 'aqt' as first-party packages with explicit version numbers (validated by the version list we get from PyPi), we can allow them to be installed without breaking other deps. https://forums.ankiweb.net/t/bundling-numpy-in-an-add-on/62669/15
This commit is contained in:
parent
1098d9ac2a
commit
1ad82ea8b5
1 changed files with 76 additions and 75 deletions
|
@ -56,6 +56,12 @@ pub enum VersionKind {
|
||||||
Uv(String),
|
Uv(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Releases {
|
||||||
|
pub latest: Vec<String>,
|
||||||
|
pub all: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MainMenuChoice {
|
pub enum MainMenuChoice {
|
||||||
Latest,
|
Latest,
|
||||||
|
@ -230,13 +236,7 @@ fn check_versions(state: &mut State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_version_install_or_update(state: &State, choice: MainMenuChoice) -> Result<()> {
|
fn handle_version_install_or_update(state: &State, choice: MainMenuChoice) -> Result<()> {
|
||||||
update_pyproject_for_version(
|
update_pyproject_for_version(choice.clone(), state)?;
|
||||||
choice.clone(),
|
|
||||||
state.dist_pyproject_path.clone(),
|
|
||||||
state.user_pyproject_path.clone(),
|
|
||||||
state.dist_python_version_path.clone(),
|
|
||||||
state.user_python_version_path.clone(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Extract current version before syncing (but don't write to file yet)
|
// Extract current version before syncing (but don't write to file yet)
|
||||||
let previous_version_to_save = extract_aqt_version(&state.uv_path, &state.uv_install_root);
|
let previous_version_to_save = extract_aqt_version(&state.uv_path, &state.uv_install_root);
|
||||||
|
@ -284,11 +284,6 @@ fn handle_version_install_or_update(state: &State, choice: MainMenuChoice) -> Re
|
||||||
command.args(["--python", version]);
|
command.args(["--python", version]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set UV_PRERELEASE=allow if beta mode is enabled
|
|
||||||
if state.prerelease_marker.exists() {
|
|
||||||
command.env("UV_PRERELEASE", "allow");
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.no_cache_marker.exists() {
|
if state.no_cache_marker.exists() {
|
||||||
command.env("UV_NO_CACHE", "1");
|
command.env("UV_NO_CACHE", "1");
|
||||||
}
|
}
|
||||||
|
@ -387,7 +382,7 @@ fn write_sync_marker(sync_complete_marker: &std::path::Path) -> Result<()> {
|
||||||
|
|
||||||
fn get_main_menu_choice(state: &State) -> Result<MainMenuChoice> {
|
fn get_main_menu_choice(state: &State) -> Result<MainMenuChoice> {
|
||||||
loop {
|
loop {
|
||||||
println!("1) Latest Anki (just press Enter)");
|
println!("1) Latest Anki (press Enter)");
|
||||||
println!("2) Choose a version");
|
println!("2) Choose a version");
|
||||||
if let Some(current_version) = &state.current_version {
|
if let Some(current_version) = &state.current_version {
|
||||||
let normalized_current = normalize_version(current_version);
|
let normalized_current = normalize_version(current_version);
|
||||||
|
@ -465,13 +460,9 @@ fn get_main_menu_choice(state: &State) -> Result<MainMenuChoice> {
|
||||||
fn get_version_kind(state: &State) -> Result<Option<VersionKind>> {
|
fn get_version_kind(state: &State) -> Result<Option<VersionKind>> {
|
||||||
println!("Please wait...");
|
println!("Please wait...");
|
||||||
|
|
||||||
let include_prereleases = state.prerelease_marker.exists();
|
let releases = get_releases(state)?;
|
||||||
let all_versions = fetch_versions(state)?;
|
let releases_str = releases
|
||||||
let all_versions = filter_and_normalize_versions(all_versions, include_prereleases);
|
.latest
|
||||||
|
|
||||||
let latest_patches = with_only_latest_patch(&all_versions);
|
|
||||||
let latest_releases: Vec<&String> = latest_patches.iter().take(5).collect();
|
|
||||||
let releases_str = latest_releases
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v.as_str())
|
.map(|v| v.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
@ -494,7 +485,7 @@ fn get_version_kind(state: &State) -> Result<Option<VersionKind>> {
|
||||||
let normalized_input = normalize_version(input);
|
let normalized_input = normalize_version(input);
|
||||||
|
|
||||||
// Check if the version exists in the available versions
|
// Check if the version exists in the available versions
|
||||||
let version_exists = all_versions.iter().any(|v| v == &normalized_input);
|
let version_exists = releases.all.iter().any(|v| v == &normalized_input);
|
||||||
|
|
||||||
match (parse_version_kind(input), version_exists) {
|
match (parse_version_kind(input), version_exists) {
|
||||||
(Some(version_kind), true) => {
|
(Some(version_kind), true) => {
|
||||||
|
@ -502,7 +493,7 @@ fn get_version_kind(state: &State) -> Result<Option<VersionKind>> {
|
||||||
Ok(Some(version_kind))
|
Ok(Some(version_kind))
|
||||||
}
|
}
|
||||||
(None, true) => {
|
(None, true) => {
|
||||||
println!("Versions before 2.1.50 can't be installedn");
|
println!("Versions before 2.1.50 can't be installed.");
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -635,37 +626,23 @@ fn fetch_versions(state: &State) -> Result<Vec<String>> {
|
||||||
Ok(versions)
|
Ok(versions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pyproject_for_version(
|
fn get_releases(state: &State) -> Result<Releases> {
|
||||||
menu_choice: MainMenuChoice,
|
let include_prereleases = state.prerelease_marker.exists();
|
||||||
dist_pyproject_path: std::path::PathBuf,
|
let all_versions = fetch_versions(state)?;
|
||||||
user_pyproject_path: std::path::PathBuf,
|
let all_versions = filter_and_normalize_versions(all_versions, include_prereleases);
|
||||||
dist_python_version_path: std::path::PathBuf,
|
|
||||||
user_python_version_path: std::path::PathBuf,
|
let latest_patches = with_only_latest_patch(&all_versions);
|
||||||
) -> Result<()> {
|
let latest_releases: Vec<String> = latest_patches.into_iter().take(5).collect();
|
||||||
match menu_choice {
|
Ok(Releases {
|
||||||
MainMenuChoice::Latest => {
|
latest: latest_releases,
|
||||||
let content = read_file(&dist_pyproject_path)?;
|
all: all_versions,
|
||||||
write_file(&user_pyproject_path, &content)?;
|
})
|
||||||
let python_version_content = read_file(&dist_python_version_path)?;
|
|
||||||
write_file(&user_python_version_path, &python_version_content)?;
|
|
||||||
}
|
}
|
||||||
MainMenuChoice::KeepExisting => {
|
|
||||||
// Do nothing - keep existing pyproject.toml and .python-version
|
fn apply_version_kind(version_kind: &VersionKind, state: &State) -> Result<()> {
|
||||||
}
|
let content = read_file(&state.dist_pyproject_path)?;
|
||||||
MainMenuChoice::ToggleBetas => {
|
let content_str = String::from_utf8(content).context("Invalid UTF-8 in pyproject.toml")?;
|
||||||
unreachable!();
|
let updated_content = match version_kind {
|
||||||
}
|
|
||||||
MainMenuChoice::ToggleCache => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
MainMenuChoice::Uninstall => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
MainMenuChoice::Version(version_kind) => {
|
|
||||||
let content = read_file(&dist_pyproject_path)?;
|
|
||||||
let content_str =
|
|
||||||
String::from_utf8(content).context("Invalid UTF-8 in pyproject.toml")?;
|
|
||||||
let updated_content = match &version_kind {
|
|
||||||
VersionKind::PyOxidizer(version) => {
|
VersionKind::PyOxidizer(version) => {
|
||||||
// Replace package name and add PyQt6 dependencies
|
// Replace package name and add PyQt6 dependencies
|
||||||
content_str.replace(
|
content_str.replace(
|
||||||
|
@ -684,21 +661,50 @@ fn update_pyproject_for_version(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
VersionKind::Uv(version) => {
|
VersionKind::Uv(version) => content_str.replace(
|
||||||
content_str.replace("anki-release", &format!("anki-release=={version}"))
|
"anki-release",
|
||||||
}
|
&format!("anki-release=={version}\",\n \"anki=={version}\",\n \"aqt=={version}"),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
write_file(&user_pyproject_path, &updated_content)?;
|
write_file(&state.user_pyproject_path, &updated_content)?;
|
||||||
|
|
||||||
// Update .python-version based on version kind
|
// Update .python-version based on version kind
|
||||||
match &version_kind {
|
match version_kind {
|
||||||
VersionKind::PyOxidizer(_) => {
|
VersionKind::PyOxidizer(_) => {
|
||||||
write_file(&user_python_version_path, "3.9")?;
|
write_file(&state.user_python_version_path, "3.9")?;
|
||||||
}
|
}
|
||||||
VersionKind::Uv(_) => {
|
VersionKind::Uv(_) => {
|
||||||
copy_file(&dist_python_version_path, &user_python_version_path)?;
|
copy_file(
|
||||||
|
&state.dist_python_version_path,
|
||||||
|
&state.user_python_version_path,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_pyproject_for_version(menu_choice: MainMenuChoice, state: &State) -> Result<()> {
|
||||||
|
match menu_choice {
|
||||||
|
MainMenuChoice::Latest => {
|
||||||
|
// Get the latest release version and create a VersionKind for it
|
||||||
|
let releases = get_releases(state)?;
|
||||||
|
let latest_version = releases.latest.first().context("No latest version found")?;
|
||||||
|
apply_version_kind(&VersionKind::Uv(latest_version.clone()), state)?;
|
||||||
|
}
|
||||||
|
MainMenuChoice::KeepExisting => {
|
||||||
|
// Do nothing - keep existing pyproject.toml and .python-version
|
||||||
|
}
|
||||||
|
MainMenuChoice::ToggleBetas => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
MainMenuChoice::ToggleCache => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
MainMenuChoice::Uninstall => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
MainMenuChoice::Version(version_kind) => {
|
||||||
|
apply_version_kind(&version_kind, state)?;
|
||||||
}
|
}
|
||||||
MainMenuChoice::Quit => {
|
MainMenuChoice::Quit => {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
|
@ -875,11 +881,6 @@ fn build_python_command(state: &State, args: &[String]) -> Result<Command> {
|
||||||
cmd.env("ANKI_LAUNCHER_UV", state.uv_path.utf8()?.as_str());
|
cmd.env("ANKI_LAUNCHER_UV", state.uv_path.utf8()?.as_str());
|
||||||
cmd.env("UV_PROJECT", state.uv_install_root.utf8()?.as_str());
|
cmd.env("UV_PROJECT", state.uv_install_root.utf8()?.as_str());
|
||||||
|
|
||||||
// Set UV_PRERELEASE=allow if beta mode is enabled
|
|
||||||
if state.prerelease_marker.exists() {
|
|
||||||
cmd.env("UV_PRERELEASE", "allow");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(cmd)
|
Ok(cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue