mirror of
https://github.com/ankitects/anki.git
synced 2025-11-07 21:27:14 -05:00
convert uv methods back to free fns
This commit is contained in:
parent
36a0e0dcc7
commit
73ac0a1cfc
4 changed files with 184 additions and 237 deletions
|
|
@ -26,7 +26,7 @@ pub fn init() -> Option<State> {
|
||||||
State::Normal(ref mut state) => state.check_versions(),
|
State::Normal(ref mut state) => state.check_versions(),
|
||||||
State::LaunchAnki(ref paths) => {
|
State::LaunchAnki(ref paths) => {
|
||||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||||
let cmd = paths.build_python_command(&args).unwrap();
|
let cmd = uv::build_python_command(paths, &args).unwrap();
|
||||||
uv::launch_anki_normally(cmd).unwrap();
|
uv::launch_anki_normally(cmd).unwrap();
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,7 @@ pub async fn choose_version<R: Runtime>(
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let warming_up = paths.post_install()?;
|
let warming_up = uv::post_install(&paths)?;
|
||||||
|
|
||||||
Ok(ChooseVersionResponse {
|
Ok(ChooseVersionResponse {
|
||||||
version,
|
version,
|
||||||
|
|
@ -210,7 +210,7 @@ pub async fn choose_version<R: Runtime>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn launch_anki<R: Runtime>(app: AppHandle<R>, _window: WebviewWindow<R>) -> Result<()> {
|
pub async fn launch_anki<R: Runtime>(app: AppHandle<R>, _window: WebviewWindow<R>) -> Result<()> {
|
||||||
app.state::<State>().paths()?.launch_anki()
|
app.state::<State>().paths().and_then(uv::launch_anki)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exit<R: Runtime>(app: AppHandle<R>, window: WebviewWindow<R>) -> Result<()> {
|
pub async fn exit<R: Runtime>(app: AppHandle<R>, window: WebviewWindow<R>) -> Result<()> {
|
||||||
|
|
|
||||||
|
|
@ -102,14 +102,14 @@ impl NormalState {
|
||||||
let (av_tx, av_rx) = tokio::sync::watch::channel(None);
|
let (av_tx, av_rx) = tokio::sync::watch::channel(None);
|
||||||
let paths = self.paths.clone();
|
let paths = self.paths.clone();
|
||||||
tauri::async_runtime::spawn_blocking(move || {
|
tauri::async_runtime::spawn_blocking(move || {
|
||||||
let res = paths.get_releases();
|
let res = uv::get_releases(&paths);
|
||||||
let _ = av_tx.send(Some(res));
|
let _ = av_tx.send(Some(res));
|
||||||
});
|
});
|
||||||
|
|
||||||
let (cv_tx, cv_rx) = tokio::sync::watch::channel(None);
|
let (cv_tx, cv_rx) = tokio::sync::watch::channel(None);
|
||||||
let paths = self.paths.clone();
|
let paths = self.paths.clone();
|
||||||
tauri::async_runtime::spawn_blocking(move || {
|
tauri::async_runtime::spawn_blocking(move || {
|
||||||
let res = paths.check_versions();
|
let res = uv::check_versions(&paths);
|
||||||
let _ = cv_tx.send(Some(res));
|
let _ = cv_tx.send(Some(res));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ use crate::platform::get_uv_binary_name;
|
||||||
pub use crate::platform::launch_anki_normally;
|
pub use crate::platform::launch_anki_normally;
|
||||||
use crate::platform::respawn_launcher;
|
use crate::platform::respawn_launcher;
|
||||||
use crate::state::ExistingVersions;
|
use crate::state::ExistingVersions;
|
||||||
|
use crate::state::State;
|
||||||
use crate::state::Version;
|
use crate::state::Version;
|
||||||
use crate::state::Versions;
|
use crate::state::Versions;
|
||||||
|
|
||||||
|
|
@ -60,6 +61,92 @@ pub enum VersionKind {
|
||||||
Uv(String),
|
Uv(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extract_aqt_version(state: &Paths) -> Option<String> {
|
||||||
|
// Check if .venv exists first
|
||||||
|
if !state.venv_folder.exists() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = uv_command(state)
|
||||||
|
.ok()?
|
||||||
|
.env("VIRTUAL_ENV", &state.venv_folder)
|
||||||
|
.args(["pip", "show", "aqt"])
|
||||||
|
.output();
|
||||||
|
|
||||||
|
let output = output.ok()?;
|
||||||
|
|
||||||
|
if !output.status.success() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stdout = String::from_utf8(output.stdout).ok()?;
|
||||||
|
for line in stdout.lines() {
|
||||||
|
if let Some(version) = line.strip_prefix("Version: ") {
|
||||||
|
return Some(version.trim().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_versions(state: &Paths) -> Result<ExistingVersions> {
|
||||||
|
let mut res = ExistingVersions {
|
||||||
|
pyproject_modified_by_user: state.pyproject_modified_by_user,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// If sync_complete_marker is missing, do nothing
|
||||||
|
if !state.sync_complete_marker.exists() {
|
||||||
|
return Ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine current version by invoking uv pip show aqt
|
||||||
|
match extract_aqt_version(state) {
|
||||||
|
Some(version) => {
|
||||||
|
res.current = Some(normalize_version(&version));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
Err(anyhow::anyhow!(
|
||||||
|
"Warning: Could not determine current Anki version"
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read previous version from "previous-version" file
|
||||||
|
let previous_version_path = state.uv_install_root.join("previous-version");
|
||||||
|
if let Ok(content) = read_file(&previous_version_path) {
|
||||||
|
if let Ok(version_str) = String::from_utf8(content) {
|
||||||
|
let version = version_str.trim().to_string();
|
||||||
|
if !version.is_empty() {
|
||||||
|
res.previous = Some(normalize_version(&version));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_allow_betas(state: &Paths, allow_betas: bool) -> Result<()> {
|
||||||
|
if allow_betas {
|
||||||
|
write_file(&state.prerelease_marker, "")?;
|
||||||
|
} else {
|
||||||
|
let _ = remove_file(&state.prerelease_marker);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_cache_enabled(state: &Paths, cache_enabled: bool) -> Result<()> {
|
||||||
|
if cache_enabled {
|
||||||
|
let _ = remove_file(&state.no_cache_marker);
|
||||||
|
} else {
|
||||||
|
write_file(&state.no_cache_marker, "")?;
|
||||||
|
// Delete the cache directory and everything in it
|
||||||
|
if state.uv_cache_dir.exists() {
|
||||||
|
let _ = anki_io::remove_dir_all(&state.uv_cache_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_version_install_or_update<F>(
|
pub fn handle_version_install_or_update<F>(
|
||||||
state: &Paths,
|
state: &Paths,
|
||||||
version: &str,
|
version: &str,
|
||||||
|
|
@ -239,25 +326,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_allow_betas(state: &Paths, allow_betas: bool) -> Result<()> {
|
fn write_sync_marker(state: &Paths) -> Result<()> {
|
||||||
if allow_betas {
|
let timestamp = SystemTime::now()
|
||||||
write_file(&state.prerelease_marker, "")?;
|
.duration_since(UNIX_EPOCH)
|
||||||
} else {
|
.context("Failed to get system time")?
|
||||||
let _ = remove_file(&state.prerelease_marker);
|
.as_secs();
|
||||||
}
|
write_file(&state.sync_complete_marker, timestamp.to_string())?;
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_cache_enabled(state: &Paths, cache_enabled: bool) -> Result<()> {
|
|
||||||
if cache_enabled {
|
|
||||||
let _ = remove_file(&state.no_cache_marker);
|
|
||||||
} else {
|
|
||||||
write_file(&state.no_cache_marker, "")?;
|
|
||||||
// Delete the cache directory and everything in it
|
|
||||||
if state.uv_cache_dir.exists() {
|
|
||||||
let _ = anki_io::remove_dir_all(&state.uv_cache_dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +450,46 @@ fn filter_and_normalize_versions1(all_versions: Vec<String>) -> Vec<Version> {
|
||||||
valid_versions
|
valid_versions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fetch_versions(state: &Paths) -> Result<Vec<String>> {
|
||||||
|
let versions_script = state.resources_dir.join("versions.py");
|
||||||
|
|
||||||
|
let mut cmd = uv_command(state)?;
|
||||||
|
cmd.args(["run", "--no-project", "--no-config", "--managed-python"])
|
||||||
|
.args(["--with", "pip-system-certs,requests[socks]"]);
|
||||||
|
|
||||||
|
let python_version = read_file(&state.dist_python_version_path)?;
|
||||||
|
let python_version_str =
|
||||||
|
String::from_utf8(python_version).context("Invalid UTF-8 in .python-version")?;
|
||||||
|
let version_trimmed = python_version_str.trim();
|
||||||
|
if !version_trimmed.is_empty() {
|
||||||
|
cmd.args(["--python", version_trimmed]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.arg(&versions_script);
|
||||||
|
|
||||||
|
let output = match cmd.utf8_output() {
|
||||||
|
Ok(output) => output,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e.into());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let versions = serde_json::from_str(&output.stdout).context("Failed to parse versions JSON")?;
|
||||||
|
Ok(versions)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_releases(state: &Paths) -> Result<Versions> {
|
||||||
|
let all_versions = fetch_versions(state)?;
|
||||||
|
let all_versions = filter_and_normalize_versions1(all_versions);
|
||||||
|
|
||||||
|
let latest_patches = with_only_latest_patch(&all_versions);
|
||||||
|
let latest_releases: Vec<Version> = latest_patches.into_iter().take(5).collect();
|
||||||
|
|
||||||
|
Ok(Versions {
|
||||||
|
latest: latest_releases,
|
||||||
|
all: all_versions,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn apply_version_kind(version_kind: &VersionKind, state: &Paths) -> Result<()> {
|
pub fn apply_version_kind(version_kind: &VersionKind, state: &Paths) -> Result<()> {
|
||||||
let content = read_file(&state.dist_pyproject_path)?;
|
let content = read_file(&state.dist_pyproject_path)?;
|
||||||
let content_str = String::from_utf8(content).context("Invalid UTF-8 in pyproject.toml")?;
|
let content_str = String::from_utf8(content).context("Invalid UTF-8 in pyproject.toml")?;
|
||||||
|
|
@ -666,8 +780,53 @@ pub fn set_mirror(state: &Paths, enabled: bool) -> Result<()> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
pub fn post_install(state: &Paths) -> Result<bool> {
|
||||||
|
// Write marker file to indicate we've completed the sync process
|
||||||
|
write_sync_marker(state)?;
|
||||||
|
|
||||||
impl crate::state::State {
|
// whether or not anki needs to warm up
|
||||||
|
Ok(cfg!(target_os = "macos"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn launch_anki(_state: &Paths) -> Result<()> {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
let cmd = self.build_python_command(&[])?;
|
||||||
|
platform::mac::prepare_for_launch_after_update(cmd, &_state.uv_install_root)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// respawn the launcher as a disconnected subprocess for normal startup
|
||||||
|
respawn_launcher()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_python_command(state: &Paths, args: &[String]) -> Result<Command> {
|
||||||
|
let python_exe = if cfg!(target_os = "windows") {
|
||||||
|
let show_console = std::env::var("ANKI_CONSOLE").is_ok();
|
||||||
|
if show_console {
|
||||||
|
state.venv_folder.join("Scripts/python.exe")
|
||||||
|
} else {
|
||||||
|
state.venv_folder.join("Scripts/pythonw.exe")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.venv_folder.join("bin/python")
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cmd = Command::new(&python_exe);
|
||||||
|
cmd.args(["-c", "import aqt, sys; sys.argv[0] = 'Anki'; aqt.run()"]);
|
||||||
|
cmd.args(args);
|
||||||
|
// tell the Python code it was invoked by the launcher, and updating is
|
||||||
|
// available
|
||||||
|
cmd.env("ANKI_LAUNCHER", std::env::current_exe()?.utf8()?.as_str());
|
||||||
|
|
||||||
|
// Set UV and Python paths for the Python code
|
||||||
|
cmd.env("ANKI_LAUNCHER_UV", state.uv_path.utf8()?.as_str());
|
||||||
|
cmd.env("UV_PROJECT", state.uv_install_root.utf8()?.as_str());
|
||||||
|
cmd.env_remove("SSLKEYLOGFILE");
|
||||||
|
|
||||||
|
Ok(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
pub fn init() -> Result<Self> {
|
pub fn init() -> Result<Self> {
|
||||||
let uv_install_root = if let Ok(custom_root) = std::env::var("ANKI_LAUNCHER_VENV_ROOT") {
|
let uv_install_root = if let Ok(custom_root) = std::env::var("ANKI_LAUNCHER_VENV_ROOT") {
|
||||||
std::path::PathBuf::from(custom_root)
|
std::path::PathBuf::from(custom_root)
|
||||||
|
|
@ -742,218 +901,6 @@ impl crate::state::State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Paths {
|
|
||||||
fn get_mirror_urls(&self) -> Result<Option<(String, String)>> {
|
|
||||||
if !self.mirror_path.exists() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = read_file(&self.mirror_path)?;
|
|
||||||
let content_str = String::from_utf8(content).context("Invalid UTF-8 in mirror file")?;
|
|
||||||
|
|
||||||
let lines: Vec<&str> = content_str.lines().collect();
|
|
||||||
if lines.len() >= 2 {
|
|
||||||
Ok(Some((
|
|
||||||
lines[0].trim().to_string(),
|
|
||||||
lines[1].trim().to_string(),
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn uv_command(&self) -> Result<Command> {
|
|
||||||
let mut command = Command::new(&self.uv_path);
|
|
||||||
command.current_dir(&self.uv_install_root);
|
|
||||||
|
|
||||||
// remove UV_* environment variables to avoid interference
|
|
||||||
for (key, _) in std::env::vars() {
|
|
||||||
if key.starts_with("UV_") {
|
|
||||||
command.env_remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
command
|
|
||||||
.env_remove("VIRTUAL_ENV")
|
|
||||||
.env_remove("SSLKEYLOGFILE");
|
|
||||||
|
|
||||||
// Add mirror environment variable if enabled
|
|
||||||
if let Some((python_mirror, pypi_mirror)) = self.get_mirror_urls()? {
|
|
||||||
command
|
|
||||||
.env("UV_PYTHON_INSTALL_MIRROR", &python_mirror)
|
|
||||||
.env("UV_DEFAULT_INDEX", &pypi_mirror);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
use std::os::windows::process::CommandExt;
|
|
||||||
|
|
||||||
command.creation_flags(windows::Win32::System::Threading::CREATE_NO_WINDOW.0);
|
|
||||||
}
|
|
||||||
Ok(command)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fetch_versions(&self) -> Result<Vec<String>> {
|
|
||||||
let versions_script = self.resources_dir.join("versions.py");
|
|
||||||
|
|
||||||
let mut cmd = self.uv_command()?;
|
|
||||||
cmd.args(["run", "--no-project", "--no-config", "--managed-python"])
|
|
||||||
.args(["--with", "pip-system-certs,requests[socks]"]);
|
|
||||||
|
|
||||||
let python_version = read_file(&self.dist_python_version_path)?;
|
|
||||||
let python_version_str =
|
|
||||||
String::from_utf8(python_version).context("Invalid UTF-8 in .python-version")?;
|
|
||||||
let version_trimmed = python_version_str.trim();
|
|
||||||
if !version_trimmed.is_empty() {
|
|
||||||
cmd.args(["--python", version_trimmed]);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.arg(&versions_script);
|
|
||||||
|
|
||||||
let output = match cmd.utf8_output() {
|
|
||||||
Ok(output) => output,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let versions =
|
|
||||||
serde_json::from_str(&output.stdout).context("Failed to parse versions JSON")?;
|
|
||||||
Ok(versions)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_releases(&self) -> Result<Versions> {
|
|
||||||
let all_versions = self.fetch_versions()?;
|
|
||||||
let all_versions = filter_and_normalize_versions1(all_versions);
|
|
||||||
|
|
||||||
let latest_patches = with_only_latest_patch(&all_versions);
|
|
||||||
let latest_releases: Vec<Version> = latest_patches.into_iter().take(5).collect();
|
|
||||||
|
|
||||||
Ok(Versions {
|
|
||||||
latest: latest_releases,
|
|
||||||
all: all_versions,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_aqt_version(&self) -> Option<String> {
|
|
||||||
// Check if .venv exists first
|
|
||||||
if !self.venv_folder.exists() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let output = self
|
|
||||||
.uv_command()
|
|
||||||
.ok()?
|
|
||||||
.env("VIRTUAL_ENV", &self.venv_folder)
|
|
||||||
.args(["pip", "show", "aqt"])
|
|
||||||
.output();
|
|
||||||
|
|
||||||
let output = output.ok()?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let stdout = String::from_utf8(output.stdout).ok()?;
|
|
||||||
for line in stdout.lines() {
|
|
||||||
if let Some(version) = line.strip_prefix("Version: ") {
|
|
||||||
return Some(version.trim().to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_versions(&self) -> Result<ExistingVersions> {
|
|
||||||
let mut res = ExistingVersions {
|
|
||||||
pyproject_modified_by_user: self.pyproject_modified_by_user,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// If sync_complete_marker is missing, do nothing
|
|
||||||
if !self.sync_complete_marker.exists() {
|
|
||||||
return Ok(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine current version by invoking uv pip show aqt
|
|
||||||
match self.extract_aqt_version() {
|
|
||||||
Some(version) => {
|
|
||||||
res.current = Some(normalize_version(&version));
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
Err(anyhow::anyhow!(
|
|
||||||
"Warning: Could not determine current Anki version"
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read previous version from "previous-version" file
|
|
||||||
let previous_version_path = self.uv_install_root.join("previous-version");
|
|
||||||
if let Ok(content) = read_file(&previous_version_path) {
|
|
||||||
if let Ok(version_str) = String::from_utf8(content) {
|
|
||||||
let version = version_str.trim().to_string();
|
|
||||||
if !version.is_empty() {
|
|
||||||
res.previous = Some(normalize_version(&version));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_sync_marker(&self) -> Result<()> {
|
|
||||||
let timestamp = SystemTime::now()
|
|
||||||
.duration_since(UNIX_EPOCH)
|
|
||||||
.context("Failed to get system time")?
|
|
||||||
.as_secs();
|
|
||||||
write_file(&self.sync_complete_marker, timestamp.to_string())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post_install(&self) -> Result<bool> {
|
|
||||||
// Write marker file to indicate we've completed the sync process
|
|
||||||
self.write_sync_marker()?;
|
|
||||||
|
|
||||||
// whether or not anki needs to warm up
|
|
||||||
Ok(cfg!(target_os = "macos"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn launch_anki(&self) -> Result<()> {
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
let cmd = self.build_python_command(&[])?;
|
|
||||||
platform::mac::prepare_for_launch_after_update(cmd, &self.uv_install_root)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// respawn the launcher as a disconnected subprocess for normal startup
|
|
||||||
respawn_launcher()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build_python_command(&self, args: &[String]) -> Result<Command> {
|
|
||||||
let python_exe = if cfg!(target_os = "windows") {
|
|
||||||
let show_console = std::env::var("ANKI_CONSOLE").is_ok();
|
|
||||||
if show_console {
|
|
||||||
self.venv_folder.join("Scripts/python.exe")
|
|
||||||
} else {
|
|
||||||
self.venv_folder.join("Scripts/pythonw.exe")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.venv_folder.join("bin/python")
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cmd = Command::new(&python_exe);
|
|
||||||
cmd.args(["-c", "import aqt, sys; sys.argv[0] = 'Anki'; aqt.run()"]);
|
|
||||||
cmd.args(args);
|
|
||||||
// tell the Python code it was invoked by the launcher, and updating is
|
|
||||||
// available
|
|
||||||
cmd.env("ANKI_LAUNCHER", std::env::current_exe()?.utf8()?.as_str());
|
|
||||||
|
|
||||||
// Set UV and Python paths for the Python code
|
|
||||||
cmd.env("ANKI_LAUNCHER_UV", self.uv_path.utf8()?.as_str());
|
|
||||||
cmd.env("UV_PROJECT", self.uv_install_root.utf8()?.as_str());
|
|
||||||
cmd.env_remove("SSLKEYLOGFILE");
|
|
||||||
|
|
||||||
Ok(cmd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue