mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-19 19:30:29 +08:00
style: apply repo formatter to the security-fix files (no behavior change)
This commit is contained in:
parent
bd9083ca1e
commit
ed251f958a
@ -25,7 +25,7 @@ function parseArgs(argv) {
|
|||||||
repoRoot: null,
|
repoRoot: null,
|
||||||
dryRun: false,
|
dryRun: false,
|
||||||
json: false,
|
json: false,
|
||||||
help: false,
|
help: false
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let index = 0; index < args.length; index += 1) {
|
for (let index = 0; index < args.length; index += 1) {
|
||||||
@ -63,9 +63,7 @@ function deriveRepoRootFromState(state) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relativeParts = operation.sourceRelativePath
|
const relativeParts = operation.sourceRelativePath.split(/[\\/]+/).filter(Boolean);
|
||||||
.split(/[\\/]+/)
|
|
||||||
.filter(Boolean);
|
|
||||||
|
|
||||||
if (relativeParts.length === 0) {
|
if (relativeParts.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
@ -149,9 +147,7 @@ function validateRepoRoot(repoRoot) {
|
|||||||
throw new Error(`Invalid ECC repo root: unreadable package.json at ${packageJsonPath}`);
|
throw new Error(`Invalid ECC repo root: unreadable package.json at ${packageJsonPath}`);
|
||||||
}
|
}
|
||||||
if (!ECC_PACKAGE_NAMES.has(pkgName)) {
|
if (!ECC_PACKAGE_NAMES.has(pkgName)) {
|
||||||
throw new Error(
|
throw new Error(`Refusing to run install from untrusted repo root ${normalized}: package.json name '${pkgName}' is not an official ECC package.`);
|
||||||
`Refusing to run install from untrusted repo root ${normalized}: package.json name '${pkgName}' is not an official ECC package.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return normalized;
|
return normalized;
|
||||||
@ -162,7 +158,7 @@ function runExternalCommand(command, args, options = {}) {
|
|||||||
cwd: options.cwd,
|
cwd: options.cwd,
|
||||||
env: options.env || process.env,
|
env: options.env || process.env,
|
||||||
encoding: 'utf8',
|
encoding: 'utf8',
|
||||||
maxBuffer: 10 * 1024 * 1024,
|
maxBuffer: 10 * 1024 * 1024
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
@ -186,7 +182,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
const records = discover({
|
const records = discover({
|
||||||
homeDir,
|
homeDir,
|
||||||
projectRoot,
|
projectRoot,
|
||||||
targets: options.targets,
|
targets: options.targets
|
||||||
}).filter(record => record.exists);
|
}).filter(record => record.exists);
|
||||||
|
|
||||||
const results = [];
|
const results = [];
|
||||||
@ -198,8 +194,8 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
summary: {
|
summary: {
|
||||||
checkedCount: 0,
|
checkedCount: 0,
|
||||||
updatedCount: 0,
|
updatedCount: 0,
|
||||||
errorCount: 0,
|
errorCount: 0
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +207,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
adapter: record.adapter,
|
adapter: record.adapter,
|
||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
status: 'error',
|
status: 'error',
|
||||||
error: record.error || 'No valid install-state available',
|
error: record.error || 'No valid install-state available'
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -220,7 +216,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
inferredRepoRoots.push(recordRepoRoot);
|
inferredRepoRoots.push(recordRepoRoot);
|
||||||
validRecords.push({
|
validRecords.push({
|
||||||
record,
|
record,
|
||||||
repoRoot: recordRepoRoot,
|
repoRoot: recordRepoRoot
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,15 +236,15 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
summary: {
|
summary: {
|
||||||
checkedCount: results.length,
|
checkedCount: results.length,
|
||||||
updatedCount: 0,
|
updatedCount: 0,
|
||||||
errorCount: results.length,
|
errorCount: results.length
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const env = {
|
const env = {
|
||||||
...process.env,
|
...process.env,
|
||||||
HOME: homeDir,
|
HOME: homeDir,
|
||||||
USERPROFILE: homeDir,
|
USERPROFILE: homeDir
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!options.dryRun) {
|
if (!options.dryRun) {
|
||||||
@ -258,11 +254,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
|
|
||||||
for (const entry of validRecords) {
|
for (const entry of validRecords) {
|
||||||
const installArgs = buildInstallApplyArgs(entry.record);
|
const installArgs = buildInstallApplyArgs(entry.record);
|
||||||
const args = [
|
const args = [path.join(repoRoot, 'scripts', 'install-apply.js'), ...installArgs, '--json'];
|
||||||
path.join(repoRoot, 'scripts', 'install-apply.js'),
|
|
||||||
...installArgs,
|
|
||||||
'--json',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (options.dryRun) {
|
if (options.dryRun) {
|
||||||
args.push('--dry-run');
|
args.push('--dry-run');
|
||||||
@ -271,7 +263,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
try {
|
try {
|
||||||
const commandResult = execute(process.execPath, args, {
|
const commandResult = execute(process.execPath, args, {
|
||||||
cwd: determineInstallCwd(entry.record, repoRoot),
|
cwd: determineInstallCwd(entry.record, repoRoot),
|
||||||
env,
|
env
|
||||||
});
|
});
|
||||||
|
|
||||||
let payload = null;
|
let payload = null;
|
||||||
@ -286,7 +278,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
cwd: determineInstallCwd(entry.record, repoRoot),
|
cwd: determineInstallCwd(entry.record, repoRoot),
|
||||||
installArgs,
|
installArgs,
|
||||||
status: options.dryRun ? 'planned' : 'updated',
|
status: options.dryRun ? 'planned' : 'updated',
|
||||||
payload,
|
payload
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
results.push({
|
results.push({
|
||||||
@ -295,7 +287,7 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
repoRoot,
|
repoRoot,
|
||||||
installArgs,
|
installArgs,
|
||||||
status: 'error',
|
status: 'error',
|
||||||
error: error.message,
|
error: error.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,8 +299,8 @@ function runAutoUpdate(options = {}, dependencies = {}) {
|
|||||||
summary: {
|
summary: {
|
||||||
checkedCount: results.length,
|
checkedCount: results.length,
|
||||||
updatedCount: results.filter(result => result.status === 'updated' || result.status === 'planned').length,
|
updatedCount: results.filter(result => result.status === 'updated' || result.status === 'planned').length,
|
||||||
errorCount: results.filter(result => result.status === 'error').length,
|
errorCount: results.filter(result => result.status === 'error').length
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +342,7 @@ function main() {
|
|||||||
projectRoot: process.cwd(),
|
projectRoot: process.cwd(),
|
||||||
targets: options.targets,
|
targets: options.targets,
|
||||||
repoRoot: options.repoRoot,
|
repoRoot: options.repoRoot,
|
||||||
dryRun: options.dryRun,
|
dryRun: options.dryRun
|
||||||
});
|
});
|
||||||
|
|
||||||
if (options.json) {
|
if (options.json) {
|
||||||
@ -375,5 +367,5 @@ module.exports = {
|
|||||||
deriveRepoRootFromState,
|
deriveRepoRootFromState,
|
||||||
buildInstallApplyArgs,
|
buildInstallApplyArgs,
|
||||||
determineInstallCwd,
|
determineInstallCwd,
|
||||||
runAutoUpdate,
|
runAutoUpdate
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,13 +5,8 @@ const path = require('path');
|
|||||||
const { resolveInstallPlan, loadInstallManifests } = require('./install-manifests');
|
const { resolveInstallPlan, loadInstallManifests } = require('./install-manifests');
|
||||||
const { readInstallState, writeInstallState } = require('./install-state');
|
const { readInstallState, writeInstallState } = require('./install-state');
|
||||||
const { assertWithinTrustedRoot } = require('./path-safety');
|
const { assertWithinTrustedRoot } = require('./path-safety');
|
||||||
const {
|
const { createManifestInstallPlan } = require('./install-executor');
|
||||||
createManifestInstallPlan,
|
const { getInstallTargetAdapter, listInstallTargetAdapters } = require('./install-targets/registry');
|
||||||
} = require('./install-executor');
|
|
||||||
const {
|
|
||||||
getInstallTargetAdapter,
|
|
||||||
listInstallTargetAdapters,
|
|
||||||
} = require('./install-targets/registry');
|
|
||||||
|
|
||||||
const DEFAULT_REPO_ROOT = path.join(__dirname, '../..');
|
const DEFAULT_REPO_ROOT = path.join(__dirname, '../..');
|
||||||
|
|
||||||
@ -52,9 +47,7 @@ function compareStringArrays(left, right) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getManagedOperations(state) {
|
function getManagedOperations(state) {
|
||||||
return Array.isArray(state && state.operations)
|
return Array.isArray(state && state.operations) ? state.operations.filter(operation => operation.ownership === 'managed') : [];
|
||||||
? state.operations.filter(operation => operation.ownership === 'managed')
|
|
||||||
: [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveOperationSourcePath(repoRoot, operation) {
|
function resolveOperationSourcePath(repoRoot, operation) {
|
||||||
@ -116,13 +109,7 @@ function parseJsonLikeValue(value, label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOperationTextContent(operation) {
|
function getOperationTextContent(operation) {
|
||||||
const candidateKeys = [
|
const candidateKeys = ['renderedContent', 'content', 'managedContent', 'expectedContent', 'templateOutput'];
|
||||||
'renderedContent',
|
|
||||||
'content',
|
|
||||||
'managedContent',
|
|
||||||
'expectedContent',
|
|
||||||
'templateOutput',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const key of candidateKeys) {
|
for (const key of candidateKeys) {
|
||||||
if (typeof operation[key] === 'string') {
|
if (typeof operation[key] === 'string') {
|
||||||
@ -134,13 +121,7 @@ function getOperationTextContent(operation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOperationJsonPayload(operation) {
|
function getOperationJsonPayload(operation) {
|
||||||
const candidateKeys = [
|
const candidateKeys = ['mergePayload', 'managedPayload', 'payload', 'value', 'expectedValue'];
|
||||||
'mergePayload',
|
|
||||||
'managedPayload',
|
|
||||||
'payload',
|
|
||||||
'value',
|
|
||||||
'expectedValue',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const key of candidateKeys) {
|
for (const key of candidateKeys) {
|
||||||
if (operation[key] !== undefined) {
|
if (operation[key] !== undefined) {
|
||||||
@ -152,11 +133,7 @@ function getOperationJsonPayload(operation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOperationPreviousContent(operation) {
|
function getOperationPreviousContent(operation) {
|
||||||
const candidateKeys = [
|
const candidateKeys = ['previousContent', 'originalContent', 'backupContent'];
|
||||||
'previousContent',
|
|
||||||
'originalContent',
|
|
||||||
'backupContent',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const key of candidateKeys) {
|
for (const key of candidateKeys) {
|
||||||
if (typeof operation[key] === 'string') {
|
if (typeof operation[key] === 'string') {
|
||||||
@ -168,11 +145,7 @@ function getOperationPreviousContent(operation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOperationPreviousJson(operation) {
|
function getOperationPreviousJson(operation) {
|
||||||
const candidateKeys = [
|
const candidateKeys = ['previousValue', 'previousJson', 'originalValue'];
|
||||||
'previousValue',
|
|
||||||
'previousJson',
|
|
||||||
'originalValue',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const key of candidateKeys) {
|
for (const key of candidateKeys) {
|
||||||
if (operation[key] !== undefined) {
|
if (operation[key] !== undefined) {
|
||||||
@ -217,10 +190,7 @@ function jsonContainsSubset(actualValue, expectedValue) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Object.entries(expectedValue).every(([key, value]) => (
|
return Object.entries(expectedValue).every(([key, value]) => Object.prototype.hasOwnProperty.call(actualValue, key) && jsonContainsSubset(actualValue[key], value));
|
||||||
Object.prototype.hasOwnProperty.call(actualValue, key)
|
|
||||||
&& jsonContainsSubset(actualValue[key], value)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(expectedValue)) {
|
if (Array.isArray(expectedValue)) {
|
||||||
@ -288,7 +258,7 @@ function hydrateRecordedOperations(repoRoot, operations) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...operation,
|
...operation,
|
||||||
sourcePath: resolveOperationSourcePath(repoRoot, operation),
|
sourcePath: resolveOperationSourcePath(repoRoot, operation)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -300,9 +270,9 @@ function buildRecordedStatePreview(state, context, operations) {
|
|||||||
source: {
|
source: {
|
||||||
...state.source,
|
...state.source,
|
||||||
repoVersion: context.packageVersion,
|
repoVersion: context.packageVersion,
|
||||||
manifestVersion: context.manifestVersion,
|
manifestVersion: context.manifestVersion
|
||||||
},
|
},
|
||||||
lastValidatedAt: new Date().toISOString(),
|
lastValidatedAt: new Date().toISOString()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,9 +314,7 @@ function executeRepairOperation(repoRoot, operation, trustedRoot) {
|
|||||||
throw new Error(`Missing merge payload for repair: ${operation.destinationPath}`);
|
throw new Error(`Missing merge payload for repair: ${operation.destinationPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentValue = fs.existsSync(operation.destinationPath)
|
const currentValue = fs.existsSync(operation.destinationPath) ? readJsonFile(operation.destinationPath) : {};
|
||||||
? readJsonFile(operation.destinationPath)
|
|
||||||
: {};
|
|
||||||
const mergedValue = deepMergeJson(currentValue, payload);
|
const mergedValue = deepMergeJson(currentValue, payload);
|
||||||
|
|
||||||
ensureParentDir(operation.destinationPath);
|
ensureParentDir(operation.destinationPath);
|
||||||
@ -374,14 +342,14 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
if (!fs.existsSync(operation.destinationPath)) {
|
if (!fs.existsSync(operation.destinationPath)) {
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.rmSync(operation.destinationPath, { force: true });
|
fs.rmSync(operation.destinationPath, { force: true });
|
||||||
return {
|
return {
|
||||||
removedPaths: [operation.destinationPath],
|
removedPaths: [operation.destinationPath],
|
||||||
cleanupTargets: [operation.destinationPath],
|
cleanupTargets: [operation.destinationPath]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,7 +360,7 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, previousContent);
|
fs.writeFileSync(operation.destinationPath, previousContent);
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,21 +370,21 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(operation.destinationPath)) {
|
if (!fs.existsSync(operation.destinationPath)) {
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.rmSync(operation.destinationPath, { force: true });
|
fs.rmSync(operation.destinationPath, { force: true });
|
||||||
return {
|
return {
|
||||||
removedPaths: [operation.destinationPath],
|
removedPaths: [operation.destinationPath],
|
||||||
cleanupTargets: [operation.destinationPath],
|
cleanupTargets: [operation.destinationPath]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +395,7 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, previousContent);
|
fs.writeFileSync(operation.destinationPath, previousContent);
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,14 +405,14 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(operation.destinationPath)) {
|
if (!fs.existsSync(operation.destinationPath)) {
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +427,7 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.rmSync(operation.destinationPath, { force: true });
|
fs.rmSync(operation.destinationPath, { force: true });
|
||||||
return {
|
return {
|
||||||
removedPaths: [operation.destinationPath],
|
removedPaths: [operation.destinationPath],
|
||||||
cleanupTargets: [operation.destinationPath],
|
cleanupTargets: [operation.destinationPath]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,7 +435,7 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, formatJson(nextValue));
|
fs.writeFileSync(operation.destinationPath, formatJson(nextValue));
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,7 +446,7 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, previousContent);
|
fs.writeFileSync(operation.destinationPath, previousContent);
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,13 +456,13 @@ function executeUninstallOperation(operation, trustedRoot) {
|
|||||||
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
fs.writeFileSync(operation.destinationPath, formatJson(previousJson));
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
cleanupTargets: [],
|
cleanupTargets: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +474,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
if (!destinationPath) {
|
if (!destinationPath) {
|
||||||
return {
|
return {
|
||||||
status: 'invalid-destination',
|
status: 'invalid-destination',
|
||||||
operation,
|
operation
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,14 +483,14 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'drifted',
|
status: 'drifted',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,7 +498,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'missing',
|
status: 'missing',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,7 +509,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
status: 'missing-source',
|
status: 'missing-source',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath,
|
||||||
sourcePath,
|
sourcePath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +518,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
status: 'drifted',
|
status: 'drifted',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath,
|
||||||
sourcePath,
|
sourcePath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,7 +526,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
status: 'ok',
|
status: 'ok',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath,
|
||||||
sourcePath,
|
sourcePath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +536,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'unverified',
|
status: 'unverified',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -576,14 +544,14 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'drifted',
|
status: 'drifted',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,7 +561,7 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'unverified',
|
status: 'unverified',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,57 +571,60 @@ function inspectManagedOperation(repoRoot, operation) {
|
|||||||
return {
|
return {
|
||||||
status: 'drifted',
|
status: 'drifted',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
status: 'drifted',
|
status: 'drifted',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status: 'unverified',
|
status: 'unverified',
|
||||||
operation,
|
operation,
|
||||||
destinationPath,
|
destinationPath
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function summarizeManagedOperationHealth(repoRoot, operations) {
|
function summarizeManagedOperationHealth(repoRoot, operations) {
|
||||||
return operations.reduce((summary, operation) => {
|
return operations.reduce(
|
||||||
const inspection = inspectManagedOperation(repoRoot, operation);
|
(summary, operation) => {
|
||||||
if (inspection.status === 'missing') {
|
const inspection = inspectManagedOperation(repoRoot, operation);
|
||||||
summary.missing.push(inspection);
|
if (inspection.status === 'missing') {
|
||||||
} else if (inspection.status === 'drifted') {
|
summary.missing.push(inspection);
|
||||||
summary.drifted.push(inspection);
|
} else if (inspection.status === 'drifted') {
|
||||||
} else if (inspection.status === 'missing-source') {
|
summary.drifted.push(inspection);
|
||||||
summary.missingSource.push(inspection);
|
} else if (inspection.status === 'missing-source') {
|
||||||
} else if (inspection.status === 'unverified' || inspection.status === 'invalid-destination') {
|
summary.missingSource.push(inspection);
|
||||||
summary.unverified.push(inspection);
|
} else if (inspection.status === 'unverified' || inspection.status === 'invalid-destination') {
|
||||||
|
summary.unverified.push(inspection);
|
||||||
|
}
|
||||||
|
return summary;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
missing: [],
|
||||||
|
drifted: [],
|
||||||
|
missingSource: [],
|
||||||
|
unverified: []
|
||||||
}
|
}
|
||||||
return summary;
|
);
|
||||||
}, {
|
|
||||||
missing: [],
|
|
||||||
drifted: [],
|
|
||||||
missingSource: [],
|
|
||||||
unverified: [],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDiscoveryRecord(adapter, context) {
|
function buildDiscoveryRecord(adapter, context) {
|
||||||
const installTargetInput = {
|
const installTargetInput = {
|
||||||
homeDir: context.homeDir,
|
homeDir: context.homeDir,
|
||||||
projectRoot: context.projectRoot,
|
projectRoot: context.projectRoot,
|
||||||
repoRoot: context.projectRoot,
|
repoRoot: context.projectRoot
|
||||||
};
|
};
|
||||||
const targetRoot = adapter.resolveRoot(installTargetInput);
|
const targetRoot = adapter.resolveRoot(installTargetInput);
|
||||||
const installStatePath = adapter.getInstallStatePath(installTargetInput);
|
const installStatePath = adapter.getInstallStatePath(installTargetInput);
|
||||||
@ -664,13 +635,13 @@ function buildDiscoveryRecord(adapter, context) {
|
|||||||
adapter: {
|
adapter: {
|
||||||
id: adapter.id,
|
id: adapter.id,
|
||||||
target: adapter.target,
|
target: adapter.target,
|
||||||
kind: adapter.kind,
|
kind: adapter.kind
|
||||||
},
|
},
|
||||||
targetRoot,
|
targetRoot,
|
||||||
installStatePath,
|
installStatePath,
|
||||||
exists: false,
|
exists: false,
|
||||||
state: null,
|
state: null,
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,26 +651,26 @@ function buildDiscoveryRecord(adapter, context) {
|
|||||||
adapter: {
|
adapter: {
|
||||||
id: adapter.id,
|
id: adapter.id,
|
||||||
target: adapter.target,
|
target: adapter.target,
|
||||||
kind: adapter.kind,
|
kind: adapter.kind
|
||||||
},
|
},
|
||||||
targetRoot,
|
targetRoot,
|
||||||
installStatePath,
|
installStatePath,
|
||||||
exists: true,
|
exists: true,
|
||||||
state,
|
state,
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
adapter: {
|
adapter: {
|
||||||
id: adapter.id,
|
id: adapter.id,
|
||||||
target: adapter.target,
|
target: adapter.target,
|
||||||
kind: adapter.kind,
|
kind: adapter.kind
|
||||||
},
|
},
|
||||||
targetRoot,
|
targetRoot,
|
||||||
installStatePath,
|
installStatePath,
|
||||||
exists: true,
|
exists: true,
|
||||||
state: null,
|
state: null,
|
||||||
error: error.message,
|
error: error.message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -707,7 +678,7 @@ function buildDiscoveryRecord(adapter, context) {
|
|||||||
function discoverInstalledStates(options = {}) {
|
function discoverInstalledStates(options = {}) {
|
||||||
const context = {
|
const context = {
|
||||||
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
||||||
projectRoot: options.projectRoot || process.cwd(),
|
projectRoot: options.projectRoot || process.cwd()
|
||||||
};
|
};
|
||||||
const targets = normalizeTargets(options.targets);
|
const targets = normalizeTargets(options.targets);
|
||||||
|
|
||||||
@ -722,7 +693,7 @@ function buildIssue(severity, code, message, extra = {}) {
|
|||||||
severity,
|
severity,
|
||||||
code,
|
code,
|
||||||
message,
|
message,
|
||||||
...extra,
|
...extra
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,7 +717,7 @@ function analyzeRecord(record, context) {
|
|||||||
return {
|
return {
|
||||||
...record,
|
...record,
|
||||||
status: determineStatus(issues),
|
status: determineStatus(issues),
|
||||||
issues,
|
issues
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,40 +726,30 @@ function analyzeRecord(record, context) {
|
|||||||
return {
|
return {
|
||||||
...record,
|
...record,
|
||||||
status: 'missing',
|
status: 'missing',
|
||||||
issues,
|
issues
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(state.target.root)) {
|
if (!fs.existsSync(state.target.root)) {
|
||||||
issues.push(buildIssue(
|
issues.push(buildIssue('error', 'missing-target-root', `Target root does not exist: ${state.target.root}`));
|
||||||
'error',
|
|
||||||
'missing-target-root',
|
|
||||||
`Target root does not exist: ${state.target.root}`
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.target.root !== record.targetRoot) {
|
if (state.target.root !== record.targetRoot) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'warning',
|
buildIssue('warning', 'target-root-mismatch', `Recorded target root differs from current target root (${record.targetRoot})`, {
|
||||||
'target-root-mismatch',
|
|
||||||
`Recorded target root differs from current target root (${record.targetRoot})`,
|
|
||||||
{
|
|
||||||
recordedTargetRoot: state.target.root,
|
recordedTargetRoot: state.target.root,
|
||||||
currentTargetRoot: record.targetRoot,
|
currentTargetRoot: record.targetRoot
|
||||||
}
|
})
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.target.installStatePath !== record.installStatePath) {
|
if (state.target.installStatePath !== record.installStatePath) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'warning',
|
buildIssue('warning', 'install-state-path-mismatch', `Recorded install-state path differs from current path (${record.installStatePath})`, {
|
||||||
'install-state-path-mismatch',
|
|
||||||
`Recorded install-state path differs from current path (${record.installStatePath})`,
|
|
||||||
{
|
|
||||||
recordedInstallStatePath: state.target.installStatePath,
|
recordedInstallStatePath: state.target.installStatePath,
|
||||||
currentInstallStatePath: record.installStatePath,
|
currentInstallStatePath: record.installStatePath
|
||||||
}
|
})
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const managedOperations = getManagedOperations(state);
|
const managedOperations = getManagedOperations(state);
|
||||||
@ -796,67 +757,43 @@ function analyzeRecord(record, context) {
|
|||||||
const missingManagedOperations = operationHealth.missing;
|
const missingManagedOperations = operationHealth.missing;
|
||||||
|
|
||||||
if (missingManagedOperations.length > 0) {
|
if (missingManagedOperations.length > 0) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'error',
|
buildIssue('error', 'missing-managed-files', `${missingManagedOperations.length} managed file(s) are missing`, {
|
||||||
'missing-managed-files',
|
paths: missingManagedOperations.map(entry => entry.destinationPath)
|
||||||
`${missingManagedOperations.length} managed file(s) are missing`,
|
})
|
||||||
{
|
);
|
||||||
paths: missingManagedOperations.map(entry => entry.destinationPath),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationHealth.drifted.length > 0) {
|
if (operationHealth.drifted.length > 0) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'warning',
|
buildIssue('warning', 'drifted-managed-files', `${operationHealth.drifted.length} managed file(s) differ from the source repo`, {
|
||||||
'drifted-managed-files',
|
paths: operationHealth.drifted.map(entry => entry.destinationPath)
|
||||||
`${operationHealth.drifted.length} managed file(s) differ from the source repo`,
|
})
|
||||||
{
|
);
|
||||||
paths: operationHealth.drifted.map(entry => entry.destinationPath),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationHealth.missingSource.length > 0) {
|
if (operationHealth.missingSource.length > 0) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'error',
|
buildIssue('error', 'missing-source-files', `${operationHealth.missingSource.length} source file(s) referenced by install-state are missing`, {
|
||||||
'missing-source-files',
|
paths: operationHealth.missingSource.map(entry => entry.sourcePath).filter(Boolean)
|
||||||
`${operationHealth.missingSource.length} source file(s) referenced by install-state are missing`,
|
})
|
||||||
{
|
);
|
||||||
paths: operationHealth.missingSource.map(entry => entry.sourcePath).filter(Boolean),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationHealth.unverified.length > 0) {
|
if (operationHealth.unverified.length > 0) {
|
||||||
issues.push(buildIssue(
|
issues.push(
|
||||||
'warning',
|
buildIssue('warning', 'unverified-managed-operations', `${operationHealth.unverified.length} managed operation(s) could not be content-verified`, {
|
||||||
'unverified-managed-operations',
|
paths: operationHealth.unverified.map(entry => entry.destinationPath).filter(Boolean)
|
||||||
`${operationHealth.unverified.length} managed operation(s) could not be content-verified`,
|
})
|
||||||
{
|
);
|
||||||
paths: operationHealth.unverified.map(entry => entry.destinationPath).filter(Boolean),
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.source.manifestVersion !== context.manifestVersion) {
|
if (state.source.manifestVersion !== context.manifestVersion) {
|
||||||
issues.push(buildIssue(
|
issues.push(buildIssue('warning', 'manifest-version-mismatch', `Recorded manifest version ${state.source.manifestVersion} differs from current manifest version ${context.manifestVersion}`));
|
||||||
'warning',
|
|
||||||
'manifest-version-mismatch',
|
|
||||||
`Recorded manifest version ${state.source.manifestVersion} differs from current manifest version ${context.manifestVersion}`
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (context.packageVersion && state.source.repoVersion && state.source.repoVersion !== context.packageVersion) {
|
||||||
context.packageVersion
|
issues.push(buildIssue('warning', 'repo-version-mismatch', `Recorded repo version ${state.source.repoVersion} differs from current repo version ${context.packageVersion}`));
|
||||||
&& state.source.repoVersion
|
|
||||||
&& state.source.repoVersion !== context.packageVersion
|
|
||||||
) {
|
|
||||||
issues.push(buildIssue(
|
|
||||||
'warning',
|
|
||||||
'repo-version-mismatch',
|
|
||||||
`Recorded repo version ${state.source.repoVersion} differs from current repo version ${context.packageVersion}`
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.request.legacyMode) {
|
if (!state.request.legacyMode) {
|
||||||
@ -869,38 +806,28 @@ function analyzeRecord(record, context) {
|
|||||||
profileId: state.request.profile || null,
|
profileId: state.request.profile || null,
|
||||||
moduleIds: state.request.modules || [],
|
moduleIds: state.request.modules || [],
|
||||||
includeComponentIds: state.request.includeComponents || [],
|
includeComponentIds: state.request.includeComponents || [],
|
||||||
excludeComponentIds: state.request.excludeComponents || [],
|
excludeComponentIds: state.request.excludeComponents || []
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (!compareStringArrays(desiredPlan.selectedModuleIds, state.resolution.selectedModules) || !compareStringArrays(desiredPlan.skippedModuleIds, state.resolution.skippedModules)) {
|
||||||
!compareStringArrays(desiredPlan.selectedModuleIds, state.resolution.selectedModules)
|
issues.push(
|
||||||
|| !compareStringArrays(desiredPlan.skippedModuleIds, state.resolution.skippedModules)
|
buildIssue('warning', 'resolution-drift', 'Current manifest resolution differs from recorded install-state', {
|
||||||
) {
|
|
||||||
issues.push(buildIssue(
|
|
||||||
'warning',
|
|
||||||
'resolution-drift',
|
|
||||||
'Current manifest resolution differs from recorded install-state',
|
|
||||||
{
|
|
||||||
expectedSelectedModules: desiredPlan.selectedModuleIds,
|
expectedSelectedModules: desiredPlan.selectedModuleIds,
|
||||||
recordedSelectedModules: state.resolution.selectedModules,
|
recordedSelectedModules: state.resolution.selectedModules,
|
||||||
expectedSkippedModules: desiredPlan.skippedModuleIds,
|
expectedSkippedModules: desiredPlan.skippedModuleIds,
|
||||||
recordedSkippedModules: state.resolution.skippedModules,
|
recordedSkippedModules: state.resolution.skippedModules
|
||||||
}
|
})
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
issues.push(buildIssue(
|
issues.push(buildIssue('error', 'resolution-unavailable', error.message));
|
||||||
'error',
|
|
||||||
'resolution-unavailable',
|
|
||||||
error.message
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...record,
|
...record,
|
||||||
status: determineStatus(issues),
|
status: determineStatus(issues),
|
||||||
issues,
|
issues
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,39 +837,42 @@ function buildDoctorReport(options = {}) {
|
|||||||
const records = discoverInstalledStates({
|
const records = discoverInstalledStates({
|
||||||
homeDir: options.homeDir,
|
homeDir: options.homeDir,
|
||||||
projectRoot: options.projectRoot,
|
projectRoot: options.projectRoot,
|
||||||
targets: options.targets,
|
targets: options.targets
|
||||||
}).filter(record => record.exists);
|
}).filter(record => record.exists);
|
||||||
const context = {
|
const context = {
|
||||||
repoRoot,
|
repoRoot,
|
||||||
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
||||||
projectRoot: options.projectRoot || process.cwd(),
|
projectRoot: options.projectRoot || process.cwd(),
|
||||||
manifestVersion: manifests.modulesVersion,
|
manifestVersion: manifests.modulesVersion,
|
||||||
packageVersion: readPackageVersion(repoRoot),
|
packageVersion: readPackageVersion(repoRoot)
|
||||||
};
|
};
|
||||||
const results = records.map(record => analyzeRecord(record, context));
|
const results = records.map(record => analyzeRecord(record, context));
|
||||||
const summary = results.reduce((accumulator, result) => {
|
const summary = results.reduce(
|
||||||
const errorCount = result.issues.filter(issue => issue.severity === 'error').length;
|
(accumulator, result) => {
|
||||||
const warningCount = result.issues.filter(issue => issue.severity === 'warning').length;
|
const errorCount = result.issues.filter(issue => issue.severity === 'error').length;
|
||||||
|
const warningCount = result.issues.filter(issue => issue.severity === 'warning').length;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
checkedCount: accumulator.checkedCount + 1,
|
checkedCount: accumulator.checkedCount + 1,
|
||||||
okCount: accumulator.okCount + (result.status === 'ok' ? 1 : 0),
|
okCount: accumulator.okCount + (result.status === 'ok' ? 1 : 0),
|
||||||
errorCount: accumulator.errorCount + errorCount,
|
errorCount: accumulator.errorCount + errorCount,
|
||||||
warningCount: accumulator.warningCount + warningCount,
|
warningCount: accumulator.warningCount + warningCount
|
||||||
};
|
};
|
||||||
}, {
|
},
|
||||||
checkedCount: 0,
|
{
|
||||||
okCount: 0,
|
checkedCount: 0,
|
||||||
errorCount: 0,
|
okCount: 0,
|
||||||
warningCount: 0,
|
errorCount: 0,
|
||||||
});
|
warningCount: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
packageVersion: context.packageVersion,
|
packageVersion: context.packageVersion,
|
||||||
manifestVersion: context.manifestVersion,
|
manifestVersion: context.manifestVersion,
|
||||||
results,
|
results,
|
||||||
summary,
|
summary
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,11 +894,9 @@ function createRepairPlanFromRecord(record, context) {
|
|||||||
installRoot: state.target.root,
|
installRoot: state.target.root,
|
||||||
installStatePath: state.target.installStatePath,
|
installStatePath: state.target.installStatePath,
|
||||||
warnings: [],
|
warnings: [],
|
||||||
languages: Array.isArray(state.request.legacyLanguages)
|
languages: Array.isArray(state.request.legacyLanguages) ? [...state.request.legacyLanguages] : [],
|
||||||
? [...state.request.legacyLanguages]
|
|
||||||
: [],
|
|
||||||
operations,
|
operations,
|
||||||
statePreview,
|
statePreview
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -980,7 +908,7 @@ function createRepairPlanFromRecord(record, context) {
|
|||||||
includeComponentIds: state.request.includeComponents || [],
|
includeComponentIds: state.request.includeComponents || [],
|
||||||
excludeComponentIds: state.request.excludeComponents || [],
|
excludeComponentIds: state.request.excludeComponents || [],
|
||||||
projectRoot: context.projectRoot,
|
projectRoot: context.projectRoot,
|
||||||
homeDir: context.homeDir,
|
homeDir: context.homeDir
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -988,8 +916,8 @@ function createRepairPlanFromRecord(record, context) {
|
|||||||
statePreview: {
|
statePreview: {
|
||||||
...desiredPlan.statePreview,
|
...desiredPlan.statePreview,
|
||||||
installedAt: state.installedAt,
|
installedAt: state.installedAt,
|
||||||
lastValidatedAt: new Date().toISOString(),
|
lastValidatedAt: new Date().toISOString()
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,12 +929,12 @@ function repairInstalledStates(options = {}) {
|
|||||||
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
homeDir: options.homeDir || process.env.HOME || os.homedir(),
|
||||||
projectRoot: options.projectRoot || process.cwd(),
|
projectRoot: options.projectRoot || process.cwd(),
|
||||||
manifestVersion: manifests.modulesVersion,
|
manifestVersion: manifests.modulesVersion,
|
||||||
packageVersion: readPackageVersion(repoRoot),
|
packageVersion: readPackageVersion(repoRoot)
|
||||||
};
|
};
|
||||||
const records = discoverInstalledStates({
|
const records = discoverInstalledStates({
|
||||||
homeDir: context.homeDir,
|
homeDir: context.homeDir,
|
||||||
projectRoot: context.projectRoot,
|
projectRoot: context.projectRoot,
|
||||||
targets: options.targets,
|
targets: options.targets
|
||||||
}).filter(record => record.exists);
|
}).filter(record => record.exists);
|
||||||
|
|
||||||
const results = records.map(record => {
|
const results = records.map(record => {
|
||||||
@ -1017,7 +945,7 @@ function repairInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
repairedPaths: [],
|
repairedPaths: [],
|
||||||
plannedRepairs: [],
|
plannedRepairs: [],
|
||||||
error: record.error,
|
error: record.error
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1032,14 +960,11 @@ function repairInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
repairedPaths: [],
|
repairedPaths: [],
|
||||||
plannedRepairs: [],
|
plannedRepairs: [],
|
||||||
error: `Missing source file(s): ${operationHealth.missingSource.map(entry => entry.sourcePath).join(', ')}`,
|
error: `Missing source file(s): ${operationHealth.missingSource.map(entry => entry.sourcePath).join(', ')}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const repairOperations = [
|
const repairOperations = [...operationHealth.missing.map(entry => ({ ...entry.operation })), ...operationHealth.drifted.map(entry => ({ ...entry.operation }))];
|
||||||
...operationHealth.missing.map(entry => ({ ...entry.operation })),
|
|
||||||
...operationHealth.drifted.map(entry => ({ ...entry.operation })),
|
|
||||||
];
|
|
||||||
const plannedRepairs = repairOperations.map(operation => operation.destinationPath);
|
const plannedRepairs = repairOperations.map(operation => operation.destinationPath);
|
||||||
|
|
||||||
if (options.dryRun) {
|
if (options.dryRun) {
|
||||||
@ -1050,7 +975,7 @@ function repairInstalledStates(options = {}) {
|
|||||||
repairedPaths: [],
|
repairedPaths: [],
|
||||||
plannedRepairs,
|
plannedRepairs,
|
||||||
stateRefreshed: plannedRepairs.length === 0,
|
stateRefreshed: plannedRepairs.length === 0,
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,7 +995,7 @@ function repairInstalledStates(options = {}) {
|
|||||||
repairedPaths: plannedRepairs,
|
repairedPaths: plannedRepairs,
|
||||||
plannedRepairs: [],
|
plannedRepairs: [],
|
||||||
stateRefreshed: true,
|
stateRefreshed: true,
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
@ -1079,28 +1004,31 @@ function repairInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
repairedPaths: [],
|
repairedPaths: [],
|
||||||
plannedRepairs: [],
|
plannedRepairs: [],
|
||||||
error: error.message,
|
error: error.message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const summary = results.reduce((accumulator, result) => ({
|
const summary = results.reduce(
|
||||||
checkedCount: accumulator.checkedCount + 1,
|
(accumulator, result) => ({
|
||||||
repairedCount: accumulator.repairedCount + (result.status === 'repaired' ? 1 : 0),
|
checkedCount: accumulator.checkedCount + 1,
|
||||||
plannedRepairCount: accumulator.plannedRepairCount + (result.status === 'planned' ? 1 : 0),
|
repairedCount: accumulator.repairedCount + (result.status === 'repaired' ? 1 : 0),
|
||||||
errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0),
|
plannedRepairCount: accumulator.plannedRepairCount + (result.status === 'planned' ? 1 : 0),
|
||||||
}), {
|
errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0)
|
||||||
checkedCount: 0,
|
}),
|
||||||
repairedCount: 0,
|
{
|
||||||
plannedRepairCount: 0,
|
checkedCount: 0,
|
||||||
errorCount: 0,
|
repairedCount: 0,
|
||||||
});
|
plannedRepairCount: 0,
|
||||||
|
errorCount: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dryRun: Boolean(options.dryRun),
|
dryRun: Boolean(options.dryRun),
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
results,
|
results,
|
||||||
summary,
|
summary
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1108,11 +1036,7 @@ function cleanupEmptyParentDirs(filePath, stopAt) {
|
|||||||
let currentPath = path.dirname(filePath);
|
let currentPath = path.dirname(filePath);
|
||||||
const normalizedStopAt = path.resolve(stopAt);
|
const normalizedStopAt = path.resolve(stopAt);
|
||||||
|
|
||||||
while (
|
while (currentPath && path.resolve(currentPath).startsWith(normalizedStopAt) && path.resolve(currentPath) !== normalizedStopAt) {
|
||||||
currentPath
|
|
||||||
&& path.resolve(currentPath).startsWith(normalizedStopAt)
|
|
||||||
&& path.resolve(currentPath) !== normalizedStopAt
|
|
||||||
) {
|
|
||||||
if (!fs.existsSync(currentPath)) {
|
if (!fs.existsSync(currentPath)) {
|
||||||
currentPath = path.dirname(currentPath);
|
currentPath = path.dirname(currentPath);
|
||||||
continue;
|
continue;
|
||||||
@ -1132,7 +1056,7 @@ function uninstallInstalledStates(options = {}) {
|
|||||||
const records = discoverInstalledStates({
|
const records = discoverInstalledStates({
|
||||||
homeDir: options.homeDir,
|
homeDir: options.homeDir,
|
||||||
projectRoot: options.projectRoot,
|
projectRoot: options.projectRoot,
|
||||||
targets: options.targets,
|
targets: options.targets
|
||||||
}).filter(record => record.exists);
|
}).filter(record => record.exists);
|
||||||
|
|
||||||
const results = records.map(record => {
|
const results = records.map(record => {
|
||||||
@ -1143,15 +1067,12 @@ function uninstallInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
plannedRemovals: [],
|
plannedRemovals: [],
|
||||||
error: record.error || 'No valid install-state available',
|
error: record.error || 'No valid install-state available'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = record.state;
|
const state = record.state;
|
||||||
const plannedRemovals = Array.from(new Set([
|
const plannedRemovals = Array.from(new Set([...getManagedOperations(state).map(operation => operation.destinationPath), state.target.installStatePath]));
|
||||||
...getManagedOperations(state).map(operation => operation.destinationPath),
|
|
||||||
state.target.installStatePath,
|
|
||||||
]));
|
|
||||||
|
|
||||||
if (options.dryRun) {
|
if (options.dryRun) {
|
||||||
return {
|
return {
|
||||||
@ -1160,7 +1081,7 @@ function uninstallInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
plannedRemovals,
|
plannedRemovals,
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1192,7 +1113,7 @@ function uninstallInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
removedPaths,
|
removedPaths,
|
||||||
plannedRemovals: [],
|
plannedRemovals: [],
|
||||||
error: null,
|
error: null
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
@ -1201,28 +1122,31 @@ function uninstallInstalledStates(options = {}) {
|
|||||||
installStatePath: record.installStatePath,
|
installStatePath: record.installStatePath,
|
||||||
removedPaths: [],
|
removedPaths: [],
|
||||||
plannedRemovals,
|
plannedRemovals,
|
||||||
error: error.message,
|
error: error.message
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const summary = results.reduce((accumulator, result) => ({
|
const summary = results.reduce(
|
||||||
checkedCount: accumulator.checkedCount + 1,
|
(accumulator, result) => ({
|
||||||
uninstalledCount: accumulator.uninstalledCount + (result.status === 'uninstalled' ? 1 : 0),
|
checkedCount: accumulator.checkedCount + 1,
|
||||||
plannedRemovalCount: accumulator.plannedRemovalCount + (result.status === 'planned' ? 1 : 0),
|
uninstalledCount: accumulator.uninstalledCount + (result.status === 'uninstalled' ? 1 : 0),
|
||||||
errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0),
|
plannedRemovalCount: accumulator.plannedRemovalCount + (result.status === 'planned' ? 1 : 0),
|
||||||
}), {
|
errorCount: accumulator.errorCount + (result.status === 'error' ? 1 : 0)
|
||||||
checkedCount: 0,
|
}),
|
||||||
uninstalledCount: 0,
|
{
|
||||||
plannedRemovalCount: 0,
|
checkedCount: 0,
|
||||||
errorCount: 0,
|
uninstalledCount: 0,
|
||||||
});
|
plannedRemovalCount: 0,
|
||||||
|
errorCount: 0
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dryRun: Boolean(options.dryRun),
|
dryRun: Boolean(options.dryRun),
|
||||||
generatedAt: new Date().toISOString(),
|
generatedAt: new Date().toISOString(),
|
||||||
results,
|
results,
|
||||||
summary,
|
summary
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1232,5 +1156,5 @@ module.exports = {
|
|||||||
discoverInstalledStates,
|
discoverInstalledStates,
|
||||||
normalizeTargets,
|
normalizeTargets,
|
||||||
repairInstalledStates,
|
repairInstalledStates,
|
||||||
uninstallInstalledStates,
|
uninstallInstalledStates
|
||||||
};
|
};
|
||||||
|
|||||||
@ -70,9 +70,7 @@ function assertWithinTrustedRoot(target, root, action = 'write') {
|
|||||||
throw new Error(`Refusing to ${action} '${target}': no trusted install root resolved.`);
|
throw new Error(`Refusing to ${action} '${target}': no trusted install root resolved.`);
|
||||||
}
|
}
|
||||||
if (!isWithinRoot(target, root)) {
|
if (!isWithinRoot(target, root)) {
|
||||||
throw new Error(
|
throw new Error(`Refusing to ${action} outside the install root: '${target}' is not within '${root}'.`);
|
||||||
`Refusing to ${action} outside the install root: '${target}' is not within '${root}'.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return realpathNearestExisting(target);
|
return realpathNearestExisting(target);
|
||||||
}
|
}
|
||||||
@ -80,5 +78,5 @@ function assertWithinTrustedRoot(target, root, action = 'write') {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
realpathNearestExisting,
|
realpathNearestExisting,
|
||||||
isWithinRoot,
|
isWithinRoot,
|
||||||
assertWithinTrustedRoot,
|
assertWithinTrustedRoot
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user