@hominis/fireforge 0.15.8 → 0.16.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 +85 -0
- package/README.md +16 -3
- package/dist/src/cli.d.ts +4 -1
- package/dist/src/cli.js +6 -3
- package/dist/src/commands/download.js +9 -0
- package/dist/src/commands/export-all.js +46 -0
- package/dist/src/commands/export-shared.d.ts +6 -1
- package/dist/src/commands/export-shared.js +7 -2
- package/dist/src/commands/export.js +10 -1
- package/dist/src/commands/furnace/diff.js +22 -2
- package/dist/src/commands/furnace/override.js +35 -12
- package/dist/src/commands/furnace/preview.js +33 -1
- package/dist/src/commands/furnace/rename.js +14 -3
- package/dist/src/commands/lint.d.ts +20 -0
- package/dist/src/commands/lint.js +167 -45
- package/dist/src/commands/package.js +16 -5
- package/dist/src/commands/re-export-files.js +6 -2
- package/dist/src/commands/re-export.js +62 -4
- package/dist/src/commands/register.js +2 -18
- package/dist/src/commands/run.js +23 -2
- package/dist/src/commands/status.js +25 -3
- package/dist/src/commands/test.js +6 -24
- package/dist/src/commands/token.js +14 -1
- package/dist/src/commands/watch.js +14 -2
- package/dist/src/core/branding.d.ts +23 -0
- package/dist/src/core/branding.js +39 -0
- package/dist/src/core/browser-wire.js +68 -23
- package/dist/src/core/mach-build-artifacts.d.ts +41 -0
- package/dist/src/core/mach-build-artifacts.js +70 -0
- package/dist/src/core/mach-error-hints.js +15 -0
- package/dist/src/core/mach-mozconfig.d.ts +25 -0
- package/dist/src/core/mach-mozconfig.js +66 -0
- package/dist/src/core/mach.d.ts +12 -1
- package/dist/src/core/mach.js +14 -1
- package/dist/src/core/manifest-rules.js +22 -1
- package/dist/src/core/patch-lint.d.ts +6 -1
- package/dist/src/core/patch-lint.js +14 -1
- package/dist/src/types/commands/options.d.ts +10 -0
- package/dist/src/types/commands/patches.d.ts +22 -0
- package/dist/src/utils/fs.d.ts +12 -0
- package/dist/src/utils/fs.js +12 -0
- package/dist/src/utils/paths.d.ts +19 -0
- package/dist/src/utils/paths.js +33 -0
- package/package.json +1 -1
|
@@ -16,7 +16,15 @@ export function getRules(binaryName) {
|
|
|
16
16
|
extractArgs: (m) => [m[1] ?? ''],
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
|
|
19
|
+
// `.inc.xhtml` fragments under browser/base/content/ are deliberately
|
|
20
|
+
// excluded: they are consumed via `#include` from a registered chrome
|
|
21
|
+
// document (typically browser.xhtml) and do not get their own
|
|
22
|
+
// packaged chrome URI. Before this carve-out, `status` flagged every
|
|
23
|
+
// wired fragment as "potentially unregistered" and `register --dry-run`
|
|
24
|
+
// proposed a bogus jar.mn entry. The lookahead blocks the match so
|
|
25
|
+
// `getUnregistrableAdvice` gets a chance to emit the correct
|
|
26
|
+
// guidance for the `.inc.xhtml` case.
|
|
27
|
+
pattern: /^browser\/base\/content\/(?!.+\.inc\.xhtml$)(.+\.(?:js|mjs|xhtml|css))$/,
|
|
20
28
|
isRegistered: (engineDir, fileName) => isBrowserContentRegistered(engineDir, fileName),
|
|
21
29
|
register: (engineDir, after, dryRun, fileName) => registerBrowserContent(engineDir, fileName, after, undefined, dryRun),
|
|
22
30
|
extractArgs: (m) => [m[1] ?? ''],
|
|
@@ -98,6 +106,19 @@ function getUnregistrableAdvice(filePath) {
|
|
|
98
106
|
if (filePath.endsWith('.ftl')) {
|
|
99
107
|
return "FTL locale files are auto-discovered via jar.mn glob patterns and don't need manual registration.";
|
|
100
108
|
}
|
|
109
|
+
// `.inc.xhtml` fragments live under browser/base/content/ but are
|
|
110
|
+
// consumed via `#include` from a registered chrome document (browser.xhtml
|
|
111
|
+
// by default; a fork's custom top-level doc when `wire --dom-target` is
|
|
112
|
+
// set). The preprocessor resolves the include at packaging time, so the
|
|
113
|
+
// fragment never needs its own chrome URI entry in jar.mn. Give the
|
|
114
|
+
// operator the actionable `wire` path instead of letting the generic
|
|
115
|
+
// "unknown file pattern" message above fire.
|
|
116
|
+
if (/^browser\/base\/content\/.+\.inc\.xhtml$/.test(filePath)) {
|
|
117
|
+
return ('`.inc.xhtml` fragments are consumed via `#include` from a registered chrome document ' +
|
|
118
|
+
'(e.g. browser.xhtml). They do not need an independent jar.mn entry — run ' +
|
|
119
|
+
'"fireforge wire <name> --dom <path>" to insert the #include, or add the directive manually ' +
|
|
120
|
+
'in the top-level chrome document.');
|
|
121
|
+
}
|
|
101
122
|
const testMatch = filePath.match(/^browser\/base\/content\/test\/([^/]+)\/(?!browser\.toml$).+$/);
|
|
102
123
|
if (testMatch) {
|
|
103
124
|
const dir = testMatch[1];
|
|
@@ -89,6 +89,11 @@ export declare function lintModifiedFileHeaders(repoDir: string, affectedFiles:
|
|
|
89
89
|
* @param diffContent - Raw unified diff string
|
|
90
90
|
* @param config - Project configuration
|
|
91
91
|
* @param patchQueueCtx - Optional cross-patch context for ownership resolution
|
|
92
|
+
* @param ignoreChecks - Optional set of per-patch `check` IDs to drop from the
|
|
93
|
+
* returned issues. Threaded from `PatchMetadata.lintIgnore` so a patch that
|
|
94
|
+
* is advisory-noisy by nature (a cohesive branding bundle, auto-generated
|
|
95
|
+
* manifest, etc.) can opt out of a specific rule without reaching for the
|
|
96
|
+
* blunt `--skip-lint` hammer. Not mutated by this function.
|
|
92
97
|
* @returns Array of all lint issues found
|
|
93
98
|
*/
|
|
94
|
-
export declare function lintExportedPatch(repoDir: string, affectedFiles: string[], diffContent: string, config: FireForgeConfig, patchQueueCtx?: import('./patch-lint-cross.js').PatchQueueContext): Promise<PatchLintIssue[]>;
|
|
99
|
+
export declare function lintExportedPatch(repoDir: string, affectedFiles: string[], diffContent: string, config: FireForgeConfig, patchQueueCtx?: import('./patch-lint-cross.js').PatchQueueContext, ignoreChecks?: ReadonlySet<string>): Promise<PatchLintIssue[]>;
|
|
@@ -455,9 +455,14 @@ export async function lintModifiedFileHeaders(repoDir, affectedFiles, newFiles)
|
|
|
455
455
|
* @param diffContent - Raw unified diff string
|
|
456
456
|
* @param config - Project configuration
|
|
457
457
|
* @param patchQueueCtx - Optional cross-patch context for ownership resolution
|
|
458
|
+
* @param ignoreChecks - Optional set of per-patch `check` IDs to drop from the
|
|
459
|
+
* returned issues. Threaded from `PatchMetadata.lintIgnore` so a patch that
|
|
460
|
+
* is advisory-noisy by nature (a cohesive branding bundle, auto-generated
|
|
461
|
+
* manifest, etc.) can opt out of a specific rule without reaching for the
|
|
462
|
+
* blunt `--skip-lint` hammer. Not mutated by this function.
|
|
458
463
|
* @returns Array of all lint issues found
|
|
459
464
|
*/
|
|
460
|
-
export async function lintExportedPatch(repoDir, affectedFiles, diffContent, config, patchQueueCtx) {
|
|
465
|
+
export async function lintExportedPatch(repoDir, affectedFiles, diffContent, config, patchQueueCtx, ignoreChecks) {
|
|
461
466
|
const newFiles = detectNewFilesInDiff(diffContent);
|
|
462
467
|
const { textLines: lineCount } = countNonBinaryDiffLines(diffContent);
|
|
463
468
|
const patchOwnedFiles = resolvePatchOwnedSysMjs(newFiles, patchQueueCtx);
|
|
@@ -482,6 +487,14 @@ export async function lintExportedPatch(repoDir, affectedFiles, diffContent, con
|
|
|
482
487
|
const checkJsIssues = await runCheckJs(repoDir, patchOwnedFiles);
|
|
483
488
|
issues.push(...checkJsIssues);
|
|
484
489
|
}
|
|
490
|
+
// Filter out ignored checks last so every rule still runs (keeps the
|
|
491
|
+
// implementation uniform) but suppressed rules do not surface. We do not
|
|
492
|
+
// reclassify severities — an ignored error simply drops, mirroring how
|
|
493
|
+
// inline `fireforge-ignore: <check>` markers work in the CSS and
|
|
494
|
+
// forward-import rules.
|
|
495
|
+
if (ignoreChecks && ignoreChecks.size > 0) {
|
|
496
|
+
return issues.filter((issue) => !ignoreChecks.has(issue.check));
|
|
497
|
+
}
|
|
485
498
|
return issues;
|
|
486
499
|
}
|
|
487
500
|
//# sourceMappingURL=patch-lint.js.map
|
|
@@ -155,6 +155,16 @@ export interface ReExportOptions {
|
|
|
155
155
|
yes?: boolean;
|
|
156
156
|
/** Bypass cross-patch lint refusal on projected shrink state */
|
|
157
157
|
forceUnsafe?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* After every selected patch re-exports cleanly, stamp each re-exported
|
|
160
|
+
* patch's `sourceEsrVersion` in `patches.json` to the current
|
|
161
|
+
* `firefox.version` from `fireforge.json`. Opt-in because the default
|
|
162
|
+
* contract of `re-export` is "refresh the patch body and filesAffected";
|
|
163
|
+
* version stamping is normally a `rebase` responsibility. Use this when
|
|
164
|
+
* re-exporting after a manual Firefox bump that did not go through
|
|
165
|
+
* `rebase`.
|
|
166
|
+
*/
|
|
167
|
+
stamp?: boolean;
|
|
158
168
|
}
|
|
159
169
|
/**
|
|
160
170
|
* Options for the rebase command.
|
|
@@ -51,6 +51,28 @@ export interface PatchMetadata {
|
|
|
51
51
|
sourceEsrVersion: string;
|
|
52
52
|
/** Array of file paths affected by this patch */
|
|
53
53
|
filesAffected: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Optional per-patch list of lint check IDs to suppress when this patch
|
|
56
|
+
* is the target of `export`, `export-all`, or `re-export`. Exists for
|
|
57
|
+
* the class of patch that is advisory-noisy by nature — a cohesive
|
|
58
|
+
* branding bundle, a localised-resource pack, an auto-generated
|
|
59
|
+
* manifest — where the generic `large-patch-lines` / `large-patch-files`
|
|
60
|
+
* thresholds do not apply but `--skip-lint` (which silences *all*
|
|
61
|
+
* errors, not just the one that does not apply) is too coarse a hammer.
|
|
62
|
+
*
|
|
63
|
+
* Previously the only escape hatches were `--skip-lint` (blunt) or the
|
|
64
|
+
* full `rebase` flow (refreshes the same patch through a code path that
|
|
65
|
+
* silently skips `runPatchLint` — an asymmetry that forced operators
|
|
66
|
+
* through a multi-minute Firefox source re-download just to refresh
|
|
67
|
+
* one patch body).
|
|
68
|
+
*
|
|
69
|
+
* Values are free-form check IDs (e.g. `"large-patch-lines"`,
|
|
70
|
+
* `"large-patch-files"`). Checks not listed here still run normally.
|
|
71
|
+
* An entry for an unknown check ID is a no-op — the patch metadata
|
|
72
|
+
* documents the *intent* to suppress even if the check is later
|
|
73
|
+
* renamed or removed.
|
|
74
|
+
*/
|
|
75
|
+
lintIgnore?: string[];
|
|
54
76
|
}
|
|
55
77
|
/**
|
|
56
78
|
* Schema for patches/patches.json file.
|
package/dist/src/utils/fs.d.ts
CHANGED
|
@@ -78,6 +78,18 @@ export declare function writeFileAtomic(path: string, content: string | Buffer):
|
|
|
78
78
|
* @param dest - Destination directory path
|
|
79
79
|
*/
|
|
80
80
|
export declare function copyDir(src: string, dest: string): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Matches the atomic-temp-file shape emitted by `createAtomicTempPath`
|
|
83
|
+
* anywhere in a normalised (forward-slash) path. The `.fireforge-tmp-`
|
|
84
|
+
* marker plus a PID/UUID tail is unique to our own rename-based atomic
|
|
85
|
+
* writes, so callers (notably `status`) can filter these mid-flight
|
|
86
|
+
* artefacts out of their listings without racing the rename.
|
|
87
|
+
*
|
|
88
|
+
* Intentionally anchored so a legitimately-named backup file like
|
|
89
|
+
* `.notes.fireforge-tmp-backup` (no PID+UUID continuation) is NOT treated
|
|
90
|
+
* as one of our temps. The full shape is `.<filename>.fireforge-tmp-<pid>-<uuid>`.
|
|
91
|
+
*/
|
|
92
|
+
export declare const FIREFORGE_TMP_PATH_PATTERN: RegExp;
|
|
81
93
|
/**
|
|
82
94
|
* Checks available disk space at a path and warns via the provided
|
|
83
95
|
* callback when it falls below `minBytes`.
|
package/dist/src/utils/fs.js
CHANGED
|
@@ -180,6 +180,18 @@ export async function copyDir(src, dest) {
|
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Matches the atomic-temp-file shape emitted by `createAtomicTempPath`
|
|
185
|
+
* anywhere in a normalised (forward-slash) path. The `.fireforge-tmp-`
|
|
186
|
+
* marker plus a PID/UUID tail is unique to our own rename-based atomic
|
|
187
|
+
* writes, so callers (notably `status`) can filter these mid-flight
|
|
188
|
+
* artefacts out of their listings without racing the rename.
|
|
189
|
+
*
|
|
190
|
+
* Intentionally anchored so a legitimately-named backup file like
|
|
191
|
+
* `.notes.fireforge-tmp-backup` (no PID+UUID continuation) is NOT treated
|
|
192
|
+
* as one of our temps. The full shape is `.<filename>.fireforge-tmp-<pid>-<uuid>`.
|
|
193
|
+
*/
|
|
194
|
+
export const FIREFORGE_TMP_PATH_PATTERN = /(^|\/)\.[^/]+\.fireforge-tmp-\d+-[0-9a-f-]{36}$/i;
|
|
183
195
|
/**
|
|
184
196
|
* Generates a unique temp file path for atomic writes.
|
|
185
197
|
*
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
/** Converts Windows path separators to forward slashes for stable comparisons. */
|
|
2
2
|
export declare function normalizePathSlashes(path: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Strips a leading `engine/` (or `engine\\`) segment from a user-supplied
|
|
5
|
+
* path so the same command invocation accepts both repo-root-relative paths
|
|
6
|
+
* (`engine/browser/base/content/foo.js`) and engine-relative paths
|
|
7
|
+
* (`browser/base/content/foo.js`). The match is case-insensitive because
|
|
8
|
+
* default macOS and Windows filesystems treat `Engine/` and `engine/` as
|
|
9
|
+
* the same directory; a literal lowercase-only check previously left `mach`
|
|
10
|
+
* / the manifest writers resolving against a wrongly-cased prefix. Leading
|
|
11
|
+
* whitespace is ignored so tab-completed inputs don't slip past the strip.
|
|
12
|
+
*
|
|
13
|
+
* The return value is trimmed of the same leading whitespace when the
|
|
14
|
+
* prefix matched, and otherwise passed through verbatim — callers that
|
|
15
|
+
* care about internal whitespace can trim on their side.
|
|
16
|
+
*
|
|
17
|
+
* @param filePath Path as provided by the user
|
|
18
|
+
* @returns Path relative to the engine directory (or the original when the
|
|
19
|
+
* prefix was absent)
|
|
20
|
+
*/
|
|
21
|
+
export declare function stripEnginePrefix(filePath: string): string;
|
|
3
22
|
/** Checks whether a path is explicitly absolute on either POSIX or Windows. */
|
|
4
23
|
export declare function isExplicitAbsolutePath(path: string): boolean;
|
|
5
24
|
/** Resolves a candidate path and returns whether it stays within the given root. */
|
package/dist/src/utils/paths.js
CHANGED
|
@@ -2,10 +2,43 @@
|
|
|
2
2
|
import { isAbsolute, relative, resolve } from 'node:path';
|
|
3
3
|
const WINDOWS_ABSOLUTE_PATH = /^[a-zA-Z]:[\\/]/;
|
|
4
4
|
const RELATIVE_PATH_ROOT = resolve('/__fireforge_path_root__');
|
|
5
|
+
/**
|
|
6
|
+
* Matches a leading `engine/` or `engine\\` segment (case-insensitive,
|
|
7
|
+
* tolerates leading whitespace). Shared between `register`, `test`, `lint`,
|
|
8
|
+
* and `export` so every command that takes an engine-relative path accepts
|
|
9
|
+
* both the repo-root form (`engine/browser/...`) and the engine-relative
|
|
10
|
+
* form (`browser/...`) without diverging.
|
|
11
|
+
*/
|
|
12
|
+
const ENGINE_PREFIX_PATTERN = /^\s*engine[/\\]/i;
|
|
5
13
|
/** Converts Windows path separators to forward slashes for stable comparisons. */
|
|
6
14
|
export function normalizePathSlashes(path) {
|
|
7
15
|
return path.replace(/\\/g, '/');
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Strips a leading `engine/` (or `engine\\`) segment from a user-supplied
|
|
19
|
+
* path so the same command invocation accepts both repo-root-relative paths
|
|
20
|
+
* (`engine/browser/base/content/foo.js`) and engine-relative paths
|
|
21
|
+
* (`browser/base/content/foo.js`). The match is case-insensitive because
|
|
22
|
+
* default macOS and Windows filesystems treat `Engine/` and `engine/` as
|
|
23
|
+
* the same directory; a literal lowercase-only check previously left `mach`
|
|
24
|
+
* / the manifest writers resolving against a wrongly-cased prefix. Leading
|
|
25
|
+
* whitespace is ignored so tab-completed inputs don't slip past the strip.
|
|
26
|
+
*
|
|
27
|
+
* The return value is trimmed of the same leading whitespace when the
|
|
28
|
+
* prefix matched, and otherwise passed through verbatim — callers that
|
|
29
|
+
* care about internal whitespace can trim on their side.
|
|
30
|
+
*
|
|
31
|
+
* @param filePath Path as provided by the user
|
|
32
|
+
* @returns Path relative to the engine directory (or the original when the
|
|
33
|
+
* prefix was absent)
|
|
34
|
+
*/
|
|
35
|
+
export function stripEnginePrefix(filePath) {
|
|
36
|
+
const match = ENGINE_PREFIX_PATTERN.exec(filePath);
|
|
37
|
+
if (match) {
|
|
38
|
+
return filePath.slice(match[0].length);
|
|
39
|
+
}
|
|
40
|
+
return filePath;
|
|
41
|
+
}
|
|
9
42
|
/** Checks whether a path is explicitly absolute on either POSIX or Windows. */
|
|
10
43
|
export function isExplicitAbsolutePath(path) {
|
|
11
44
|
return isAbsolute(path) || WINDOWS_ABSOLUTE_PATH.test(path);
|