trouble-in-terror-town/node_modules/openupm-cli/lib/cmd-add.js
Mikolaj 2bbacbea09 did some more work on networking and removed EOS in favor of LRM
did some more work on networking and removed EOS in favor of Light Reflective Mirror
2022-05-31 15:04:31 +02:00

224 lines
6.8 KiB
JavaScript

const { log } = require("./logger");
const url = require("url");
const {
compareEditorVersion,
env,
fetchPackageDependencies,
fetchPackageInfo,
getLatestVersion,
loadManifest,
parseEditorVersion,
parseEnv,
parseName,
saveManifest
} = require("./core");
const add = async function(pkgs, options) {
if (!Array.isArray(pkgs)) pkgs = [pkgs];
// parse env
const envOk = await parseEnv(options, { checkPath: true });
if (!envOk) return 1;
// add
const results = [];
for (const pkg of pkgs)
results.push(
await _add({ pkg, testables: options.test, force: options.force })
);
const result = {
code: results.filter(x => x.code != 0).length > 0 ? 1 : 0,
dirty: results.filter(x => x.dirty).length > 0
};
// print manifest notice
if (result.dirty)
log.notice("", "please open Unity project to apply changes");
return result.code;
};
const _add = async function({ pkg, testables, force }) {
// dirty flag
let dirty = false;
// is upstream package flag
let isUpstreamPackage = false;
// parse name
let { name, version } = parseName(pkg);
// load manifest
let manifest = loadManifest();
if (manifest === null) return { code: 1, dirty };
// ensure manifest.dependencies
if (!manifest.dependencies) {
manifest.dependencies = {};
}
// packages that added to scope registry
const pkgsInScope = [];
const isGitOrLocal =
version &&
(version.startsWith("git") ||
version.startsWith("file") ||
version.startsWith("http"));
if (!isGitOrLocal) {
// verify name
let pkgInfo = await fetchPackageInfo(name);
if (!pkgInfo && env.upstream) {
pkgInfo = await fetchPackageInfo(name, env.upstreamRegistry);
if (pkgInfo) isUpstreamPackage = true;
}
if (!pkgInfo) {
log.error("404", `package not found: ${name}`);
return { code: 1, dirty };
}
// verify version
const versions = Object.keys(pkgInfo.versions);
// eslint-disable-next-line require-atomic-updates
if (!version || version == "latest") version = getLatestVersion(pkgInfo);
if (versions.filter(x => x == version).length <= 0) {
log.warn(
"404",
`version ${version} is not a valid choice of: ${versions
.reverse()
.join(", ")}`
);
return { code: 1, dirty };
}
const versionInfo = pkgInfo.versions[version];
// verify editor version
if (versionInfo.unity) {
const requiredEditorVersion = versionInfo.unityRelease
? versionInfo.unity + "." + versionInfo.unityRelease
: versionInfo.unity;
if (env.editorVersion) {
const editorVersionResult = parseEditorVersion(env.editorVersion);
const requiredEditorVersionResult = parseEditorVersion(
requiredEditorVersion
);
if (!editorVersionResult) {
log.warn(
"editor.version",
`${env.editorVersion} is unknown, the editor version check is disabled`
);
}
if (!requiredEditorVersionResult) {
log.warn("package.unity", `${requiredEditorVersion} is not valid`);
if (!force) {
log.notice(
"suggest",
"contact the package author to fix the issue, or run with option -f to ignore the warning"
);
return { code: 1, dirty };
}
}
if (
editorVersionResult &&
requiredEditorVersionResult &&
compareEditorVersion(env.editorVersion, requiredEditorVersion) < 0
) {
log.warn(
"editor.version",
`requires ${requiredEditorVersion} but found ${env.editorVersion}`
);
if (!force) {
log.notice(
"suggest",
`upgrade the editor to ${requiredEditorVersion}, or run with option -f to ignore the warning`
);
return { code: 1, dirty };
}
}
}
}
// pkgsInScope
if (!isUpstreamPackage) {
const [depsValid, depsInvalid] = await fetchPackageDependencies({
name,
version,
deep: true
});
// add depsValid to pkgsInScope.
depsValid
.filter(x => !x.upstream && !x.internal)
.map(x => x.name)
.forEach(name => pkgsInScope.push(name));
// print suggestion for depsInvalid
depsInvalid.forEach(depObj => {
if (depObj.reason == "package404" || depObj.reason == "version404") {
const resolvedVersion = manifest.dependencies[depObj.name];
depObj.resolved = Boolean(resolvedVersion);
if (!depObj.resolved)
log.notice(
"suggest",
`to install ${depObj.name}@${depObj.version} or a replaceable version manually`
);
}
});
if (depsInvalid.filter(x => !x.resolved).length > 0) {
if (!force) {
log.error(
"missing dependencies",
"please resolve thie issue or run with option -f to ignore the warning"
);
return { code: 1, dirty };
}
}
} else pkgsInScope.push(name);
}
// add to dependencies
const oldVersion = manifest.dependencies[name];
manifest.dependencies[name] = version;
if (!oldVersion) {
// Log the added package
log.notice("manifest", `added ${name}@${version}`);
dirty = true;
} else if (oldVersion != version) {
// Log the modified package version
log.notice("manifest", `modified ${name} ${oldVersion} => ${version}`);
dirty = true;
} else {
// Log the existed package
log.notice("manifest", `existed ${name}@${version}`);
}
if (!isUpstreamPackage) {
// add to scopedRegistries
if (!manifest.scopedRegistries) {
manifest.scopedRegistries = [];
dirty = true;
}
const filterEntry = x => {
let addr = x.url || "";
if (addr.endsWith("/")) addr = addr.slice(0, -1);
return addr == env.registry;
};
if (manifest.scopedRegistries.filter(filterEntry).length <= 0) {
manifest.scopedRegistries.push({
name: url.parse(env.registry).hostname,
url: env.registry,
scopes: []
});
dirty = true;
}
let entry = manifest.scopedRegistries.filter(filterEntry)[0];
// apply pkgsInScope
let scopesSet = new Set(entry.scopes || []);
pkgsInScope.push(env.namespace);
pkgsInScope.forEach(name => {
if (!scopesSet.has(name)) {
scopesSet.add(name);
dirty = true;
}
});
entry.scopes = Array.from(scopesSet).sort();
}
if (testables) {
if (!manifest.testables) {
manifest.testables = [];
}
if (manifest.testables.indexOf(name) === -1) {
manifest.testables.push(name);
}
}
// save manifest
if (dirty) {
if (!saveManifest(manifest)) return { code: 1, dirty };
}
return { code: 0, dirty };
};
module.exports = add;