Fixed the Flatpak issue that prevented Pandoc from being found (#807)
Some checks are pending
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions

This commit is contained in:
Thorsten Sommer 2026-06-11 12:33:19 +02:00 committed by GitHub
parent e4fa1cd72a
commit 71ae52753a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 66 additions and 5 deletions

View File

@ -17,6 +17,7 @@ public sealed class PandocProcessBuilder
private static readonly RID CPU_ARCHITECTURE = RIDExtensions.GetCurrentRID();
private static readonly RID METADATA_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
private static readonly ILogger LOGGER = Program.LOGGER_FACTORY.CreateLogger(nameof(PandocProcessBuilder));
private const string FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY = "/app/plugins/pandoc/bin";
// Tracks whether the first log has been written to avoid log spam on repeated calls:
private static bool HAS_LOGGED_ONCE;
@ -220,7 +221,8 @@ public sealed class PandocProcessBuilder
}
}
foreach (var candidate in SystemPandocExecutableCandidates(PandocExecutableName))
var runtimeInfo = await rustService.GetRuntimeInfo();
foreach (var candidate in SystemPandocExecutableCandidates(PandocExecutableName, runtimeInfo.LinuxPackageType))
{
if (!File.Exists(candidate))
continue;
@ -250,7 +252,7 @@ public sealed class PandocProcessBuilder
/// </summary>
public static string PandocExecutableName => CPU_ARCHITECTURE is RID.WIN_ARM64 or RID.WIN_X64 ? "pandoc.exe" : "pandoc";
private static IEnumerable<string> SystemPandocExecutableCandidates(string executableName)
private static IEnumerable<string> SystemPandocExecutableCandidates(string executableName, string linuxPackageType)
{
var candidates = new List<string>();
@ -269,6 +271,9 @@ public sealed class PandocProcessBuilder
break;
case RID.LINUX_X64 or RID.LINUX_ARM64:
if (string.Equals(linuxPackageType, "flatpak", StringComparison.OrdinalIgnoreCase))
AddCandidate(candidates, FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY, executableName);
AddCandidate(candidates, "/usr/local/bin", executableName);
AddCandidate(candidates, "/usr/bin", executableName);
AddCandidate(candidates, "/snap/bin", executableName);

View File

@ -15,4 +15,5 @@
- Fixed workspace creation and renaming to prevent new workspaces from using an existing name.
- Fixed an issue on Microsoft Windows where reading attached documents could briefly open a terminal window while processing files.
- Fixed an issue where AI Studio could be started multiple times on Microsoft Windows by launching it from different virtual desktops.
- Fixed an issue where Flatpak installations could not find Pandoc from the bundled plugin extension.
- Upgraded dependencies.

View File

@ -105,13 +105,18 @@ fn detect_linux_package_type() -> &'static str {
}
#[cfg(target_os = "linux")]
fn is_flatpak() -> bool {
pub(crate) fn is_flatpak() -> bool {
env_var_has_value("FLATPAK_ID")
|| Path::new("/.flatpak-info").is_file()
|| env::var("container")
.is_ok_and(|value| value.trim().eq_ignore_ascii_case("flatpak"))
}
#[cfg(not(target_os = "linux"))]
pub(crate) fn is_flatpak() -> bool {
false
}
#[cfg(target_os = "linux")]
fn is_appimage() -> bool {
env_var_has_value("APPIMAGE") || env_var_has_value("APPDIR")

View File

@ -5,12 +5,13 @@ use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use log::{info, warn};
use tokio::process::Command;
use crate::environment::DATA_DIRECTORY;
use crate::environment::{DATA_DIRECTORY, is_flatpak};
use crate::metadata::META_DATA;
/// Tracks whether the RID mismatch warning has been logged.
static HAS_LOGGED_RID_MISMATCH: OnceLock<()> = OnceLock::new();
static HAS_LOGGED_PANDOC_PATH: OnceLock<()> = OnceLock::new();
const FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY: &str = "/app/plugins/pandoc/bin";
/// Microsoft documents CREATE_NO_WINDOW as a process creation flag with value 0x08000000.
/// It starts console applications without opening a console window:
@ -186,8 +187,12 @@ impl PandocProcessBuilder {
}
fn system_pandoc_executable_candidates(executable_name: &str) -> Vec<PathBuf> {
Self::system_pandoc_executable_candidates_for(env::consts::OS, executable_name, is_flatpak())
}
fn system_pandoc_executable_candidates_for(os: &str, executable_name: &str, include_flatpak_extension: bool) -> Vec<PathBuf> {
let mut candidates: Vec<PathBuf> = Vec::new();
match env::consts::OS {
match os {
"windows" => {
Self::push_env_candidate(&mut candidates, "LOCALAPPDATA", &["Pandoc", executable_name]);
Self::push_env_candidate(&mut candidates, "ProgramFiles", &["Pandoc", executable_name]);
@ -199,6 +204,9 @@ impl PandocProcessBuilder {
candidates.push(PathBuf::from("/usr/bin").join(executable_name));
},
"linux" => {
if include_flatpak_extension {
candidates.push(PathBuf::from(FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY).join(executable_name));
}
candidates.push(PathBuf::from("/usr/local/bin").join(executable_name));
candidates.push(PathBuf::from("/usr/bin").join(executable_name));
candidates.push(PathBuf::from("/snap/bin").join(executable_name));
@ -281,4 +289,46 @@ impl PandocProcessBuilder {
_ => "pandoc".to_string(),
}
}
}
#[cfg(test)]
mod tests {
use super::{FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY, PandocProcessBuilder};
use std::fs;
use std::path::PathBuf;
use tempfile::tempdir;
#[test]
fn linux_candidates_include_flatpak_pandoc_extension_first_when_flatpak() {
let candidates = PandocProcessBuilder::system_pandoc_executable_candidates_for("linux", "pandoc", true);
let flatpak_candidate = PathBuf::from(FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY).join("pandoc");
let usr_local_candidate = PathBuf::from("/usr/local/bin").join("pandoc");
let flatpak_index = candidates.iter().position(|candidate| candidate == &flatpak_candidate).unwrap();
let usr_local_index = candidates.iter().position(|candidate| candidate == &usr_local_candidate).unwrap();
assert!(flatpak_index < usr_local_index);
}
#[test]
fn linux_candidates_skip_flatpak_pandoc_extension_when_not_flatpak() {
let candidates = PandocProcessBuilder::system_pandoc_executable_candidates_for("linux", "pandoc", false);
let flatpak_candidate = PathBuf::from(FLATPAK_PANDOC_PLUGIN_BIN_DIRECTORY).join("pandoc");
assert!(!candidates.contains(&flatpak_candidate));
}
#[test]
fn local_pandoc_search_finds_data_directory_installation() {
let directory = tempdir().unwrap();
let pandoc_directory = directory.path().join("pandoc").join("bin");
fs::create_dir_all(&pandoc_directory).unwrap();
let pandoc_path = pandoc_directory.join("pandoc");
fs::File::create(&pandoc_path).unwrap();
assert_eq!(
PandocProcessBuilder::find_executable_in_dir(directory.path(), "pandoc").unwrap(),
pandoc_path
);
}
}