@dylanpiercey/work 0.2.69 → 0.2.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli/session.mjs +36 -4
- package/bin/cli/topic.mjs +421 -23
- package/dist/{_Da7kjbAP.js → _B3z3x0nb.js} +100 -11
- package/dist/_BawMVLA9.js +2 -0
- package/dist/{_DDCmzS5h.js → _BcuBHot2.js} +113 -113
- package/dist/_D3ixWlKr.js +2 -0
- package/dist/{_CilTmd3l.js → _DHaRHB4s.js} +237 -36
- package/dist/index.mjs +1225 -1098
- package/dist/public/assets/{_DIEqAzJB.js → _-JtZtVz8.js} +1 -1
- package/dist/public/assets/_-JtZtVz8.js.br +0 -0
- package/dist/public/assets/{_DeGJuali.js → _0QJDM3NO.js} +1 -1
- package/dist/public/assets/_0QJDM3NO.js.br +0 -0
- package/dist/public/assets/{_BiIrl8ml.js → _0vqLbImj.js} +1 -1
- package/dist/public/assets/_0vqLbImj.js.br +0 -0
- package/dist/public/assets/_2W-pgjXX.js +1 -0
- package/dist/public/assets/{_ZlbOPzr7.js → _4ogr0vzb.js} +1 -1
- package/dist/public/assets/_4ogr0vzb.js.br +0 -0
- package/dist/public/assets/{_wC0cYIUL.js → _5lt7STSU.js} +10 -10
- package/dist/public/assets/_5lt7STSU.js.br +0 -0
- package/dist/public/assets/{_DPKcpw43.js → _6D14OK7z.js} +1 -1
- package/dist/public/assets/_6D14OK7z.js.br +0 -0
- package/dist/public/assets/{_BnDvb8rh.js → _9D7sZPkr.js} +1 -1
- package/dist/public/assets/_9D7sZPkr.js.br +0 -0
- package/dist/public/assets/{_w3JsvUod.js → _Alp3-sd6.js} +1 -1
- package/dist/public/assets/_B0CqgYFf.js +1 -0
- package/dist/public/assets/{_DLoAVrbv.js → _B0sUN2tx.js} +1 -1
- package/dist/public/assets/_B0sUN2tx.js.br +0 -0
- package/dist/public/assets/_B1KbLd5h.js +1 -0
- package/dist/public/assets/{_D4XHSL1o.js → _B5SjUyop.js} +1 -1
- package/dist/public/assets/_B5SjUyop.js.br +0 -0
- package/dist/public/assets/_B7FCBIYG.js +1 -0
- package/dist/public/assets/_B7FCBIYG.js.br +0 -0
- package/dist/public/assets/_B9G7-El7.js +1 -0
- package/dist/public/assets/_BDNW7Ugd.js +1 -0
- package/dist/public/assets/{_G0Ur49hc.js → _BGXJVx0k.js} +1 -1
- package/dist/public/assets/_BGXJVx0k.js.br +0 -0
- package/dist/public/assets/{_HnJD2Vzo.js → _BHypHLzv.js} +1 -1
- package/dist/public/assets/_BHypHLzv.js.br +0 -0
- package/dist/public/assets/{_YTVYw9XV.js → _BJ0RWeiG.js} +1 -1
- package/dist/public/assets/_BJ0RWeiG.js.br +0 -0
- package/dist/public/assets/{_D-pAxlQ-.js → _BLALkhiZ.js} +4 -4
- package/dist/public/assets/_BLALkhiZ.js.br +0 -0
- package/dist/public/assets/_BMNhhqEV.js +1 -0
- package/dist/public/assets/{_C3k75NG8.js → _BPHBcrYh.js} +1 -1
- package/dist/public/assets/_BPHBcrYh.js.br +0 -0
- package/dist/public/assets/{_KtT9ovgB.js → _BPoePslg.js} +1 -1
- package/dist/public/assets/_BPoePslg.js.br +0 -0
- package/dist/public/assets/{_B5QrsHwd.js → _BQuf46P2.js} +1 -1
- package/dist/public/assets/_BQuf46P2.js.br +0 -0
- package/dist/public/assets/_BTydwZJh.js +1 -0
- package/dist/public/assets/{_CLpJpkGL.js → _BUbGYrKa.js} +1 -1
- package/dist/public/assets/_BUbGYrKa.js.br +0 -0
- package/dist/public/assets/{_Dh_fGh7B.js → _BUh4HTF3.js} +1 -1
- package/dist/public/assets/_BUh4HTF3.js.br +0 -0
- package/dist/public/assets/{_DE5SUDS8.js → _BVXZCAXs.js} +1 -1
- package/dist/public/assets/_BVXZCAXs.js.br +0 -0
- package/dist/public/assets/_BWBW2sE5.js +1 -0
- package/dist/public/assets/_BXgfsaug.js +1 -0
- package/dist/public/assets/_BXgfsaug.js.br +0 -0
- package/dist/public/assets/_BZycN9ye.js +1 -0
- package/dist/public/assets/_BaQeAF-B.js +1 -0
- package/dist/public/assets/_BhA6H8WQ.js +1 -0
- package/dist/public/assets/_BikFQJva.js +1 -0
- package/dist/public/assets/_Bk0YJ7b1.js +1 -0
- package/dist/public/assets/{_DcCeapFB.js → _BlSH3TRK.js} +1 -1
- package/dist/public/assets/_BlSH3TRK.js.br +0 -0
- package/dist/public/assets/_BqSnw21E.js +1 -0
- package/dist/public/assets/{_DdWxi_D9.js → _BtWMgvvl.js} +2 -2
- package/dist/public/assets/_BtWMgvvl.js.br +0 -0
- package/dist/public/assets/{_5pKDjgHs.js → _BvskbvTW.js} +1 -1
- package/dist/public/assets/_BvskbvTW.js.br +0 -0
- package/dist/public/assets/{_rizgJsHK.js → _Bx8oVkmQ.js} +1 -1
- package/dist/public/assets/_Bx8oVkmQ.js.br +0 -0
- package/dist/public/assets/_BxPoJO_L.js +1 -0
- package/dist/public/assets/{_BH9u6x7L.js → _C09HUxcS.js} +1 -1
- package/dist/public/assets/_C09HUxcS.js.br +0 -0
- package/dist/public/assets/_C14PL76N.js +1 -0
- package/dist/public/assets/{_3jDFL-Cg.js → _C15TsQVx.js} +1 -1
- package/dist/public/assets/_C15TsQVx.js.br +0 -0
- package/dist/public/assets/_C1bNeWUD.js +1 -0
- package/dist/public/assets/{_B9OVFXEI.js → _C2IlBo8e.js} +1 -1
- package/dist/public/assets/_C2IlBo8e.js.br +0 -0
- package/dist/public/assets/{_lCk1CAYf.js → _C3F6fdUB.js} +1 -1
- package/dist/public/assets/_C5KZ0ozw.js +1 -0
- package/dist/public/assets/_C5KZ0ozw.js.br +0 -0
- package/dist/public/assets/_C94IJ4uX.js +1 -0
- package/dist/public/assets/_CCRiWfSo.js +1 -0
- package/dist/public/assets/{_CUPYyx5O.js → _CCl1txGr.js} +1 -1
- package/dist/public/assets/{_TOwFHHoM.js → _CDHWB_us.js} +1 -1
- package/dist/public/assets/_CDHWB_us.js.br +0 -0
- package/dist/public/assets/_CE-UlWde.js +1 -0
- package/dist/public/assets/{_BJcqxD6V.js → _CEgYI4gj.js} +1 -1
- package/dist/public/assets/_CEgYI4gj.js.br +0 -0
- package/dist/public/assets/_CI9y5SMD.js +1 -0
- package/dist/public/assets/_CLrYkY55.js +1 -0
- package/dist/public/assets/{_C4Hln-a1.js → _CPTaxuJG.js} +1 -1
- package/dist/public/assets/_CPTaxuJG.js.br +0 -0
- package/dist/public/assets/_CQKcBCsl.js +1 -0
- package/dist/public/assets/{_9PIiwVmz.js → _CQuARfyY.js} +1 -1
- package/dist/public/assets/_CQuARfyY.js.br +0 -0
- package/dist/public/assets/_CRdqojLF.js +1 -0
- package/dist/public/assets/{_B0tb8Vgp.js → _CRew7lgJ.js} +1 -1
- package/dist/public/assets/_CRew7lgJ.js.br +0 -0
- package/dist/public/assets/_CS11TygF.js +1 -0
- package/dist/public/assets/{_kHV7j6Zv.js → _CS9qmTkt.js} +1 -1
- package/dist/public/assets/_CS9qmTkt.js.br +0 -0
- package/dist/public/assets/_CSSixb56.js +1 -0
- package/dist/public/assets/_CSa_w7tA.js +86 -0
- package/dist/public/assets/_CSa_w7tA.js.br +0 -0
- package/dist/public/assets/_CTbIErzd.js +1 -0
- package/dist/public/assets/_CTbIErzd.js.br +0 -0
- package/dist/public/assets/_CXf2VxeD.js +1 -0
- package/dist/public/assets/{_BciKbAaO.js → _CYHURCb7.js} +1 -1
- package/dist/public/assets/_CYHURCb7.js.br +0 -0
- package/dist/public/assets/_C_vPuVhA.js +1 -0
- package/dist/public/assets/_Cajx7i0I.js +1 -0
- package/dist/public/assets/{_B1rg6S37.js → _Cb-D3ERI.js} +1 -1
- package/dist/public/assets/_Cb-D3ERI.js.br +0 -0
- package/dist/public/assets/_Cc8Hhqep.js +1 -0
- package/dist/public/assets/{_CbAa5uAw.js → _Ce6hwXny.js} +1 -1
- package/dist/public/assets/_Ce6hwXny.js.br +0 -0
- package/dist/public/assets/_CeSD_6xP.js +1 -0
- package/dist/public/assets/_CfFIePkk.js +1 -0
- package/dist/public/assets/_CfUhSwyu.js +1 -0
- package/dist/public/assets/_CfziTCiN.js +1 -0
- package/dist/public/assets/_Ci7l0V_h.js +1 -0
- package/dist/public/assets/{_ByZbJftZ.js → _Cif8YVIW.js} +1 -1
- package/dist/public/assets/_Cif8YVIW.js.br +0 -0
- package/dist/public/assets/_CjI_b19m.js +1 -0
- package/dist/public/assets/{_DUEm1sqD.js → _CjT2-NNY.js} +1 -1
- package/dist/public/assets/_CjT2-NNY.js.br +0 -0
- package/dist/public/assets/_Cjromvor.js +1 -0
- package/dist/public/assets/{_l9Ig5EJO.js → _CmcVar5g.js} +1 -1
- package/dist/public/assets/_CmcVar5g.js.br +0 -0
- package/dist/public/assets/_Cof8T6gT.js +1 -0
- package/dist/public/assets/{_BICdCzpd.js → _CreV-6z6.js} +1 -1
- package/dist/public/assets/_CreV-6z6.js.br +0 -0
- package/dist/public/assets/_CsKkccjn.js +1 -0
- package/dist/public/assets/{_CXhoovwf.js → _CsnlIPmX.js} +1 -1
- package/dist/public/assets/_CsnlIPmX.js.br +0 -0
- package/dist/public/assets/_CsxBH5UX.js +1 -0
- package/dist/public/assets/{_CtYn_7Ld.js → _CvrDFzmP.js} +1 -1
- package/dist/public/assets/_CvrDFzmP.js.br +0 -0
- package/dist/public/assets/{_CRAhvbwb.js → _CwAvlnWz.js} +1 -1
- package/dist/public/assets/_CwAvlnWz.js.br +0 -0
- package/dist/public/assets/{_DJVQZQI-.js → _CwBNy_7k.js} +1 -1
- package/dist/public/assets/_CwBNy_7k.js.br +0 -0
- package/dist/public/assets/{_BMXY56L9.js → _Cx0sSSLJ.js} +1 -1
- package/dist/public/assets/_Cx0sSSLJ.js.br +0 -0
- package/dist/public/assets/_CxyaZiJz.js +1 -0
- package/dist/public/assets/{_BSyW2RLw.js → _D-4UJozU.js} +1 -1
- package/dist/public/assets/_D-4UJozU.js.br +0 -0
- package/dist/public/assets/{_Coj9l4W_.js → _D0PrCOmg.js} +1 -1
- package/dist/public/assets/_D0PrCOmg.js.br +0 -0
- package/dist/public/assets/{_LsFmgSj_.js → _D0n_5okc.js} +1 -1
- package/dist/public/assets/_D0n_5okc.js.br +0 -0
- package/dist/public/assets/{_aVJfol8S.js → _D1ZTqBtg.js} +1 -1
- package/dist/public/assets/_D1ZTqBtg.js.br +0 -0
- package/dist/public/assets/_D2m31-DG.js +1 -0
- package/dist/public/assets/_D2vTqjKk.js +1 -0
- package/dist/public/assets/{_DxgeJa1G.js → _D2zuXOi5.js} +1 -1
- package/dist/public/assets/_D2zuXOi5.js.br +0 -0
- package/dist/public/assets/{_BoRNFqwj.js → _D3mGPwaD.js} +1 -1
- package/dist/public/assets/{_DmBJQY0z.js → _D4SspWzi.js} +1 -1
- package/dist/public/assets/_D4SspWzi.js.br +0 -0
- package/dist/public/assets/_D8BYyk4L.js +1 -0
- package/dist/public/assets/_D8c2vqae.js +1 -0
- package/dist/public/assets/{_SkNT3g1t.js → _D93e76eJ.js} +1 -1
- package/dist/public/assets/_D93e76eJ.js.br +0 -0
- package/dist/public/assets/{_a3BQDAxj.js → _DB0x3S_V.js} +1 -1
- package/dist/public/assets/_DB0x3S_V.js.br +0 -0
- package/dist/public/assets/{_CiYp9PxT.js → _DBqiCvB3.js} +1 -1
- package/dist/public/assets/_DBqiCvB3.js.br +0 -0
- package/dist/public/assets/_DDPfcBYW.js +1 -0
- package/dist/public/assets/_DE7f6G-4.js +1 -0
- package/dist/public/assets/_DFc8nVyA.js +1 -0
- package/dist/public/assets/_DGNNG6hE.js +1 -0
- package/dist/public/assets/{_BiIQdsrx.js → _DI_3CxxT.js} +1 -1
- package/dist/public/assets/_DKaZoJEU.js +1 -0
- package/dist/public/assets/_DPCcVPqS.js +1 -0
- package/dist/public/assets/{_BUPTpTYH.js → _DPO20UhE.js} +1 -1
- package/dist/public/assets/_DPO20UhE.js.br +0 -0
- package/dist/public/assets/_DQ9KMZkg.js +1 -0
- package/dist/public/assets/_DQfR4nGA.js +1 -0
- package/dist/public/assets/_DRl7_NsH.js +1 -0
- package/dist/public/assets/_DSjKT54G.js +1 -0
- package/dist/public/assets/{_B-cgAjqV.js → _DUQ4-DAq.js} +1 -1
- package/dist/public/assets/_DUQ4-DAq.js.br +0 -0
- package/dist/public/assets/{_ulL_yezz.js → _DVUACl-0.js} +1 -1
- package/dist/public/assets/_DVUACl-0.js.br +0 -0
- package/dist/public/assets/_DVaVJl4U.js +1 -0
- package/dist/public/assets/{_C1EEKbbh.js → _DWJFJSQt.js} +1 -1
- package/dist/public/assets/_DWJFJSQt.js.br +0 -0
- package/dist/public/assets/{_zGawNqPU.js → _DW_3eCmy.js} +1 -1
- package/dist/public/assets/_DW_3eCmy.js.br +0 -0
- package/dist/public/assets/_DWcr4WT2.js +1 -0
- package/dist/public/assets/_D_uqbH0s.js +1 -0
- package/dist/public/assets/_Db3LFxDp.js +1 -0
- package/dist/public/assets/{_D9-mnhpM.js → _DcKVJllO.js} +1 -1
- package/dist/public/assets/_DcKVJllO.js.br +0 -0
- package/dist/public/assets/_De55CP4F.js +1 -0
- package/dist/public/assets/{_CEzgbnFo.js → _DglTnOtH.js} +1 -1
- package/dist/public/assets/_DglTnOtH.js.br +0 -0
- package/dist/public/assets/_DhyrSLt_.js +1 -0
- package/dist/public/assets/_DishjoMc.js +1 -0
- package/dist/public/assets/_DlHs_b1x.js +1 -0
- package/dist/public/assets/{_C23aBO0p.js → _DmlL12SP.js} +1 -1
- package/dist/public/assets/_DmlL12SP.js.br +0 -0
- package/dist/public/assets/{_B40fHLkj.js → _Dnj7y5O6.js} +1 -1
- package/dist/public/assets/_Dnj7y5O6.js.br +0 -0
- package/dist/public/assets/_DqB9AEIR.js +1 -0
- package/dist/public/assets/_DqmZjpyA.js +1 -0
- package/dist/public/assets/_DrC0PHwd.js +1 -0
- package/dist/public/assets/_DrtDlCCB.js +1 -0
- package/dist/public/assets/{_Dv298HDL.js → _DsxZHqAt.js} +1 -1
- package/dist/public/assets/_DsxZHqAt.js.br +0 -0
- package/dist/public/assets/{_B_zlRrUP.js → _DucELdm1.js} +1 -1
- package/dist/public/assets/_DucELdm1.js.br +0 -0
- package/dist/public/assets/{_CKvOm2QG.js → _Dw2w_cI1.js} +1 -1
- package/dist/public/assets/_Dw2w_cI1.js.br +0 -0
- package/dist/public/assets/{_C0W4EC0Z.js → _Dx2nYKAs.js} +1 -1
- package/dist/public/assets/_Dx2nYKAs.js.br +0 -0
- package/dist/public/assets/{_gy0a9Cmp.js → _DxZFU6SY.js} +1 -1
- package/dist/public/assets/_DxZFU6SY.js.br +0 -0
- package/dist/public/assets/_DyztCqYX.js +1 -0
- package/dist/public/assets/_Dz42MOZj.js +1 -0
- package/dist/public/assets/{_CsNZdkZU.js → _DzSNrU-9.js} +1 -1
- package/dist/public/assets/_DzSNrU-9.js.br +0 -0
- package/dist/public/assets/{_BORTVznS.js → _HnLpRxna.js} +2 -2
- package/dist/public/assets/_HnLpRxna.js.br +0 -0
- package/dist/public/assets/{_0H09AGax.js → _Im1dFxR8.js} +1 -1
- package/dist/public/assets/_Im1dFxR8.js.br +0 -0
- package/dist/public/assets/_ImlHzwYY.js +1 -0
- package/dist/public/assets/_J-P8YHmV.js +1 -0
- package/dist/public/assets/_KsdD4dsM.js +1 -0
- package/dist/public/assets/_KsdD4dsM.js.br +0 -0
- package/dist/public/assets/_LRjlRqrU.js +7 -0
- package/dist/public/assets/_LRjlRqrU.js.br +0 -0
- package/dist/public/assets/_LTl-SYyD.js +1 -0
- package/dist/public/assets/{_Cw9GxBkQ.js → _LniUny_a.js} +1 -1
- package/dist/public/assets/_LniUny_a.js.br +0 -0
- package/dist/public/assets/_Oup4mCuX.js +1 -0
- package/dist/public/assets/{_DuKrnKV2.js → _R3Kvmve2.js} +1 -1
- package/dist/public/assets/_R3Kvmve2.js.br +0 -0
- package/dist/public/assets/{_Cw3MnPjo.js → _R7YbF1yw.js} +1 -1
- package/dist/public/assets/_R7YbF1yw.js.br +0 -0
- package/dist/public/assets/{_CDG0zRut.js → _S9Qy4Cmi.js} +1 -1
- package/dist/public/assets/_S9Qy4Cmi.js.br +0 -0
- package/dist/public/assets/{_BF2_gMS8.js → _ShiWFlWr.js} +1 -1
- package/dist/public/assets/_ShiWFlWr.js.br +0 -0
- package/dist/public/assets/{_CDPOV9zA.js → _TLB-Nq6Z.js} +1 -1
- package/dist/public/assets/_TLB-Nq6Z.js.br +0 -0
- package/dist/public/assets/_YcOZiOZ4.js +2 -0
- package/dist/public/assets/_YcOZiOZ4.js.br +0 -0
- package/dist/public/assets/_YjSW_ahw.js +1 -0
- package/dist/public/assets/_c9iXcb5V.js +1 -0
- package/dist/public/assets/{_T32b15Ve.js → _dSWMMogH.js} +1 -1
- package/dist/public/assets/_dSWMMogH.js.br +0 -0
- package/dist/public/assets/_dp0lBRTw.js +1 -0
- package/dist/public/assets/_etOTb_Um.js +1 -0
- package/dist/public/assets/{_DmISa8wc.js → _fZ9Nn0aY.js} +1 -1
- package/dist/public/assets/_fZ9Nn0aY.js.br +0 -0
- package/dist/public/assets/_h3o298tf.js +1 -0
- package/dist/public/assets/_iTnQEpuR.js +1 -0
- package/dist/public/assets/{_BWwfOfMX.js → _ii--A0F-.js} +1 -1
- package/dist/public/assets/_ii--A0F-.js.br +0 -0
- package/dist/public/assets/{_BZhRz8TB.js → _ixsF2ttz.js} +1 -1
- package/dist/public/assets/_ixsF2ttz.js.br +0 -0
- package/dist/public/assets/_kQ2OAVME.js +1 -0
- package/dist/public/assets/{_fBJXUlyl.js → _l71VhzhS.js} +1 -1
- package/dist/public/assets/_l71VhzhS.js.br +0 -0
- package/dist/public/assets/{_CY7Wr_6h.js → _ptpihSzL.js} +1 -1
- package/dist/public/assets/_ptpihSzL.js.br +0 -0
- package/dist/public/assets/{_B6Zw_zoM.js → _suQAT3jW.js} +1 -1
- package/dist/public/assets/_suQAT3jW.js.br +0 -0
- package/dist/public/assets/{_Bdq41ArX.js → _t5-hsdI5.js} +1 -1
- package/dist/public/assets/_t5-hsdI5.js.br +0 -0
- package/dist/public/assets/{_CAN3Gwlo.js → _tEBqbfOJ.js} +1 -1
- package/dist/public/assets/_tEBqbfOJ.js.br +0 -0
- package/dist/public/assets/{_C3La6EyV.js → _vy4Y1hd_.js} +1 -1
- package/dist/public/assets/_vy4Y1hd_.js.br +0 -0
- package/dist/public/assets/{_CKNilRtP.js → _x7Lebeio.js} +1 -1
- package/dist/public/assets/_x7Lebeio.js.br +0 -0
- package/dist/public/assets/_z3J861v3.js +1 -0
- package/dist/public/assets/files-view-DyuIyBwJ.js +2 -0
- package/dist/public/assets/manage-workspace-CtSdSPLU.js +2 -0
- package/dist/public/assets/new-ClUAGfpX.js +1 -0
- package/dist/public/assets/new-workspace-BLb55_cv.js +2 -0
- package/dist/public/assets/review-view-BhRXZEwU.js +2 -0
- package/dist/public/assets/settings-ClUAGfpX.js +1 -0
- package/dist/public/assets/settings-page-CTit2PgC.js +2 -0
- package/dist/public/assets/styles-C4hTgteh.css +1 -0
- package/dist/public/assets/styles-C4hTgteh.css.br +0 -0
- package/dist/public/assets/w-ClUAGfpX.js +1 -0
- package/dist/public/assets/w._-ClUAGfpX.js +1 -0
- package/dist/public/assets/w._-CtbjyBu3.js +1 -0
- package/dist/public/assets/w._-D5ZiKvyZ.js +1 -0
- package/package.json +1 -1
- package/dist/_BkRvQO5r.js +0 -2
- package/dist/_C29NgtBI.js +0 -2
- package/dist/public/assets/_-EmIcUKk.js +0 -1
- package/dist/public/assets/_-Zp0T_lO.js +0 -1
- package/dist/public/assets/_0H09AGax.js.br +0 -0
- package/dist/public/assets/_3jDFL-Cg.js.br +0 -0
- package/dist/public/assets/_42tHqFp1.js +0 -1
- package/dist/public/assets/_43jDY_uH.js +0 -1
- package/dist/public/assets/_5pKDjgHs.js.br +0 -0
- package/dist/public/assets/_73JN1my-.js +0 -1
- package/dist/public/assets/_7X0H8kL8.js +0 -1
- package/dist/public/assets/_9PIiwVmz.js.br +0 -0
- package/dist/public/assets/_Ag37ZLrV.js +0 -1
- package/dist/public/assets/_B-cgAjqV.js.br +0 -0
- package/dist/public/assets/_B0YQ-oFW.js +0 -1
- package/dist/public/assets/_B0tb8Vgp.js.br +0 -0
- package/dist/public/assets/_B1fJukJK.js +0 -1
- package/dist/public/assets/_B1rg6S37.js.br +0 -0
- package/dist/public/assets/_B40fHLkj.js.br +0 -0
- package/dist/public/assets/_B4a1Ga-C.js +0 -1
- package/dist/public/assets/_B5QrsHwd.js.br +0 -0
- package/dist/public/assets/_B6Gi_-aO.js +0 -1
- package/dist/public/assets/_B6Zw_zoM.js.br +0 -0
- package/dist/public/assets/_B7FUbkdd.js +0 -1
- package/dist/public/assets/_B9OVFXEI.js.br +0 -0
- package/dist/public/assets/_BAxxcUnT.js +0 -1
- package/dist/public/assets/_BBVcNRD6.js +0 -1
- package/dist/public/assets/_BCO2lKSr.js +0 -1
- package/dist/public/assets/_BF2_gMS8.js.br +0 -0
- package/dist/public/assets/_BH9u6x7L.js.br +0 -0
- package/dist/public/assets/_BHyPBbeA.js +0 -1
- package/dist/public/assets/_BICdCzpd.js.br +0 -0
- package/dist/public/assets/_BJcqxD6V.js.br +0 -0
- package/dist/public/assets/_BKsJcK3w.js +0 -1
- package/dist/public/assets/_BMXY56L9.js.br +0 -0
- package/dist/public/assets/_BORTVznS.js.br +0 -0
- package/dist/public/assets/_BOr_i2db.js +0 -1
- package/dist/public/assets/_BSCc1FVi.js +0 -1
- package/dist/public/assets/_BSEhhZ07.js +0 -1
- package/dist/public/assets/_BSyW2RLw.js.br +0 -0
- package/dist/public/assets/_BUPTpTYH.js.br +0 -0
- package/dist/public/assets/_BUqHNT5-.js +0 -1
- package/dist/public/assets/_BWwfOfMX.js.br +0 -0
- package/dist/public/assets/_BZXQzilG.js +0 -1
- package/dist/public/assets/_BZhRz8TB.js.br +0 -0
- package/dist/public/assets/_B_1_7y_i.js +0 -1
- package/dist/public/assets/_B_zlRrUP.js.br +0 -0
- package/dist/public/assets/_BciKbAaO.js.br +0 -0
- package/dist/public/assets/_BdNI84NG.js +0 -1
- package/dist/public/assets/_Bdq41ArX.js.br +0 -0
- package/dist/public/assets/_BfT9QWYM.js +0 -1
- package/dist/public/assets/_BflxkINP.js +0 -1
- package/dist/public/assets/_BiIrl8ml.js.br +0 -0
- package/dist/public/assets/_Bmgmfh64.js +0 -1
- package/dist/public/assets/_BnDvb8rh.js.br +0 -0
- package/dist/public/assets/_BstVSsFN.js +0 -1
- package/dist/public/assets/_Bu1DxZly.js +0 -1
- package/dist/public/assets/_By3jAAQI.js +0 -1
- package/dist/public/assets/_By3jAAQI.js.br +0 -0
- package/dist/public/assets/_ByZbJftZ.js.br +0 -0
- package/dist/public/assets/_BzU0dRn3.js +0 -1
- package/dist/public/assets/_C-IpRzUC.js +0 -1
- package/dist/public/assets/_C0W4EC0Z.js.br +0 -0
- package/dist/public/assets/_C1EEKbbh.js.br +0 -0
- package/dist/public/assets/_C1I4axdk.js +0 -1
- package/dist/public/assets/_C23aBO0p.js.br +0 -0
- package/dist/public/assets/_C3La6EyV.js.br +0 -0
- package/dist/public/assets/_C3k75NG8.js.br +0 -0
- package/dist/public/assets/_C4Hln-a1.js.br +0 -0
- package/dist/public/assets/_C7nRA4nl.js +0 -1
- package/dist/public/assets/_CAN3Gwlo.js.br +0 -0
- package/dist/public/assets/_CB6bJYj7.js +0 -1
- package/dist/public/assets/_CDG0zRut.js.br +0 -0
- package/dist/public/assets/_CDPOV9zA.js.br +0 -0
- package/dist/public/assets/_CEzgbnFo.js.br +0 -0
- package/dist/public/assets/_CH7j19or.js +0 -1
- package/dist/public/assets/_CH7j19or.js.br +0 -0
- package/dist/public/assets/_CKNilRtP.js.br +0 -0
- package/dist/public/assets/_CKvOm2QG.js.br +0 -0
- package/dist/public/assets/_CLpJpkGL.js.br +0 -0
- package/dist/public/assets/_CN4xiFtS.js +0 -1
- package/dist/public/assets/_CRAhvbwb.js.br +0 -0
- package/dist/public/assets/_CRkxKTgw.js +0 -1
- package/dist/public/assets/_CS08pKi4.js +0 -1
- package/dist/public/assets/_CSE16QHd.js +0 -1
- package/dist/public/assets/_CT4ei2Jg.js +0 -1
- package/dist/public/assets/_CW5ES2vr.js +0 -1
- package/dist/public/assets/_CWhF-4OC.js +0 -1
- package/dist/public/assets/_CXhoovwf.js.br +0 -0
- package/dist/public/assets/_CY7Wr_6h.js.br +0 -0
- package/dist/public/assets/_C_-mBehU.js +0 -1
- package/dist/public/assets/_CazYpkki.js +0 -1
- package/dist/public/assets/_CbAa5uAw.js.br +0 -0
- package/dist/public/assets/_CcbwLXni.js +0 -1
- package/dist/public/assets/_CiYp9PxT.js.br +0 -0
- package/dist/public/assets/_CmLGUmi9.js +0 -1
- package/dist/public/assets/_CmLGUmi9.js.br +0 -0
- package/dist/public/assets/_Coj9l4W_.js.br +0 -0
- package/dist/public/assets/_Cp1MBi_q.js +0 -1
- package/dist/public/assets/_CpXvQ4wL.js +0 -1
- package/dist/public/assets/_CsNZdkZU.js.br +0 -0
- package/dist/public/assets/_Ct8a3v8n.js +0 -1
- package/dist/public/assets/_CtYn_7Ld.js.br +0 -0
- package/dist/public/assets/_CthHHBjW.js +0 -2
- package/dist/public/assets/_CthHHBjW.js.br +0 -0
- package/dist/public/assets/_CtliFzZo.js +0 -1
- package/dist/public/assets/_Cw3MnPjo.js.br +0 -0
- package/dist/public/assets/_Cw9GxBkQ.js.br +0 -0
- package/dist/public/assets/_CwLlOfhS.js +0 -1
- package/dist/public/assets/_Cz606f5R.js +0 -7
- package/dist/public/assets/_Cz606f5R.js.br +0 -0
- package/dist/public/assets/_D-pAxlQ-.js.br +0 -0
- package/dist/public/assets/_D24Cf_aJ.js +0 -1
- package/dist/public/assets/_D2Bfy3Mq.js +0 -1
- package/dist/public/assets/_D3_-HE_e.js +0 -1
- package/dist/public/assets/_D4XHSL1o.js.br +0 -0
- package/dist/public/assets/_D8WYrmFe.js +0 -1
- package/dist/public/assets/_D8WYrmFe.js.br +0 -0
- package/dist/public/assets/_D9-mnhpM.js.br +0 -0
- package/dist/public/assets/_DBjp4Oaj.js +0 -1
- package/dist/public/assets/_DBzqRlRQ.js +0 -1
- package/dist/public/assets/_DC6M2qH2.js +0 -1
- package/dist/public/assets/_DE5SUDS8.js.br +0 -0
- package/dist/public/assets/_DEGMhwoO.js +0 -1
- package/dist/public/assets/_DIEqAzJB.js.br +0 -0
- package/dist/public/assets/_DJVQZQI-.js.br +0 -0
- package/dist/public/assets/_DL8YLICC.js +0 -1
- package/dist/public/assets/_DLoAVrbv.js.br +0 -0
- package/dist/public/assets/_DLpha-BN.js +0 -1
- package/dist/public/assets/_DPKcpw43.js.br +0 -0
- package/dist/public/assets/_DUEm1sqD.js.br +0 -0
- package/dist/public/assets/_DX8wVfyk.js +0 -1
- package/dist/public/assets/_DXEbBRHY.js +0 -1
- package/dist/public/assets/_DX_AAVan.js +0 -1
- package/dist/public/assets/_DXhgTM12.js +0 -1
- package/dist/public/assets/_DcCeapFB.js.br +0 -0
- package/dist/public/assets/_DdWxi_D9.js.br +0 -0
- package/dist/public/assets/_DeGJuali.js.br +0 -0
- package/dist/public/assets/_Dge-T7VA.js +0 -1
- package/dist/public/assets/_Dh_fGh7B.js.br +0 -0
- package/dist/public/assets/_DlKCZs5m.js +0 -1
- package/dist/public/assets/_DmAY0SHM.js +0 -1
- package/dist/public/assets/_DmBJQY0z.js.br +0 -0
- package/dist/public/assets/_DmISa8wc.js.br +0 -0
- package/dist/public/assets/_DpUeYTvU.js +0 -1
- package/dist/public/assets/_DqcTAqJs.js +0 -1
- package/dist/public/assets/_DrntETw8.js +0 -1
- package/dist/public/assets/_Dsb-mJGm.js +0 -1
- package/dist/public/assets/_DuKrnKV2.js.br +0 -0
- package/dist/public/assets/_Dv298HDL.js.br +0 -0
- package/dist/public/assets/_DxgeJa1G.js.br +0 -0
- package/dist/public/assets/_DxpwwPqc.js +0 -1
- package/dist/public/assets/_G0Ur49hc.js.br +0 -0
- package/dist/public/assets/_GRlZXT_k.js +0 -1
- package/dist/public/assets/_HnJD2Vzo.js.br +0 -0
- package/dist/public/assets/_KtT9ovgB.js.br +0 -0
- package/dist/public/assets/_LsFmgSj_.js.br +0 -0
- package/dist/public/assets/_M2eABJML.js +0 -1
- package/dist/public/assets/_N7_4E3sa.js +0 -1
- package/dist/public/assets/_SCQ7gzWP.js +0 -1
- package/dist/public/assets/_SkNT3g1t.js.br +0 -0
- package/dist/public/assets/_T32b15Ve.js.br +0 -0
- package/dist/public/assets/_TOwFHHoM.js.br +0 -0
- package/dist/public/assets/_UUd1gazT.js +0 -1
- package/dist/public/assets/_YTVYw9XV.js.br +0 -0
- package/dist/public/assets/_ZlbOPzr7.js.br +0 -0
- package/dist/public/assets/_a3BQDAxj.js.br +0 -0
- package/dist/public/assets/_aVJfol8S.js.br +0 -0
- package/dist/public/assets/_ee3nMJZE.js +0 -86
- package/dist/public/assets/_ee3nMJZE.js.br +0 -0
- package/dist/public/assets/_fBJXUlyl.js.br +0 -0
- package/dist/public/assets/_gy0a9Cmp.js.br +0 -0
- package/dist/public/assets/_iTbVHO4b.js +0 -1
- package/dist/public/assets/_k79dEMkm.js +0 -1
- package/dist/public/assets/_kHV7j6Zv.js.br +0 -0
- package/dist/public/assets/_l9Ig5EJO.js.br +0 -0
- package/dist/public/assets/_lYxkU02J.js +0 -1
- package/dist/public/assets/_rizgJsHK.js.br +0 -0
- package/dist/public/assets/_rmo2BlTL.js +0 -1
- package/dist/public/assets/_sEygC0rY.js +0 -1
- package/dist/public/assets/_sEygC0rY.js.br +0 -0
- package/dist/public/assets/_ulL_yezz.js.br +0 -0
- package/dist/public/assets/_vWNf9U23.js +0 -1
- package/dist/public/assets/_vd2rHjSk.js +0 -1
- package/dist/public/assets/_wC0cYIUL.js.br +0 -0
- package/dist/public/assets/_zGawNqPU.js.br +0 -0
- package/dist/public/assets/files-view-D9y_w_28.js +0 -2
- package/dist/public/assets/manage-workspace-BCRACsUn.js +0 -2
- package/dist/public/assets/new-BdLH98ro.js +0 -1
- package/dist/public/assets/new-workspace-TMTnjdBC.js +0 -2
- package/dist/public/assets/review-view-CvIicWqZ.js +0 -2
- package/dist/public/assets/settings-BdLH98ro.js +0 -1
- package/dist/public/assets/settings-page-I3W3CL5p.js +0 -2
- package/dist/public/assets/styles-D39vLjzP.css +0 -1
- package/dist/public/assets/styles-D39vLjzP.css.br +0 -0
- package/dist/public/assets/w-BdLH98ro.js +0 -1
- package/dist/public/assets/w._-BD4s-fU6.js +0 -1
- package/dist/public/assets/w._-BdLH98ro.js +0 -1
- package/dist/public/assets/w._-DnOj6Zzs.js +0 -1
package/bin/cli/session.mjs
CHANGED
|
@@ -382,7 +382,7 @@ work session send <id> "<text>"|- [--no-reply] [--now|--interrupt]
|
|
|
382
382
|
work session unsend <id>
|
|
383
383
|
Take back what this session queued for <id> that is not typed in yet:
|
|
384
384
|
a message that went in stays in its turn (send a correction instead).
|
|
385
|
-
work session reopen <id> [--agent <id>] [--now]
|
|
385
|
+
work session reopen <id> [--agent <id>] [--now] [--team]
|
|
386
386
|
Start a session again on its own conversation, where its CLI can resume
|
|
387
387
|
one (Claude, Codex): one closed — by its lead's close, the user's, or
|
|
388
388
|
for being done — back under the session that started it, or under this
|
|
@@ -392,8 +392,17 @@ work session reopen <id> [--agent <id>] [--now]
|
|
|
392
392
|
where the two share their conversations. What is queued for it and what
|
|
393
393
|
it owes you stay: send it a message to carry it on. A restart ends the
|
|
394
394
|
turn under way and what its pane runs (a background job, a dev server),
|
|
395
|
-
so a running one mid-turn or with jobs is
|
|
396
|
-
|
|
395
|
+
so a running one mid-turn or with jobs moves once it is idle, saying
|
|
396
|
+
what it waits out, unless --now restarts it at once. On this session
|
|
397
|
+
itself (\`reopen $WORK_SESSION_ID --agent claude2\`, a lead moving to
|
|
398
|
+
another account) it always waits for this turn's end, --now or not:
|
|
399
|
+
finish the turn and it moves, its conversation, team and queue kept.
|
|
400
|
+
--team, for a closed lead, brings back with it the sessions closed in
|
|
401
|
+
the same close, each under its own parent again and on its own
|
|
402
|
+
conversation (as --agent too, where that is another instance of its
|
|
403
|
+
CLI), naming any that cannot be reopened; those under one come back
|
|
404
|
+
under the nearest above them that did. It needs no --force: it brings
|
|
405
|
+
back what ran, not more.
|
|
397
406
|
work session wait [<id>|<group>...] [--any] [--timeout <seconds>]
|
|
398
407
|
Wait for the replies owed to this session (by those sessions or groups,
|
|
399
408
|
else by any), printing each as it comes; a reply printed here is not
|
|
@@ -777,16 +786,39 @@ work session kill --done
|
|
|
777
786
|
case "reopen": {
|
|
778
787
|
const [id] = rest;
|
|
779
788
|
if (!id)
|
|
780
|
-
ctx.die(
|
|
789
|
+
ctx.die(
|
|
790
|
+
"usage: work session reopen <id> [--agent <id>] [--now] [--team]",
|
|
791
|
+
);
|
|
781
792
|
const agent = ctx.flag("--agent");
|
|
782
793
|
const r = await ctx.api.post(`/api/sessions/${id}/reopen${by()}`, {
|
|
783
794
|
...(agent ? { agent } : {}),
|
|
784
795
|
...(ctx.has("--now") ? { now: true } : {}),
|
|
796
|
+
...(ctx.has("--team") ? { team: true } : {}),
|
|
785
797
|
});
|
|
786
798
|
return ctx.out(r, (r) => {
|
|
799
|
+
if (r.scheduled) {
|
|
800
|
+
const self = r.id === process.env.WORK_SESSION_ID;
|
|
801
|
+
console.log(
|
|
802
|
+
`${r.id} moves to ${r.scheduled} once ${self ? "this turn ends" : `it is idle (it waits out ${r.waits.join(", and ")})`}, on its own conversation, its team and queue kept.`,
|
|
803
|
+
);
|
|
804
|
+
if (self)
|
|
805
|
+
console.log(
|
|
806
|
+
"Finish this turn: say what you were on, then stop. The move starts this conversation again as the new instance.",
|
|
807
|
+
);
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
787
810
|
console.log(
|
|
788
811
|
`${r.restarted ? "restarted" : "reopened"} ${r.id} on its conversation as ${r.agent}${r.parent ? `, under ${r.parent}` : ""}`,
|
|
789
812
|
);
|
|
813
|
+
if (r.team) {
|
|
814
|
+
console.log(
|
|
815
|
+
r.team.reopened.length
|
|
816
|
+
? `with its team: ${r.team.reopened.join(", ")}`
|
|
817
|
+
: "nothing was closed with it to bring back",
|
|
818
|
+
);
|
|
819
|
+
for (const s of r.team.skipped)
|
|
820
|
+
console.log(` not reopened ${s.id}: ${s.why}`);
|
|
821
|
+
}
|
|
790
822
|
console.log(
|
|
791
823
|
`It is at its prompt: \`work session send ${r.id} "…"\` carries it on.`,
|
|
792
824
|
);
|
package/bin/cli/topic.mjs
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// plus the server's workspace rows (bases) and status (PRs).
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
8
8
|
import fs from "node:fs";
|
|
9
|
+
import os from "node:os";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
|
|
11
12
|
/** A topic's name: a word, or `<group>.<topic>` (folded into one review
|
|
@@ -24,11 +25,12 @@ const INSTALLERS = [
|
|
|
24
25
|
["Gemfile.lock", "bundle install"],
|
|
25
26
|
];
|
|
26
27
|
|
|
27
|
-
function git(cwd, args, { allowFail = false } = {}) {
|
|
28
|
+
function git(cwd, args, { allowFail = false, env = {}, input } = {}) {
|
|
28
29
|
const r = spawnSync("git", args, {
|
|
29
30
|
cwd,
|
|
30
31
|
encoding: "utf8",
|
|
31
|
-
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
32
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0", ...env },
|
|
33
|
+
input,
|
|
32
34
|
});
|
|
33
35
|
if (r.status !== 0 && !allowFail) {
|
|
34
36
|
const why = (r.stderr || r.stdout || "").trim() || `exit ${r.status}`;
|
|
@@ -106,6 +108,27 @@ function aheadBehind(dir, base, tip) {
|
|
|
106
108
|
return { ahead, behind };
|
|
107
109
|
}
|
|
108
110
|
|
|
111
|
+
/** Its changes are all in `base` already though its commits are not —
|
|
112
|
+
* squashed into another PR, cherry-picked, folded in by hand: merging it
|
|
113
|
+
* there would change nothing, or every one of its commits' patches is
|
|
114
|
+
* there. Either way nothing is lost by putting it away, where ancestry
|
|
115
|
+
* alone called it unmerged for good. */
|
|
116
|
+
function landedIn(dir, base, tip) {
|
|
117
|
+
const merged = git(dir, ["merge-tree", "--write-tree", base, tip], {
|
|
118
|
+
allowFail: true,
|
|
119
|
+
});
|
|
120
|
+
// A clean merge prints its tree alone; one with conflicts exits 1.
|
|
121
|
+
if (merged.ok && merged.out === oid(dir, `${base}^{tree}`)) return true;
|
|
122
|
+
// Each commit's patch already there (`-`), even where the base has moved
|
|
123
|
+
// the same lines on since and the merge would conflict.
|
|
124
|
+
const cherry = git(dir, ["cherry", base, tip], { allowFail: true });
|
|
125
|
+
return (
|
|
126
|
+
cherry.ok &&
|
|
127
|
+
cherry.out !== "" &&
|
|
128
|
+
cherry.out.split("\n").every((l) => l.startsWith("- "))
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
/** Where the workspace and its repos are, the other workspaces' branches
|
|
110
133
|
* (whose topics are not this one's), and each repo's PRs — dismissed ones
|
|
111
134
|
* too: a merged chip the user dismissed is still the merge that lets
|
|
@@ -125,9 +148,56 @@ async function context(ctx, fresh) {
|
|
|
125
148
|
dir: path.join(ws.path, r.worktree),
|
|
126
149
|
prs: prsOf.get(r.full_name) || [],
|
|
127
150
|
}));
|
|
151
|
+
await withOlderPrs(ctx, ws, repos, foreign);
|
|
128
152
|
return { ws, repos, foreign };
|
|
129
153
|
}
|
|
130
154
|
|
|
155
|
+
/** The PRs the workspace's search no longer holds, for the topics that
|
|
156
|
+
* point at one. That search keeps only its latest finished PRs, so a topic
|
|
157
|
+
* squash-merged long ago read as unmerged work for good. Its tell: pushed
|
|
158
|
+
* once (an upstream recorded) and its copy on origin gone, which is how a
|
|
159
|
+
* merged PR's branch ends when GitHub deletes it, while a topic never
|
|
160
|
+
* pushed (most of a team's) asks nothing. Those few are asked for by name,
|
|
161
|
+
* in one request, and added to the repo's list. */
|
|
162
|
+
async function withOlderPrs(ctx, ws, repos, foreign) {
|
|
163
|
+
const heads = new Set();
|
|
164
|
+
for (const repo of repos) {
|
|
165
|
+
if (!fs.existsSync(repo.dir)) continue;
|
|
166
|
+
const pushed = git(
|
|
167
|
+
repo.dir,
|
|
168
|
+
[
|
|
169
|
+
"config",
|
|
170
|
+
"--get-regexp",
|
|
171
|
+
`^branch\\.${ws.branch.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}-.*\\.remote$`,
|
|
172
|
+
],
|
|
173
|
+
{ allowFail: true },
|
|
174
|
+
).out;
|
|
175
|
+
for (const line of pushed.split("\n")) {
|
|
176
|
+
const branch = line.match(/^branch\.(.+)\.remote /)?.[1];
|
|
177
|
+
if (
|
|
178
|
+
branch &&
|
|
179
|
+
owns(branch, ws.branch, foreign) &&
|
|
180
|
+
!prFor(repo, branch) &&
|
|
181
|
+
oid(repo.dir, `refs/heads/${branch}`) &&
|
|
182
|
+
!oid(repo.dir, `refs/remotes/origin/${branch}`)
|
|
183
|
+
)
|
|
184
|
+
heads.add(branch);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (!heads.size) return;
|
|
188
|
+
const found = await ctx.api
|
|
189
|
+
.get(
|
|
190
|
+
`/api/workspaces/${ws.id}/prs?heads=${encodeURIComponent([...heads].join(","))}`,
|
|
191
|
+
)
|
|
192
|
+
.catch(() => null);
|
|
193
|
+
for (const r of found?.repos || []) {
|
|
194
|
+
const repo = repos.find((x) => x.full_name === r.full_name);
|
|
195
|
+
if (!repo) continue;
|
|
196
|
+
const have = new Set(repo.prs.map((p) => p.number));
|
|
197
|
+
repo.prs.push(...(r.prs || []).filter((p) => !have.has(p.number)));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
131
201
|
const topicDir = (ws, name, repo) =>
|
|
132
202
|
path.join(ws.path, ".worktrees", name, repo.worktree);
|
|
133
203
|
|
|
@@ -374,6 +444,7 @@ function topicsIn(ws, repo, foreign) {
|
|
|
374
444
|
// What `topic new` recorded for gh: the branch it stacks on, else the
|
|
375
445
|
// repo's base.
|
|
376
446
|
const recorded = mergeBases(repo.dir);
|
|
447
|
+
const dropped = droppedBranches(repo.dir);
|
|
377
448
|
const bases = new Map();
|
|
378
449
|
return [...branches].sort().map((branch) => {
|
|
379
450
|
const name = branch.slice(prefix.length);
|
|
@@ -389,6 +460,7 @@ function topicsIn(ws, repo, foreign) {
|
|
|
389
460
|
: { ahead: null, behind: null };
|
|
390
461
|
const worktree = trees.get(branch) || null;
|
|
391
462
|
const pr = prFor(repo, branch);
|
|
463
|
+
const contained = !!base && ahead === 0;
|
|
392
464
|
return {
|
|
393
465
|
topic: name,
|
|
394
466
|
repo: repo.worktree,
|
|
@@ -424,7 +496,12 @@ function topicsIn(ws, repo, foreign) {
|
|
|
424
496
|
// Nothing of its own past the base: either merged as it was, or a
|
|
425
497
|
// topic with no commits yet. Either way, nothing is lost by
|
|
426
498
|
// putting its worktree away.
|
|
427
|
-
contained
|
|
499
|
+
contained,
|
|
500
|
+
// Commits of its own, but none of its changes the base lacks.
|
|
501
|
+
landed: !!base && !contained && landedIn(repo.dir, base, tip),
|
|
502
|
+
// Dropped here (`topic drop`), its local branch gone: what is left is
|
|
503
|
+
// origin's copy, which drop leaves alone.
|
|
504
|
+
dropped: !local && dropped.has(branch),
|
|
428
505
|
link: link(ws, repo, name),
|
|
429
506
|
};
|
|
430
507
|
});
|
|
@@ -433,9 +510,11 @@ function topicsIn(ws, repo, foreign) {
|
|
|
433
510
|
async function topicList(ctx) {
|
|
434
511
|
const { ws, repos, foreign } = await context(ctx, ctx.has("--fresh"));
|
|
435
512
|
const all = repos.flatMap((repo) => topicsIn(ws, repo, foreign));
|
|
436
|
-
// Put away: merged (or nothing
|
|
437
|
-
// its branch kept, as the after-merge chores leave it
|
|
438
|
-
|
|
513
|
+
// Put away: merged (or nothing of it its base lacks) with no worktree
|
|
514
|
+
// left — its branch kept, as the after-merge chores leave it — or dropped
|
|
515
|
+
// here. Listed on asking.
|
|
516
|
+
const away = (t) =>
|
|
517
|
+
t.dropped || (!t.worktree && (t.merged || t.contained || t.landed));
|
|
439
518
|
const rows = ctx.has("--all") ? all : all.filter((t) => !away(t));
|
|
440
519
|
const hidden = all.length - rows.length;
|
|
441
520
|
ctx.out(rows, (list) => {
|
|
@@ -450,7 +529,9 @@ async function topicList(ctx) {
|
|
|
450
529
|
? `no ${t.baseBranch} or origin/${t.baseBranch} here to count against`
|
|
451
530
|
: t.contained
|
|
452
531
|
? `nothing past ${t.base}`
|
|
453
|
-
:
|
|
532
|
+
: t.landed
|
|
533
|
+
? `landed in ${t.base} (by other commits: ${t.ahead} of its own, none of its changes missing there)`
|
|
534
|
+
: `${t.ahead} ahead, ${t.behind} behind ${t.base}`;
|
|
454
535
|
const flags = [
|
|
455
536
|
t.dirty ? `${t.dirty} uncommitted` : null,
|
|
456
537
|
t.local && !t.onOrigin && t.ahead ? "not pushed" : null,
|
|
@@ -458,7 +539,8 @@ async function topicList(ctx) {
|
|
|
458
539
|
t.local && t.onOrigin && !t.unpushed && !t.pushed
|
|
459
540
|
? "origin has newer"
|
|
460
541
|
: null,
|
|
461
|
-
|
|
542
|
+
t.dropped ? "dropped here, origin keeps it" : null,
|
|
543
|
+
!t.local && !t.dropped ? "only on origin" : null,
|
|
462
544
|
].filter(Boolean);
|
|
463
545
|
const pr = t.pr
|
|
464
546
|
? ` #${t.pr.number} ${t.pr.state === "OPEN" ? (t.pr.draft ? "draft" : "open") : t.pr.state.toLowerCase()}`
|
|
@@ -471,7 +553,7 @@ async function topicList(ctx) {
|
|
|
471
553
|
}
|
|
472
554
|
if (hidden)
|
|
473
555
|
console.log(
|
|
474
|
-
`${hidden} put away (merged
|
|
556
|
+
`${hidden} put away (merged or landed with its worktree removed, or dropped): --all lists them`,
|
|
475
557
|
);
|
|
476
558
|
});
|
|
477
559
|
}
|
|
@@ -483,7 +565,7 @@ async function topicList(ctx) {
|
|
|
483
565
|
* PR's head, or past what origin has of it. */
|
|
484
566
|
function leftover(repo, t, pr) {
|
|
485
567
|
const local = oid(repo.dir, `refs/heads/${t.branch}`);
|
|
486
|
-
if (!local || t.contained) return null;
|
|
568
|
+
if (!local || t.contained || t.landed) return null;
|
|
487
569
|
let head = pr?.headRefOid || null;
|
|
488
570
|
if (head && !has(repo.dir, `${head}^{commit}`)) {
|
|
489
571
|
// A squash-merged PR's head lives on in GitHub's pull ref.
|
|
@@ -532,15 +614,18 @@ async function topicDone(ctx) {
|
|
|
532
614
|
const t = topicsIn(ws, repo, foreign).find((x) => x.branch === branch);
|
|
533
615
|
if (!t) continue;
|
|
534
616
|
const pr = prFor(repo, branch);
|
|
535
|
-
if (!t.merged && !t.contained) {
|
|
617
|
+
if (!t.merged && !t.contained && !t.landed) {
|
|
536
618
|
const prState = t.pr
|
|
537
619
|
? ` (#${t.pr.number} is ${t.pr.state.toLowerCase()})`
|
|
538
620
|
: "";
|
|
621
|
+
// An abandoned topic is never merged: say how it goes instead.
|
|
539
622
|
result.refused.push({
|
|
540
623
|
repo: repo.worktree,
|
|
541
|
-
why:
|
|
542
|
-
|
|
543
|
-
|
|
624
|
+
why: `${
|
|
625
|
+
t.base
|
|
626
|
+
? `${branch} is not merged${prState} and has changes in ${t.ahead} commit(s) ${t.base} lacks`
|
|
627
|
+
: `${branch} is not merged${prState}, and there is no ${t.baseBranch} or origin/${t.baseBranch} here to check it against`
|
|
628
|
+
} (to abandon it: work topic drop ${name})`,
|
|
544
629
|
});
|
|
545
630
|
continue;
|
|
546
631
|
}
|
|
@@ -603,7 +688,8 @@ async function topicDone(ctx) {
|
|
|
603
688
|
}
|
|
604
689
|
// Nothing of its own: left where it is, unless what it stacks on
|
|
605
690
|
// moved out from under it.
|
|
606
|
-
if (other.contained && !moved.has(other.baseBranch))
|
|
691
|
+
if ((other.contained || other.landed) && !moved.has(other.baseBranch))
|
|
692
|
+
continue;
|
|
607
693
|
const base = restack ? t.base : other.base;
|
|
608
694
|
if (!other.local || !base) continue;
|
|
609
695
|
const { behind } = aheadBehind(repo.dir, base, other.branch);
|
|
@@ -684,6 +770,307 @@ async function topicDone(ctx) {
|
|
|
684
770
|
process.exitCode = 1;
|
|
685
771
|
}
|
|
686
772
|
|
|
773
|
+
// -- drop --------------------------------------------------------------------
|
|
774
|
+
|
|
775
|
+
/** Where a dropped topic's last tip is kept, a ref per drop
|
|
776
|
+
* (`<branch>/<UTC stamp>`): outside `refs/work/<workspace>/`, whose
|
|
777
|
+
* snapshots the server prunes, and in no push. */
|
|
778
|
+
const DROPPED = "refs/work-dropped/";
|
|
779
|
+
/** How long a dropped topic can be brought back. */
|
|
780
|
+
const KEEP_DROPPED_DAYS = 30;
|
|
781
|
+
const DAY = 86_400_000;
|
|
782
|
+
|
|
783
|
+
const stampOf = (d) =>
|
|
784
|
+
d
|
|
785
|
+
.toISOString()
|
|
786
|
+
.replace(/[-:]/g, "")
|
|
787
|
+
.replace(/\.\d+Z$/, "Z");
|
|
788
|
+
|
|
789
|
+
function stampTime(stamp) {
|
|
790
|
+
const m = /^(\d{4})(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)Z$/.exec(stamp);
|
|
791
|
+
return m ? Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6]) : null;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/** Each dropped ref: its branch, the time of its drop. */
|
|
795
|
+
function droppedRefs(dir) {
|
|
796
|
+
return git(dir, ["for-each-ref", "--format=%(refname)", DROPPED], {
|
|
797
|
+
allowFail: true,
|
|
798
|
+
})
|
|
799
|
+
.out.split("\n")
|
|
800
|
+
.filter(Boolean)
|
|
801
|
+
.map((ref) => {
|
|
802
|
+
const rest = ref.slice(DROPPED.length);
|
|
803
|
+
const cut = rest.lastIndexOf("/");
|
|
804
|
+
return {
|
|
805
|
+
ref,
|
|
806
|
+
branch: rest.slice(0, cut),
|
|
807
|
+
at: stampTime(rest.slice(cut + 1)),
|
|
808
|
+
};
|
|
809
|
+
})
|
|
810
|
+
.filter((r) => r.branch && r.at !== null);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/** The branches dropped here (within their keep). */
|
|
814
|
+
function droppedBranches(dir) {
|
|
815
|
+
return new Set(droppedRefs(dir).map((r) => r.branch));
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/** Dropped refs past their keep, gone: every workspace's on this repo,
|
|
819
|
+
* since its cache is shared and a deleted workspace drops nothing again. */
|
|
820
|
+
function pruneDropped(dir, now = Date.now()) {
|
|
821
|
+
const gone = droppedRefs(dir).filter(
|
|
822
|
+
(r) => r.at < now - KEEP_DROPPED_DAYS * DAY,
|
|
823
|
+
);
|
|
824
|
+
if (gone.length)
|
|
825
|
+
git(dir, ["update-ref", "--stdin"], {
|
|
826
|
+
allowFail: true,
|
|
827
|
+
input: gone.map((r) => `delete ${r.ref}\n`).join(""),
|
|
828
|
+
});
|
|
829
|
+
return gone.length;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/** A worktree as it is — uncommitted and untracked files too — as a commit
|
|
833
|
+
* on its HEAD, made through an index of its own so the worktree and its
|
|
834
|
+
* index are untouched: a forced drop keeps what it discards. */
|
|
835
|
+
function snapshotOf(worktree, message) {
|
|
836
|
+
const index = path.join(
|
|
837
|
+
os.tmpdir(),
|
|
838
|
+
`work-topic-drop-${process.pid}-${Date.now()}.index`,
|
|
839
|
+
);
|
|
840
|
+
// An identity of its own (a machine with none set still drops) and no
|
|
841
|
+
// signing (a key's passphrase prompt would hang a script).
|
|
842
|
+
const env = {
|
|
843
|
+
GIT_INDEX_FILE: index,
|
|
844
|
+
GIT_AUTHOR_NAME: "work",
|
|
845
|
+
GIT_AUTHOR_EMAIL: "work@localhost",
|
|
846
|
+
GIT_COMMITTER_NAME: "work",
|
|
847
|
+
GIT_COMMITTER_EMAIL: "work@localhost",
|
|
848
|
+
};
|
|
849
|
+
try {
|
|
850
|
+
git(worktree, ["read-tree", "HEAD"], { env });
|
|
851
|
+
git(worktree, ["add", "-A"], { env });
|
|
852
|
+
const tree = git(worktree, ["write-tree"], { env }).out;
|
|
853
|
+
return git(
|
|
854
|
+
worktree,
|
|
855
|
+
["commit-tree", "--no-gpg-sign", tree, "-p", "HEAD", "-m", message],
|
|
856
|
+
{ env },
|
|
857
|
+
).out;
|
|
858
|
+
} finally {
|
|
859
|
+
fs.rmSync(index, { force: true });
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
const real = (p) => {
|
|
864
|
+
try {
|
|
865
|
+
return fs.realpathSync(p);
|
|
866
|
+
} catch {
|
|
867
|
+
return path.resolve(p);
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
const within = (dir, root) => dir === root || dir.startsWith(root + path.sep);
|
|
871
|
+
|
|
872
|
+
/** Everything about dropping the topic in one repo, before any of it is
|
|
873
|
+
* done: what goes, what would be lost, and what stands in the way —
|
|
874
|
+
* `blocks` give way to --yes, `stops` never do. */
|
|
875
|
+
function planDrop(ctx, ws, repo, t, sessions, topics) {
|
|
876
|
+
const plan = { repo, t, lost: [], blocks: [], stops: [], dirty: [] };
|
|
877
|
+
plan.local = oid(repo.dir, `refs/heads/${t.branch}`);
|
|
878
|
+
if (!plan.local) return plan;
|
|
879
|
+
if (t.worktree && real(t.worktree) === real(repo.dir))
|
|
880
|
+
plan.stops.push(
|
|
881
|
+
`${t.branch} is checked out in the workspace's own checkout (${repo.dir}): switch that off it first`,
|
|
882
|
+
);
|
|
883
|
+
if (t.worktree) {
|
|
884
|
+
plan.dirty = dirtyIn(t.worktree);
|
|
885
|
+
if (plan.dirty.length)
|
|
886
|
+
plan.blocks.push(
|
|
887
|
+
`${t.worktree} has ${plan.dirty.length} uncommitted change(s):\n ${plan.dirty.slice(0, 10).join("\n ")}`,
|
|
888
|
+
);
|
|
889
|
+
const here = real(t.worktree);
|
|
890
|
+
for (const s of sessions)
|
|
891
|
+
if (
|
|
892
|
+
s.state?.alive &&
|
|
893
|
+
s.launch_dir &&
|
|
894
|
+
within(real(path.resolve(ws.path, s.launch_dir)), here)
|
|
895
|
+
)
|
|
896
|
+
plan.blocks.push(
|
|
897
|
+
`session ${s.id}${s.title ? ` ("${s.title}")` : ""} is working in ${t.worktree}`,
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
// What the drop discards: none of it when its base holds every change.
|
|
901
|
+
const merged = t.merged && !leftover(repo, t, prFor(repo, t.branch));
|
|
902
|
+
if (!t.contained && !t.landed && !merged) {
|
|
903
|
+
if (!t.base)
|
|
904
|
+
plan.blocks.push(
|
|
905
|
+
`there is no ${t.baseBranch} or origin/${t.baseBranch} here to tell what of ${t.branch} would be lost`,
|
|
906
|
+
);
|
|
907
|
+
else {
|
|
908
|
+
plan.lost = git(repo.dir, [
|
|
909
|
+
"log",
|
|
910
|
+
"--format=%h %s",
|
|
911
|
+
`${t.base}..${plan.local}`,
|
|
912
|
+
]).out.split("\n");
|
|
913
|
+
plan.blocks.push(
|
|
914
|
+
`${t.branch} has ${plan.lost.length} commit(s) whose changes ${t.base} lacks${
|
|
915
|
+
t.unpushed
|
|
916
|
+
? `, ${t.onOrigin ? t.unpushed : "all"} of them on no remote`
|
|
917
|
+
: ""
|
|
918
|
+
}:\n ${plan.lost.slice(0, 10).join("\n ")}`,
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (t.pr?.state === "OPEN")
|
|
923
|
+
plan.blocks.push(
|
|
924
|
+
`#${t.pr.number} is open (the drop leaves the PR and origin's copy as they are)`,
|
|
925
|
+
);
|
|
926
|
+
plan.stacked = topics.filter(
|
|
927
|
+
(o) => o.branch !== t.branch && o.local && o.baseBranch === t.branch,
|
|
928
|
+
);
|
|
929
|
+
for (const o of plan.stacked)
|
|
930
|
+
plan.blocks.push(
|
|
931
|
+
`${o.branch} stacks on it (with --yes it is counted against ${t.baseBranch} instead, still carrying ${t.branch}'s commits)`,
|
|
932
|
+
);
|
|
933
|
+
return plan;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
async function topicDrop(ctx) {
|
|
937
|
+
const [name] = ctx.parse([]);
|
|
938
|
+
if (!name) ctx.die("usage: work topic drop <name> [--yes] [--json]");
|
|
939
|
+
const { ws, repos, foreign } = await context(ctx, false);
|
|
940
|
+
const branch = `${ws.branch}-${name}`;
|
|
941
|
+
const touched = repos.filter(
|
|
942
|
+
(r) =>
|
|
943
|
+
has(r.dir, `refs/heads/${branch}`) ||
|
|
944
|
+
has(r.dir, `refs/remotes/origin/${branch}`),
|
|
945
|
+
);
|
|
946
|
+
if (!touched.length)
|
|
947
|
+
ctx.die(`no topic ${name} in ${ws.name} (see: work topic list)`);
|
|
948
|
+
const sessions = await ctx.api
|
|
949
|
+
.get(`/api/workspaces/${ws.id}/sessions`)
|
|
950
|
+
.catch(() => []);
|
|
951
|
+
// Every repo is planned before any is touched: half a topic dropped is
|
|
952
|
+
// worse than none.
|
|
953
|
+
const plans = [];
|
|
954
|
+
for (const repo of touched) {
|
|
955
|
+
// A fetch that fails (offline) only leaves the base older, which can
|
|
956
|
+
// only find more to lose.
|
|
957
|
+
ctx.log(`fetching ${repo.full_name}…`);
|
|
958
|
+
if (
|
|
959
|
+
!git(repo.dir, ["fetch", "--prune", "--quiet", "origin"], {
|
|
960
|
+
allowFail: true,
|
|
961
|
+
}).ok
|
|
962
|
+
)
|
|
963
|
+
ctx.warn(
|
|
964
|
+
`${repo.worktree}: could not fetch origin; counting against what is here`,
|
|
965
|
+
);
|
|
966
|
+
const topics = topicsIn(ws, repo, foreign);
|
|
967
|
+
const t = topics.find((x) => x.branch === branch);
|
|
968
|
+
if (t) plans.push(planDrop(ctx, ws, repo, t, sessions, topics));
|
|
969
|
+
}
|
|
970
|
+
const result = {
|
|
971
|
+
topic: name,
|
|
972
|
+
dropped: [],
|
|
973
|
+
skipped: [],
|
|
974
|
+
refused: [],
|
|
975
|
+
restacked: [],
|
|
976
|
+
};
|
|
977
|
+
for (const p of plans) {
|
|
978
|
+
for (const why of p.stops)
|
|
979
|
+
result.refused.push({ repo: p.repo.worktree, why });
|
|
980
|
+
if (!ctx.yes)
|
|
981
|
+
for (const why of p.blocks)
|
|
982
|
+
result.refused.push({ repo: p.repo.worktree, why });
|
|
983
|
+
}
|
|
984
|
+
if (!result.refused.length) {
|
|
985
|
+
const at = new Date();
|
|
986
|
+
for (const p of plans) {
|
|
987
|
+
const { repo, t } = p;
|
|
988
|
+
if (!p.local) {
|
|
989
|
+
result.skipped.push({
|
|
990
|
+
repo: repo.worktree,
|
|
991
|
+
why: `${branch} is only on origin: nothing here to drop (git push origin --delete ${branch} removes it there)`,
|
|
992
|
+
});
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
pruneDropped(repo.dir, at.getTime());
|
|
996
|
+
const keep = p.dirty.length
|
|
997
|
+
? snapshotOf(
|
|
998
|
+
t.worktree,
|
|
999
|
+
`work topic drop: ${branch} with its uncommitted changes`,
|
|
1000
|
+
)
|
|
1001
|
+
: p.local;
|
|
1002
|
+
const ref = `${DROPPED}${branch}/${stampOf(at)}`;
|
|
1003
|
+
git(repo.dir, ["update-ref", ref, keep]);
|
|
1004
|
+
if (t.worktree) {
|
|
1005
|
+
git(repo.dir, [
|
|
1006
|
+
"worktree",
|
|
1007
|
+
"remove",
|
|
1008
|
+
...(p.dirty.length ? ["--force"] : []),
|
|
1009
|
+
t.worktree,
|
|
1010
|
+
]);
|
|
1011
|
+
// The topic's own folder, once its last repo's worktree is gone.
|
|
1012
|
+
try {
|
|
1013
|
+
fs.rmdirSync(path.dirname(t.worktree));
|
|
1014
|
+
} catch {}
|
|
1015
|
+
}
|
|
1016
|
+
for (const o of p.stacked) {
|
|
1017
|
+
git(repo.dir, [
|
|
1018
|
+
"config",
|
|
1019
|
+
`branch.${o.branch}.gh-merge-base`,
|
|
1020
|
+
t.baseBranch,
|
|
1021
|
+
]);
|
|
1022
|
+
result.restacked.push({
|
|
1023
|
+
repo: repo.worktree,
|
|
1024
|
+
branch: o.branch,
|
|
1025
|
+
base: t.baseBranch,
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
// Its config (the recorded base) goes with it.
|
|
1029
|
+
git(repo.dir, ["branch", "-D", branch]);
|
|
1030
|
+
result.dropped.push({
|
|
1031
|
+
repo: repo.worktree,
|
|
1032
|
+
branch,
|
|
1033
|
+
worktree: t.worktree,
|
|
1034
|
+
commits: p.lost.filter(Boolean).length,
|
|
1035
|
+
unpushed: p.lost.length ? t.unpushed : 0,
|
|
1036
|
+
uncommitted: p.dirty.length,
|
|
1037
|
+
kept: ref,
|
|
1038
|
+
keptDays: KEEP_DROPPED_DAYS,
|
|
1039
|
+
restore: `git -C ${repo.dir} branch ${branch} ${ref}`,
|
|
1040
|
+
onOrigin: t.onOrigin,
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
ctx.out(result, (r) => {
|
|
1045
|
+
for (const x of r.dropped) {
|
|
1046
|
+
const lost = [
|
|
1047
|
+
x.commits ? `${x.commits} commit(s) its base lacks` : null,
|
|
1048
|
+
x.uncommitted ? `${x.uncommitted} uncommitted change(s)` : null,
|
|
1049
|
+
].filter(Boolean);
|
|
1050
|
+
console.log(
|
|
1051
|
+
`${x.repo}: dropped ${x.branch}${lost.length ? ` (${lost.join(", ")})` : ""}`,
|
|
1052
|
+
);
|
|
1053
|
+
if (x.worktree) console.log(` removed ${x.worktree}`);
|
|
1054
|
+
console.log(
|
|
1055
|
+
` kept as ${x.kept} for ${x.keptDays} days; to bring it back: ${x.restore}${x.uncommitted ? " (its top commit holds the uncommitted changes)" : ""}`,
|
|
1056
|
+
);
|
|
1057
|
+
if (x.onOrigin)
|
|
1058
|
+
console.log(
|
|
1059
|
+
` origin/${x.branch} is still on origin (git push origin --delete ${x.branch} removes it)`,
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
for (const x of r.skipped) console.log(`${x.repo}: ${x.why}`);
|
|
1063
|
+
for (const x of r.restacked)
|
|
1064
|
+
console.log(`${x.repo}: ${x.branch} now counts against ${x.base}`);
|
|
1065
|
+
for (const x of r.refused) console.log(`${x.repo}: ${x.why}`);
|
|
1066
|
+
if (r.refused.length)
|
|
1067
|
+
console.log(
|
|
1068
|
+
`nothing dropped${ctx.yes ? "" : `: pass --yes to drop it anyway (its tip and uncommitted changes are kept ${KEEP_DROPPED_DAYS} days)`}`,
|
|
1069
|
+
);
|
|
1070
|
+
});
|
|
1071
|
+
if (result.refused.length) process.exitCode = 1;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
687
1074
|
// -- command -----------------------------------------------------------------
|
|
688
1075
|
|
|
689
1076
|
const HELP = `work topic new <name> [--repo <repo>]… [--from <ref>] [--install]
|
|
@@ -703,17 +1090,27 @@ work topic list [--all] [--fresh] [--json]
|
|
|
703
1090
|
answer.
|
|
704
1091
|
work topic done <name> [--rebase] [--json]
|
|
705
1092
|
after its PR merged, or once its base holds all of it (merged there
|
|
706
|
-
by hand, say)
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
1093
|
+
by hand, say) or all of its changes by other commits (squashed into
|
|
1094
|
+
another PR, cherry-picked): fetch --prune, remove its worktree (only
|
|
1095
|
+
if clean, and only if the merge took every commit), keep the branch,
|
|
1096
|
+
and list the other open topics to rebase, each onto its own base — one
|
|
1097
|
+
stacked on this topic onto this one's, which becomes its base.
|
|
1098
|
+
--rebase does it where the worktree is clean, aborting on conflict.
|
|
1099
|
+
Never touches the workspace's own checkout.
|
|
1100
|
+
work topic drop <name> [--yes] [--json]
|
|
1101
|
+
abandon a topic: remove its worktree and delete its local branch,
|
|
1102
|
+
keeping its tip (with any uncommitted changes) as
|
|
1103
|
+
refs/work-dropped/<branch>/<when> for ${KEEP_DROPPED_DAYS} days; the output says how to
|
|
1104
|
+
bring it back. Refuses, unless --yes, whatever would discard work:
|
|
1105
|
+
commits whose changes its base lacks (and which of them no remote has),
|
|
1106
|
+
uncommitted changes, a session working in it, a topic stacked on it, an
|
|
1107
|
+
open PR. Origin's copy and any PR are left as they are. Never touches
|
|
1108
|
+
the workspace's own checkout.`;
|
|
712
1109
|
|
|
713
1110
|
export const commands = [
|
|
714
1111
|
{
|
|
715
1112
|
name: "topic",
|
|
716
|
-
summary: "start, list
|
|
1113
|
+
summary: "start, list, put away and drop topic branches (work help topic)",
|
|
717
1114
|
help: HELP,
|
|
718
1115
|
async run(ctx) {
|
|
719
1116
|
const [verb] = ctx.positional;
|
|
@@ -725,11 +1122,12 @@ export const commands = [
|
|
|
725
1122
|
if (verb === "list" || verb === "ls" || !verb)
|
|
726
1123
|
return await topicList(sub);
|
|
727
1124
|
if (verb === "done") return await topicDone(sub);
|
|
1125
|
+
if (verb === "drop") return await topicDrop(sub);
|
|
728
1126
|
} catch (err) {
|
|
729
1127
|
ctx.die(err instanceof Error ? err.message : String(err));
|
|
730
1128
|
}
|
|
731
1129
|
ctx.die(
|
|
732
|
-
`no \`work topic ${verb}\`: new, list or
|
|
1130
|
+
`no \`work topic ${verb}\`: new, list, done or drop (see: work help topic)`,
|
|
733
1131
|
);
|
|
734
1132
|
},
|
|
735
1133
|
},
|