From 2c06bf566f604c459c18b5d17e8d325b9fa4670f Mon Sep 17 00:00:00 2001 From: David Richardson Date: Tue, 8 Sep 2026 18:02:47 -0600 Subject: [PATCH] Refactor Tests/Manual orchestration Removes recursive JAKE.subjake calls from the root Jakefile, eliminating silent error masking and path evaluation failures during test suite compilation. Replace subjake with POSIX find. * Replaces Node-based directory traversal with POSIX find and -execdir to guarantee correct working directory context and propagate standard output. * Restricts the `clean` task strictly to the removal of build artifacts. * Introduces a `clobber` task to remove Frameworks symlinks alongside build artifacts, restoring the test directories to a pristine state. --- Tests/Manual/Jakefile | 163 +++++++----------------------------------- 1 file changed, 27 insertions(+), 136 deletions(-) diff --git a/Tests/Manual/Jakefile b/Tests/Manual/Jakefile index 065bc5011..786ea705b 100644 --- a/Tests/Manual/Jakefile +++ b/Tests/Manual/Jakefile @@ -1,153 +1,44 @@ -/* - * Jakefile - * Tests/Manual - * - * Provisions ./Frameworks for every manual integration test app. - * See FRAMEWORKS-PROVISIONING-PLAN.md for the reasoning behind this design. - * - * Scope: this file only manages Frameworks symlinks. It does not build, - * run, or modify any individual test app. - */ - -const path = require("path"); -const fs = require("fs"); +// ./Tests/Manual/Jakefile var ENV = process.env, - task = JAKE.task; + task = JAKE.task, + cp = require("child_process"), + path = require("path"); -// Single source of truth for the merge: every app links to this, and -// this links into dist. A dist rebuild is then visible everywhere with -// no re-provisioning. -var SHARED_FRAMEWORKS = ".Frameworks"; +task ("default", ["build"]); -// Left side: name under Tests/Manual/.Frameworks (and .../Debug). -// Right side: path under dist, relative to Tests/Manual. -var RELEASE_MEMBERS = { - "AppKit": path.join("..", "..", "dist", "cappuccino", "Frameworks", "AppKit"), - "BlendKit": path.join("..", "..", "dist", "cappuccino", "Frameworks", "BlendKit"), - "Foundation": path.join("..", "..", "dist", "cappuccino", "Frameworks", "Foundation"), - "Objective-J": path.join("..", "..", "dist", "objective-j", "Frameworks", "Objective-J") -}; - -var DEBUG_MEMBERS = { - "AppKit": path.join("..", "..", "dist", "cappuccino", "Frameworks", "Debug", "AppKit"), - "BlendKit": path.join("..", "..", "dist", "cappuccino", "Frameworks", "Debug", "BlendKit"), - "Foundation": path.join("..", "..", "dist", "cappuccino", "Frameworks", "Debug", "Foundation"), - "Objective-J": path.join("..", "..", "dist", "objective-j", "Frameworks", "Debug", "Objective-J") -}; - -// lstat, not stat -- a broken symlink must be seen as "exists, is a -// symlink", not thrown away as ENOENT. -function lstatOrNull(aPath) +task ("configure", function() { - try - { - return fs.lstatSync(aPath); - } - catch (e) - { - return null; - } -} - -// Creates or repairs a single symlink. Safe to call every time: skips -// when the link is already correct, so a repeat `configure` costs one -// lstat and one readlink per member when nothing changed. -function ensureSymlink(linkPath, targetPath) -{ - var desiredRelative = path.relative(path.dirname(linkPath), targetPath); - var info = lstatOrNull(linkPath); - - if (info) - { - if (info.isSymbolicLink() && fs.readlinkSync(linkPath) === desiredRelative) - return; - - if (info.isSymbolicLink()) - fs.unlinkSync(linkPath); - else - { - console.log("configure: replacing non-symlink at " + linkPath); - fs.rmSync(linkPath, { recursive: true, force: true }); - } - } - - fs.symlinkSync(desiredRelative, linkPath, "dir"); -} - -function buildSharedFrameworks() -{ - fs.mkdirSync(path.join(SHARED_FRAMEWORKS, "Debug"), { recursive: true }); - - Object.keys(RELEASE_MEMBERS).forEach(function(name) - { - ensureSymlink(path.join(SHARED_FRAMEWORKS, name), RELEASE_MEMBERS[name]); - }); - - Object.keys(DEBUG_MEMBERS).forEach(function(name) - { - ensureSymlink(path.join(SHARED_FRAMEWORKS, "Debug", name), DEBUG_MEMBERS[name]); - }); -} - -// An app directory is anything under Tests/Manual with Info.plist or -// index.html -- the same test migrate_jakefiles.py already uses to -// find app roots. Excludes the shared cache and any dotfile entries. -function listAppDirs() -{ - return fs.readdirSync(".", { withFileTypes: true }) - .filter(function(entry) - { - if (!entry.isDirectory()) - return false; - if (entry.name.charAt(0) === ".") - return false; - - return fs.existsSync(path.join(entry.name, "Info.plist")) || - fs.existsSync(path.join(entry.name, "index.html")); - }) - .map(function(entry) { return entry.name; }); -} - -function linkAllApps() -{ - listAppDirs().forEach(function(appDir) - { - ensureSymlink(path.join(appDir, "Frameworks"), SHARED_FRAMEWORKS); - }); -} - -task ("refresh-dist", function() -{ - JAKE.subjake(["../.."], "dist", ENV); + var targetPath = path.join(process.cwd(), ".Frameworks"); + cp.execSync("find . -mindepth 2 -iname 'jakefile' -execdir sh -c 'echo \"Configuring $(basename \\\"$PWD\\\")\"; ln -sfn \"$1\" Frameworks' _ '" + targetPath + "' \\;", { stdio: "inherit" }); }); -task ("configure", ["refresh-dist"], function() +task ("build", function() { - buildSharedFrameworks(); - linkAllApps(); + cp.execSync("find . -mindepth 2 -iname 'jakefile' -execdir npx jake build \\;", { stdio: "inherit", env: ENV }); +}); + +task ("build-all", ["debug", "release"]); + +task ("debug", function() +{ + ENV["CONFIGURATION"] = "Debug"; + cp.execSync("find . -mindepth 2 -iname 'jakefile' -execdir npx jake debug \\;", { stdio: "inherit", env: ENV }); +}); + +task ("release", function() +{ + ENV["CONFIGURATION"] = "Release"; + cp.execSync("find . -mindepth 2 -iname 'jakefile' -execdir npx jake release \\;", { stdio: "inherit", env: ENV }); }); task ("clean", function() { - listAppDirs().forEach(function(appDir) - { - var linkPath = path.join(appDir, "Frameworks"); - var info = lstatOrNull(linkPath); - - if (!info) - return; - - if (info.isSymbolicLink()) - fs.unlinkSync(linkPath); - else - console.log("clean: skipping non-symlink at " + linkPath); - }); + var targetDir = ENV["BUILD_PATH"] || ENV["CAPP_BUILD"] || "Build"; + cp.execSync("find . -name '" + targetDir + "' -type d -prune -exec rm -rf {} +", { stdio: "inherit" }); }); task ("clobber", ["clean"], function() { - fs.rmSync(SHARED_FRAMEWORKS, { recursive: true, force: true }); + cp.execSync("find . -mindepth 2 -type l -name 'Frameworks' -exec rm -f {} +", { stdio: "inherit" }); }); - -task ("default", ["configure"]);