add glob and regex support to all pkg args
This commit is contained in:
parent
7367cc7f5d
commit
cefea8ef54
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ lint: node_modules
|
||||
npx eslint --color .
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint: node_modules
|
||||
lint-fix: node_modules
|
||||
npx eslint --color . --fix
|
||||
|
||||
.PHONY: test
|
||||
|
@ -24,7 +24,11 @@ deno run -A npm:updates
|
||||
|
||||
## Options
|
||||
|
||||
See `--help`. Options that take multiple arguments can take them either via comma-separated value or by specifying the option multiple times. If an option has a optional `pkg` argument but none is given, the option will be applied to all packages instead.
|
||||
See `--help`. Options that take multiple arguments can take them either via comma-separated value or by specifying the option multiple times.
|
||||
|
||||
If an option has a optional `pkg` argument but none is given, the option will be applied to all packages instead.
|
||||
|
||||
All `pkg` options support glob matching via [picomatch](https://github.com/micromatch/picomatch) or regex (on CLI, wrap the regex in slashes, e.g. `'/^foo/'`).
|
||||
|
||||
## Config File
|
||||
|
||||
|
13
package-lock.json
generated
13
package-lock.json
generated
@ -26,6 +26,7 @@
|
||||
"minimist": "1.2.8",
|
||||
"node-fetch": "3.3.2",
|
||||
"p-all": "5.0.0",
|
||||
"picomatch": "2.3.1",
|
||||
"rc": "1.2.8",
|
||||
"registry-auth-token": "4.2.2",
|
||||
"restana": "4.9.7",
|
||||
@ -3486,6 +3487,18 @@
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pkg-types": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"minimist": "1.2.8",
|
||||
"node-fetch": "3.3.2",
|
||||
"p-all": "5.0.0",
|
||||
"picomatch": "2.3.1",
|
||||
"rc": "1.2.8",
|
||||
"registry-auth-token": "4.2.2",
|
||||
"restana": "4.9.7",
|
||||
|
@ -24,6 +24,30 @@ exports[`exclude 2`] = `
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`exclude 3`] = `
|
||||
{
|
||||
"dependencies": {
|
||||
"gulp-sourcemaps": {
|
||||
"info": "https://github.com/gulp-sourcemaps/gulp-sourcemaps",
|
||||
"new": "2.6.5",
|
||||
"old": "2.0.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`exclude 4`] = `
|
||||
{
|
||||
"dependencies": {
|
||||
"gulp-sourcemaps": {
|
||||
"info": "https://github.com/floridoo/gulp-sourcemaps",
|
||||
"new": "2.0.1",
|
||||
"old": "2.0.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`greatest 1`] = `
|
||||
{
|
||||
"dependencies": {
|
||||
|
61
updates.js
61
updates.js
@ -17,6 +17,7 @@ import {magenta, red, green, disableColor} from "glowie";
|
||||
import {getProperty} from "dot-prop";
|
||||
import pAll from "p-all";
|
||||
import memize from "memize";
|
||||
import picomatch from "picomatch";
|
||||
|
||||
let fetch;
|
||||
if (globalThis.fetch && !versions?.node) { // avoid node experimental warning
|
||||
@ -96,11 +97,11 @@ const args = minimist(argv.slice(2), {
|
||||
|
||||
if (args["no-color"] || !supportsColor.stdout) disableColor();
|
||||
|
||||
const greatest = parseMixedArg(args.greatest);
|
||||
const prerelease = parseMixedArg(args.prerelease);
|
||||
const release = parseMixedArg(args.release);
|
||||
const patch = parseMixedArg(args.patch);
|
||||
const minor = parseMixedArg(args.minor);
|
||||
const greatest = argSetToRegexes(parseMixedArg(args.greatest));
|
||||
const prerelease = argSetToRegexes(parseMixedArg(args.prerelease));
|
||||
const release = argSetToRegexes(parseMixedArg(args.release));
|
||||
const patch = argSetToRegexes(parseMixedArg(args.patch));
|
||||
const minor = argSetToRegexes(parseMixedArg(args.minor));
|
||||
const allowDowngrade = parseMixedArg(args["allow-downgrade"]);
|
||||
|
||||
const npmrc = rc("npm", {registry: "https://registry.npmjs.org"});
|
||||
@ -109,6 +110,13 @@ const githubApiUrl = args.githubapi ? normalizeUrl(args.githubapi) : "https://ap
|
||||
const pypiApiUrl = args.pypiapi ? normalizeUrl(args.pypiapi) : "https://pypi.org";
|
||||
const maxSockets = typeof args.sockets === "number" ? parseInt(args.sockets) : MAX_SOCKETS;
|
||||
|
||||
function matchesAny(str, set) {
|
||||
for (const re of (set instanceof Set ? set : [])) {
|
||||
if (re.test(str)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const registryUrl = memize((scope, npmrc) => {
|
||||
const url = npmrc[`${scope}:registry`] || npmrc.registry;
|
||||
return url.endsWith("/") ? url : `${url}/`;
|
||||
@ -502,7 +510,7 @@ function findNewVersion(data, {language, range, useGreatest, useRel, usePre, sem
|
||||
|
||||
// prevent downgrade to older version except with --allow-downgrade
|
||||
if (lt(latestTag, oldVersion) && !latestIsPre) {
|
||||
if (allowDowngrade === true || allowDowngrade?.has?.(data.name)) {
|
||||
if (allowDowngrade === true || matchesAny(data.name, allowDowngrade)) {
|
||||
return latestTag;
|
||||
} else {
|
||||
return null;
|
||||
@ -611,14 +619,35 @@ async function getCerts(extra = []) {
|
||||
return [...(await import("node:tls")).rootCertificates, ...extra];
|
||||
}
|
||||
|
||||
// convert arg from cli or config to regex
|
||||
function argToRegex(arg, cli) {
|
||||
if (cli) {
|
||||
return /\/.+\//.test(arg) ? new RegExp(arg.slice(1, -1)) : picomatch.makeRe(arg);
|
||||
} else {
|
||||
return arg instanceof RegExp ? arg : picomatch.makeRe(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// parse cli arg into regex set
|
||||
function argSetToRegexes(arg) {
|
||||
if (arg instanceof Set) {
|
||||
const ret = new Set();
|
||||
for (const entry of arg) {
|
||||
ret.add(argToRegex(entry, true));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
// parse include/exclude into a Set of regexes
|
||||
function matchersToRegexSet(cliArgs, configArgs) {
|
||||
const ret = new Set();
|
||||
for (const arg of cliArgs || []) {
|
||||
ret.add(new RegExp(/\/.+\//.test(arg) ? arg.slice(1, -1) : `^${esc(arg)}$`));
|
||||
ret.add(argToRegex(arg, true));
|
||||
}
|
||||
for (const arg of configArgs || []) {
|
||||
ret.add(arg instanceof RegExp ? arg : new RegExp(`^${esc(arg)}$`));
|
||||
ret.add(argToRegex(arg, false));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -636,8 +665,8 @@ async function main() {
|
||||
Options:
|
||||
-u, --update Update versions and write package file
|
||||
-f, --file <path> Use given package file or module directory
|
||||
-i, --include <pkg,...> Include only given packages, supports '/regex/' syntax
|
||||
-e, --exclude <pkg,...> Exclude given packages, supports '/regex/' syntax
|
||||
-i, --include <pkg,...> Include only given packages
|
||||
-e, --exclude <pkg,...> Exclude given packages
|
||||
-p, --prerelease [<pkg,...>] Consider prerelease versions
|
||||
-R, --release [<pkg,...>] Only use release versions, may downgrade
|
||||
-g, --greatest [<pkg,...>] Prefer greatest over latest version
|
||||
@ -850,14 +879,14 @@ async function main() {
|
||||
for (const [data, type, registry, name] of entries) {
|
||||
if (data?.error) throw new Error(data.error);
|
||||
|
||||
const useGreatest = typeof greatest === "boolean" ? greatest : greatest.has(data.name);
|
||||
const usePre = typeof prerelease === "boolean" ? prerelease : prerelease.has(data.name);
|
||||
const useRel = typeof release === "boolean" ? release : release.has(data.name);
|
||||
const useGreatest = typeof greatest === "boolean" ? greatest : matchesAny(data.name, greatest);
|
||||
const usePre = typeof prerelease === "boolean" ? prerelease : matchesAny(data.name, prerelease);
|
||||
const useRel = typeof release === "boolean" ? release : matchesAny(data.name, release);
|
||||
|
||||
let semvers;
|
||||
if (patch === true || patch?.has?.(data.name)) {
|
||||
if (patch === true || matchesAny(data.name, patch)) {
|
||||
semvers = patchSemvers;
|
||||
} else if (minor === true || minor?.has?.(data.name)) {
|
||||
} else if (minor === true || matchesAny(data.name, minor)) {
|
||||
semvers = minorSemvers;
|
||||
} else {
|
||||
semvers = majorSemvers;
|
||||
@ -892,7 +921,7 @@ async function main() {
|
||||
if (Object.keys(maybeUrlDeps).length) {
|
||||
const results = await Promise.all(Object.entries(maybeUrlDeps).map(([key, dep]) => {
|
||||
const name = key.split(sep)[1];
|
||||
const useGreatest = typeof greatest === "boolean" ? greatest : greatest.has(name);
|
||||
const useGreatest = typeof greatest === "boolean" ? greatest : matchesAny(name, greatest);
|
||||
return checkUrlDep([key, dep], {useGreatest});
|
||||
}));
|
||||
|
||||
|
@ -172,6 +172,8 @@ test("include 2", makeTest("-j -i noty -i noty,noty"));
|
||||
test("include 3", makeTest("-j -i /^noty/"));
|
||||
test("exclude", makeTest("-j -e gulp-sourcemaps,prismjs,svgstore,html-webpack-plugin,noty,jpeg-buffer-orientation,styled-components,@babel/preset-env,versions/updates,react"));
|
||||
test("exclude", makeTest("-j -e gulp-sourcemaps -i /react/"));
|
||||
test("exclude", makeTest("-j -i gulp*"));
|
||||
test("exclude", makeTest("-j -i /^gulp/ -P gulp*"));
|
||||
|
||||
test("pypi", makeTest(
|
||||
`-j -f ${fileURLToPath(new URL("fixtures/pyproject.toml", import.meta.url))}`,
|
||||
|
Loading…
Reference in New Issue
Block a user