@@ -2,7 +2,7 @@ import { defaultExecOptions, execRoot, execRootSync } from "admina"
22import { GITHUB_ACTIONS } from "ci-info"
33import { info , warning } from "ci-log"
44import escapeRegex from "escape-string-regexp"
5- import { type ExecaError , execa } from "execa"
5+ import { type ExecaError , type SyncOptions , execa } from "execa"
66import { appendFile } from "fs/promises"
77import memoize from "micro-memoize"
88import { sourceRC } from "os-env"
@@ -47,7 +47,7 @@ export async function setupAptPack(packages: AptPackage[], update = false): Prom
4747 // Add the repos if needed
4848 await addRepositories ( apt , packages )
4949
50- const needToInstall = await filterAndQualifyAptPackages ( packages )
50+ const needToInstall = await filterAndQualifyAptPackages ( apt , packages )
5151
5252 if ( needToInstall . length === 0 ) {
5353 info ( "All packages are already installed" )
@@ -62,13 +62,17 @@ export async function setupAptPack(packages: AptPackage[], update = false): Prom
6262
6363 // Install
6464 try {
65- execRootSync ( apt , [ "install" , "--fix-broken" , "-y" , ...needToInstall ] , getAptExecOptions ( apt ) )
65+ execRootSync ( apt , [ "install" , "--fix-broken" , "-y" , ...needToInstall ] , getAptExecOptions ( { apt } ) )
6666 } catch ( err ) {
6767 if ( "stderr" in ( err as ExecaError ) ) {
6868 const stderr = ( err as ExecaError ) . stderr
6969 if ( retryErrors . some ( ( error ) => stderr . includes ( error ) ) ) {
7070 warning ( `Failed to install packages ${ needToInstall } . Retrying...` )
71- execRootSync ( apt , [ "install" , "--fix-broken" , "-y" , "-o" , aptTimeout , ...needToInstall ] , getAptExecOptions ( apt ) )
71+ execRootSync (
72+ apt ,
73+ [ "install" , "--fix-broken" , "-y" , "-o" , aptTimeout , ...needToInstall ] ,
74+ getAptExecOptions ( { apt } ) ,
75+ )
7276 }
7377 } else {
7478 throw err
@@ -108,8 +112,14 @@ function getEnv(apt: string) {
108112 return env
109113}
110114
111- function getAptExecOptionsRaw ( apt : string = "apt-get" ) {
112- return { env : getEnv ( apt ) , ...defaultExecOptions }
115+ function getAptExecOptionsRaw ( givenOpts : { apt ?: string ; pipe ?: boolean } = { } ) : SyncOptions {
116+ const opts = {
117+ apt : "apt-get" ,
118+ pipe : false ,
119+ ...givenOpts ,
120+ }
121+
122+ return { env : getEnv ( opts . apt ) , ...defaultExecOptions , stdio : opts . pipe ? "pipe" : "inherit" }
113123}
114124
115125const getAptExecOptions = memoize ( getAptExecOptionsRaw )
@@ -124,14 +134,14 @@ export enum AptPackageType {
124134/**
125135 * Filter out the packages that are already installed and qualify the packages into a full package name/version
126136 */
127- async function filterAndQualifyAptPackages ( packages : AptPackage [ ] ) {
128- return ( await Promise . all ( packages . map ( qualifiedNeededAptPackage ) ) )
137+ async function filterAndQualifyAptPackages ( apt : string , packages : AptPackage [ ] ) {
138+ return ( await Promise . all ( packages . map ( ( pack ) => qualifiedNeededAptPackage ( apt , pack ) ) ) )
129139 . filter ( ( pack ) => pack !== undefined )
130140}
131141
132- async function qualifiedNeededAptPackage ( pack : AptPackage ) {
142+ async function qualifiedNeededAptPackage ( apt : string , pack : AptPackage ) {
133143 // Qualify the packages into full package name/version
134- const qualified = await getAptArg ( pack . name , pack . version )
144+ const qualified = await getAptArg ( apt , pack . name , pack . version )
135145 // filter out the packages that are already installed
136146 return ( await isPackageInstalled ( qualified ) ) ? undefined : qualified
137147}
@@ -153,13 +163,13 @@ async function addRepositories(apt: string, packages: AptPackage[]) {
153163 }
154164}
155165
156- export async function aptPackageType ( name : string , version : string | undefined ) : Promise < AptPackageType > {
166+ async function aptPackageType ( apt : string , name : string , version : string | undefined ) : Promise < AptPackageType > {
157167 if ( version !== undefined && version !== "" ) {
158168 const { stdout } = await execa ( "apt-cache" , [
159169 "search" ,
160170 "--names-only" ,
161171 `^${ escapeRegex ( name ) } -${ escapeRegex ( version ) } $` ,
162- ] , getAptExecOptions ( ) )
172+ ] , getAptExecOptions ( { apt , pipe : true } ) )
163173 if ( stdout . trim ( ) !== "" ) {
164174 return AptPackageType . NameDashVersion
165175 }
@@ -177,7 +187,7 @@ export async function aptPackageType(name: string, version: string | undefined):
177187 }
178188
179189 try {
180- const { stdout : showStdout } = await execa ( "apt-cache" , [ "show" , name ] , getAptExecOptions ( ) )
190+ const { stdout : showStdout } = await execa ( "apt-cache" , [ "show" , name ] , getAptExecOptions ( { pipe : true } ) )
181191 if ( showStdout . trim ( ) !== "" ) {
182192 return AptPackageType . Name
183193 }
@@ -189,14 +199,14 @@ export async function aptPackageType(name: string, version: string | undefined):
189199 if ( ! didUpdate ) {
190200 updateRepos ( getApt ( ) )
191201 didUpdate = true
192- return aptPackageType ( name , version )
202+ return aptPackageType ( apt , name , version )
193203 }
194204
195205 return AptPackageType . None
196206}
197207
198- async function getAptArg ( name : string , version : string | undefined ) {
199- const package_type = await aptPackageType ( name , version )
208+ async function getAptArg ( apt : string , name : string , version : string | undefined ) {
209+ const package_type = await aptPackageType ( apt , name , version )
200210 switch ( package_type ) {
201211 case AptPackageType . NameDashVersion :
202212 return `${ name } -${ version } `
@@ -213,7 +223,7 @@ function updateRepos(apt: string) {
213223 execRootSync (
214224 apt ,
215225 apt !== "nala" ? [ "update" , "-y" , "-o" , aptTimeout ] : [ "update" , "-o" , aptTimeout ] ,
216- getAptExecOptions ( apt ) ,
226+ getAptExecOptions ( { apt } ) ,
217227 )
218228}
219229
@@ -224,7 +234,7 @@ async function installAddAptRepo(apt: string) {
224234 execRootSync (
225235 apt ,
226236 [ "install" , "-y" , "--fix-broken" , "-o" , aptTimeout , "software-properties-common" ] ,
227- getAptExecOptions ( apt ) ,
237+ getAptExecOptions ( { apt } ) ,
228238 )
229239}
230240
@@ -236,14 +246,14 @@ async function initApt(apt: string) {
236246 didUpdate = true
237247 }
238248
239- const toInstall = await filterAndQualifyAptPackages ( [
249+ const toInstall = await filterAndQualifyAptPackages ( apt , [
240250 { name : "ca-certificates" } ,
241251 { name : "gnupg" } ,
242252 { name : "apt-utils" } ,
243253 ] )
244254
245255 if ( toInstall . length !== 0 ) {
246- execRootSync ( apt , [ "install" , "-y" , "--fix-broken" , "-o" , aptTimeout , ...toInstall ] , getAptExecOptions ( apt ) )
256+ execRootSync ( apt , [ "install" , "-y" , "--fix-broken" , "-o" , aptTimeout , ...toInstall ] , getAptExecOptions ( { apt } ) )
247257 }
248258
249259 const promises : Promise < string | void > [ ] = [
@@ -312,7 +322,7 @@ export async function updateAptAlternatives(name: string, path: string, rcPath:
312322export async function isPackageInstalled ( pack : string ) {
313323 try {
314324 // check if a package is installed
315- const { stdout } = await execa ( "dpkg" , [ "-s" , pack ] , getAptExecOptions ( ) )
325+ const { stdout } = await execa ( "dpkg" , [ "-s" , pack ] , getAptExecOptions ( { pipe : true } ) )
316326 if ( typeof stdout !== "string" ) {
317327 return false
318328 }
@@ -327,7 +337,7 @@ export async function isPackageInstalled(pack: string) {
327337export async function isPackageRegexInstalled ( regexp : string ) {
328338 try {
329339 // check if a package matching the regexp is installed
330- const { stdout } = await execa ( "dpkg" , [ "-l" , regexp ] , getAptExecOptions ( ) )
340+ const { stdout } = await execa ( "dpkg" , [ "-l" , regexp ] , getAptExecOptions ( { pipe : true } ) )
331341 if ( typeof stdout !== "string" ) {
332342 return false
333343 }
0 commit comments