Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/ENGINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ the same on every PC. An external engine is looked for in this order:
1. a copy the user picked in Settings → *Engines*;
2. Filee's own copy (bundled or downloaded);
3. a copy already on the computer: on `PATH`, in Homebrew's and the usual Unix folders, or where the LibreOffice,
calibre, Ghostscript and Tesseract installers put it. Settings → *Engines* shows it as "Found on this PC", with a note when
calibre, Ghostscript and Tesseract installers put it. On Windows, FFmpeg, Tesseract and Whisper are also looked for in
the native environments under the system drive's `msys64` folder, after these locations. Settings → *Engines* shows it as "Found on this PC", with a note when
its version is older than the one Filee downloads.

Where Filee has no download of an engine (FFmpeg, Ghostscript and Tesseract on macOS, LibreOffice, Ghostscript and
Expand Down
9 changes: 9 additions & 0 deletions src/Filee.Engines/Infrastructure/EngineEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,21 @@ private static IEnumerable<string> SystemFolders(string id)
break;
}
}
// MSYS2 is an optional fallback after PATH and the usual installer locations, never ahead of Filee's copies.
if (OperatingSystem.IsWindows() && Path.GetPathRoot(Environment.SystemDirectory) is { Length: > 0 } drive)
folders.AddRange(Msys2Folders(id, Path.Combine(drive, "msys64")));
// Never Filee's own folders: those are its own copy, found before.
var comparison = OperatingSystem.IsWindows() ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
return folders.Distinct(OperatingSystem.IsWindows() ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal)
.Where(f => !IsWithin(f, DownloadRoot, comparison) && !IsWithin(f, AppContext.BaseDirectory, comparison));
}

/// <summary>Native MSYS2 environments under a standard installation; do not search MSYS's own Unix tools.</summary>
internal static IEnumerable<string> Msys2Folders(string id, string root) =>
id is "ffmpeg" or "tesseract" or "whisper"
? new[] { "ucrt64", "clang64", "mingw64", "clangarm64", "mingw32" }.Select(env => Path.Combine(root, env, "bin"))
: [];

/// <summary>Where LibreOffice's Windows installer records its program folder (the key's default value).</summary>
internal const string LibreOfficeInstallPathKey = @"SOFTWARE\LibreOffice\UNO\InstallPath";

Expand Down
21 changes: 21 additions & 0 deletions tests/Filee.Engines.Tests/PortableEngineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,27 @@ public void Unix_FFmpeg_requires_both_tools_in_the_same_folder()
Assert.Equal(_root, EngineEnvironment.FolderWithPrograms("ffmpeg", _root, windows: false));
}

[Theory]
[InlineData("ffmpeg", "mingw64", "ffmpeg.exe", "ffprobe.exe")]
[InlineData("tesseract", "clang64", "tesseract.exe", null)]
[InlineData("whisper", "ucrt64", "whisper-cli.exe", null)]
public void Msys2_native_engines_are_found_only_when_the_required_programs_exist(
string id, string environment, string program, string? second)
{
var bin = Path.Combine(_root, environment, "bin");
Directory.CreateDirectory(bin);
File.WriteAllText(Path.Combine(bin, program), "binary");
var folders = EngineEnvironment.Msys2Folders(id, _root).ToList();
if (second is not null)
{
Assert.Null(folders.Select(path => EngineEnvironment.FolderWithPrograms(id, path, windows: true)).FirstOrDefault(path => path is not null));
File.WriteAllText(Path.Combine(bin, second), "binary");
}
Assert.Equal(bin, folders.Select(path => EngineEnvironment.FolderWithPrograms(id, path, windows: true)).FirstOrDefault(path => path is not null));
Assert.DoesNotContain(Path.Combine(_root, "usr", "bin"), folders);
Assert.Empty(EngineEnvironment.Msys2Folders("pandoc", _root));
}

[Fact]
public async Task Tar_archives_preserve_program_layout_contents_and_Unix_executable_mode()
{
Expand Down
Loading