(forceUpdate)
| 762 | } |
| 763 | |
| 764 | function _executeForceUpdateInner(forceUpdate) { |
| 765 | const INSTALL_ROOT = getEvolverInstallRoot(); |
| 766 | |
| 767 | // Defense in depth: if a future refactor breaks path resolution and |
| 768 | // INSTALL_ROOT no longer points at the evolver package (no package.json |
| 769 | // / wrong package name), refuse the update rather than risk |
| 770 | // overwriting an unrelated directory. This is the last guard between |
| 771 | // the deletion loop and the user's data. |
| 772 | try { |
| 773 | const pkg = JSON.parse(fs.readFileSync(path.join(INSTALL_ROOT, 'package.json'), 'utf8')); |
| 774 | if (!pkg || !_isEvolverPackageName(pkg.name)) { |
| 775 | console.warn('[ForceUpdate] Refusing — ' + INSTALL_ROOT + |
| 776 | '/package.json has name="' + (pkg && pkg.name) + |
| 777 | '", expected "@evomap/evolver". Aborting to avoid data loss.'); |
| 778 | return _fail(FORCE_UPDATE_FAIL_CODES.INSTALL_GUARD_NAME_MISMATCH, |
| 779 | 'install root package.json name="' + (pkg && pkg.name) + '", expected "@evomap/evolver"'); |
| 780 | } |
| 781 | } catch (e) { |
| 782 | if (_recoverPackageCommitMarkerIfMissing(INSTALL_ROOT)) { |
| 783 | try { |
| 784 | const recoveredPkg = JSON.parse(fs.readFileSync(path.join(INSTALL_ROOT, 'package.json'), 'utf8')); |
| 785 | if (!recoveredPkg || !_isEvolverPackageName(recoveredPkg.name)) { |
| 786 | console.warn('[ForceUpdate] Refusing — recovered ' + INSTALL_ROOT + |
| 787 | '/package.json has name="' + (recoveredPkg && recoveredPkg.name) + |
| 788 | '", expected "@evomap/evolver". Aborting to avoid data loss.'); |
| 789 | return _fail(FORCE_UPDATE_FAIL_CODES.INSTALL_GUARD_NAME_MISMATCH, |
| 790 | 'recovered install root package.json name="' + (recoveredPkg && recoveredPkg.name) + |
| 791 | '", expected "@evomap/evolver"'); |
| 792 | } |
| 793 | } catch (recoverReadErr) { |
| 794 | console.warn('[ForceUpdate] Refusing — cannot read recovered ' + INSTALL_ROOT + |
| 795 | '/package.json: ' + (recoverReadErr && recoverReadErr.message || recoverReadErr)); |
| 796 | return _fail(FORCE_UPDATE_FAIL_CODES.INSTALL_GUARD_UNREADABLE, |
| 797 | 'cannot read recovered install root package.json: ' + _errStr(recoverReadErr)); |
| 798 | } |
| 799 | } else if (_hasStrongEvolverInstallMarkers(INSTALL_ROOT)) { |
| 800 | console.warn('[ForceUpdate] install package.json is unreadable, but strong evolver install markers are present; bootstrap recovery allowed'); |
| 801 | } else { |
| 802 | console.warn('[ForceUpdate] Refusing — cannot read ' + INSTALL_ROOT + |
| 803 | '/package.json: ' + (e && e.message || e)); |
| 804 | return _fail(FORCE_UPDATE_FAIL_CODES.INSTALL_GUARD_UNREADABLE, |
| 805 | 'cannot read install root package.json: ' + _errStr(e)); |
| 806 | } |
| 807 | } |
| 808 | |
| 809 | const requiredVersion = normalizeRequiredVersion(forceUpdate.required_version); |
| 810 | if (!requiredVersion) { |
| 811 | console.warn('[ForceUpdate] Refusing — required_version "' + |
| 812 | String(forceUpdate.required_version || '').replace(/^[>=^~\s]+/, '') + |
| 813 | '" is not a concrete semver (ranges not accepted).'); |
| 814 | return _fail(FORCE_UPDATE_FAIL_CODES.BAD_REQUIRED_VERSION, |
| 815 | 'required_version=' + JSON.stringify(forceUpdate && forceUpdate.required_version) + ' is not a concrete semver'); |
| 816 | } |
| 817 | |
| 818 | function getCurrentVersion() { |
| 819 | try { |
| 820 | var pkg = JSON.parse(fs.readFileSync(path.join(INSTALL_ROOT, 'package.json'), 'utf8')); |
| 821 | return pkg.version || '0.0.0'; |
no test coverage detected