Skip to content

Commit 13050ad

Browse files
authored
Merge pull request #44 from pkgxdev/outdated
`pkgm outdated`
2 parents b28a097 + 1c520ba commit 13050ad

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

pkgm.ts

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env -S pkgx --quiet deno^2.1 run --ext=ts --allow-sys=uid --allow-run --allow-env --allow-read --allow-write --allow-ffi
1+
#!/usr/bin/env -S pkgx --quiet deno^2.1 run --ext=ts --allow-sys=uid --allow-run --allow-env --allow-read --allow-write --allow-ffi --allow-net=dist.pkgx.dev
22
import {
33
hooks,
44
Installation,
@@ -10,6 +10,7 @@ import {
1010
import { dirname, fromFileUrl, join } from "jsr:@std/path@^1";
1111
import { ensureDir, existsSync, walk } from "jsr:@std/fs@^1";
1212
import { parseArgs } from "jsr:@std/cli@^1";
13+
import hydrate from "https://deno.land/x/libpkgx@v0.20.3/src/plumbing/hydrate.ts";
1314

1415
function standardPath() {
1516
let path = "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
@@ -86,9 +87,9 @@ if (parsedArgs.help) {
8687
case "up":
8788
case "update":
8889
case "pin":
90+
break;
8991
case "outdated":
90-
console.error("%cunimplemented. soz. U EARLY.", "color: red");
91-
Deno.exit(1);
92+
await outdated();
9293
break;
9394
case "sudo-install": {
9495
const [pkgx_dir, runtime_env, basePath, ...paths] = args;
@@ -591,3 +592,61 @@ function writable(path: string) {
591592
return false;
592593
}
593594
}
595+
596+
async function outdated() {
597+
const pkgs: Installation[] = [];
598+
for await (const pkg of walk_pkgs()) {
599+
pkgs.push(pkg);
600+
}
601+
602+
const { pkgs: raw_graph } = await hydrate(
603+
pkgs.map((x) => ({
604+
project: x.pkg.project,
605+
constraint: new semver.Range(`^${x.pkg.version}`),
606+
})),
607+
);
608+
const graph: Record<string, semver.Range> = {};
609+
for (const { project, constraint } of raw_graph) {
610+
graph[project] = constraint;
611+
}
612+
613+
for (const { path, pkg } of pkgs) {
614+
const versions = await hooks.useInventory().get(pkg);
615+
// console.log(pkg, graph[pkg.project]);
616+
const constrained_versions = versions.filter((x) =>
617+
graph[pkg.project].satisfies(x) && x.gt(pkg.version)
618+
);
619+
if (constrained_versions.length) {
620+
console.log(
621+
pkg.project,
622+
"is outdated",
623+
pkg.version,
624+
"<",
625+
constrained_versions.slice(-1)[0],
626+
`\x1b[2m${path}\x1b[22m`,
627+
);
628+
}
629+
}
630+
}
631+
632+
async function* walk_pkgs() {
633+
for (
634+
const root of [new Path("/usr/local/pkgs"), Path.home().join(".local/bin")]
635+
) {
636+
const dirs = [root];
637+
let dir: Path | undefined;
638+
while ((dir = dirs.pop()) !== undefined) {
639+
if (!dir.isDirectory()) continue;
640+
for await (const [path, { name, isSymlink, isDirectory }] of dir.ls()) {
641+
if (isSymlink || !isDirectory) continue;
642+
if (semver.parse(name)) {
643+
const project = path.parent().relative({ to: root });
644+
const version = new SemVer(path.basename());
645+
yield { path, pkg: { project, version } };
646+
} else {
647+
dirs.push(path);
648+
}
649+
}
650+
}
651+
}
652+
}

0 commit comments

Comments
 (0)