mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Merge branch 'main' into issue-4276
This commit is contained in:
commit
43832e18e2
6 changed files with 113 additions and 63 deletions
|
@ -1,10 +1,5 @@
|
|||
adding-add-shortcut-ctrlandenter = Add (shortcut: ctrl+enter)
|
||||
adding-added = Added
|
||||
adding-added-cards =
|
||||
Added { $count ->
|
||||
[one] { $count } card
|
||||
*[other] { $count } cards
|
||||
}
|
||||
adding-discard-current-input = Discard current input?
|
||||
adding-keep-editing = Keep Editing
|
||||
adding-edit = Edit "{ $val }"
|
||||
|
|
|
@ -300,7 +300,7 @@ class AddCards(QMainWindow):
|
|||
|
||||
self.addHistory(note)
|
||||
|
||||
tooltip(tr.adding_added_cards(count=changes.count), period=500)
|
||||
tooltip(tr.importing_cards_added(count=changes.count), period=500)
|
||||
av_player.stop_and_clear_queue()
|
||||
self._load_new_note(sticky_fields_from=note)
|
||||
gui_hooks.add_cards_did_add_note(note)
|
||||
|
|
|
@ -30,6 +30,12 @@ lipo -create \
|
|||
-output "$APP_LAUNCHER/Contents/MacOS/launcher"
|
||||
cp "$OUTPUT_DIR/uv" "$APP_LAUNCHER/Contents/MacOS/"
|
||||
|
||||
# Build install_name_tool stub
|
||||
clang -arch arm64 -o "$OUTPUT_DIR/stub_arm64" stub.c
|
||||
clang -arch x86_64 -o "$OUTPUT_DIR/stub_x86_64" stub.c
|
||||
lipo -create "$OUTPUT_DIR/stub_arm64" "$OUTPUT_DIR/stub_x86_64" -output "$APP_LAUNCHER/Contents/MacOS/install_name_tool"
|
||||
rm "$OUTPUT_DIR/stub_arm64" "$OUTPUT_DIR/stub_x86_64"
|
||||
|
||||
# Copy support files
|
||||
ANKI_VERSION=$(cat ../../../.version | tr -d '\n')
|
||||
sed "s/ANKI_VERSION/$ANKI_VERSION/g" Info.plist > "$APP_LAUNCHER/Contents/Info.plist"
|
||||
|
@ -40,7 +46,7 @@ cp ../versions.py "$APP_LAUNCHER/Contents/Resources/"
|
|||
|
||||
# Codesign/bundle
|
||||
if [ -z "$NODMG" ]; then
|
||||
for i in "$APP_LAUNCHER/Contents/MacOS/uv" "$APP_LAUNCHER/Contents/MacOS/launcher" "$APP_LAUNCHER"; do
|
||||
for i in "$APP_LAUNCHER/Contents/MacOS/uv" "$APP_LAUNCHER/Contents/MacOS/install_name_tool" "$APP_LAUNCHER/Contents/MacOS/launcher" "$APP_LAUNCHER"; do
|
||||
codesign --force -vvvv -o runtime -s "Developer ID Application:" \
|
||||
--entitlements entitlements.python.xml \
|
||||
"$i"
|
||||
|
|
6
qt/launcher/mac/stub.c
Normal file
6
qt/launcher/mac/stub.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}
|
|
@ -51,6 +51,8 @@ struct State {
|
|||
previous_version: Option<String>,
|
||||
resources_dir: std::path::PathBuf,
|
||||
venv_folder: std::path::PathBuf,
|
||||
/// system Python + PyQt6 library mode
|
||||
system_qt: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -88,9 +90,13 @@ fn main() {
|
|||
}
|
||||
|
||||
fn run() -> Result<()> {
|
||||
let uv_install_root = dirs::data_local_dir()
|
||||
.context("Unable to determine data_dir")?
|
||||
.join("AnkiProgramFiles");
|
||||
let uv_install_root = if let Ok(custom_root) = std::env::var("ANKI_LAUNCHER_VENV_ROOT") {
|
||||
std::path::PathBuf::from(custom_root)
|
||||
} else {
|
||||
dirs::data_local_dir()
|
||||
.context("Unable to determine data_dir")?
|
||||
.join("AnkiProgramFiles")
|
||||
};
|
||||
|
||||
let (exe_dir, resources_dir) = get_exe_and_resources_dirs()?;
|
||||
|
||||
|
@ -113,6 +119,8 @@ fn run() -> Result<()> {
|
|||
mirror_path: uv_install_root.join("mirror"),
|
||||
pyproject_modified_by_user: false, // calculated later
|
||||
previous_version: None,
|
||||
system_qt: (cfg!(unix) && !cfg!(target_os = "macos"))
|
||||
&& resources_dir.join("system_qt").exists(),
|
||||
resources_dir,
|
||||
venv_folder: uv_install_root.join(".venv"),
|
||||
};
|
||||
|
@ -193,8 +201,8 @@ fn extract_aqt_version(state: &State) -> Option<String> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let output = Command::new(&state.uv_path)
|
||||
.current_dir(&state.uv_install_root)
|
||||
let output = uv_command(state)
|
||||
.ok()?
|
||||
.env("VIRTUAL_ENV", &state.venv_folder)
|
||||
.args(["pip", "show", "aqt"])
|
||||
.output()
|
||||
|
@ -261,34 +269,45 @@ fn handle_version_install_or_update(state: &State, choice: MainMenuChoice) -> Re
|
|||
None
|
||||
};
|
||||
|
||||
let have_venv = state.venv_folder.exists();
|
||||
if cfg!(target_os = "macos") && !have_developer_tools() && !have_venv {
|
||||
println!("If you see a pop-up about 'install_name_tool', you can cancel it, and ignore the warning below.\n");
|
||||
}
|
||||
|
||||
// Prepare to sync the venv
|
||||
let mut command = Command::new(&state.uv_path);
|
||||
command.current_dir(&state.uv_install_root);
|
||||
let mut command = uv_command(state)?;
|
||||
|
||||
// remove UV_* environment variables to avoid interference
|
||||
for (key, _) in std::env::vars() {
|
||||
if key.starts_with("UV_") || key == "VIRTUAL_ENV" {
|
||||
command.env_remove(key);
|
||||
if cfg!(target_os = "macos") {
|
||||
// remove CONDA_PREFIX/bin from PATH to avoid conda interference
|
||||
if let Ok(conda_prefix) = std::env::var("CONDA_PREFIX") {
|
||||
if let Ok(current_path) = std::env::var("PATH") {
|
||||
let conda_bin = format!("{conda_prefix}/bin");
|
||||
let filtered_paths: Vec<&str> = current_path
|
||||
.split(':')
|
||||
.filter(|&path| path != conda_bin)
|
||||
.collect();
|
||||
let new_path = filtered_paths.join(":");
|
||||
command.env("PATH", new_path);
|
||||
}
|
||||
}
|
||||
// put our fake install_name_tool at the top of the path to override
|
||||
// potential conflicts
|
||||
if let Ok(current_path) = std::env::var("PATH") {
|
||||
let exe_dir = std::env::current_exe()
|
||||
.ok()
|
||||
.and_then(|exe| exe.parent().map(|p| p.to_path_buf()));
|
||||
if let Some(exe_dir) = exe_dir {
|
||||
let new_path = format!("{}:{}", exe_dir.display(), current_path);
|
||||
command.env("PATH", new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove CONDA_PREFIX/bin from PATH to avoid conda interference
|
||||
#[cfg(target_os = "macos")]
|
||||
if let Ok(conda_prefix) = std::env::var("CONDA_PREFIX") {
|
||||
if let Ok(current_path) = std::env::var("PATH") {
|
||||
let conda_bin = format!("{conda_prefix}/bin");
|
||||
let filtered_paths: Vec<&str> = current_path
|
||||
.split(':')
|
||||
.filter(|&path| path != conda_bin)
|
||||
.collect();
|
||||
let new_path = filtered_paths.join(":");
|
||||
command.env("PATH", new_path);
|
||||
}
|
||||
// Create venv with system site packages if system Qt is enabled
|
||||
if state.system_qt {
|
||||
let mut venv_command = uv_command(state)?;
|
||||
venv_command.args([
|
||||
"venv",
|
||||
"--no-managed-python",
|
||||
"--system-site-packages",
|
||||
"--no-config",
|
||||
]);
|
||||
venv_command.ensure_success()?;
|
||||
}
|
||||
|
||||
command
|
||||
|
@ -297,25 +316,24 @@ fn handle_version_install_or_update(state: &State, choice: MainMenuChoice) -> Re
|
|||
.env(
|
||||
"UV_HTTP_TIMEOUT",
|
||||
std::env::var("UV_HTTP_TIMEOUT").unwrap_or_else(|_| "180".to_string()),
|
||||
)
|
||||
.args(["sync", "--upgrade", "--managed-python", "--no-config"]);
|
||||
);
|
||||
|
||||
// Add python version if .python-version file exists
|
||||
command.args(["sync", "--upgrade", "--no-config"]);
|
||||
if !state.system_qt {
|
||||
command.arg("--managed-python");
|
||||
}
|
||||
|
||||
// Add python version if .python-version file exists (but not for system Qt)
|
||||
if let Some(version) = &python_version_trimmed {
|
||||
command.args(["--python", version]);
|
||||
if !state.system_qt {
|
||||
command.args(["--python", version]);
|
||||
}
|
||||
}
|
||||
|
||||
if state.no_cache_marker.exists() {
|
||||
command.env("UV_NO_CACHE", "1");
|
||||
}
|
||||
|
||||
// Add mirror environment variable if enabled
|
||||
if let Some((python_mirror, pypi_mirror)) = get_mirror_urls(state)? {
|
||||
command
|
||||
.env("UV_PYTHON_INSTALL_MIRROR", &python_mirror)
|
||||
.env("UV_DEFAULT_INDEX", &pypi_mirror);
|
||||
}
|
||||
|
||||
match command.ensure_success() {
|
||||
Ok(_) => {
|
||||
// Sync succeeded
|
||||
|
@ -665,9 +683,8 @@ fn filter_and_normalize_versions(
|
|||
fn fetch_versions(state: &State) -> Result<Vec<String>> {
|
||||
let versions_script = state.resources_dir.join("versions.py");
|
||||
|
||||
let mut cmd = Command::new(&state.uv_path);
|
||||
cmd.current_dir(&state.uv_install_root)
|
||||
.args(["run", "--no-project", "--no-config", "--managed-python"])
|
||||
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)?;
|
||||
|
@ -680,12 +697,6 @@ fn fetch_versions(state: &State) -> Result<Vec<String>> {
|
|||
|
||||
cmd.arg(&versions_script);
|
||||
|
||||
// Add mirror environment variable if enabled
|
||||
if let Some((python_mirror, pypi_mirror)) = get_mirror_urls(state)? {
|
||||
cmd.env("UV_PYTHON_INSTALL_MIRROR", &python_mirror)
|
||||
.env("UV_DEFAULT_INDEX", &pypi_mirror);
|
||||
}
|
||||
|
||||
let output = match cmd.utf8_output() {
|
||||
Ok(output) => output,
|
||||
Err(e) => {
|
||||
|
@ -738,7 +749,26 @@ fn apply_version_kind(version_kind: &VersionKind, state: &State) -> Result<()> {
|
|||
&format!("anki-release=={version}\",\n \"anki=={version}\",\n \"aqt=={version}"),
|
||||
),
|
||||
};
|
||||
write_file(&state.user_pyproject_path, &updated_content)?;
|
||||
|
||||
let final_content = if state.system_qt {
|
||||
format!(
|
||||
concat!(
|
||||
"{}\n\n[tool.uv]\n",
|
||||
"override-dependencies = [\n",
|
||||
" \"pyqt6; sys_platform=='never'\",\n",
|
||||
" \"pyqt6-qt6; sys_platform=='never'\",\n",
|
||||
" \"pyqt6-webengine; sys_platform=='never'\",\n",
|
||||
" \"pyqt6-webengine-qt6; sys_platform=='never'\",\n",
|
||||
" \"pyqt6_sip; sys_platform=='never'\"\n",
|
||||
"]\n"
|
||||
),
|
||||
updated_content
|
||||
)
|
||||
} else {
|
||||
updated_content
|
||||
};
|
||||
|
||||
write_file(&state.user_pyproject_path, &final_content)?;
|
||||
|
||||
// Update .python-version based on version kind
|
||||
match version_kind {
|
||||
|
@ -930,12 +960,25 @@ fn handle_uninstall(state: &State) -> Result<bool> {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
fn have_developer_tools() -> bool {
|
||||
Command::new("xcode-select")
|
||||
.args(["-p"])
|
||||
.output()
|
||||
.map(|output| output.status.success())
|
||||
.unwrap_or(false)
|
||||
fn uv_command(state: &State) -> Result<Command> {
|
||||
let mut command = Command::new(&state.uv_path);
|
||||
command.current_dir(&state.uv_install_root);
|
||||
|
||||
// remove UV_* environment variables to avoid interference
|
||||
for (key, _) in std::env::vars() {
|
||||
if key.starts_with("UV_") || key == "VIRTUAL_ENV" {
|
||||
command.env_remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
// Add mirror environment variable if enabled
|
||||
if let Some((python_mirror, pypi_mirror)) = get_mirror_urls(state)? {
|
||||
command
|
||||
.env("UV_PYTHON_INSTALL_MIRROR", &python_mirror)
|
||||
.env("UV_DEFAULT_INDEX", &pypi_mirror);
|
||||
}
|
||||
|
||||
Ok(command)
|
||||
}
|
||||
|
||||
fn build_python_command(state: &State, args: &[String]) -> Result<Command> {
|
||||
|
|
|
@ -62,7 +62,7 @@ pub fn prepare_for_launch_after_update(mut cmd: Command, root: &Path) -> Result<
|
|||
pub fn relaunch_in_terminal() -> Result<()> {
|
||||
let current_exe = std::env::current_exe().context("Failed to get current executable path")?;
|
||||
Command::new("open")
|
||||
.args(["-a", "Terminal"])
|
||||
.args(["-na", "Terminal"])
|
||||
.arg(current_exe)
|
||||
.ensure_spawn()?;
|
||||
std::process::exit(0);
|
||||
|
|
Loading…
Reference in a new issue