Use runtime information for arch decisions

This commit is contained in:
Thorsten Sommer 2026-01-20 10:04:55 +01:00
parent ab0803272e
commit 91b993b201
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108
5 changed files with 120 additions and 17 deletions

View File

@ -1,7 +1,4 @@
using System.Reflection;
using AIStudio.Components;
using AIStudio.Tools.Metadata;
using AIStudio.Components;
using AIStudio.Tools.Services;
using Microsoft.AspNetCore.Components;
@ -11,9 +8,8 @@ namespace AIStudio.Dialogs;
public partial class PandocDialog : MSGComponentBase
{
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
// Use runtime detection instead of metadata to ensure correct RID on dev machines:
private static readonly RID CPU_ARCHITECTURE = RIDExtensions.GetCurrentRID();
[Parameter]
public bool ShowInstallationPage { get; set; }

View File

@ -14,14 +14,17 @@ namespace AIStudio.Tools;
public static partial class Pandoc
{
private static string TB(string fallbackEN) => PluginSystem.I18N.I.T(fallbackEN, typeof(Pandoc).Namespace, nameof(Pandoc));
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
// Use runtime detection instead of metadata to ensure correct RID on dev machines:
private static readonly RID CPU_ARCHITECTURE = RIDExtensions.GetCurrentRID();
private static readonly RID METADATA_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
private const string DOWNLOAD_URL = "https://github.com/jgm/pandoc/releases/download";
private const string LATEST_URL = "https://github.com/jgm/pandoc/releases/latest";
private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(nameof(Pandoc));
private static readonly Version MINIMUM_REQUIRED_VERSION = new (3, 7, 0, 2);
private static readonly Version FALLBACK_VERSION = new (3, 7, 0, 2);
@ -53,6 +56,19 @@ public static partial class Pandoc
try
{
//
// Log a warning if the runtime-detected RID differs from the metadata RID.
// This can happen on dev machines where the metadata.txt contains stale values.
// We always use the runtime-detected RID for correct behavior.
//
if (shouldLog && CPU_ARCHITECTURE != METADATA_ARCHITECTURE)
{
LOG.LogWarning(
"Runtime-detected RID '{RuntimeRID}' differs from metadata RID '{MetadataRID}'. Using runtime-detected RID. This is expected on dev machines where metadata.txt may be outdated.",
CPU_ARCHITECTURE.ToUserFriendlyName(),
METADATA_ARCHITECTURE.ToUserFriendlyName());
}
var preparedProcess = await PreparePandocProcess().AddArgument("--version").BuildAsync(rustService);
if (shouldLog)
LOG.LogInformation("Checking Pandoc availability using executable: '{Executable}' (IsLocal: {IsLocal}).", preparedProcess.StartInfo.FileName, preparedProcess.IsLocal);

View File

@ -13,7 +13,10 @@ public sealed class PandocProcessBuilder
{
private static readonly Assembly ASSEMBLY = Assembly.GetExecutingAssembly();
private static readonly MetaDataArchitectureAttribute META_DATA_ARCH = ASSEMBLY.GetCustomAttribute<MetaDataArchitectureAttribute>()!;
private static readonly RID CPU_ARCHITECTURE = META_DATA_ARCH.Architecture.ToRID();
// Use runtime detection instead of metadata to ensure correct RID on dev machines:
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));
// Tracks whether the first log has been written to avoid log spam on repeated calls:
@ -122,6 +125,19 @@ public sealed class PandocProcessBuilder
try
{
//
// Log a warning if the runtime-detected RID differs from the metadata RID.
// This can happen on dev machines where the metadata.txt contains stale values.
// We always use the runtime-detected RID for correct behavior.
//
if (shouldLog && CPU_ARCHITECTURE != METADATA_ARCHITECTURE)
{
LOGGER.LogWarning(
"Runtime-detected RID '{RuntimeRID}' differs from metadata RID '{MetadataRID}'. Using runtime-detected RID. This is expected on dev machines where metadata.txt may be outdated.",
CPU_ARCHITECTURE.ToUserFriendlyName(),
METADATA_ARCHITECTURE.ToUserFriendlyName());
}
//
// First, we try to find the pandoc executable in the data directory.
// Any local installation should be preferred over the system-wide installation.

View File

@ -1,7 +1,39 @@
using System.Runtime.InteropServices;
namespace SharedTools;
public static class RIDExtensions
{
/// <summary>
/// Detects the current Runtime Identifier (RID) at runtime based on OS and architecture.
/// </summary>
/// <remarks>
/// This method should be preferred over reading the RID from metadata,
/// as the metadata may contain stale values in development environments.
/// </remarks>
/// <returns>The detected RID for the current platform.</returns>
public static RID GetCurrentRID()
{
var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
var isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
var isMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
var arch = RuntimeInformation.OSArchitecture;
return (isWindows, isLinux, isMacOS, arch) switch
{
(true, _, _, Architecture.X64) => RID.WIN_X64,
(true, _, _, Architecture.Arm64) => RID.WIN_ARM64,
(_, true, _, Architecture.X64) => RID.LINUX_X64,
(_, true, _, Architecture.Arm64) => RID.LINUX_ARM64,
(_, _, true, Architecture.X64) => RID.OSX_X64,
(_, _, true, Architecture.Arm64) => RID.OSX_ARM64,
_ => RID.NONE,
};
}
public static string AsMicrosoftRid(this RID rid) => rid switch
{
RID.WIN_X64 => "win-x64",

View File

@ -1,9 +1,14 @@
use std::path::{Path, PathBuf};
use std::fs;
use std::sync::OnceLock;
use log::warn;
use tokio::process::Command;
use crate::environment::DATA_DIRECTORY;
use crate::metadata::META_DATA;
/// Tracks whether the RID mismatch warning has been logged.
static HAS_LOGGED_RID_MISMATCH: OnceLock<()> = OnceLock::new();
pub struct PandocExecutable {
pub executable: String,
pub is_local_installation: bool,
@ -156,13 +161,51 @@ impl PandocProcessBuilder {
Err("Executable not found".into())
}
/// Reads the os platform to determine the used executable name.
/// Determines the executable name based on the current OS at runtime.
///
/// This uses runtime detection instead of metadata to ensure correct behavior
/// on dev machines where the metadata may contain stale values.
fn pandoc_executable_name() -> String {
let metadata = META_DATA.lock().unwrap();
let metadata = metadata.as_ref().unwrap();
// Log a warning (once) if the runtime OS differs from the metadata architecture.
// This can happen on dev machines where the metadata.txt contains stale values.
HAS_LOGGED_RID_MISMATCH.get_or_init(|| {
let runtime_os = std::env::consts::OS;
let runtime_arch = std::env::consts::ARCH;
match metadata.architecture.as_str() {
"win-arm64" | "win-x64" => "pandoc.exe".to_string(),
if let Ok(metadata) = META_DATA.lock() {
if let Some(metadata) = metadata.as_ref() {
let metadata_arch = &metadata.architecture;
// Determine expected OS from metadata:
let metadata_is_windows = metadata_arch.starts_with("win-");
let metadata_is_macos = metadata_arch.starts_with("osx-");
let metadata_is_linux = metadata_arch.starts_with("linux-");
// Compare with runtime OS:
let runtime_is_windows = runtime_os == "windows";
let runtime_is_macos = runtime_os == "macos";
let runtime_is_linux = runtime_os == "linux";
let os_mismatch = (metadata_is_windows != runtime_is_windows)
|| (metadata_is_macos != runtime_is_macos)
|| (metadata_is_linux != runtime_is_linux);
if os_mismatch {
warn!(
Source = "Pandoc";
"Runtime-detected OS '{}-{}' differs from metadata architecture '{}'. Using runtime-detected OS. This is expected on dev machines where metadata.txt may be outdated.",
runtime_os,
runtime_arch,
metadata_arch
);
}
}
}
});
// Use std::env::consts::OS for runtime detection instead of metadata
match std::env::consts::OS {
"windows" => "pandoc.exe".to_string(),
_ => "pandoc".to_string(),
}
}