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
22import {
33 hooks ,
44 Installation ,
@@ -10,6 +10,7 @@ import {
1010import { dirname , fromFileUrl , join } from "jsr:@std/path@^1" ;
1111import { ensureDir , existsSync , walk } from "jsr:@std/fs@^1" ;
1212import { parseArgs } from "jsr:@std/cli@^1" ;
13+ import hydrate from "https://deno.land/x/libpkgx@v0.20.3/src/plumbing/hydrate.ts" ;
1314
1415function 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