From d0de27b66c2c2c46a3220fa4cc547b702210b1b8 Mon Sep 17 00:00:00 2001 From: Lucas Bustamante Date: Wed, 13 Mar 2024 18:31:39 -0300 Subject: [PATCH] Improve verbosity, console output --- qit | Bin 2017413 -> 2019217 bytes .../Environment/DownEnvironmentCommand.php | 63 +++++++++++------- .../Environment/UpEnvironmentCommand.php | 4 +- src/src/Environment/Docker.php | 8 ++- .../EnvironmentDanglingCleanup.php | 12 ++-- src/src/Environment/EnvironmentDownloader.php | 9 +++ .../Environments/E2E/E2EEnvironment.php | 2 +- .../Environment/Environments/Environment.php | 29 +++++--- .../ExtensionDownload/ExtensionZip.php | 12 ++-- .../ExtensionDownload/Handlers/QITHandler.php | 4 +- src/src/RequestBuilder.php | 2 +- 11 files changed, 92 insertions(+), 53 deletions(-) diff --git a/qit b/qit index 5eeddabf14055e8bf2c679c9d83e44b83d448e19..f4be07d32e66bca6c4d0e20a8962720e4033515c 100755 GIT binary patch delta 65359 zcmce91$dN4^LXBaBqxzePLjKe3keA^oM6E{3GRg86iING6fe#KLj|kS(gM}DrKLcH z3QlQh(NJnoB-HW$?7nw_-S<7n*YErN`#gR2VP&1F#)D&ELnz9AdaZu1hr-;EO+f ze4gHSpb^Q`r7^${HXon#w@+r0;ksH3Fe=K&XX3%$G300?3)!WMX8g|S8Zl(QV?I8+ zgGRO_RV!sMMDI%3tX)^BnT-y3D#gdA$I@AMo|k;sf63&!&O&BaGLpc`p^Qb|gi1ck zU;N%cnwTx5QRM{IeQ;$(-Y@)od`jNUFC<$lXEN$$W*?uyhPO76pDQL^!ZoXCP(1Aq-P$ z^zpg9GWIkH^sB85mF45(x2JEc!r9M7X84&I;)Ng|pXi_Vv?EXYHD!P`$n?fB5gZQ|L}^3Bn?RtT`da-jxQQJ zCB1l9aZ6u?khb@7{>&hU{JXMY-$&&JM7^|zWQC#XC}3ZGI77@p#NIXADxs2%8Nd5iRv~;s8xt;Iy1mC79XF&8oIs+Xh{y9 zFqrosfOe&AL{g1l5<7_UjSFkvrdf;JW-YQ&L5ins_T)ZGP*E2t2n>b8b#xKtN$5Bf zOWPUMdwoJ?){P+j1C!WT>(PQ^fB19-dA%9yLiPkY8RBt7ObvOXpNALe^H_xWbp%pY zw7om!o8LW1I9x@F40can61MHPyb?yvq`Rf4BKbpl9i7GO?-rD{F;mZ9#A#ASjR;mI zbTcyUQoH$nk`t`><}PG*v)&iANM0REX#``k6lxymwk2&tLM}`o8){Rmo?H$#v1N5L zxIWV&YPOG$b=FU#aLv_WfLt8;=M!tFue-=bb36m~#SKejs~1{R%8GOzyX^PuFkuenCnSlVM{X zhJ_C-sVsm+qkGJ~Fl(b{dA1-~sZn6=s0$!ftZ}UKAT(ZRcHDQQW0oQgEa{|+H=jmZ zP+e#nbZFE^<+?;RLtUPCOH11t@yA~B$P@s14JD^}wA(vr`$Bs2-^et3CY0t#QD$&= zr0q+ueUR(vXoN$}qzE(BgpNwvtG^F8NMh}|Ov)Vy$iFiACUWY;0Lu}uu+fvB;Bs_} zy}XMq+`Q7wfVMwRF5QksZpke11_JuOyl$b#60syUDw4b$rnr_I){}8Pfo?G~;%XIi zbL84rGLa79%F;<{>f_Vxj~2x^UKY$As|zy^cF#6#yO!+FCLLW_I6u$e>6|+nCyOGsu`i7jaXN6%k5Q$iyYIGCkg(L;mPS)(-daslGqG zSGoCc9`rD6sLmEVQQ@70t+COOFU#ek2G)~}kv1mW1yr>`J)cWBUF{iQ0=i<)x33hD zWtml=c(^XZywhzJ+9utNe*$T9wVC| zf1ng-zK&ZAog&)qKDNKC+{n=QF27L!kKZpD06%F0JObm zulbzErjR*77YZ9E>dfZK?ir$OM7xL^=p4!n^+x~uJ+^r8BQJ?n z961E{n|8&}i-w=Iqoe@nH&Qa2tKuF@#iMQE<}V*GYs?Vz%;(+G)3)yUV`E9bxE{<_ zw{V>A&qlRmXA+Rqmkse9iulBbRlX;8n$RVqYg{oJ9 z(s~#qYBp4u()OR5fB%lsB#|A-sf_$A3bL|f&@IxxS{3MDLkff=)g_a;DRQBL(6;uw z%MUP1VIpm}AyG7N1~qK&V+hp~`XQ!H$#V|q;Imdwe<1>cbYrXZt3r*FK^7-hE6g_8cM zdWNB?$dZ=!>mE(Q%?I6)n6~y8hWza569BH(I-_}mTSwadVHuxyU!4Zk6shx2o%S!6 zRzsFbPJ9DL@BUA%>112AW^B+^$a+n{-B)RNB{|jgu&tXe1TtGm29^g#ySNjFpA#$C(~6f z4dZySP-ihaQDZtTZF^0>(6oHLcm|GYIeg^c_CY==wp931m}N zW%DweXUdDVx|VM@!33o{Q|mHz9}#y;#^q24a{A~jP~1TZFu&}kr|sW6d;UzE)q6Ag z<*4ItvkSgO`d$oBjJy2VgMD_ey|Oe{s$vds%T3!C4m4_klI6gPo;sU(xZ6;)-8T2m zAkI+e1UB<2cWk6>UYGfM$?{$>P zM3D2f!@_$Ojv7hl?>)EaY1?jcRw~(AE0rbH-_=rb=ufx#_|)p?MRpxMc-+9kV#TvsxifOwcG@4g5XV!ZUNp|*AKNcg!fYIq@A|kNK9+)%(^2OZ z)!h2fcJ7+U*6h%+qe&3-Ux#7JT-VB!ORC$BwG-+pNx)&W=AC+brla8$mgX;{;8pc1 zGa~nq2J@UA{SgF3(36r+9u_HdDp>xZ#k zA3J?~Do@|B92bU%or@$kP-5oWsLiHQ-zV82L>bFK?yU>-|J=o_Pv$jH)INf)(SGgA zapX(`CBvDAs;$3LX&43u7unv(1g}L)HZr=QA`NvX=dm_BXB1mRvlsgK{1p63vPZZcB&)uQI-W1dZxTgr=EO3xcYnb{T0+i#4_T)N z$?CD0+k%_$>K}7jVe&wSY{Gyf-N$Fa$&Yv9Ja=P&bex%v;}XE_z7AOTu@p!)HLc9B zzalpO=5x(4in>VV00T4*&?T8yqlsxmq3zE1mbAuj&#)w;nGznhBjTLA9v4^@#i>E8$0sW3AXAk0W6DszVKN#^TBB=0??>z#-$o3vOfz>k)u6xO4mXHYl{x zW8*(ok{PVXycyYbTyXtQ+@kIep7XcE`~o7V*tG3C^ZkS9I@r5KB4hbGvaEma`C2$m z2L|YffMl}j2Frssb2?%(tz{tVO|N6BK2`D# zhT?ccIM^P&U0D@_Y5P~N)M}VeQe+fEK7;uOm5#QfDnA!OMzm7SnJ?iS=qmSZjFP26 zaWG!J&|3mZO52?&M^}>#9phnnRon@#yU${@-7@ae!Bj_a*+q9qRqZ;;b^-rVsjYVi98e|?@B@D zX>K00efGp!6dnKKTTxsiKW~a$S_sXl@r)H;^Nb}5UiaxZx^mqK5j4M^y-Oos# zX{TgFoiPQ-7!_WV>}aP1t@D`4w`^=lXI@<1rFMHI*Ex}Z^B;cxgl8xddFD!}`E5*; zsrhKzGrM{wn*cf#L{-w+&DjnGP1_?kTDi#b4k-|3$NY3KIt=Yd+qCa*?_>EX9kf)3 z7980@iN;$Hd**V}1nj45Q3a^*pHtsk&o*KY`KnxHMo51jpZC8CTvE=@Xv*Z}u3_srR>Nn-~qH;hxUv!Z*jTBL78&q`RK)Dw&QPcC3 zjP@rK^~(HbDzSL!kqpW#m=3qXZG-Ac+ZQH(_{oC|T;|u@vrOA6;ko0=&Cl4E-+e8IO4CVES!6UC-piiQ-226#<9BHu9T}r?FyNaRN0*CUVyaC>((?Fm!@)Y zo{6jD`RqZ>G3v!DmNs`%ZZWh$m$i3}o34LFO6m z#EQ0CNpdH45$bAhMgl!V{*8yfl1ycKXxrh5yHPA8BbLdE4+ z$_#Bno|glQ75`ME(ZlSUc#$v|vo^Mpu&w=h!9VV8w308n3uQ`M=hBQH%iRXC{v@coBGhVBqrsAac7~tX#33%kv;G+$wJU9u+)i%h)>-Cn6}Yr+Xs`J9`Pje zOfbppp@{zn!5CMwAOI1y*~u-}j5GKCX;Ko5DJ4dXYk`s<+1f*S9@>e=x>N7VOeBi2 znJ*wY9iFxyt$OWSluLPxnu^P@pJ8~Fa?O$4L>Bc_!i9vI*BRgXPPv;>EF22JxV$z- z;Yiz8)69NsKVnk2dMSnpLmSKtAGwG{Y>I(rVsRro>b5y;fBtc1cZ{XYnawsMphpfQ zdOU{d1Pvo`-DfAdt%vO^yZ0Sq^5pbZcJYtVM|hZ5E~(+MI~z*@k@-uZ}@>EjDibkXa7u{IecK_OO znJnw8gpo9K>fIL)E%(dH+``kg>OE^a&srfH`ujs^hA!B=+wFq1eS37Xe^{Q6u8S0DOpd-7 zjQ;G<*k!_# z`ww`!z^)YZ!F*JNP9$xAJZS3743;@SNp_B7my=P?HDGDnp0Y@@!M%2A`&`><=NYfe z0XDM!w_x)ZZX|7OU#uF(6we%Bhgbb{dh_G%KugNyC&od_IVF6Ma*~>ZKKke7SO>lkB{}P6X0XRQ{&*VD z?&==4lIqtFAw`4z$hGYO{?ipRk;{WRGwUqHC3kYQ?-_O?GY^g?pX~_p@1iVF^3>oi z%)71+?#kLWL;A7yl_5E-y)r~uw{%xMarH+XhE^BJALf87OL0d2Qn(DJZN2a2-b1&G zg4dSlg3FaTI#fCF(sh6Nhjjxm>x_biOLcY(hj~c+&fP=rIyLB8?fb^@yg7by$>-&#)nT?C6O& zVi4IgLdmF-QMF$>#YSK(a}gW?0_Ng-(*@kkD1X|%6JZ&H#-(zS{E^CWt5q``w@a-v zEJMUzWc5fJTfrC8@uqND|7gz&P9U)(oN#vnW=-qdSqyD&P2GJ4m5hV@PtcH4Mp?tB z4jx-XPsVrfwvUcX+wAPX!4Fa?&w_JNrsu~!o6Z)(o>6g3y>7TVYFoSCAXi5zH=BRc zAlH9ZJT5Y(7cq}E!l@Fxb^I+-8G*JFw+uY$o&!c;nuGatDH@fEK-=Ly=NDkSa4WAT zh9V_ft1=Mt^q890aDianT;!*9G`|@6{2dfBf*dIdB5R72#A<7i;@nq@nzQ+-Ra}d; zql!B+MF!xYzqT&;8_NVN-0%d!iBcc&OGqyJgRqT*1JJw{P`9wPdbb?-@rjZvP5 z8QTO8w$eOXreVGki>FWHvrsVM0x{RV2 zDPl(i0I`hAW&k=$q8!?t^c)vilMcHd*TIwz8+`AP4*#i0H$k~4`4|VKbhO=E%dmmG zGA_M<`Mn)ST^3%2v{2NX(6dKUb*^zGQ!6vXM5i{ zWa#+V+LUo4wAY1Pxa|=Dt;GarRy2CZ@S)T~dYdvDZC^NhVF&qeykhG5=!e~RoLEM# zj91}JNx}qW!?}wIO5HUBJ|}%A)L`;_hd0+fF5THkVkgFuT@w^n`V>WY zse4K{a&|%;MpcTwd~;Ard!(w(0DCa1W~ zSNNj!GAckZv`xFUYYOcGr@zBJZmoMWpl$nw_xy=%lCl{L$8_bT*%4Do$4SZ+=|-G| zX}6jTCQByOV&l`O{>@Bz1X8eJf>^Q<;@;zE+p6@!SSkd0YmdX+0=IQ418sl%x?~?aYS%Tt~Y&$dkMAi6>U+LEF(?0{^4~ksl^2vF1w@IOqFu^UyvH5!Of6aqZXmzW=j3Leci^9fMm@1i8D@X@1U)pzR-D4VB4PQ?nS0&vB~W(H-qg z%+r+moiY^R{VP*iq1~&ofOra}|Ljb&>K+j=J(`I(I@5y83*1a;`;D*ld$NC;G9g`2 zu13?!@<`7a>15VS1KIdxkhzB24Qab2vBgZ%XL?I>I?fbToVF*X{Qeg9s6%271)1M> zy8&&7{b*WG{AV;Z|A025)U?g*H=_wsD>=+joR9S%FYQUT&1lbrj>eVz!o^=Fd4$d& z=IQBd(r@GXpgd@+o4LIs={U2Ic@VAy3Z(7PX0~t1#+h}^C20zfwi{Ok>?A+WY|NO? zL*}|U6F>4WuYndxA(5X4nAf{?r0t3mRUM>cR$bO*87`5)KA(;7bg9COczISZn}o~g zz)NOMage?x(IoIwbMOYYS!nxe^`)f6>?CtlJjhZRX?tse|A#1e1X(v*2@7@5BAX^! z0?3!M8?phN=+iBKx0^fzrn3RFODyKXbcGLX-|0DS84j9Z{wG=i(zfeHmY27?|~uHm;l-hlo4=f_*I zHfxTOkC)8p&i;LBPAAr8&Q;*E=k{j*K0CJ;YwOQb{{7^sfg%jge3p(ICBaILwz zg#7vDy(d1a95AR}R*ia@1BTS7Rc|0^@^l!vxV#<@Jh~}?{IxQY6s<_$5o0#Tl07SG z@<8d?c+zK0B*|In;1D2XNO9!dHF2<~5G!5YTxsFZBsTi=khCAmECc_Qd?k>qm}u=h*J{$}shdv!6j24)SZTRp3K-FgFS71qca zP_yQcta`Nu))-V+dqDN-b!tJA_Z;>&JHdrY90#;nbsj+NHFUj;2U1)8`m_L~wyO0E z4^-?l^O+dFKQ+%Gk(8MyY`s8A%`-p*E?eKj_TW_a>C>@Imx5;P+mP2bhLdy882RC< zZs3(t>@;J;E{Uh34%2tjFdlex(`p_tX7gMgAU(T~11L(%&yMDx=o3$H0L33JJ|~c& z!f@egM12y27cmE(kLCIhbPV|AYD8_a=TsH){3Zdr`-M?FdEFOhaR5d0?_Lb$Ekwcb z#QAy$j+g|z;ex#VQW)gKOIGsU>#aoeG#)_SSj+=b-fYJMO5PNPIQeECM**)Nl+wuL z_Y>fsgHj|p^iHq}9Ys#RHBg~a5DC8cNLP^j&odwiksR}u8A&3;eWhV_Mn90Zw z>?#U7x%bWhH59fUL6(PhCXmM_g=%+%jYshjP5@; ztlYVt>x_Un(&zmdDj@7WF1b+UOiYMk$&tPMq_A!~J`kLN^6I&3lE}*jv%bM+=nq?~ z5M=m=Jyk&HdO|XLW(sDVknHN=kM53wFHcCpE)EQjI z6F=qqQOv4+qAm74&UJ^CXQga16qTayp8Kp8 zY4e4+{q93O&!d;U_C+Dr5yfMe6cW5InH-)T;!b|O^{=#_4-T|HS-u}sOc59Xi!Pvh z?b_dzymuf`lY&GaEYe0CJ~%-W0W*F?U!*)&%m^Z%9}xWqCqC*hZ(Woz95($VMUl@g z1(CAD?RmznkF4MUKO7m$0l@l;lm&YhGN%b5+mG^z0<8N*ssY<`%F#xWKF&q@{mF|4 zF&ELMqN;mQkygU2gY%>)H5_Q2JR{SX$;qo6i&;7ed5v2HBORscTy;E8pO8>;^ zPzNBImbv-q$xEeEw73{xcME?#>2sc+VV3bmT`<7tzcCsexKIsV{#$aY!@4qrfz13~ zSZ502G3_DKZ?OHs%aA)M_R!9tRX;n(k*q+m>uOL=M@>n^QT0oN4hlE~~|3seYl?MeXIei_SDE~}h3+Kn8q-K*CXjj6kK zWu_)I%&3GV%%iSkz|KlK2f24u*a)dMRFoFigtVO+U}I%nEG7j)#BpPMA;(weB+rxy z8?y&Z_FOlTwCn20qHKK;>m6f&dwx31DSzvx(#g}=KyLjuQiUZO|1?3mUKdG&bp*-$ zGn72hJc5}2;R7}EDkLTOe~i)M5emB-;uf6wXLBv=TrHppI@HG6((+-KHw#tm51wJ6 zk4fjePnz?0h9<|g0lH{~s`PJ-C_`1<7NE1ik*RJ~H~y2tGs?P|Lhk)DP77#(BW5}a zH-u%Hb#skKUJpvmRs*?mrv@!)iiaIT#ju%mvz~_?qX}02Wx6Tk%Wk?LFxJB~xcD5c z!)l@)ZgvP>31r?GB4Sd=fji4NAY7NEBv>A*bF3L9rIHo7;cK=^{9G#}sTQ4$k)-EY zwMod4d%U+P9UEJ9R_xeCHEi0No04#QfWo9fcN>=N)4c&URhEL`14*i?>N`gTNrK^a zoXQV$l92T=1@GALcO8gJ#j=(VZSi4rWl4{>5fUFw6eSSHuN4Ix=qvFyR>1Wg=$(6f zrCu6RcJR|MMG~BGV%b`Mr_L9Cj*t>q%?vH;!K#>Ga(V|Ja+E=^hlPB8i=$-~G-lHG zq*jMfF0`vrFXd`TwOFsINPG z;f@$3;W*5|E240ghMFXP>r~hw&JW5=l5n8)utQS?Nc_&H^uwWip=zMiUqcUu+Y>0x z6Y{JIc|p=dRTuU42s7evuAdH;_;VDjwBWLeF^g7Z;QSE$ImnK9oa_B&&3;HAjP2>? zzcy6j4|>W-8$!j2!X9a`&n#uq8Vx_FRt2l_maAq8sf2jIM)FU>Ut6GXskDHk3U7wJ zR*BC%L9(MKWG3U>ZL*204{`hnpHf$auk2DEjxCMs&?`(*@4-+hToM8>rQMK<#VL`g zIy1Z*F6F6tA>QdpS@eK~OX-?4dZ<}V;gLcDyPLt~6rvv!tdCRhR|ZW@(?!907g`BR zF(SMq!|z96y1PFOg+WRUof$qoLhxP2A5r||FzAFxiBB}>EnXT#OvMA%j#$YC{h}oP z@_`bxV*8*%fc4=SoH5{fmaZ_%qMVYqD`k}q z1+&o}bSGD+f@|pF)vTDi*LI3b+im1ZN;E51*gs*tsxI5NkS?}N9da@@p&h#OqF6_RJJY*ZX}CAmf`-% z)&=1O0Peh1MIY)|A6>+pqS37ikQ9keg6K$9ASG4e591WPfS+wP?4D{^Be$_32E@E- zQVVSYVK2qkk96pgCh_M2dheYMSJEUtDOJEMmU!)EOtt`m>-{U z+?OHow+ITyNlkDIPI`@TY^3TI2e&h&jT+#CO?Am0K}--{U24D+ZO+FWF^2wTa7A@- zTn~;vY=H-CfbGq7F*JKhqQ5#cz_u0`_jfkO5O=kv#3z${Clf5IDNWTD!~i+9GzB?Q zOYq-vo_d&3Tk;~L9?rJH+~CVP7_smdgCP)9SIi(h`rz;QS}UYNzHp!5ZfjJoUJWUO zl%-aN2KduO^<}{WVy$R{_Q9hpe}D4;!7KHISo{F4S++*MG$_p$0ub$z25ag|{7FXv zvq*iUK1S-N8i=cm^}E+Vnys3MH0U>5IhAFR0!svB#)`hn`g)>TmMWSlgWDU6@s@Sl z-B?`9(1x(02Ywk~c(D`-{X0pafIm;I!P`aZsq4&^tLNvd zq4al4@~ zcDOoNs!l&`!C!Pk$6>lwq;zY<+CKQ+hhLcxvb>VVbQzE`99P`-J{ZMk_LA!HVj@8n zTpf;ipTfie?R!ggRWx0w?RgZJ;!XAD)5x4HEKTU|`!| zi9gaR;8x=?x%Fs|AEXdY3u7keYQwGZxH53^t9w2K5(3xgkxU)9ki1Wr{$G$t_ggD~tnE|5D+O5n9Zrgh-ynHaRSCn*HwcPJ)~;%D;Ri- zomd%O8zuS|5@oF&E%EP(fYAEXM8ZuMf^ZKZYaUMz}N!!(DbqRTOW75v`c*xPbI=0(HwCkTr0sJxu~w~-NYt1@Hn1_ z(0?9akJZ+ZYDZ=g^__!T=E(_CD^4|rDxHY=_L(`D&*HYJaHB=*(WGA~e~9)_3%43n zq8XFKJAyHrBcNy=K0M%?5n1t45IM5BGGtE{0y3dwD<(_)vn{+n9~JSPBJm|J6kLxT zQ5mzcskqGW^9bSUoC*o?19VfxM4o}~F2LJ*yg3&VbB6QWs;7E6v{Gq*nI=ffbm%i( zfWpy5x-5FgVzNd)p~K&Y&k(jV)^o%Ycy?`lPobMPLkJj*>Vqno1P zW<*>)ctiFc!n?aft~bf66t2IRKC#!koxQx=F1Q6Tsuc@JL_noB7JMKa5at1ibfR|je{|F z^_D;m0kI>aBH{CAB{R1YYxNmc1u=y`7WtSAcv*3fBX*T zsr%zE`w?0duIVuV-`-+?$yR46Yjv_~QXTo84zEXqM`tc`Wtnq6E(@XKKW!X6~!NzJoA-E!hRr>KyxhQ~A;RpWbMc;Fy9_IwR z-=WF(!d*H;?fza`r0U=)>Jws@QUe%)#e4zK_y-|%r`%{ia`<2{T=^bvZDJ1DAh(SW z!8~NNzE234bZ(;#$3yB*!VNw4VTFDC9S>=Jq&BqwS#InB0oQkxPkAH2U zMSJ{&Vx687mR*$igD}beDvE~75V&zs%+7Xwg}K0KM0LF+_&z*-Nti1*e@R%VQ1@5S z`>}?vCnq=7t+UcSNWUz+O1Lq0i1-Ifv-*?7RVO0VD~wSUpRmJISERmb&Y9oZVM{2M z++cq)``bv3$)f_4eOncFv{A?)|C+dqDI~PwFNp4Dj2k7hL&GvDS~V(cDiiKmnUsr9 z#ZoD2lO3iQIMqm4u9Sq<1PTtMlmQ0Ah7?`&+TVpqz=y}W)I8B-*O@2{+t3GDtPT`h zo+02hF?LgBV)y=YWF0gw51VqE!7s_&*pe@WUICTH~|Y zKfWfw(;LhEoK#sMJS&1ZC?*L%%n_{Kl|2jqD*%PaqjWX^R{wdyw7e;v{M>!WtRJJP zGeolwiQv~egjGe!9;p5^LU<(7;ws)i~ZN^wAIA06ng44*HTNJy2F=I7~H&rw)*o7zRO^ua3VvDDRDRh8CFRrxR{G+(XhbL{@Al#KZ^DSZHX0 zUcS0&`0)n^oQo27HL91p?2u0bm=7pbhG=iSPDsR*eyr5c4tr|hHBOlkFC{-P==j@e zHyiv8YbQ4isoM<82Rms^AQc23(NZX{+A514q6}wIN*6>+r*#w;f9DVZkkv z`b5Ntk6;xe4wJ4hr2itOnJHC8jCgnX9Jeq7=DdVIse&C}1o`SUz{Rw43hhJw@JgjMis z1&k$#eD*-WwE%A6)eV0BN~nlJ9IHOm5DBpGP^f`m)U4K!gz56Q$yG!}oE=ibb;6|` z>xTu07Wgn+*H)t+RvnJe0As883PWi|7RDT!etF3R{i1ckYXeth7z~%@bM*LGC>xZf2E?;O9qZ3a3_ZedO zp$XdI_D;vfWu?W2RUT5oQ}VXU_l%!6#43)^5R4b-O{U&yxyTu zY{s8+WF(3@uxh}3cfDdRZ$uByr3hC3K`B@tf`?f3^^1p|)-Z;$k?9wvQZ$%iHDfR( z;FY0br@^g6am6CIez^#--Uh~!Mqx=~A!B1jj8vNxrJ=m1u93grpaqOgX*wf#C#!25 zSXEdMYzDBdF&_L2+)hJ2DTsyceKa;7TIv`{GjM+CGajCLNB-)@gW@OH17*dHyyr0# zmNN#z#6K{Y;YZjk+L;qzbt4~6SXWOuqi{(>w|h?|BmUSZUDt-2R!`Sz5SgLl*CIn< zO=CFRS%wDcpN6{{el{zX>t9~t$kKo?2+qPMA*^$Z)R=876x_gfX4Q?(0Nk{;X9;^c zEmwR-Ma>Er@#kt;_&$!`;Z5TSaDX(xxf=|;i<9taa8IBeb~M2CsajK>F09ZI-zRDbappcAQySs4Q(lCK z#f|(P%X(oM<19{Z4>T08YS9k)b-j*-$xgL$@e|b{jd8-7MH@XayA|D3PcR@O!V*R^ zyjTZ=V@$T_60C9%iy4J&oq@5AkzYc9<%_d9b(9jtN)3eks=RVB2sSp*@kdvRs{@Pb z>k^?|L!D3$!^ZU#GB!~S6$6MfLqsE;fMfNA&`8IxYo)#r3mI+Dps^5A6dYDF3i}{( zst4U$;TIn0UwK%bqvKCZO1B?#gmg>+VpHeU@V5|=Hn`+{)ijlu9qZL^9>lOnb zwK>*^;9ot!il(;WzTzRpd)qdcYY(e|Kk@fY#i|;o^EUNxU^o+uZXuk0%B5k&i$PSH zRQkseqBYoH8Dk_IZjORP)W%0C)iNvR#i|-@j1>PigB2@KG#2Fp)L7>zY&ssXSz)7B z9M&`nS>yeFSimThEZoOo?P4(1GzF%$)$yn72c$aIR)agMV#J?y=HuFZt({J&AjctC zJ!7;&(6_ygzlEUOSq*v^HBS864m$pVK*3{SW2C~MLqpsV)wvGif_09yV8<}50%3ox z$zAM-A5&DNMvR;t*6K$p0Py*VHJ;VBOK|d ztDz!D1FU_-2g*+30fouRB4fF%fCZ2)Z^B{~q}x{bmzuoV3X39zhbbJ#T?QH0RX0E- zAH!8=lSIr_5@7ZeETM_Sugme2p2|oeDk1oJo)D`N-%&wW-Q!>$jD?PBLRQcixVD!V zty!((qF%a@0*~IhHw8#}8Dnm5EC|BCPEl2xKnVVx636@1i+B^%S0~EcPxper&Rw$@ z1A%?8OfkDa^mA4bh}DaNUytA@h*#W2`0PM3x?iWvBZ>O%OTJVfql#(>9k)jidW zLYl=Wv5=8}-k{}+LK5hySX{u5&SYCPPOHa9R;Q1?B>`#@&^SXGd z5iLBanKX(Gq$PWy8st}sb^O&L9dr{<$mR$O6BYI7Uvm={DI>rVMVF%g?Qk#prvnx& zMpGi;GJ-L{s>QMVz@9=y!8s88qKc3e9tt-&T#+Fwbkq_YOABpGaQJbOki;tGlvrfw zgo4Rp;>Co40U3LcC{vvGULb(Vrs& zT(NeDo+j??tZeY5DOlkavnjHh^z zl^XJvWT^ggg;>a-SXUTIO&A3U^K|^OXO(eSVaVTdFenxjn%2(O)#dGu6@HOWIA1&* zAy_yMuu?#*9&{htS3H4*y1N%*UWb3FN%Q1Rs|~TNP*~iI&9a3;Ld66OTcm5o3CEyV zLui7fi$uAxkdTiLj2O!XdB0*%tQ2g_Gk&m0FcA7J79S(rcp)_}Tq2yJX$>GN4aBOR zepsPL3jy)#%Vy|yQM{BzO2WyY^z~E*^3GC@v(kGM;XV~>0fn<7D}}?#KO0d&GOxaMKN-@QVNXOs$y0EKH~gpT8NW!$jX zZ;l2SOZx)p-9a#HT8j@pd*&!^GKshj_!~m-q>n0JDzyVT{`B7c6fs@%u?A-9&Pmyk(`| z@6sdLl!T?ihPM8GP-(RvA8O>1)o67U0~?H4>*wIXn@5C&%iGraJ#OUTR1WC4*{=={ zX0mVH>=&y6MwKFYaN(G+B)Rdkel>;TJ90_pDbN4qmn@$;=GQQYha;s^Zgk$SNYF;j zVaFeS;ZXaIs2?(p19Oh8vYdax&mtuLMSuA5#nm!$*&z(2A_63GLhimOURD{0`n0lI zd^m8+PdIE*tti+CD{uSp8!l8-Gr9L2zh_LU;RL&)sIhVnga6S=Jmt0F{x#*{f&Lc3 z{Scl7XTOXv!TSwDjq;%g|Ic-*o(hG0Hrl_nV5|GxN5}dL#`fR>;fq-R-&IU&!tFSJ z-lE{?VuD@^tS0Ci?;oY==N6X{9E$fB+`GgQR-5lq_;@H^%nK_QIP3E?C9<`V09ox! zm$MW7JM!0D^f>|RhYT`)_^XC6_b7Y?bV89$GOprOKYl>$oh=7<^snoyf@^Wz+|9o| zPk8SAp#OdU-3@BOcY{1iGWrx<2Lwfih<0nr>aju5(q$QjE6Cm($ahh=hNsx0N z_xBV0hLOKttT({Yx&Fd|lHpucg99Obo_`CCVOYP+Wnp~119%r93%;p>+wixG{bQl( z#Lxh_biV%xVS*mgTmE9P{~}?@+*hDy5Y+c}gw4xG9$Rk&|-tlZ4n;j`SuDbp&lwrpN=D>VHr> zk2jNOPI#h>12olgvcbLdyZm{3Z#El~;NC!7jr|7b`4b7;$EjB;!+BY$o_-}>hLS%R zq`x2-&C|yqpBkc178dAzWaAO~P2PHfdO6oG$cHmjD;l=VGzP%zaDxMuUkKOOdg8D^Uef~h=UU)UI8 z@P`_S`Y`#%eEqeCoDLdB%L=x>)ZtS-zbMso=i5`8v^VMH!w2-fyi7=)3S~h?BRF3) z7$N$Uo<9RH{M8c%KR9$s|MjB;@;Y4|;nPug=rx@*41pET;b9|xlhI$Ua#lZ6C63@3 z7}D*~-(R#Do4F&q4Wbi!l|XCy(eNoS@v7(*p83$4rus#aLAG4erv{3)aGP<~ZT;(- zC_Bu!qyI=mdC}Gva_t5i?76EKJkMheMj)Jr9ws+>o#I~dd-wFC`0!pn$MQg5!&*K- zs=di0fnXgrA(~6Im7JzGoP3m%R!sP_WVtFYLoC@1>P59NMp7a8Dv!5{EkBBrfMw%;Dj;Hq-W2!QP2)hht zi;7vyP1WPPAqEcG4E!oqjH|YfXB@TbL_wc+Bm_c%oAtt z(b_crFZUA9413))?$32h51i}wx0{5yzEAM)oPljSa%N4#ApUust#20Nr`b#fIQyL8 zNzRaJk6|YCvK{BXV2IhC??^ z=(Af44sN)I$d)gUd)d&BPv^aeklM-?1kK(v2oGu0O7f=n46-Vm3K5B!)5~V%#hm{O z|7F9fvl}M%*}aCx9ueu$7!OZpXo@ErKQR=l_ChWFwH-vxIcAuovR^7-%5jjJN%hot zk0xGn#;)?6?+gz9h6LH(-?)vWPOKTyPT_fPaj7A{g5%#0t40~);p)%|_ESeeZ%HlA zm{$72QtW1b8ib2sHZ3K88dmc+0xAR2b+l%tk-v{YU?X1s&BjD9OGf@!iDc2xUNZ8L zfO3RYlA2{W9F&ZFm}a!0I-?NpAC?BN-0OXv@h*Q~>6yY$c)3+)jQ_}AWVHDreq#m9 zqm!XuqF{>h5aX10B^vASzWm5OfPF^Gf2JA-3fB^Buq7Erp@Q&HGEja^;B2=rz5GL_ zvE9FrrU^7|X4K23I>zR_ohzivFu83r<9&R)Wv)1QFgk zN47Rrdk8Loejd`SkyYIv{=3#j;qZ4Km)b@H=Owm0Wa*|tW?Q3>ec~XRE1Di(F1Iyi za7v+rCqrI4BftGH=&S9FS!&uz?TvvD)!vw>iQ-QUjLoU`##A*eLIWW!1Z(Z`I~e&~ zh4rfceuxP+b};gRtQ;ldm##h%PVSyNiwoRnbhcyQ&}2M?R+?s5I3$X|cCKJ(I^FoHHcC#OVeGBi0i$I+zgOY8$)&T6(|OSS0ft(_gxuF_#-1!U zo@-p7+8ywx$!m?Ghi3&x!LG+5gy6^mei0ajcLp4>DgD@?e(gG8nt%zjBq1zFp0v)m zoIg1!YwX-l8cQ!3G_w^gPkvayEch9Vds^B1FC`R42Dlg7E+ zoIO-f%x^;FO{a`Ig-}<{SzdPDSj7vH-}~q|$$*(r0_6T|+@>u9lk^pBoEAInw18h~5G5FXzrssuf2ZUFFMx#uEL?hangzHJ%)$#N4 z?Lkt{2NR0=mHiZtxb!Ex=FSW$Z9z z!V3J2g#67%rkVWH3#jGr=;4$v?>CL-6CEmKB4B6>B@=5z!N~J|ddPXo6bv~vO}=pE zkcq$DQOMCJ405F-rp-}8mB0u;{1hPUQV)}k;n*ZE{5hbgm{(bQ7#WAr8M!YM)(5FtRHQs@K;R34hpOw3 z=!o+CL4p0g;s%q;>IAjx&4XHzpaA~qST6V_NaoKLa$Ke0G4WhS*qjxd1T#{C4f5eC z!K($47}Co+_TZ*@;Ros(9M4!|ymXOMQiHRERf2sYVbj21exspc^H+Bik_-V&G3msY zr~tWH_28QPshLuEVU-L&4h&9INu?g4s{HhzVEq)1Qr>F>hlrhBo>MuO#=iHEI z_{Uy(`I3-Lf{eH*6QJP3kU?B$@PILeUl!&MH-5DRL%$JNl5udJe|K-B>XHn`rtzMT zPTsnx=d65WdD`BPuLS=nM`{FOhKv3rWCA}{Y@Q_nLy_^W#S8+5S# zScnje@4S1!f&Ezwq zLM=iX`R_zK+St}u_MI4dK)5sicibwdQMx>0PH016*Zw~qvFVmjmvDUkcO(8+PNkm9 zdh)UlLJh(a-}{uMIzQ`bcV|u&lc=}ILym{8_2tRc3~+VSmZzT#O%{?7q)d>Hmxg8t zi&f3Rix;comU{tLRr3rzpV!(s3+I_A#^}Lm3j%V zuc_q&HCTS5nWc%4psRIZCz77I7U7`5c8iU<79nq{h>BzKEJ7iv`k)b#FVc7{Ae@Xm zV6TQzA5iwDSepvgNU>stdZN<^8x}f+EsGszjGZj8d>6LYckE=Tlg-1`2E?_K2!AiJ zB=Cd`+#jOCC38ZR(t57U7=Hi~lhnxxLIXR@i3MGOLY-X29Cf)fOYf zt+ohra342jwMDqeq&OM-`KlL_ux>FTCc%Q{HsMf)zL5p9pSFC@n@=sX7p1AAu03uQ zEW}K)biL(0!L5;P0!)0<@HrAyf!uY-u?vTUQDz zQO)HcQ?6vP3oX`8LQbRRq7K4pg*9VFBJ50X3JVnpA0A5ZW(5CcXGnyfT$*bAM7SLrD zR>2=Ucp-{)BAQ>(BqcyJG`BZtw=tU^%m^s~ZO&8!YDV#?9Yt$xB;3{?}{9e-me zY^p4y`>ne*RXEwG`!dScdRt%A@gk@x)wZX7p=yD38{bv>&MG_+;bEX+S9*BZs0M%a z7j4YIoeQl(B97yC;D=^=cV3Q7a2xe5tp3?oNmf`B*)Y($K)AR3FSKDh-j?a26Vl`n z?o77|`-wVlu87zy+&7+SJtUk2)MBfTPY8*Ccjk+WtirS9#o7;vUFsddok{z__Jvl# z(bWb~pV2C8qRc0(EBR`qWi94?md{te_Hw1H$#tFV-d`9p0Cz za0R8#BD9acM`LZmB@>HuOMeq*0l`Ud+RrKK_Pez{AI=$J(eL8qsuxy;(>q4^>>pNj zZX;~@nC<+lB#5P?rGHxU_?k5O3pKAZ@vxLpZB#G1BDeX0#u&FuT+) z_^*dR@GTEm4}s_H!eOn#8H{#dWE=4H9MKdAuFw*OOHFLT*`2M}22E|k*`0#bm#A*2 z*4~Y7n+RdeY{Gj1V_(qBCYZs?C3l6sN}zqVu278C`sqL0jRWDs7UJ}KS$6838r{|f z2QS)#;Q5xK9U0Ec3o_y?fWOw@D`la7E1U4{O`mk+Us~DfE#RYNNF94TmwZ)cUngA6{Ku^7 z$OT4wvaqTC$6VOslS>{RWPeLoR}W*wj>cQl?Tdt1j(yT#RBih@)$FfPLA3k006bwLRgfS!R zWxTp-=J#d!Wu$$naKrF0^4pW_P&U%;FQ56`zDh6_3J?Ks+#bqLHti!{J#J4IRydMtB`){(;Q!0b z-7L>NZI=Yc!J&og8ub^)Q0hoXDzyuF(S4~Ok#XqZlTy2I-+RBaI_<#mEOOiP_CCV< zJi=WvZe31a-r8QQidQB%@?+QRG3q&UL9r>!51w*}Ddh2+c433_p3Q4*!|MH(c~#JD zyE+ABLWIZzZrguW=eGS4#H2A8%uf!H=gXpkk!plrn zns{ef5pL*lE#-{~VQ&cnBDZ+?@#L_R!nXBaj50kn?B)LnH?_xNN|!8;PYl{m3BbC83_2zK>SOeVB~jRc~(i-KSD&L z4?p-pj4-d&!}kfieCJCbP=D|T3Gh$7-4Tu8>1TwPyJ14OW4I&7!-dSw(*?h7MYF`> z6=84j&m?lD95zh&ed&KOd;;K?t#F(JVU2|sQYOirOJTy5Jc6?zT{ns#)kaYYPI%=3$Mt^A1R3+KJokX`4ziSd6lCEYd2N#ErbQ-NLb!tRdmD?Re_tMU`Q9lr~+v8bQp7SC`+ zfkTLV&i;-?TrD??^;Y<#zk|OmA{8-=`eDCcm+R$4wYH9%5gOjF#uU;K&q~>t5L*oWn4`&VaOc9l~=X z5{AQve~0+Nq<0;B7@#FrSsGo`YBSkuyywUjl5aI7%L9K!M-Vc%!Z)1Za`JZ$5b{|y zhqAMdOqDIIkaNz#ADiT%=N$b7g*3QTbb8o4Ui%_KIPaq7Rv0--tf^vZ*80<7F$UDB zlQwi<&B3)Y2M$hxm2dgsUmbWN7|-ilEhc%^J;xj&l4UuZalCp*nz)2P)hROG4ro24 z{JY0U%v9?@fZi#*!{QY2E+r4sJ9i1UbZYTm-{%s%qVS^#;o?`VP(>uCMux_3oBZVc zPG=9{b|@pxDJ;3XCN5!PPz%!WWv5{4*gTPsT3GebRb5x0PXGU-iW?b=_pS*?d$o!o zN1ejWqFN!f_!Y6Wrua4Ge;PQyc%-CoFP0_>(QD4gG)Y-)zQpYn);NrWQnPEwl|QuMLKFqn$xe zcabwz-tv?)PRQkOD)2)P8=T_X)&J*+3K&rXdFY^75Vjp1aYbXTn>3LdeubAbs$qm1EzQbRw z&|iZ`$gbam5hP22AA+Yr&f|B85Jp|($rm8b?nIk%NT@} zwX>!xLB42m9e$(}WW|Yny(r>k5)mw%qBS*+19h#5+NCR^F~*s?@N`X=a5Q2X-wbnI zH*oO-)D!ieX#8(gt4K!k-zuAw=-SF(kZ36T-%cj>PlTA^5yHLie=)}xb>k}MP8c~7 zvOW{PRHK_S2M<4gv-Du8#hT`i%{E@vSAD&FY}2dlX{z`kf#Ey$yP z6KB&$4nJ5?-<4)h7+*BLaAd*Y`*CAjOv4xmj&wzW>9`{(AYow9gwf*%k40z}TnGPf zm^D8_59X!#hcV}cU}P*i>*ovkr<{RplH>Y}Z9t<=qt4@tii?Mj9vV|Pa%9YdywlUu zV|q{X@SKq`O=J8SeIdHJGh%H6RPD1v&OlpCh97cT zU7E_|G40^`WB;$Us}G9my5jEgv9OEo0F$@t!83pGhbuTu2uTzKg!^F13W1c3yO)d!4|hupWA^(!Upmt3J?;du*o_yk7JiaC5z7O^Yu@` zm;P?Dj>DIl-DI)aki=;fk(h{a#jX4E7l?&D(?f_JZhp*oD_jVXY`oz6`CHR0ko!wx z7EJZqlGEBdJ?_G)&cHhSyEI?Q%ab7Mbcz{9pCF0aKnFa$hnm6OoSu--*3s>A!QK&L zMtpHuX({~6nN|!J&k-xTyn`fg{BbP9Qb5F+#gs$zA`%cIK@_BexNn(CnQY=-vd5qj z!NzAv9_)OGa63y;?IN1NSC_!(8IlZN8RW^!>(72LNYvD~+~gAG$G54DS$|4g96znRe&iX#{gNY&1`Dnc6j97ZA0-8GaJh#j!@IvCHcb{w zJwRqS4)F^#5`EuegXF_Ja8nqL+QUQ>Hw(~p(4(OXz;whyVCzwG4~))`L~y*QOJJ`a zB|DO?DyHce$>IEE%zch!bwySly!0%|QR#H}O=5xddDO^qkCXegP;!?!6Yk5<8DQ%6 zg%-G6r`Hd^uS;T=MoHI~H<8hGY+;^L@fLA>WUXq?Y{Z;+=nd@Zei zP)bE=An->r+W^A`62j`fZDzLaHq~eVJxUg|FQzwiJ+auNs8Fn40__Ffizs4oGm7(F zEL*S%etm&(j3UMkwPAxeS$MuxqyvS8IRwEgQ}Q zczW+f$eAzg+$m+byL*Bmn6V%$_{ z(PLV;QmMoA6gQ@mwp`^0;FWXfE9J?}x$0LP(+F`Li_JRde8g-3>6Qg^q4>&t6IJ=|_gR1!cQrt|bE;$F0_T>wHqk*DLiokvtCi zq&8VQvT88)U>;*QjZ-acZYuH?)of|@)>KGM?!Yo7NI5-y&QRd`i`Z5ZMh>@ zo7CPL?De~sOG_KvZN6?~t6gqaJ{%0u41KQC8|YK$CO8?QcGz<?s+qKpV8HcfN?xwBg z&uCEu)@;QSDQC?JA!E2b+&M%YVK`2X^Xwl(w2%vK;`$d|Z7d!^T)%jIK>>3CEwC9{ zg1(mRPEV)H8H8;WI+E)2`<vC;J58@W0dna}6A=bZ(K2;CSO&lTIK|I{Zh~^Z zqt;FE)$f|1+-Z;Ee(jwJnyqdSW1qCIV!#ONPxBvxioY#mejXP(uVw6IhFfU!EX}x~ zz8N0P)p0phQMR@s+ckS3JJ)BCheY}=(#f47%tR~^^{ZoX(JOa@C>IV!zf@2M@9-B6 zGISR2X$)aWiQh3zQf8X8{qKX%u#%sAFVPBjj4$M}fW-wKMW3jqrR=Toh4*XdfnC3U gajRqPaov$`S=R3S>*Vlv$2M!{%$c*k_V(KU1LJrA761SM delta 64794 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 SrhNqq%k*Q$jCnF|Y2LrEe&_Z8 diff --git a/src/src/Commands/Environment/DownEnvironmentCommand.php b/src/src/Commands/Environment/DownEnvironmentCommand.php index b8bf21ac..520c6ca7 100644 --- a/src/src/Commands/Environment/DownEnvironmentCommand.php +++ b/src/src/Commands/Environment/DownEnvironmentCommand.php @@ -9,6 +9,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use function QIT_CLI\format_elapsed_time; @@ -43,44 +44,58 @@ protected function execute( InputInterface $input, OutputInterface $output ): in return Command::SUCCESS; } - if ( count( $running_environments ) === 1 ) { - $this->stop_environment( array_shift( $running_environments ), $output ); + $selected_environment = null; - return Command::SUCCESS; + if ( count( $running_environments ) === 1 ) { + $selected_environment = array_shift( $running_environments ); } - $environment_choices = array_map( function ( EnvInfo $environment ) { - return sprintf( 'Created: %s, Status: %s', - format_elapsed_time( time() - $environment->created_at ), - $environment->status ); - }, $running_environments ); - - $environment_choices['all'] = 'Stop all environments'; - - // More than one environment running, let user choose which one to stop. - $helper = new QuestionHelper(); - $question = new ChoiceQuestion( - 'Please select the environment to stop (or choose to stop all):', - $environment_choices, - 'all' - ); - $question->setErrorMessage( 'Environment %s is invalid.' ); - - $selected_environment = $helper->ask( $input, $output, $question ); + if ( is_null( $selected_environment ) ) { + $environment_choices = array_map( function ( EnvInfo $environment ) { + return sprintf( 'Created: %s, Status: %s', + format_elapsed_time( time() - $environment->created_at ), + $environment->status ); + }, $running_environments ); + + $environment_choices['all'] = 'Stop all environments'; + + // More than one environment running, let user choose which one to stop. + $helper = new QuestionHelper(); + $question = new ChoiceQuestion( + 'Please select the environment to stop (or choose to stop all):', + $environment_choices, + 'all' + ); + $question->setErrorMessage( 'Environment %s is invalid.' ); + + $selected_environment = $helper->ask( $input, $output, $question ); + } if ( $selected_environment === 'all' ) { + $total_environments = count( $running_environments ); + $counter = 1; + foreach ( $running_environments as $environment ) { - $this->stop_environment( $environment, $output ); + $output->write( "\rStopping all environments... [{$counter}/{$total_environments}]" ); + $this->stop_environment( $environment, $output->isVerbose() ? $output : new NullOutput() ); + ++$counter; } } else { - $this->stop_environment( $this->environment_monitor->get_env_info_by_id( $selected_environment ), $output ); + $total_environments = 1; + if ( ! $selected_environment instanceof EnvInfo ) { + $selected_environment = $this->environment_monitor->get_env_info_by_id( $selected_environment ); + } + $output->write( "\rStopping all environments... [1/1]" ); + $this->stop_environment( $selected_environment, $output->isVerbose() ? $output : new NullOutput() ); } + $output->write( "\rStopped all environments [{$total_environments}/{$total_environments}]." ); + return Command::SUCCESS; } private function stop_environment( EnvInfo $environment, OutputInterface $output ): void { - Environment::down( $environment ); + Environment::down( $environment, $output ); $environment_id = $environment->env_id; $output->writeln( "Environment '$environment_id' stopped." ); } diff --git a/src/src/Commands/Environment/UpEnvironmentCommand.php b/src/src/Commands/Environment/UpEnvironmentCommand.php index 4d32952b..dda52cdc 100644 --- a/src/src/Commands/Environment/UpEnvironmentCommand.php +++ b/src/src/Commands/Environment/UpEnvironmentCommand.php @@ -252,7 +252,9 @@ protected function execute( InputInterface $input, OutputInterface $output ): in $env_info = App::make( EnvConfigLoader::class )->init_env_info( $options_to_env_info ); - $this->output->writeln( json_encode( $env_info, JSON_PRETTY_PRINT ) ); + if ( $output->isVeryVerbose() ) { + $this->output->writeln( 'Environment info: ' . json_encode( $env_info, JSON_PRETTY_PRINT ) ); + } $this->e2e_environment->init( $env_info ); $this->e2e_environment->up(); diff --git a/src/src/Environment/Docker.php b/src/src/Environment/Docker.php index 80e06e88..7ccbff81 100644 --- a/src/src/Environment/Docker.php +++ b/src/src/Environment/Docker.php @@ -113,7 +113,7 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env $docker_image = $env_info->get_docker_container( $image ); $docker_command = [ $this->find_docker(), 'exec' ]; - if ( use_tty() ) { + if ( $this->output->isVerbose() && use_tty() ) { $docker_command = array_merge( $docker_command, [ '-it' ] ); } @@ -157,7 +157,7 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env } $process = new Process( $docker_command ); - $process->setTty( use_tty() ); + $process->setTty( $this->output->isVerbose() && use_tty() ); $process->setTimeout( $timeout ); $process->setIdleTimeout( $timeout ); @@ -167,7 +167,9 @@ public function run_inside_docker( EnvInfo $env_info, array $command, array $env } $process->run( function ( $type, $buffer ) { - $this->output->write( $buffer ); + if ( $this->output->isVerbose() ) { + $this->output->write( $buffer ); + } } ); if ( ! $process->isSuccessful() ) { diff --git a/src/src/Environment/EnvironmentDanglingCleanup.php b/src/src/Environment/EnvironmentDanglingCleanup.php index 0366c30c..9502e8e5 100644 --- a/src/src/Environment/EnvironmentDanglingCleanup.php +++ b/src/src/Environment/EnvironmentDanglingCleanup.php @@ -76,7 +76,7 @@ public function cleanup_dangling(): void { } if ( ! $this->header_printed ) { - $this->output->writeln( 'Cleaning up dangling temp environments...' ); + $this->output->writeln( 'Cleaning up dangling temporary environments...' ); $this->header_printed = true; } @@ -119,7 +119,7 @@ public function cleanup_dangling(): void { // Skip asking the user permission to delete in this directory if they answer with an "A". $always_delete_from_this_directory = $this->cache->get( 'always_delete_from_this_directory' ); - $parent_dir = $this->get_parent_dir_to_delete(); + $parent_dir = $this->get_parent_dir_to_delete(); if ( $always_delete_from_this_directory !== $parent_dir && ! is_ci() ) { $this->output->writeln( "Found dangling temporary environments in directory: $parent_dir" ); @@ -140,7 +140,7 @@ public function cleanup_dangling(): void { break; case 'n': default: - $this->output->writeln( 'Action cancelled by user.' ); + $this->output->writeln( 'Please delete the dangling environments in that directory manually.' ); return; } @@ -339,12 +339,12 @@ protected function remove_dangling_environments(): void { } if ( ! empty( $containers_not_running ) ) { if ( ! $this->header_printed ) { - $this->output->writeln( 'Dangling Temporary Environments found.' ); + $this->output->writeln( 'Cleaning up dangling temporary environments...' ); $this->header_printed = true; } - $this->output->writeln( "Removing dangling environment: {$env_info->env_id}" ); - if ( $this->output->isVerbose() ) { + $this->debug_output( "Removing dangling environment: {$env_info->env_id}" ); + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( 'Expected containers: ' . implode( ', ', $env_info->docker_images ) ); $this->output->writeln( 'Missing containers: ' . implode( ', ', $containers_not_running ) ); } diff --git a/src/src/Environment/EnvironmentDownloader.php b/src/src/Environment/EnvironmentDownloader.php index 85a9cc4c..7fb28271 100644 --- a/src/src/Environment/EnvironmentDownloader.php +++ b/src/src/Environment/EnvironmentDownloader.php @@ -87,6 +87,15 @@ public function maybe_download( string $env_name ): void { if ( ! $zip->extractTo( $environments_dir . '/' . $env_name ) ) { throw new \RuntimeException( 'Could not extract environment zip.' ); } + + // Ensure .sh files in the extracted directory are executable, just in case. + $iterator = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator( $environments_dir . '/' . $env_name ) ); + foreach ( $iterator as $file ) { + if ( $file->isFile() && $file->getExtension() === 'sh' ) { + chmod( $file->getPathname(), 0755 ); + } + } + $zip->close(); $this->cache->set( "{$env_name}_environment_hash", $manager_hashes[ $env_name ]['checksum'], MONTH_IN_SECONDS ); } else { diff --git a/src/src/Environment/Environments/E2E/E2EEnvironment.php b/src/src/Environment/Environments/E2E/E2EEnvironment.php index b8253789..c75376b3 100644 --- a/src/src/Environment/Environments/E2E/E2EEnvironment.php +++ b/src/src/Environment/Environments/E2E/E2EEnvironment.php @@ -61,7 +61,7 @@ protected function post_up(): void { // Setup WordPress. $this->output->writeln( 'Setting up WordPress...' ); - $this->docker->run_inside_docker( $this->env_info, [ '/bin/bash', '/qit/bin/wordpress-setup.sh' ], [ + $this->docker->run_inside_docker( $this->env_info, [ '/bin/bash', '-c', '/qit/bin/wordpress-setup.sh 2>&1' ], [ 'WORDPRESS_VERSION' => $this->env_info->wordpress_version, 'WOOCOMMERCE_VERSION' => $this->env_info->woocommerce_version, 'PLUGINS_TO_INSTALL' => json_encode( $this->env_info->plugins ), diff --git a/src/src/Environment/Environments/Environment.php b/src/src/Environment/Environments/Environment.php index 76978e5a..a159c76f 100644 --- a/src/src/Environment/Environments/Environment.php +++ b/src/src/Environment/Environments/Environment.php @@ -109,14 +109,20 @@ public function up( bool $attached = false ): void { $this->maybe_create_cache_dir(); $this->copy_environment(); $this->environment_monitor->environment_added_or_updated( $this->env_info ); + if ( ! empty( $this->env_info->plugins ) || ! empty( $this->env_info->themes ) ) { + $this->output->writeln( 'Downloading plugins and themes...' ); + } $this->extension_downloader->download( $this->env_info, $this->cache_dir, $this->env_info->plugins, $this->env_info->themes ); + $this->output->writeln( 'Setting up Docker...' ); $this->generate_docker_compose(); $this->post_generate_docker_compose(); $this->up_docker_compose( $attached ); $this->post_up(); - $this->output->writeln( 'Server started at ' . round( microtime( true ) - $start, 2 ) . ' seconds' ); - $this->output->writeln( "Temporary environment: {$this->env_info->temporary_env}\n" ); + if ( $this->output->isVerbose() ) { + $this->output->writeln( 'Server started in ' . round( microtime( true ) - $start, 2 ) . ' seconds' ); + } + $this->additional_output(); } @@ -194,13 +200,14 @@ protected function generate_docker_compose(): void { 'QIT_DOCKER_REDIS' => 'no', // Default. Might be overridden by the concrete environment. ], $this->get_generate_docker_compose_envs() ) ); - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( $process->getCommandLine() ); - $this->output->writeln( json_encode( $process->getEnv(), JSON_PRETTY_PRINT ) ); } $process->run( function ( $type, $buffer ) { - $this->output->write( $buffer ); + if ( $this->output->isVerbose() || $type === Process::ERR ) { + $this->output->write( $buffer ); + } } ); if ( ! $process->isSuccessful() ) { @@ -233,10 +240,12 @@ protected function up_docker_compose( bool $attached ): void { $up_process->setTimeout( 300 ); $up_process->setIdleTimeout( 300 ); - $up_process->setTty( use_tty() ); + $up_process->setPty( use_tty() ); $up_process->run( function ( $type, $buffer ) { - $this->output->write( $buffer ); + if ( $this->output->isVerbose() ) { + $this->output->write( $buffer ); + } } ); if ( ! $up_process->isSuccessful() ) { @@ -249,8 +258,8 @@ protected function up_docker_compose( bool $attached ): void { $this->environment_monitor->environment_added_or_updated( $this->env_info ); } - public static function down( EnvInfo $env_info ): void { - $output = App::make( OutputInterface::class ); + public static function down( EnvInfo $env_info, ?OutputInterface $output = null ): void { + $output = $output ?? App::make( OutputInterface::class ); $environment_monitor = App::make( EnvironmentMonitor::class ); if ( ! file_exists( $env_info->temporary_env ) ) { @@ -267,7 +276,7 @@ public static function down( EnvInfo $env_info ): void { $down_process = new Process( array_merge( App::make( Docker::class )->find_docker_compose(), [ '-f', $env_info->temporary_env . '/docker-compose.yml', 'down' ] ) ); $down_process->setTimeout( 300 ); $down_process->setIdleTimeout( 300 ); - $down_process->setTty( use_tty() ); + $down_process->setPty( use_tty() ); $down_process->run( static function ( $type, $buffer ) use ( $output ) { $output->write( $buffer ); diff --git a/src/src/Environment/ExtensionDownload/ExtensionZip.php b/src/src/Environment/ExtensionDownload/ExtensionZip.php index 7a4ce7ff..f97c55d8 100644 --- a/src/src/Environment/ExtensionDownload/ExtensionZip.php +++ b/src/src/Environment/ExtensionDownload/ExtensionZip.php @@ -52,13 +52,13 @@ public function extract_zip( string $zip_file, string $extract_to ): void { $zip->extractTo( $extract_to ); $zip->close(); - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'ZipArchive extraction of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } return; } else { - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'ZipArchive extraction of %s failed, falling back to Docker (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } } @@ -86,7 +86,7 @@ public function extract_zip( string $zip_file, string $extract_to ): void { 'Docker ZIP Extraction: ' . $this->output->writeln( $out ); } } ); - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'Docker ZIP extraction of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } } @@ -104,13 +104,13 @@ public function validate_zip( string $zip_file ): void { if ( $zip->open( $zip_file, \ZipArchive::CHECKCONS ) === true ) { $zip->close(); - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'ZipArchive validation of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } return; } else { - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'ZipArchive validation of %s failed, falling back to Docker (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } } @@ -140,7 +140,7 @@ public function validate_zip( string $zip_file ): void { } } ); - if ( $this->output->isVerbose() ) { + if ( $this->output->isVeryVerbose() ) { $this->output->writeln( sprintf( 'Docker ZIP validation of %s successful (%f seconds).', basename( $zip_file ), microtime( true ) - $start ) ); } } diff --git a/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php b/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php index 969cf5c9..cf18aabf 100644 --- a/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php +++ b/src/src/Environment/ExtensionDownload/Handlers/QITHandler.php @@ -30,7 +30,9 @@ public function populate_extension_versions( array $extensions ): void { 'extensions' => $extensions_to_download, ] ) ->request(); - $output->writeln( sprintf( 'Fetched versions for %d extensions from QIT in %f seconds.', count( $extensions ), microtime( true ) - $start ) ); + if ( $output->isVerbose() ) { + $output->writeln( sprintf( 'Fetched versions for %d extensions from QIT in %f seconds.', count( $extensions ), microtime( true ) - $start ) ); + } /** * @param $download_urls array{ diff --git a/src/src/RequestBuilder.php b/src/src/RequestBuilder.php index 71b1872b..894e47ae 100644 --- a/src/src/RequestBuilder.php +++ b/src/src/RequestBuilder.php @@ -175,7 +175,7 @@ public function request(): string { } } - if ( App::make( Output::class )->isVeryVerbose() ) { + if ( getenv( 'QIT_DEBUG_REQUESTS' ) ) { $curl_parameters[ CURLOPT_VERBOSE ] = true; }