@hominis/fireforge 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE.md +294 -0
- package/README.md +435 -0
- package/dist/bin/fireforge.d.ts +10 -0
- package/dist/bin/fireforge.js +29 -0
- package/dist/src/cli.d.ts +33 -0
- package/dist/src/cli.js +180 -0
- package/dist/src/commands/bootstrap.d.ts +9 -0
- package/dist/src/commands/bootstrap.js +73 -0
- package/dist/src/commands/build.d.ts +11 -0
- package/dist/src/commands/build.js +102 -0
- package/dist/src/commands/config.d.ts +13 -0
- package/dist/src/commands/config.js +135 -0
- package/dist/src/commands/discard.d.ts +12 -0
- package/dist/src/commands/discard.js +84 -0
- package/dist/src/commands/doctor.d.ts +18 -0
- package/dist/src/commands/doctor.js +356 -0
- package/dist/src/commands/download.d.ts +11 -0
- package/dist/src/commands/download.js +127 -0
- package/dist/src/commands/export-all.d.ts +11 -0
- package/dist/src/commands/export-all.js +122 -0
- package/dist/src/commands/export-shared.d.ts +48 -0
- package/dist/src/commands/export-shared.js +208 -0
- package/dist/src/commands/export.d.ts +13 -0
- package/dist/src/commands/export.js +178 -0
- package/dist/src/commands/furnace/apply.d.ts +7 -0
- package/dist/src/commands/furnace/apply.js +80 -0
- package/dist/src/commands/furnace/create.d.ts +8 -0
- package/dist/src/commands/furnace/create.js +377 -0
- package/dist/src/commands/furnace/deploy.d.ts +8 -0
- package/dist/src/commands/furnace/deploy.js +338 -0
- package/dist/src/commands/furnace/diff.d.ts +7 -0
- package/dist/src/commands/furnace/diff.js +119 -0
- package/dist/src/commands/furnace/index.d.ts +16 -0
- package/dist/src/commands/furnace/index.js +121 -0
- package/dist/src/commands/furnace/list.d.ts +5 -0
- package/dist/src/commands/furnace/list.js +65 -0
- package/dist/src/commands/furnace/override.d.ts +8 -0
- package/dist/src/commands/furnace/override.js +188 -0
- package/dist/src/commands/furnace/preview.d.ts +7 -0
- package/dist/src/commands/furnace/preview.js +96 -0
- package/dist/src/commands/furnace/remove.d.ts +8 -0
- package/dist/src/commands/furnace/remove.js +159 -0
- package/dist/src/commands/furnace/scan.d.ts +5 -0
- package/dist/src/commands/furnace/scan.js +112 -0
- package/dist/src/commands/furnace/status.d.ts +7 -0
- package/dist/src/commands/furnace/status.js +137 -0
- package/dist/src/commands/furnace/validate.d.ts +6 -0
- package/dist/src/commands/furnace/validate.js +91 -0
- package/dist/src/commands/furnace/validation-output.d.ts +7 -0
- package/dist/src/commands/furnace/validation-output.js +22 -0
- package/dist/src/commands/import.d.ts +11 -0
- package/dist/src/commands/import.js +241 -0
- package/dist/src/commands/lint.d.ts +10 -0
- package/dist/src/commands/lint.js +118 -0
- package/dist/src/commands/package.d.ts +11 -0
- package/dist/src/commands/package.js +80 -0
- package/dist/src/commands/re-export.d.ts +12 -0
- package/dist/src/commands/re-export.js +242 -0
- package/dist/src/commands/rebase/abort.d.ts +7 -0
- package/dist/src/commands/rebase/abort.js +49 -0
- package/dist/src/commands/rebase/confirm.d.ts +18 -0
- package/dist/src/commands/rebase/confirm.js +33 -0
- package/dist/src/commands/rebase/continue.d.ts +7 -0
- package/dist/src/commands/rebase/continue.js +81 -0
- package/dist/src/commands/rebase/index.d.ts +22 -0
- package/dist/src/commands/rebase/index.js +127 -0
- package/dist/src/commands/rebase/patch-loop.d.ts +9 -0
- package/dist/src/commands/rebase/patch-loop.js +135 -0
- package/dist/src/commands/rebase/summary.d.ts +12 -0
- package/dist/src/commands/rebase/summary.js +43 -0
- package/dist/src/commands/rebase.d.ts +4 -0
- package/dist/src/commands/rebase.js +6 -0
- package/dist/src/commands/register.d.ts +13 -0
- package/dist/src/commands/register.js +67 -0
- package/dist/src/commands/reset.d.ts +11 -0
- package/dist/src/commands/reset.js +83 -0
- package/dist/src/commands/resolve.d.ts +9 -0
- package/dist/src/commands/resolve.js +124 -0
- package/dist/src/commands/run.d.ts +9 -0
- package/dist/src/commands/run.js +91 -0
- package/dist/src/commands/setup-support.d.ts +23 -0
- package/dist/src/commands/setup-support.js +310 -0
- package/dist/src/commands/setup.d.ts +11 -0
- package/dist/src/commands/setup.js +94 -0
- package/dist/src/commands/status.d.ts +11 -0
- package/dist/src/commands/status.js +268 -0
- package/dist/src/commands/test.d.ts +12 -0
- package/dist/src/commands/test.js +182 -0
- package/dist/src/commands/token-coverage.d.ts +5 -0
- package/dist/src/commands/token-coverage.js +57 -0
- package/dist/src/commands/token.d.ts +14 -0
- package/dist/src/commands/token.js +121 -0
- package/dist/src/commands/watch.d.ts +9 -0
- package/dist/src/commands/watch.js +112 -0
- package/dist/src/commands/wire.d.ts +13 -0
- package/dist/src/commands/wire.js +149 -0
- package/dist/src/core/ast-utils.d.ts +47 -0
- package/dist/src/core/ast-utils.js +57 -0
- package/dist/src/core/brand-validation.d.ts +7 -0
- package/dist/src/core/brand-validation.js +15 -0
- package/dist/src/core/branding.d.ts +49 -0
- package/dist/src/core/branding.js +229 -0
- package/dist/src/core/browser-wire.d.ts +40 -0
- package/dist/src/core/browser-wire.js +66 -0
- package/dist/src/core/build-prepare.d.ts +25 -0
- package/dist/src/core/build-prepare.js +93 -0
- package/dist/src/core/config-mutate.d.ts +15 -0
- package/dist/src/core/config-mutate.js +51 -0
- package/dist/src/core/config-paths.d.ts +28 -0
- package/dist/src/core/config-paths.js +65 -0
- package/dist/src/core/config-state.d.ts +28 -0
- package/dist/src/core/config-state.js +152 -0
- package/dist/src/core/config-validate.d.ts +11 -0
- package/dist/src/core/config-validate.js +141 -0
- package/dist/src/core/config.d.ts +39 -0
- package/dist/src/core/config.js +70 -0
- package/dist/src/core/file-lock.d.ts +11 -0
- package/dist/src/core/file-lock.js +80 -0
- package/dist/src/core/firefox-archive.d.ts +40 -0
- package/dist/src/core/firefox-archive.js +63 -0
- package/dist/src/core/firefox-cache.d.ts +23 -0
- package/dist/src/core/firefox-cache.js +134 -0
- package/dist/src/core/firefox-download.d.ts +21 -0
- package/dist/src/core/firefox-download.js +129 -0
- package/dist/src/core/firefox-extract.d.ts +21 -0
- package/dist/src/core/firefox-extract.js +53 -0
- package/dist/src/core/firefox.d.ts +34 -0
- package/dist/src/core/firefox.js +78 -0
- package/dist/src/core/furnace-apply-helpers.d.ts +21 -0
- package/dist/src/core/furnace-apply-helpers.js +244 -0
- package/dist/src/core/furnace-apply.d.ts +16 -0
- package/dist/src/core/furnace-apply.js +147 -0
- package/dist/src/core/furnace-config.d.ts +94 -0
- package/dist/src/core/furnace-config.js +372 -0
- package/dist/src/core/furnace-constants.d.ts +4 -0
- package/dist/src/core/furnace-constants.js +6 -0
- package/dist/src/core/furnace-registration-ast.d.ts +24 -0
- package/dist/src/core/furnace-registration-ast.js +218 -0
- package/dist/src/core/furnace-registration-remove.d.ts +14 -0
- package/dist/src/core/furnace-registration-remove.js +89 -0
- package/dist/src/core/furnace-registration-validate.d.ts +20 -0
- package/dist/src/core/furnace-registration-validate.js +40 -0
- package/dist/src/core/furnace-registration.d.ts +29 -0
- package/dist/src/core/furnace-registration.js +96 -0
- package/dist/src/core/furnace-rollback.d.ts +20 -0
- package/dist/src/core/furnace-rollback.js +66 -0
- package/dist/src/core/furnace-scanner.d.ts +40 -0
- package/dist/src/core/furnace-scanner.js +143 -0
- package/dist/src/core/furnace-stories.d.ts +37 -0
- package/dist/src/core/furnace-stories.js +185 -0
- package/dist/src/core/furnace-validate-accessibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-accessibility.js +32 -0
- package/dist/src/core/furnace-validate-checks.d.ts +4 -0
- package/dist/src/core/furnace-validate-checks.js +7 -0
- package/dist/src/core/furnace-validate-compatibility.d.ts +6 -0
- package/dist/src/core/furnace-validate-compatibility.js +57 -0
- package/dist/src/core/furnace-validate-helpers.d.ts +28 -0
- package/dist/src/core/furnace-validate-helpers.js +129 -0
- package/dist/src/core/furnace-validate-registration.d.ts +37 -0
- package/dist/src/core/furnace-validate-registration.js +220 -0
- package/dist/src/core/furnace-validate-structure.d.ts +6 -0
- package/dist/src/core/furnace-validate-structure.js +66 -0
- package/dist/src/core/furnace-validate.d.ts +16 -0
- package/dist/src/core/furnace-validate.js +103 -0
- package/dist/src/core/git-base.d.ts +47 -0
- package/dist/src/core/git-base.js +50 -0
- package/dist/src/core/git-diff.d.ts +63 -0
- package/dist/src/core/git-diff.js +246 -0
- package/dist/src/core/git-file-ops.d.ts +65 -0
- package/dist/src/core/git-file-ops.js +141 -0
- package/dist/src/core/git-status.d.ts +65 -0
- package/dist/src/core/git-status.js +163 -0
- package/dist/src/core/git.d.ts +113 -0
- package/dist/src/core/git.js +363 -0
- package/dist/src/core/license-headers.d.ts +36 -0
- package/dist/src/core/license-headers.js +83 -0
- package/dist/src/core/mach-build-artifacts.d.ts +29 -0
- package/dist/src/core/mach-build-artifacts.js +117 -0
- package/dist/src/core/mach-mozconfig.d.ts +17 -0
- package/dist/src/core/mach-mozconfig.js +50 -0
- package/dist/src/core/mach-python.d.ts +16 -0
- package/dist/src/core/mach-python.js +126 -0
- package/dist/src/core/mach.d.ts +106 -0
- package/dist/src/core/mach.js +166 -0
- package/dist/src/core/manifest-helpers.d.ts +25 -0
- package/dist/src/core/manifest-helpers.js +96 -0
- package/dist/src/core/manifest-register.d.ts +30 -0
- package/dist/src/core/manifest-register.js +65 -0
- package/dist/src/core/manifest-rules.d.ts +39 -0
- package/dist/src/core/manifest-rules.js +151 -0
- package/dist/src/core/manifest-tokenizers.d.ts +34 -0
- package/dist/src/core/manifest-tokenizers.js +84 -0
- package/dist/src/core/parser-fallback.d.ts +36 -0
- package/dist/src/core/parser-fallback.js +43 -0
- package/dist/src/core/patch-apply-fuzz.d.ts +29 -0
- package/dist/src/core/patch-apply-fuzz.js +70 -0
- package/dist/src/core/patch-apply.d.ts +46 -0
- package/dist/src/core/patch-apply.js +235 -0
- package/dist/src/core/patch-export.d.ts +99 -0
- package/dist/src/core/patch-export.js +314 -0
- package/dist/src/core/patch-files.d.ts +11 -0
- package/dist/src/core/patch-files.js +51 -0
- package/dist/src/core/patch-lint.d.ts +72 -0
- package/dist/src/core/patch-lint.js +403 -0
- package/dist/src/core/patch-lock.d.ts +8 -0
- package/dist/src/core/patch-lock.js +29 -0
- package/dist/src/core/patch-manifest-consistency.d.ts +24 -0
- package/dist/src/core/patch-manifest-consistency.js +135 -0
- package/dist/src/core/patch-manifest-io.d.ts +36 -0
- package/dist/src/core/patch-manifest-io.js +77 -0
- package/dist/src/core/patch-manifest-query.d.ts +48 -0
- package/dist/src/core/patch-manifest-query.js +124 -0
- package/dist/src/core/patch-manifest-validate.d.ts +22 -0
- package/dist/src/core/patch-manifest-validate.js +72 -0
- package/dist/src/core/patch-manifest.d.ts +11 -0
- package/dist/src/core/patch-manifest.js +12 -0
- package/dist/src/core/patch-parse.d.ts +43 -0
- package/dist/src/core/patch-parse.js +143 -0
- package/dist/src/core/patch-transform.d.ts +21 -0
- package/dist/src/core/patch-transform.js +138 -0
- package/dist/src/core/rebase-session.d.ts +47 -0
- package/dist/src/core/rebase-session.js +65 -0
- package/dist/src/core/register-browser-content.d.ts +11 -0
- package/dist/src/core/register-browser-content.js +116 -0
- package/dist/src/core/register-module.d.ts +11 -0
- package/dist/src/core/register-module.js +76 -0
- package/dist/src/core/register-shared-css.d.ts +11 -0
- package/dist/src/core/register-shared-css.js +117 -0
- package/dist/src/core/register-test-manifest.d.ts +18 -0
- package/dist/src/core/register-test-manifest.js +99 -0
- package/dist/src/core/state-file.d.ts +4 -0
- package/dist/src/core/state-file.js +25 -0
- package/dist/src/core/token-coverage.d.ts +12 -0
- package/dist/src/core/token-coverage.js +74 -0
- package/dist/src/core/token-manager.d.ts +55 -0
- package/dist/src/core/token-manager.js +387 -0
- package/dist/src/core/wire-destroy.d.ts +21 -0
- package/dist/src/core/wire-destroy.js +103 -0
- package/dist/src/core/wire-dom-fragment.d.ts +23 -0
- package/dist/src/core/wire-dom-fragment.js +129 -0
- package/dist/src/core/wire-init.d.ts +23 -0
- package/dist/src/core/wire-init.js +201 -0
- package/dist/src/core/wire-subscript.d.ts +20 -0
- package/dist/src/core/wire-subscript.js +134 -0
- package/dist/src/core/wire-targets.d.ts +7 -0
- package/dist/src/core/wire-targets.js +9 -0
- package/dist/src/core/wire-utils.d.ts +88 -0
- package/dist/src/core/wire-utils.js +279 -0
- package/dist/src/errors/base.d.ts +60 -0
- package/dist/src/errors/base.js +87 -0
- package/dist/src/errors/build.d.ts +52 -0
- package/dist/src/errors/build.js +114 -0
- package/dist/src/errors/codes.d.ts +29 -0
- package/dist/src/errors/codes.js +30 -0
- package/dist/src/errors/config.d.ts +31 -0
- package/dist/src/errors/config.js +61 -0
- package/dist/src/errors/download.d.ts +42 -0
- package/dist/src/errors/download.js +95 -0
- package/dist/src/errors/furnace.d.ts +10 -0
- package/dist/src/errors/furnace.js +22 -0
- package/dist/src/errors/git.d.ts +41 -0
- package/dist/src/errors/git.js +99 -0
- package/dist/src/errors/patch.d.ts +10 -0
- package/dist/src/errors/patch.js +26 -0
- package/dist/src/errors/rebase.d.ts +20 -0
- package/dist/src/errors/rebase.js +30 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.js +21 -0
- package/dist/src/types/cli.d.ts +14 -0
- package/dist/src/types/cli.js +2 -0
- package/dist/src/types/commands/index.d.ts +6 -0
- package/dist/src/types/commands/index.js +6 -0
- package/dist/src/types/commands/options.d.ts +239 -0
- package/dist/src/types/commands/options.js +6 -0
- package/dist/src/types/commands/patches.d.ts +89 -0
- package/dist/src/types/commands/patches.js +6 -0
- package/dist/src/types/commands/project.d.ts +71 -0
- package/dist/src/types/commands/project.js +6 -0
- package/dist/src/types/config.d.ts +101 -0
- package/dist/src/types/config.js +2 -0
- package/dist/src/types/furnace.d.ts +158 -0
- package/dist/src/types/furnace.js +2 -0
- package/dist/src/types/index.d.ts +6 -0
- package/dist/src/types/index.js +6 -0
- package/dist/src/utils/errors.d.ts +2 -0
- package/dist/src/utils/errors.js +15 -0
- package/dist/src/utils/fs.d.ts +72 -0
- package/dist/src/utils/fs.js +179 -0
- package/dist/src/utils/logger.d.ts +58 -0
- package/dist/src/utils/logger.js +120 -0
- package/dist/src/utils/options.d.ts +8 -0
- package/dist/src/utils/options.js +16 -0
- package/dist/src/utils/package-root.d.ts +10 -0
- package/dist/src/utils/package-root.js +53 -0
- package/dist/src/utils/parse.d.ts +110 -0
- package/dist/src/utils/parse.js +200 -0
- package/dist/src/utils/paths.d.ts +10 -0
- package/dist/src/utils/paths.js +43 -0
- package/dist/src/utils/platform.d.ts +38 -0
- package/dist/src/utils/platform.js +56 -0
- package/dist/src/utils/process.d.ts +80 -0
- package/dist/src/utils/process.js +188 -0
- package/dist/src/utils/regex.d.ts +24 -0
- package/dist/src/utils/regex.js +40 -0
- package/dist/src/utils/validation.d.ts +133 -0
- package/dist/src/utils/validation.js +250 -0
- package/package.json +106 -0
- package/templates/configs/common.mozconfig +24 -0
- package/templates/configs/darwin.mozconfig +10 -0
- package/templates/configs/linux.mozconfig +12 -0
- package/templates/configs/win32.mozconfig +14 -0
- package/templates/licenses/0BSD.md +14 -0
- package/templates/licenses/EUPL-1.2.md +294 -0
- package/templates/licenses/GPL-2.0-or-later.md +339 -0
- package/templates/licenses/MPL-2.0.md +383 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { validateBrandOverride } from '../core/brand-validation.js';
|
|
2
|
+
import { prepareBuildEnvironment } from '../core/build-prepare.js';
|
|
3
|
+
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
4
|
+
import { buildArtifactMismatchMessage, hasBuildArtifacts, machPackage } from '../core/mach.js';
|
|
5
|
+
import { GeneralError } from '../errors/base.js';
|
|
6
|
+
import { AmbiguousBuildArtifactsError, BuildError } from '../errors/build.js';
|
|
7
|
+
import { pathExists } from '../utils/fs.js';
|
|
8
|
+
import { error, info, intro, outro, verbose } from '../utils/logger.js';
|
|
9
|
+
import { pickDefined } from '../utils/options.js';
|
|
10
|
+
/**
|
|
11
|
+
* Runs the package command to create a distribution package.
|
|
12
|
+
* @param projectRoot - Root directory of the project
|
|
13
|
+
* @param options - Package options
|
|
14
|
+
*/
|
|
15
|
+
export async function packageCommand(projectRoot, options) {
|
|
16
|
+
const brandInfo = options.brand ? ` [${options.brand}]` : '';
|
|
17
|
+
intro(`FireForge Package${brandInfo}`);
|
|
18
|
+
// Load configuration
|
|
19
|
+
const config = await loadConfig(projectRoot);
|
|
20
|
+
const paths = getProjectPaths(projectRoot);
|
|
21
|
+
validateBrandOverride(config.binaryName, options.brand);
|
|
22
|
+
// Check if engine exists
|
|
23
|
+
if (!(await pathExists(paths.engine))) {
|
|
24
|
+
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
25
|
+
}
|
|
26
|
+
const buildCheck = await hasBuildArtifacts(paths.engine);
|
|
27
|
+
if (buildCheck.ambiguous && buildCheck.objDirs && buildCheck.objDirs.length > 0) {
|
|
28
|
+
throw new AmbiguousBuildArtifactsError(buildCheck.objDirs);
|
|
29
|
+
}
|
|
30
|
+
const mismatchMessage = buildArtifactMismatchMessage(paths.engine, buildCheck, 'Package');
|
|
31
|
+
if (mismatchMessage) {
|
|
32
|
+
throw new GeneralError(mismatchMessage);
|
|
33
|
+
}
|
|
34
|
+
if (!buildCheck.exists) {
|
|
35
|
+
const detail = buildCheck.objDir
|
|
36
|
+
? `Build artifacts incomplete in ${buildCheck.objDir}/`
|
|
37
|
+
: 'No build artifacts found (obj-*/ directory missing)';
|
|
38
|
+
throw new GeneralError(`Packaging requires a completed build. ${detail}\n\n` +
|
|
39
|
+
"Run 'fireforge build' first, then rerun 'fireforge package'.");
|
|
40
|
+
}
|
|
41
|
+
// Log brand info if specified
|
|
42
|
+
if (options.brand) {
|
|
43
|
+
verbose(`Packaging with brand: ${options.brand}`);
|
|
44
|
+
info(`Brand: ${options.brand}`);
|
|
45
|
+
}
|
|
46
|
+
// Shared pre-flight: branding, Furnace, mozconfig
|
|
47
|
+
await prepareBuildEnvironment(projectRoot, paths, config);
|
|
48
|
+
// Run package
|
|
49
|
+
info('Creating distribution package...');
|
|
50
|
+
info('This may take a while.\n');
|
|
51
|
+
const startTime = Date.now();
|
|
52
|
+
let exitCode;
|
|
53
|
+
try {
|
|
54
|
+
exitCode = await machPackage(paths.engine);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new BuildError('Package process failed to start', 'mach package', error instanceof Error ? error : undefined);
|
|
58
|
+
}
|
|
59
|
+
const duration = Date.now() - startTime;
|
|
60
|
+
const minutes = Math.floor(duration / 60000);
|
|
61
|
+
const seconds = Math.floor((duration % 60000) / 1000);
|
|
62
|
+
const timeStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
63
|
+
if (exitCode !== 0) {
|
|
64
|
+
error(`Packaging failed after ${timeStr}`);
|
|
65
|
+
throw new BuildError(`Packaging failed with exit code ${exitCode}`, 'mach package');
|
|
66
|
+
}
|
|
67
|
+
info(`\nPackage created in obj-*/dist/`);
|
|
68
|
+
outro(`Packaging completed in ${timeStr}!`);
|
|
69
|
+
}
|
|
70
|
+
/** Registers the package command on the CLI program. */
|
|
71
|
+
export function registerPackage(program, { getProjectRoot, withErrorHandling }) {
|
|
72
|
+
program
|
|
73
|
+
.command('package')
|
|
74
|
+
.description('Create distribution package')
|
|
75
|
+
.option('--brand <name>', 'Package specific brand')
|
|
76
|
+
.action(withErrorHandling(async (options) => {
|
|
77
|
+
await packageCommand(getProjectRoot(), pickDefined(options));
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=package.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { CommandContext } from '../types/cli.js';
|
|
3
|
+
import type { ReExportOptions } from '../types/commands/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Runs the re-export command to regenerate existing patches from current engine state.
|
|
6
|
+
* @param projectRoot - Root directory of the project
|
|
7
|
+
* @param patches - Patch identifiers (numbers or filenames)
|
|
8
|
+
* @param options - Re-export options
|
|
9
|
+
*/
|
|
10
|
+
export declare function reExportCommand(projectRoot: string, patches: string[], options: ReExportOptions): Promise<void>;
|
|
11
|
+
/** Registers the re-export command on the CLI program. */
|
|
12
|
+
export declare function registerReExport(program: Command, { getProjectRoot, withErrorHandling }: CommandContext): void;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { multiselect } from '@clack/prompts';
|
|
4
|
+
import { getProjectPaths, loadConfig } from '../core/config.js';
|
|
5
|
+
import { isGitRepository } from '../core/git.js';
|
|
6
|
+
import { getDiffForFilesAgainstHead } from '../core/git-diff.js';
|
|
7
|
+
import { getModifiedFilesInDir, getUntrackedFilesInDir } from '../core/git-status.js';
|
|
8
|
+
import { updatePatch, updatePatchMetadata } from '../core/patch-export.js';
|
|
9
|
+
import { lintExportedPatch } from '../core/patch-lint.js';
|
|
10
|
+
import { getClaimedFiles, loadPatchesManifest } from '../core/patch-manifest.js';
|
|
11
|
+
import { GeneralError, InvalidArgumentError } from '../errors/base.js';
|
|
12
|
+
import { toError } from '../utils/errors.js';
|
|
13
|
+
import { pathExists } from '../utils/fs.js';
|
|
14
|
+
import { cancel, info, intro, isCancel, outro, spinner, success, warn } from '../utils/logger.js';
|
|
15
|
+
import { pickDefined } from '../utils/options.js';
|
|
16
|
+
/**
|
|
17
|
+
* Resolves patch identifiers (numbers or filenames) to manifest entries.
|
|
18
|
+
* @param identifier - Patch number (e.g. "005") or filename (e.g. "005-ui-storage-modules.patch")
|
|
19
|
+
* @param patches - All patches from the manifest
|
|
20
|
+
* @returns Matching patch metadata
|
|
21
|
+
*/
|
|
22
|
+
function resolvePatchIdentifier(identifier, patches) {
|
|
23
|
+
// If all digits, match by order number
|
|
24
|
+
if (/^\d+$/.test(identifier)) {
|
|
25
|
+
const order = parseInt(identifier, 10);
|
|
26
|
+
return patches.find((p) => p.order === order) ?? null;
|
|
27
|
+
}
|
|
28
|
+
// Match by filename (with or without .patch suffix)
|
|
29
|
+
const normalized = identifier.endsWith('.patch') ? identifier : `${identifier}.patch`;
|
|
30
|
+
return patches.find((p) => p.filename === normalized) ?? null;
|
|
31
|
+
}
|
|
32
|
+
async function scanPatchFiles(currentFilesAffected, engineDir, manifest, patchFilename, isDryRun) {
|
|
33
|
+
const parentDirs = [...new Set(currentFilesAffected.map((f) => dirname(f)))];
|
|
34
|
+
const claimedByOthers = getClaimedFiles(manifest, patchFilename);
|
|
35
|
+
const discoveredFiles = new Set();
|
|
36
|
+
for (const dir of parentDirs) {
|
|
37
|
+
const modifiedFiles = await getModifiedFilesInDir(engineDir, dir);
|
|
38
|
+
const untrackedFiles = await getUntrackedFilesInDir(engineDir, dir);
|
|
39
|
+
for (const f of [...modifiedFiles, ...untrackedFiles]) {
|
|
40
|
+
discoveredFiles.add(f);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const currentSet = new Set(currentFilesAffected);
|
|
44
|
+
const added = [];
|
|
45
|
+
for (const f of discoveredFiles) {
|
|
46
|
+
if (!currentSet.has(f) && !claimedByOthers.has(f)) {
|
|
47
|
+
added.push(f);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const removed = [];
|
|
51
|
+
for (const f of currentFilesAffected) {
|
|
52
|
+
const filePath = join(engineDir, f);
|
|
53
|
+
if (!(await pathExists(filePath))) {
|
|
54
|
+
removed.push(f);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const f of added.sort()) {
|
|
58
|
+
info(` + ${f}`);
|
|
59
|
+
}
|
|
60
|
+
for (const f of removed.sort()) {
|
|
61
|
+
info(` - ${f}`);
|
|
62
|
+
}
|
|
63
|
+
if (added.length > 0 || removed.length > 0) {
|
|
64
|
+
const removedSet = new Set(removed);
|
|
65
|
+
const updated = [...currentFilesAffected.filter((f) => !removedSet.has(f)), ...added].sort();
|
|
66
|
+
info(` ${isDryRun ? 'Would update' : 'Updated'} ${patchFilename}: +${added.length} / -${removed.length} files`);
|
|
67
|
+
return updated;
|
|
68
|
+
}
|
|
69
|
+
return currentFilesAffected;
|
|
70
|
+
}
|
|
71
|
+
async function reExportSinglePatch(patch, paths, manifest, options, isDryRun, config) {
|
|
72
|
+
let currentFilesAffected = [...patch.filesAffected];
|
|
73
|
+
// --- Scan for new/removed files ---
|
|
74
|
+
if (options.scan) {
|
|
75
|
+
currentFilesAffected = await scanPatchFiles(currentFilesAffected, paths.engine, manifest, patch.filename, isDryRun);
|
|
76
|
+
}
|
|
77
|
+
const missingFiles = [];
|
|
78
|
+
for (const file of currentFilesAffected) {
|
|
79
|
+
const filePath = join(paths.engine, file);
|
|
80
|
+
if (!(await pathExists(filePath))) {
|
|
81
|
+
missingFiles.push(file);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (missingFiles.length === currentFilesAffected.length) {
|
|
85
|
+
warn(`Skipped ${patch.filename}: all affected files missing`);
|
|
86
|
+
warn(`Missing files: ${missingFiles.join(', ')}`);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (missingFiles.length > 0) {
|
|
90
|
+
warn(`${patch.filename}: missing files will be skipped: ${missingFiles.join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
const missingSet = new Set(missingFiles);
|
|
93
|
+
const existingFiles = currentFilesAffected.filter((f) => !missingSet.has(f));
|
|
94
|
+
const diffContent = await getDiffForFilesAgainstHead(paths.engine, existingFiles);
|
|
95
|
+
if (!diffContent.trim()) {
|
|
96
|
+
warn(`Skipped ${patch.filename}: no changes (files unchanged from HEAD)`);
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
if (isDryRun) {
|
|
100
|
+
info(`[dry-run] ${patch.filename}: ${existingFiles.length} file(s)`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const patchPath = join(paths.patches, patch.filename);
|
|
104
|
+
await updatePatch(patchPath, diffContent);
|
|
105
|
+
await updatePatchMetadata(paths.patches, patch.filename, {
|
|
106
|
+
filesAffected: currentFilesAffected,
|
|
107
|
+
});
|
|
108
|
+
const patchIndex = manifest.patches.findIndex((pm) => pm.filename === patch.filename);
|
|
109
|
+
if (patchIndex !== -1) {
|
|
110
|
+
const existingEntry = manifest.patches[patchIndex];
|
|
111
|
+
if (existingEntry) {
|
|
112
|
+
manifest.patches[patchIndex] = {
|
|
113
|
+
...existingEntry,
|
|
114
|
+
filesAffected: currentFilesAffected,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const lintIssues = await lintExportedPatch(paths.engine, existingFiles, diffContent, config);
|
|
119
|
+
for (const issue of lintIssues) {
|
|
120
|
+
const prefix = issue.severity === 'error' && !options.skipLint ? 'ERROR ' : '';
|
|
121
|
+
warn(`${prefix}[${issue.check}] ${issue.file}: ${issue.message}`);
|
|
122
|
+
}
|
|
123
|
+
const lintErrors = lintIssues.filter((i) => i.severity === 'error');
|
|
124
|
+
if (lintErrors.length > 0 && !options.skipLint) {
|
|
125
|
+
warn(`${patch.filename}: ${lintErrors.length} lint error(s). Use --skip-lint to bypass.`);
|
|
126
|
+
}
|
|
127
|
+
success(`Re-exported ${patch.filename}`);
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
async function resolveSelectedPatches(patches, options, manifest) {
|
|
132
|
+
if (options.all) {
|
|
133
|
+
return [...manifest.patches];
|
|
134
|
+
}
|
|
135
|
+
if (patches.length > 0) {
|
|
136
|
+
const selectedPatches = [];
|
|
137
|
+
for (const identifier of patches) {
|
|
138
|
+
const match = resolvePatchIdentifier(identifier, manifest.patches);
|
|
139
|
+
if (!match) {
|
|
140
|
+
const available = manifest.patches.map((p) => p.filename).join(', ');
|
|
141
|
+
throw new InvalidArgumentError(`Patch "${identifier}" not found in manifest.\n\nAvailable patches: ${available}`, identifier);
|
|
142
|
+
}
|
|
143
|
+
selectedPatches.push(match);
|
|
144
|
+
}
|
|
145
|
+
return selectedPatches;
|
|
146
|
+
}
|
|
147
|
+
// No patches specified — prompt or error
|
|
148
|
+
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
149
|
+
if (!isInteractive) {
|
|
150
|
+
throw new InvalidArgumentError('Specify patch identifiers or use --all in non-interactive mode.\n\n' +
|
|
151
|
+
'Usage: fireforge re-export [patches...] or fireforge re-export --all', 'patches');
|
|
152
|
+
}
|
|
153
|
+
const selected = await multiselect({
|
|
154
|
+
message: 'Select patches to re-export:',
|
|
155
|
+
options: manifest.patches.map((patch) => ({
|
|
156
|
+
value: patch.filename,
|
|
157
|
+
label: `${patch.filename} — ${patch.description || patch.name}`,
|
|
158
|
+
})),
|
|
159
|
+
});
|
|
160
|
+
if (isCancel(selected)) {
|
|
161
|
+
cancel('Re-export cancelled');
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const selectedFilenames = selected;
|
|
165
|
+
return manifest.patches.filter((p) => selectedFilenames.includes(p.filename));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Runs the re-export command to regenerate existing patches from current engine state.
|
|
169
|
+
* @param projectRoot - Root directory of the project
|
|
170
|
+
* @param patches - Patch identifiers (numbers or filenames)
|
|
171
|
+
* @param options - Re-export options
|
|
172
|
+
*/
|
|
173
|
+
export async function reExportCommand(projectRoot, patches, options) {
|
|
174
|
+
const isDryRun = options.dryRun === true;
|
|
175
|
+
intro(isDryRun ? 'FireForge Re-export (dry run)' : 'FireForge Re-export');
|
|
176
|
+
const paths = getProjectPaths(projectRoot);
|
|
177
|
+
// Check if engine exists
|
|
178
|
+
if (!(await pathExists(paths.engine))) {
|
|
179
|
+
throw new GeneralError('Firefox source not found. Run "fireforge download" first.');
|
|
180
|
+
}
|
|
181
|
+
// Check if it's a git repository
|
|
182
|
+
if (!(await isGitRepository(paths.engine))) {
|
|
183
|
+
throw new GeneralError('Engine directory is not a git repository. Run "fireforge download" to initialize.');
|
|
184
|
+
}
|
|
185
|
+
// Load the manifest
|
|
186
|
+
const manifest = await loadPatchesManifest(paths.patches);
|
|
187
|
+
if (!manifest || manifest.patches.length === 0) {
|
|
188
|
+
throw new GeneralError('No patches found in manifest. Run "fireforge export" to create patches first.');
|
|
189
|
+
}
|
|
190
|
+
// Resolve which patches to re-export
|
|
191
|
+
const selectedPatches = await resolveSelectedPatches(patches, options, manifest);
|
|
192
|
+
if (!selectedPatches)
|
|
193
|
+
return;
|
|
194
|
+
if (selectedPatches.length === 0) {
|
|
195
|
+
warn('No patches selected');
|
|
196
|
+
outro('Nothing to re-export');
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
const config = await loadConfig(projectRoot);
|
|
200
|
+
let reExported = 0;
|
|
201
|
+
const progress = spinner('Preparing re-export...');
|
|
202
|
+
for (const patch of selectedPatches) {
|
|
203
|
+
progress.message(`Re-exporting ${patch.filename}...`);
|
|
204
|
+
try {
|
|
205
|
+
const exported = await reExportSinglePatch(patch, paths, manifest, options, isDryRun, config);
|
|
206
|
+
if (exported)
|
|
207
|
+
reExported++;
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
warn(`Failed to re-export ${patch.filename}`);
|
|
211
|
+
warn(toError(error).message);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (reExported === 0 && selectedPatches.length > 0) {
|
|
215
|
+
progress.error('Re-export failed');
|
|
216
|
+
throw new GeneralError('All selected patches failed to re-export. Check the errors above.');
|
|
217
|
+
}
|
|
218
|
+
if (isDryRun) {
|
|
219
|
+
progress.stop('Dry run complete');
|
|
220
|
+
success(`[dry-run] Would re-export ${reExported} of ${selectedPatches.length} patch(es)`);
|
|
221
|
+
outro('Dry run complete');
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
progress.stop('Re-export complete');
|
|
225
|
+
success(`Re-exported ${reExported} of ${selectedPatches.length} patch(es)`);
|
|
226
|
+
outro('Re-export complete');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/** Registers the re-export command on the CLI program. */
|
|
230
|
+
export function registerReExport(program, { getProjectRoot, withErrorHandling }) {
|
|
231
|
+
program
|
|
232
|
+
.command('re-export [patches...]')
|
|
233
|
+
.description('Re-export existing patches from current engine state')
|
|
234
|
+
.option('-a, --all', 'Re-export all patches')
|
|
235
|
+
.option('-s, --scan', 'Scan directories for new/removed files and update filesAffected')
|
|
236
|
+
.option('--dry-run', 'Show what would change without writing')
|
|
237
|
+
.option('--skip-lint', 'Skip patch lint checks (downgrade errors to warnings)')
|
|
238
|
+
.action(withErrorHandling(async (patches, options) => {
|
|
239
|
+
await reExportCommand(getProjectRoot(), patches, pickDefined(options));
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=re-export.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Rebase abort flow.
|
|
4
|
+
*/
|
|
5
|
+
import { getProjectPaths, loadState, saveState } from '../../core/config.js';
|
|
6
|
+
import { resetChanges } from '../../core/git.js';
|
|
7
|
+
import { clearRebaseSession, loadRebaseSession } from '../../core/rebase-session.js';
|
|
8
|
+
import { NoRebaseSessionError } from '../../errors/rebase.js';
|
|
9
|
+
import { intro, outro, spinner, success } from '../../utils/logger.js';
|
|
10
|
+
import { confirmDirtyEngineReset } from './confirm.js';
|
|
11
|
+
/**
|
|
12
|
+
* Handles `fireforge rebase --abort`.
|
|
13
|
+
*/
|
|
14
|
+
export async function handleAbort(projectRoot, force) {
|
|
15
|
+
intro('FireForge Rebase — Abort');
|
|
16
|
+
const session = await loadRebaseSession(projectRoot);
|
|
17
|
+
if (!session)
|
|
18
|
+
throw new NoRebaseSessionError();
|
|
19
|
+
const paths = getProjectPaths(projectRoot);
|
|
20
|
+
if (!(await confirmDirtyEngineReset({
|
|
21
|
+
engineDir: paths.engine,
|
|
22
|
+
force: force ?? false,
|
|
23
|
+
nonInteractiveHint: 'Use: fireforge rebase --abort --force',
|
|
24
|
+
warningMessage: 'The engine directory has uncommitted changes that will be lost.',
|
|
25
|
+
promptMessage: 'Discard uncommitted changes and abort rebase?',
|
|
26
|
+
cancelMessage: 'Abort cancelled',
|
|
27
|
+
}))) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const s = spinner('Restoring engine to pre-rebase state...');
|
|
31
|
+
try {
|
|
32
|
+
await resetChanges(paths.engine);
|
|
33
|
+
s.stop('Engine restored');
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
s.error('Failed to restore engine');
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
// Clear pending resolution state if any
|
|
40
|
+
const state = await loadState(projectRoot);
|
|
41
|
+
if (state.pendingResolution) {
|
|
42
|
+
delete state.pendingResolution;
|
|
43
|
+
await saveState(projectRoot, state);
|
|
44
|
+
}
|
|
45
|
+
await clearRebaseSession(projectRoot);
|
|
46
|
+
success('Rebase aborted and session cleared.');
|
|
47
|
+
outro('Rebase aborted');
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=abort.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dirty-engine confirmation/reset flow.
|
|
3
|
+
*/
|
|
4
|
+
/** Options for the dirty-engine confirmation prompt. */
|
|
5
|
+
export interface DirtyEngineConfirmationOptions {
|
|
6
|
+
engineDir: string;
|
|
7
|
+
force: boolean;
|
|
8
|
+
nonInteractiveHint: string;
|
|
9
|
+
warningMessage: string;
|
|
10
|
+
promptMessage: string;
|
|
11
|
+
cancelMessage: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks if the engine has uncommitted changes and prompts for confirmation.
|
|
15
|
+
* Returns true if safe to proceed, false if the user cancelled.
|
|
16
|
+
* Throws in non-interactive mode without --force.
|
|
17
|
+
*/
|
|
18
|
+
export declare function confirmDirtyEngineReset({ engineDir, force, nonInteractiveHint, warningMessage, promptMessage, cancelMessage, }: DirtyEngineConfirmationOptions): Promise<boolean>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Dirty-engine confirmation/reset flow.
|
|
4
|
+
*/
|
|
5
|
+
import { confirm } from '@clack/prompts';
|
|
6
|
+
import { hasChanges } from '../../core/git.js';
|
|
7
|
+
import { InvalidArgumentError } from '../../errors/base.js';
|
|
8
|
+
import { cancel, isCancel, warn } from '../../utils/logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* Checks if the engine has uncommitted changes and prompts for confirmation.
|
|
11
|
+
* Returns true if safe to proceed, false if the user cancelled.
|
|
12
|
+
* Throws in non-interactive mode without --force.
|
|
13
|
+
*/
|
|
14
|
+
export async function confirmDirtyEngineReset({ engineDir, force, nonInteractiveHint, warningMessage, promptMessage, cancelMessage, }) {
|
|
15
|
+
if (!(await hasChanges(engineDir)) || force) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
|
|
19
|
+
if (!isInteractive) {
|
|
20
|
+
throw new InvalidArgumentError('Engine has uncommitted changes and interactive confirmation is not available. Use --force to proceed.', nonInteractiveHint);
|
|
21
|
+
}
|
|
22
|
+
warn(warningMessage);
|
|
23
|
+
const confirmed = await confirm({
|
|
24
|
+
message: promptMessage,
|
|
25
|
+
initialValue: false,
|
|
26
|
+
});
|
|
27
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
28
|
+
cancel(cancelMessage);
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=confirm.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// SPDX-License-Identifier: EUPL-1.2
|
|
2
|
+
/**
|
|
3
|
+
* Rebase --continue flow.
|
|
4
|
+
*/
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { getProjectPaths, loadState, saveState } from '../../core/config.js';
|
|
7
|
+
import { getStagedDiffForFiles } from '../../core/git-diff.js';
|
|
8
|
+
import { stageFiles, unstageFiles } from '../../core/git-file-ops.js';
|
|
9
|
+
import { updatePatch, updatePatchMetadata } from '../../core/patch-export.js';
|
|
10
|
+
import { loadPatchesManifest } from '../../core/patch-manifest.js';
|
|
11
|
+
import { loadRebaseSession, saveRebaseSession } from '../../core/rebase-session.js';
|
|
12
|
+
import { GeneralError } from '../../errors/base.js';
|
|
13
|
+
import { NoRebaseSessionError, RebaseError } from '../../errors/rebase.js';
|
|
14
|
+
import { pathExists } from '../../utils/fs.js';
|
|
15
|
+
import { info, intro, success, warn } from '../../utils/logger.js';
|
|
16
|
+
import { runPatchLoop } from './patch-loop.js';
|
|
17
|
+
/**
|
|
18
|
+
* Handles `fireforge rebase --continue`.
|
|
19
|
+
*/
|
|
20
|
+
export async function handleContinue(projectRoot, maxFuzz) {
|
|
21
|
+
intro('FireForge Rebase — Continue');
|
|
22
|
+
const session = await loadRebaseSession(projectRoot);
|
|
23
|
+
if (!session)
|
|
24
|
+
throw new NoRebaseSessionError();
|
|
25
|
+
const paths = getProjectPaths(projectRoot);
|
|
26
|
+
// The current patch should be in 'failed' state
|
|
27
|
+
const currentPatch = session.patches[session.currentIndex];
|
|
28
|
+
if (!currentPatch || currentPatch.status !== 'failed') {
|
|
29
|
+
throw new RebaseError('Expected the current patch to be in a failed state. The session may be corrupt.');
|
|
30
|
+
}
|
|
31
|
+
info(`Resolving: ${currentPatch.filename}`);
|
|
32
|
+
// Look up the patch's files from the manifest
|
|
33
|
+
const manifest = await loadPatchesManifest(paths.patches);
|
|
34
|
+
if (!manifest)
|
|
35
|
+
throw new GeneralError('Patches manifest not found.');
|
|
36
|
+
const meta = manifest.patches.find((p) => p.filename === currentPatch.filename);
|
|
37
|
+
if (!meta)
|
|
38
|
+
throw new GeneralError(`Patch ${currentPatch.filename} not found in manifest.`);
|
|
39
|
+
// Re-export the resolved patch from current engine state
|
|
40
|
+
const activeFiles = [];
|
|
41
|
+
for (const f of meta.filesAffected) {
|
|
42
|
+
if (await pathExists(join(paths.engine, f))) {
|
|
43
|
+
activeFiles.push(f);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let staged = false;
|
|
47
|
+
try {
|
|
48
|
+
await stageFiles(paths.engine, activeFiles);
|
|
49
|
+
staged = true;
|
|
50
|
+
const diffContent = await getStagedDiffForFiles(paths.engine, activeFiles);
|
|
51
|
+
if (!diffContent.trim()) {
|
|
52
|
+
warn('No diff generated — the files may not have changed from HEAD.');
|
|
53
|
+
warn('Either apply your fixes and re-run --continue, or skip this patch (not yet supported).');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const patchPath = join(paths.patches, currentPatch.filename);
|
|
57
|
+
await updatePatch(patchPath, diffContent);
|
|
58
|
+
await updatePatchMetadata(paths.patches, currentPatch.filename, {
|
|
59
|
+
sourceEsrVersion: session.toVersion,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
if (staged) {
|
|
64
|
+
await unstageFiles(paths.engine, activeFiles);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Mark resolved and advance
|
|
68
|
+
currentPatch.status = 'resolved';
|
|
69
|
+
session.currentIndex++;
|
|
70
|
+
await saveRebaseSession(projectRoot, session);
|
|
71
|
+
// Clear pending resolution
|
|
72
|
+
const state = await loadState(projectRoot);
|
|
73
|
+
if (state.pendingResolution) {
|
|
74
|
+
delete state.pendingResolution;
|
|
75
|
+
await saveState(projectRoot, state);
|
|
76
|
+
}
|
|
77
|
+
success(`Resolved ${currentPatch.filename}`);
|
|
78
|
+
// Continue applying remaining patches
|
|
79
|
+
await runPatchLoop(projectRoot, session, paths, maxFuzz);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=continue.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fireforge rebase` — semi-automated ESR version upgrade.
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the full patch-rebase workflow:
|
|
5
|
+
* 1. Reset engine to baseline
|
|
6
|
+
* 2. Apply each patch with escalating fuzz
|
|
7
|
+
* 3. Pause on failures for manual resolution
|
|
8
|
+
* 4. Re-export successfully applied patches with the new version stamp
|
|
9
|
+
*
|
|
10
|
+
* Supports `--continue` (resume after manual fix) and `--abort` (cancel).
|
|
11
|
+
*/
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
import type { CommandContext } from '../../types/cli.js';
|
|
14
|
+
import type { RebaseOptions } from '../../types/commands/index.js';
|
|
15
|
+
/**
|
|
16
|
+
* Runs the rebase command to orchestrate an ESR version upgrade.
|
|
17
|
+
* @param projectRoot - Root directory of the project
|
|
18
|
+
* @param options - Rebase options
|
|
19
|
+
*/
|
|
20
|
+
export declare function rebaseCommand(projectRoot: string, options?: RebaseOptions): Promise<void>;
|
|
21
|
+
/** Registers the rebase command on the CLI program. */
|
|
22
|
+
export declare function registerRebase(program: Command, { getProjectRoot, withErrorHandling }: CommandContext): void;
|