From 6a55836e9f69f446c16508e44f73f2addbacd28b Mon Sep 17 00:00:00 2001 From: shaunmower Date: Sat, 3 Oct 2026 19:55:45 +1000 Subject: [PATCH 1/4] test: assert Windows MakeMKV executable name --- tests/unit/filesystem.test.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/unit/filesystem.test.js b/tests/unit/filesystem.test.js index 653ebff..9eb5c70 100644 --- a/tests/unit/filesystem.test.js +++ b/tests/unit/filesystem.test.js @@ -80,6 +80,9 @@ describe("FileSystemUtils", () => { const result = await FileSystemUtils.detectMakeMKVInstallation(); expect(result).toBe("C:/Program Files/MakeMKV"); expect(mockedFsPromises.access).toHaveBeenCalled(); + expect(mockedFsPromises.access).toHaveBeenLastCalledWith( + expect.stringMatching(/makemkvcon64\.exe$/) + ); }); it("should detect MakeMKV on Linux", async () => { @@ -125,7 +128,9 @@ describe("FileSystemUtils", () => { "C:/Program Files/MakeMKV" ); expect(result).toBe(true); - expect(mockedFsPromises.access).toHaveBeenCalled(); + expect(mockedFsPromises.access).toHaveBeenCalledWith( + expect.stringMatching(/makemkvcon64\.exe$/) + ); }); it("should validate Unix installation", async () => { From 6904720becfd046c99d1828dd102eb5b72f8cc6d Mon Sep 17 00:00:00 2001 From: shaunmower Date: Sat, 3 Oct 2026 20:29:57 +1000 Subject: [PATCH 2/4] fix: detect 64-bit MakeMKV executable on Windows --- src/utils/filesystem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/filesystem.js b/src/utils/filesystem.js index a3204a8..5875131 100644 --- a/src/utils/filesystem.js +++ b/src/utils/filesystem.js @@ -121,7 +121,7 @@ export class FileSystemUtils { // Check if makemkvcon executable exists in this path const executableName = - platform === "win32" ? "makemkvcon.exe" : "makemkvcon"; + platform === "win32" ? "makemkvcon64.exe" : "makemkvcon"; const executablePath = join(basePath, executableName); try { @@ -155,7 +155,7 @@ export class FileSystemUtils { try { const platform = os.platform(); const executableName = - platform === "win32" ? "makemkvcon.exe" : "makemkvcon"; + platform === "win32" ? "makemkvcon64.exe" : "makemkvcon"; const executablePath = join(mkvDir, executableName); await access(executablePath); From cf14c8dbf63ab88be4b6cd88391c9a39f829c94f Mon Sep 17 00:00:00 2001 From: shaunmower Date: Mon, 5 Oct 2026 18:50:24 +1100 Subject: [PATCH 3/4] docs: add changelog entry for Windows MakeMKV detection fix --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fb1e80..fc8773f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to MakeMKV Auto Rip will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Fixed + +- **Windows MakeMKV detection** - Installation detection and validation now look for `makemkvcon64.exe`, matching the executable the app runs + ## [1.0.0] - 2025-08-12 ### Added From 23da6ae33bdf6418b25efa6ac525ad440548e695 Mon Sep 17 00:00:00 2001 From: shaunmower Date: Mon, 5 Oct 2026 19:01:41 +1100 Subject: [PATCH 4/4] fix: fall back to makemkvcon.exe when makemkvcon64.exe is missing --- CHANGELOG.md | 2 +- src/config/index.js | 8 +++---- src/utils/filesystem.js | 41 ++++++++++++++++++++--------------- tests/unit/config.test.js | 10 +++++++++ tests/unit/filesystem.test.js | 12 ++++++++++ 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc8773f..5c0aed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- **Windows MakeMKV detection** - Installation detection and validation now look for `makemkvcon64.exe`, matching the executable the app runs +- **Windows MakeMKV detection** - Detection, validation and the executable the app runs now all use `makemkvcon64.exe`, falling back to `makemkvcon.exe` when the 64-bit executable is not installed ## [1.0.0] - 2025-08-12 diff --git a/src/config/index.js b/src/config/index.js index 9769fdd..57cf7dd 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,5 +1,5 @@ import { readFileSync } from "fs"; -import { dirname, join, resolve, normalize, sep } from "path"; +import { dirname, resolve, normalize, sep } from "path"; import { fileURLToPath } from "url"; import { parse } from "yaml"; import { FileSystemUtils } from "../utils/filesystem.js"; @@ -168,10 +168,8 @@ export class AppConfig { const mkvDir = await this.getMkvDir(); if (!mkvDir) return null; - // Handle cross-platform executable names - const executableName = - process.platform === "win32" ? "makemkvcon64.exe" : "makemkvcon"; - const executablePath = join(mkvDir, executableName); + const executablePath = await FileSystemUtils.findMakeMKVExecutable(mkvDir); + if (!executablePath) return null; // Quote the path if it contains spaces (important for Windows paths) return executablePath.includes(" ") diff --git a/src/utils/filesystem.js b/src/utils/filesystem.js index 5875131..b9733d9 100644 --- a/src/utils/filesystem.js +++ b/src/utils/filesystem.js @@ -120,17 +120,9 @@ export class FileSystemUtils { await access(basePath); // Check if makemkvcon executable exists in this path - const executableName = - platform === "win32" ? "makemkvcon64.exe" : "makemkvcon"; - const executablePath = join(basePath, executableName); - - try { - await access(executablePath); + if (await this.findMakeMKVExecutable(basePath)) { Logger.info(`Found MakeMKV installation at: ${basePath}`); return basePath; - } catch { - // Executable not found in this directory, try next - continue; } } catch { // Directory doesn't exist, try next @@ -151,17 +143,30 @@ export class FileSystemUtils { */ static async validateMakeMKVInstallation(mkvDir) { if (!mkvDir) return false; + return Boolean(await this.findMakeMKVExecutable(mkvDir)); + } - try { - const platform = os.platform(); - const executableName = - platform === "win32" ? "makemkvcon64.exe" : "makemkvcon"; - const executablePath = join(mkvDir, executableName); + /** + * Find the makemkvcon executable in a MakeMKV directory. + * On Windows, prefers makemkvcon64.exe and falls back to makemkvcon.exe. + * @param {string} mkvDir - Path to MakeMKV directory + * @returns {Promise} - Full executable path or null if not found + */ + static async findMakeMKVExecutable(mkvDir) { + const executableNames = + os.platform() === "win32" + ? ["makemkvcon64.exe", "makemkvcon.exe"] + : ["makemkvcon"]; - await access(executablePath); - return true; - } catch { - return false; + for (const executableName of executableNames) { + const executablePath = join(mkvDir, executableName); + try { + await access(executablePath); + return executablePath; + } catch { + // Not found, try next name + } } + return null; } } diff --git a/tests/unit/config.test.js b/tests/unit/config.test.js index bd14da1..76b62d6 100644 --- a/tests/unit/config.test.js +++ b/tests/unit/config.test.js @@ -3,12 +3,19 @@ */ import { describe, it, expect, beforeEach, vi, afterEach } from "vitest"; +import { join } from "path"; // Partially mock FileSystemUtils for detection/validation only const mockFileSystemUtils = { detectMakeMKVInstallation: vi.fn().mockResolvedValue("/usr/bin"), validateMakeMKVInstallation: vi.fn().mockResolvedValue(true), + findMakeMKVExecutable: vi.fn(), }; +const platformExecutable = async (mkvDir) => + join( + mkvDir, + process.platform === "win32" ? "makemkvcon64.exe" : "makemkvcon" + ); vi.mock("../../src/utils/filesystem.js", async () => { const actual = await vi.importActual("../../src/utils/filesystem.js"); return { @@ -33,6 +40,9 @@ describe("AppConfig", () => { // Reset mock implementation mockFileSystemUtils.detectMakeMKVInstallation.mockResolvedValue("/usr/bin"); mockFileSystemUtils.validateMakeMKVInstallation.mockResolvedValue(true); + mockFileSystemUtils.findMakeMKVExecutable.mockImplementation( + platformExecutable + ); }); afterEach(() => { diff --git a/tests/unit/filesystem.test.js b/tests/unit/filesystem.test.js index 9eb5c70..5f032f5 100644 --- a/tests/unit/filesystem.test.js +++ b/tests/unit/filesystem.test.js @@ -133,6 +133,18 @@ describe("FileSystemUtils", () => { ); }); + it("should fall back to makemkvcon.exe on Windows", async () => { + mockedOs.platform.mockReturnValue("win32"); + mockedFsPromises.access.mockImplementation(async (path) => { + if (path.endsWith("makemkvcon64.exe")) throw new Error("ENOENT"); + }); + + const result = await FileSystemUtils.findMakeMKVExecutable( + "C:/Program Files/MakeMKV" + ); + expect(result).toMatch(/[\\/]makemkvcon\.exe$/); + }); + it("should validate Unix installation", async () => { mockedOs.platform.mockReturnValue("linux"); mockedFsPromises.access.mockResolvedValue(); // Simulates successful access