1- import install , { Logger as InstallLogger } from "../plumbing/install.ts"
1+ import install , { Logger as BaseLogger , ConsoleLogger as BaseConsoleLogger } from "../plumbing/install.ts"
22import { Installation , PackageSpecification } from "../types.ts"
33import resolve , { Resolution } from "../plumbing/resolve.ts"
44import usePantry from "../hooks/usePantry.ts"
@@ -9,8 +9,21 @@ import link from "../plumbing/link.ts"
99import { is_what } from "../deps.ts"
1010const { isString } = is_what
1111
12- export interface Logger extends InstallLogger {
12+ export interface Logger extends BaseLogger {
1313 resolved ?( resolution : Resolution ) : void
14+ /// from 0.0–1.0
15+ /// currently you won’t get this immediately since we are waiting for all our
16+ /// network requests to return before we know the final download size
17+ progress ?( completion : number ) : void
18+ }
19+
20+ // deno-lint-ignore no-explicit-any
21+ export function ConsoleLogger ( prefix ?: any ) : Logger {
22+ prefix = prefix ? `${ prefix } : ` : ""
23+ return {
24+ ...BaseConsoleLogger ( prefix ) ,
25+ progress : function ( ) { console . error ( `${ prefix } progress` , ...arguments ) } ,
26+ }
1427}
1528
1629/// eg. install("python.org~3.10")
@@ -31,12 +44,59 @@ export default async function(pkgs: PackageSpecification[] | string[] | string,
3144 const resolution = await resolve ( pkgs )
3245 logger ?. resolved ?.( resolution )
3346
34- const { pending, installed} = resolution
35- for ( const pkg of pending ) {
36- const installation = await install ( pkg , logger )
37- await link ( installation )
38- installed . push ( installation )
39- }
47+ const { pending, installed } = resolution
48+ logger = WrapperLogger ( pending , logger )
49+ const installers = pending
50+ . map ( pkg => install ( pkg , logger )
51+ . then ( i => link ( i ) . then ( ( ) => i ) ) )
52+
53+ installed . push ( ...await Promise . all ( installers ) )
4054
4155 return installed
4256}
57+
58+ function WrapperLogger ( pending : PackageSpecification [ ] , logger ?: Logger ) : Logger | undefined {
59+ if ( ! logger ?. progress ) return logger
60+
61+ const projects = pending . map ( pkg => pkg . project )
62+ const totals : Record < string , number > = { }
63+ const progresses : Record < string , number > = { }
64+ return {
65+ ...logger ,
66+ downloading : args => {
67+ const { pkg : { project} , total } = args
68+ if ( total ) {
69+ totals [ project ] = total
70+ updateProgress ( )
71+ }
72+ if ( logger ?. downloading ) {
73+ logger . downloading ( args )
74+ }
75+ } ,
76+ installing : args => {
77+ const { pkg : { project} , progress } = args
78+ if ( progress ) {
79+ progresses [ project ] = progress
80+ updateProgress ( )
81+ }
82+ if ( logger ?. installing ) {
83+ logger . installing ( args )
84+ }
85+ }
86+ }
87+
88+ function updateProgress ( ) {
89+ let total_untard_bytes = 0
90+ let grand_total = 0
91+ for ( const project of projects ) {
92+ const total = totals [ project ]
93+ const bytes = progresses [ project ] * total
94+ total_untard_bytes += bytes
95+ grand_total += total
96+ }
97+ const rv = total_untard_bytes / grand_total
98+ if ( ! isNaN ( rv ) ) {
99+ logger ! . progress ! ( total_untard_bytes / grand_total )
100+ }
101+ }
102+ }
0 commit comments