Skip to content

Commit

Permalink
feat: fail if missing dependencies for command add, unless add option -f
Browse files Browse the repository at this point in the history
  • Loading branch information
favoyang committed Nov 15, 2020
1 parent 5c2129c commit 920d7a4
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 33 deletions.
4 changes: 4 additions & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ program
.command("add <pkg> [otherPkgs...]")
.aliases(["install", "i"])
.option("-t, --test", "add package as testable")
.option(
"-f, --force",
"force add package if missing deps or editor version is not qualified"
)
.description(
`add package to manifest json
openupm add <pkg> [otherPkgs...]
Expand Down
66 changes: 51 additions & 15 deletions lib/cmd-add.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const add = async function(pkgs, options) {
// add
const results = [];
for (const pkg of pkgs)
results.push(await _add({ pkg, testables: options.test }));
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
Expand All @@ -32,13 +34,20 @@ const add = async function(pkgs, options) {
return result.code;
};

const _add = async function({ pkg, testables }) {
const _add = async function({ pkg, testables, force }) {
// dirty flag
let dirty = false;
// upstream flag
let useUpstream = 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 =
Expand Down Expand Up @@ -84,12 +93,18 @@ const _add = async function({ pkg, testables }) {
if (!editorVersionResult) {
log.warn(
"editor.version",
`${env.editorVersion} is unknown. The editor version check is disabled.`
`${env.editorVersion} is unknown, the editor version check is disabled`
);
}
if (!requiredEditorVersionResult) {
log.error("package.unity", `${requiredEditorVersion} is not valid.`);
return { code: 1, dirty };
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 &&
Expand All @@ -100,31 +115,52 @@ const _add = async function({ pkg, testables }) {
"editor.version",
`requires ${requiredEditorVersion} but found ${env.editorVersion}`
);
return { code: 1, dirty };
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 (!useUpstream) {
const pkgs = await fetchPackageDependencies({
const [depsValid, depsInvalid] = await fetchPackageDependencies({
name,
version,
deep: true
});
pkgs
// add depsValid to pkgsInScope.
depsValid
.filter(x => !x.upstream && !x.module)
.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);
}
// load manifest
let manifest = loadManifest();
if (manifest === null) return { code: 1, dirty };
// add to dependencies
if (!manifest.dependencies) {
manifest.dependencies = {};
dirty = true;
}
const oldVersion = manifest.dependencies[name];
manifest.dependencies[name] = version;
if (!oldVersion) {
Expand Down
17 changes: 15 additions & 2 deletions lib/cmd-deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,23 @@ const deps = async function(pkg, options) {
};

const _deps = async function({ name, version, deep }) {
const results = await fetchPackageDependencies({ name, version, deep });
results
// eslint-disable-next-line no-unused-vars
const [depsValid, depsInvalid] = await fetchPackageDependencies({
name,
version,
deep
});
depsValid
.filter(x => !x.self)
.forEach(x => log.notice("dependency", `${x.name}@${x.version}`));
depsInvalid
.filter(x => !x.self)
.forEach(x => {
let reason = "unknown";
if (x.reason == "package404") reason = "missing dependency";
else if (x.reason == "version404") reason = "missing dependency version";
log.warn(reason, `${x.name}@${x.version}`);
});
};

module.exports = deps;
41 changes: 25 additions & 16 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,15 @@ const fetchPackageInfo = async function(name, registry) {
} catch (err) {}
};

/* Fetch package dependencies
/* Fetch package [valid dependencies, invalid dependencies] with a structure of
[
{
name,
version,
upstream, // whether belongs to upstream registry
self, // whether is the source package
module, // whether is an unity module
reason // invalid reason of "version404", "package404"
}, ...
]
*/
Expand All @@ -192,7 +193,9 @@ const fetchPackageDependencies = async function({ name, version, deep }) {
// a list of processed dependency {name, version}
const processedList = [];
// a list of dependency entry exists on the registry
const validDeps = [];
const depsValid = [];
// a list of dependency entry doesn't exist on the registry
const depsInvalid = [];
// cached dict: {pkg-name: pkgInfo}
const cachedPacakgeInfoDict = {};
while (pendingList.length > 0) {
Expand All @@ -201,49 +204,52 @@ const fetchPackageDependencies = async function({ name, version, deep }) {
// add entry to processed list
processedList.push(entry);
// create valid depedenency structure
const validDep = {
const depObj = {
...entry,
module:
/com.unity.modules/i.test(entry.name) ||
entry.name == "com.unity.ugui",
upstream: false,
self: entry.name == name
self: entry.name == name,
reason: null
};
if (!validDep.module) {
if (!depObj.module) {
// try fetching package info from cache
let { pkgInfo, upstream } = _.get(cachedPacakgeInfoDict, entry.name, {
pkgInfo: null,
upstream: false
});
if (pkgInfo) {
validDep.upstream = upstream;
depObj.upstream = upstream;
}
// try fetching package info from the default registry
if (!pkgInfo) {
pkgInfo = await fetchPackageInfo(entry.name);
if (pkgInfo) {
validDep.upstream = false;
depObj.upstream = false;
cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: false };
}
}
// try fetching package info from the upstream registry
if (!pkgInfo) {
pkgInfo = await fetchPackageInfo(entry.name, env.upstreamRegistry);
if (pkgInfo) {
validDep.upstream = true;
depObj.upstream = true;
cachedPacakgeInfoDict[entry.name] = { pkgInfo, upstream: true };
}
}
// handle package not exist
if (!pkgInfo) {
log.warn("404", `package not found: ${entry.name}`);
depObj.reason = "package404";
depsInvalid.push(depObj);
continue;
}
// verify version
const versions = Object.keys(pkgInfo.versions);
if (!entry.version || entry.version == "latest") {
// eslint-disable-next-line require-atomic-updates
validDep.version = entry.version = getLatestVersion(pkgInfo);
depObj.version = entry.version = getLatestVersion(pkgInfo);
}
// handle version not exist
if (!versions.find(x => x == entry.version)) {
Expand All @@ -253,12 +259,15 @@ const fetchPackageDependencies = async function({ name, version, deep }) {
entry.version
} is not a valid choice of ${versions.reverse().join(", ")}`
);
depObj.reason = "version404";
// eslint-disable-next-line require-atomic-updates
validDep.version = entry.version = getLatestVersion(pkgInfo);
log.warn("404", `fall back to ${entry.name}@${entry.version}`);
// depObj.version = entry.version = getLatestVersion(pkgInfo);
// log.warn("notarget", `fallback to ${entry.name}@${entry.version}`);
depsInvalid.push(depObj);
continue;
}
// add dependencies to pending list
if (validDep.self || deep) {
if (depObj.self || deep) {
const deps = _.toPairs(
pkgInfo.versions[entry.version]["dependencies"]
).map(x => {
Expand All @@ -267,16 +276,16 @@ const fetchPackageDependencies = async function({ name, version, deep }) {
deps.forEach(x => pendingList.push(x));
}
}
validDeps.push(validDep);
depsValid.push(depObj);
log.verbose(
"dependency",
`${entry.name}@${entry.version} ${validDep.module ? "[module] " : ""}${
validDep.upstream ? "[upstream]" : ""
`${entry.name}@${entry.version} ${depObj.module ? "[module] " : ""}${
depObj.upstream ? "[upstream]" : ""
}`
);
}
}
return validDeps;
return [depsValid, depsInvalid];
};

// Get latest version from package info
Expand Down
27 changes: 27 additions & 0 deletions test/test-cmd-add.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ describe("cmd-add.js", function() {
},
test: true
};
const forceOptions = {
parent: {
registry: "http://example.com",
upstream: false,
chdir: getWorkDir("test-openupm-cli")
},
force: true
};
describe("add", function() {
let stdoutInspect = null;
let stderrInspect = null;
Expand Down Expand Up @@ -445,6 +453,15 @@ describe("cmd-add.js", function() {
const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect);
stdout.includes("requires 2020.2 but found 2019.2.13f1").should.be.ok();
});
it("force add pkg with higher editor version", async function() {
const retCode = await add(
"com.base.package-with-higher-editor-version",
forceOptions
);
retCode.should.equal(0);
const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect);
stdout.includes("requires 2020.2 but found 2019.2.13f1").should.be.ok();
});
it("add pkg with wrong editor version", async function() {
const retCode = await add(
"com.base.package-with-wrong-editor-version",
Expand All @@ -455,5 +472,15 @@ describe("cmd-add.js", function() {
stdout.includes("2020 is not valid").should.be.ok();
console.log(stdout);
});
it("force add pkg with wrong editor version", async function() {
const retCode = await add(
"com.base.package-with-wrong-editor-version",
forceOptions
);
retCode.should.equal(0);
const [stdout, stderr] = getOutputs(stdoutInspect, stderrInspect);
stdout.includes("2020 is not valid").should.be.ok();
console.log(stdout);
});
});
});

0 comments on commit 920d7a4

Please sign in to comment.