@dylanpiercey/work 0.2.68 → 0.2.70
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/topic.mjs +374 -23
- package/dist/_B25P__C4.js +2 -0
- package/dist/{_iwl-plYP.js → _COL0wji1.js} +113 -113
- package/dist/{_D3vayu01.js → _CSFzm8Kj.js} +1 -1
- package/dist/{_KNWFiRfu.js → _DK0sGNuL.js} +341 -17
- package/dist/_wbrwjNyW.js +2 -0
- package/dist/index.mjs +906 -868
- package/dist/public/assets/{_wvT-w49n.js → _0NYkT7Ka.js} +1 -1
- package/dist/public/assets/_0NYkT7Ka.js.br +0 -0
- package/dist/public/assets/_18ckOF7L.js +1 -0
- package/dist/public/assets/_25qbKqTG.js +1 -0
- package/dist/public/assets/{_CcA9L8Uv.js → _6R8pHfHu.js} +1 -1
- package/dist/public/assets/_6R8pHfHu.js.br +0 -0
- package/dist/public/assets/_8cC5eK8l.js +1 -0
- package/dist/public/assets/_8eN6y624.js +1 -0
- package/dist/public/assets/_8eN6y624.js.br +0 -0
- package/dist/public/assets/_9-vCfD1H.js +1 -0
- package/dist/public/assets/_9PSE1hBd.js +1 -0
- package/dist/public/assets/{_BpXuBLlJ.js → _B-ItC5A4.js} +1 -1
- package/dist/public/assets/_B-ItC5A4.js.br +0 -0
- package/dist/public/assets/{_Dr-IU6HK.js → _B-IuONfT.js} +5 -5
- package/dist/public/assets/_B-IuONfT.js.br +0 -0
- package/dist/public/assets/_B-Nak9W-.js +1 -0
- package/dist/public/assets/_B-Nak9W-.js.br +0 -0
- package/dist/public/assets/_B0vuJGqQ.js +1 -0
- package/dist/public/assets/{_BKxZiX8Y.js → _B24stjuF.js} +5 -5
- package/dist/public/assets/_B24stjuF.js.br +0 -0
- package/dist/public/assets/_B2HaD9d5.js +1 -0
- package/dist/public/assets/{_CDUHEtRr.js → _B3B2tRvZ.js} +1 -1
- package/dist/public/assets/_B3B2tRvZ.js.br +0 -0
- package/dist/public/assets/_B4oiI3_4.js +1 -0
- package/dist/public/assets/_B5CpgKE4.js +1 -0
- package/dist/public/assets/_B7Rpwq9e.js +1 -0
- package/dist/public/assets/{_Cv3jQpwd.js → _B7THbxch.js} +1 -1
- package/dist/public/assets/_B7THbxch.js.br +0 -0
- package/dist/public/assets/{_CHyLG_jb.js → _B9BZLh7B.js} +1 -1
- package/dist/public/assets/_B9BZLh7B.js.br +0 -0
- package/dist/public/assets/{_Cd0WqXuH.js → _B9_Lal-7.js} +1 -1
- package/dist/public/assets/_B9_Lal-7.js.br +0 -0
- package/dist/public/assets/{_CWUZ37Z2.js → _BC-QJfsn.js} +1 -1
- package/dist/public/assets/_BC-QJfsn.js.br +0 -0
- package/dist/public/assets/{_Cn1d1sxS.js → _BC1pxNUd.js} +1 -1
- package/dist/public/assets/_BC1pxNUd.js.br +0 -0
- package/dist/public/assets/{_BWcGdDBZ.js → _BC7rcYFE.js} +1 -1
- package/dist/public/assets/_BC7rcYFE.js.br +0 -0
- package/dist/public/assets/{_DPT6h_sp.js → _BCgm7As-.js} +1 -1
- package/dist/public/assets/_BCgm7As-.js.br +0 -0
- package/dist/public/assets/{_BmgC95YK.js → _BDmhvLCs.js} +1 -1
- package/dist/public/assets/_BDmhvLCs.js.br +0 -0
- package/dist/public/assets/{_BDJY1Xd1.js → _BEO7OuGG.js} +2 -2
- package/dist/public/assets/_BEO7OuGG.js.br +0 -0
- package/dist/public/assets/{_BtZdp5Pb.js → _BEg-5EkS.js} +1 -1
- package/dist/public/assets/_BEg-5EkS.js.br +0 -0
- package/dist/public/assets/_BFTxeP-D.js +1 -0
- package/dist/public/assets/_BGCoTA5R.js +1 -0
- package/dist/public/assets/{_CpU0Rdtw.js → _BJHD6sFy.js} +1 -1
- package/dist/public/assets/_BJHD6sFy.js.br +0 -0
- package/dist/public/assets/_BJeQROi4.js +1 -0
- package/dist/public/assets/_BJeQROi4.js.br +0 -0
- package/dist/public/assets/_BKDJIaLf.js +1 -0
- package/dist/public/assets/{_Dju_1f03.js → _BM9h7XBb.js} +1 -1
- package/dist/public/assets/_BM9h7XBb.js.br +0 -0
- package/dist/public/assets/{_Dqo4vWfH.js → _BNlAaEUI.js} +1 -1
- package/dist/public/assets/_BNlAaEUI.js.br +0 -0
- package/dist/public/assets/{_DWu6n0v3.js → _BOmZO9bQ.js} +1 -1
- package/dist/public/assets/_BOmZO9bQ.js.br +0 -0
- package/dist/public/assets/{_CI7eaQDi.js → _BQvedQNA.js} +1 -1
- package/dist/public/assets/_BQvedQNA.js.br +0 -0
- package/dist/public/assets/{_BByUXZCR.js → _BTJ4QNYJ.js} +1 -1
- package/dist/public/assets/_BTJ4QNYJ.js.br +0 -0
- package/dist/public/assets/_BUnVFLfD.js +1 -0
- package/dist/public/assets/{_DM3cX6sN.js → _BUpeVCdC.js} +1 -1
- package/dist/public/assets/_BUpeVCdC.js.br +0 -0
- package/dist/public/assets/{_CrHoYLWK.js → _BVIQdL1e.js} +1 -1
- package/dist/public/assets/_BVIQdL1e.js.br +0 -0
- package/dist/public/assets/{_TY_Pdc3F.js → _BVN5lLXw.js} +1 -1
- package/dist/public/assets/_BVN5lLXw.js.br +0 -0
- package/dist/public/assets/{_RyUSIajb.js → _BVOoaIUz.js} +1 -1
- package/dist/public/assets/_BVOoaIUz.js.br +0 -0
- package/dist/public/assets/_BYd6ll6G.js +1 -0
- package/dist/public/assets/_BZnPwq2i.js +1 -0
- package/dist/public/assets/{_kdC_mk_s.js → _BaULj7kH.js} +1 -1
- package/dist/public/assets/_BaULj7kH.js.br +0 -0
- package/dist/public/assets/_BbdvSQaN.js +1 -0
- package/dist/public/assets/{_BTK0j-x0.js → _BjJMzhJj.js} +1 -1
- package/dist/public/assets/_BjJMzhJj.js.br +0 -0
- package/dist/public/assets/_BkFty1Oi.js +1 -0
- package/dist/public/assets/{_BGVrbRXU.js → _BmAd0-4z.js} +1 -1
- package/dist/public/assets/{_CjsopDcM.js → _Bo5sqml-.js} +1 -1
- package/dist/public/assets/_BryOeCV4.js +1 -0
- package/dist/public/assets/_BtAYOnhU.js +1 -0
- package/dist/public/assets/{_D46vZBR0.js → _BvDvgf2D.js} +1 -1
- package/dist/public/assets/_BvDvgf2D.js.br +0 -0
- package/dist/public/assets/{_CTwtnjHT.js → _Bwj1cG6Z.js} +1 -1
- package/dist/public/assets/_Bwj1cG6Z.js.br +0 -0
- package/dist/public/assets/{_LDz6VXdO.js → _Bwl5RU7m.js} +1 -1
- package/dist/public/assets/_Bwl5RU7m.js.br +0 -0
- package/dist/public/assets/_Bx7eXUeM.js +1 -0
- package/dist/public/assets/_Bxw4J8BV.js +1 -0
- package/dist/public/assets/{_CWw2xrr5.js → _BzDLIQE5.js} +1 -1
- package/dist/public/assets/_BzDLIQE5.js.br +0 -0
- package/dist/public/assets/_BzvCB8DB.js +1 -0
- package/dist/public/assets/_C-9WWLQ3.js +1 -0
- package/dist/public/assets/_C-_bdY5V.js +1 -0
- package/dist/public/assets/{_DyYt1xor.js → _C0zpPwSp.js} +1 -1
- package/dist/public/assets/_C0zpPwSp.js.br +0 -0
- package/dist/public/assets/{_CJYGh-X3.js → _C2Tbc73e.js} +1 -1
- package/dist/public/assets/_C2Tbc73e.js.br +0 -0
- package/dist/public/assets/{_uwuCbs_Z.js → _C3RYgw_5.js} +1 -1
- package/dist/public/assets/_C3RYgw_5.js.br +0 -0
- package/dist/public/assets/_C7P0cxfL.js +1 -0
- package/dist/public/assets/_C81AvAMk.js +1 -0
- package/dist/public/assets/{_2WOV-Xxm.js → _C8l-PMHJ.js} +1 -1
- package/dist/public/assets/_C8l-PMHJ.js.br +0 -0
- package/dist/public/assets/{_D7kyaI0s.js → _CAUoTaA1.js} +1 -1
- package/dist/public/assets/_CAUoTaA1.js.br +0 -0
- package/dist/public/assets/{_D8G71X2r.js → _CCTE_j9L.js} +1 -1
- package/dist/public/assets/_CCTE_j9L.js.br +0 -0
- package/dist/public/assets/{_rKxafATp.js → _CDXnpAfh.js} +1 -1
- package/dist/public/assets/_CDXnpAfh.js.br +0 -0
- package/dist/public/assets/_CEWoPra5.js +1 -0
- package/dist/public/assets/{_C8Nimh8k.js → _CGSo9tnY.js} +2 -2
- package/dist/public/assets/_CGSo9tnY.js.br +0 -0
- package/dist/public/assets/_CGsbbcpE.js +1 -0
- package/dist/public/assets/{_DA-5OGva.js → _CHuWNcjJ.js} +1 -1
- package/dist/public/assets/_CHuWNcjJ.js.br +0 -0
- package/dist/public/assets/_CI0KXyAu.js +1 -0
- package/dist/public/assets/{_Cs2Zd8pI.js → _CI8Dmpt-.js} +1 -1
- package/dist/public/assets/_CI8Dmpt-.js.br +0 -0
- package/dist/public/assets/_CKmnCHzt.js +1 -0
- package/dist/public/assets/_CNY02rQP.js +1 -0
- package/dist/public/assets/{_BiHBXSk1.js → _COjB6Mds.js} +1 -1
- package/dist/public/assets/_COjB6Mds.js.br +0 -0
- package/dist/public/assets/_CPGWIVjG.js +1 -0
- package/dist/public/assets/_CQ0SDG17.js +1 -0
- package/dist/public/assets/{_BdeQis2A.js → _CWmrlUIL.js} +1 -1
- package/dist/public/assets/_CWmrlUIL.js.br +0 -0
- package/dist/public/assets/{_CHy8Yzm5.js → _CXLLGxAE.js} +4 -4
- package/dist/public/assets/_CXLLGxAE.js.br +0 -0
- package/dist/public/assets/_CXciWQH3.js +1 -0
- package/dist/public/assets/_CXjFOElm.js +1 -0
- package/dist/public/assets/{_BWZsCsQQ.js → _CbzlAKJK.js} +1 -1
- package/dist/public/assets/_CbzlAKJK.js.br +0 -0
- package/dist/public/assets/{_BpDpZv1R.js → _CcLifUnb.js} +1 -1
- package/dist/public/assets/_CcLifUnb.js.br +0 -0
- package/dist/public/assets/{_-mM4yo3H.js → _CcbgX86v.js} +1 -1
- package/dist/public/assets/_CcbgX86v.js.br +0 -0
- package/dist/public/assets/{_C_VkFQv_.js → _CdDgM-x6.js} +1 -1
- package/dist/public/assets/_CdDgM-x6.js.br +0 -0
- package/dist/public/assets/_Ce53vsUM.js +1 -0
- package/dist/public/assets/_CgdBa1Kb.js +1 -0
- package/dist/public/assets/_ChxOfm1L.js +1 -0
- package/dist/public/assets/{_CLWpBKoo.js → _Ck0GxYNQ.js} +1 -1
- package/dist/public/assets/_Ck0GxYNQ.js.br +0 -0
- package/dist/public/assets/_CmIuIy4h.js +1 -0
- package/dist/public/assets/{_CRd8czom.js → _Cp-ZKt1Y.js} +1 -1
- package/dist/public/assets/_Cp-ZKt1Y.js.br +0 -0
- package/dist/public/assets/{_DTseWZHC.js → _CrEFB_dj.js} +1 -1
- package/dist/public/assets/_CrEFB_dj.js.br +0 -0
- package/dist/public/assets/{_zuaxHefE.js → _Cu31pL3p.js} +1 -1
- package/dist/public/assets/_CwaUSclh.js +1 -0
- package/dist/public/assets/_Cy9eBufF.js +1 -0
- package/dist/public/assets/_CynmXPn2.js +1 -0
- package/dist/public/assets/{_DHOPvA0j.js → _CzBug9-x.js} +1 -1
- package/dist/public/assets/_CzBug9-x.js.br +0 -0
- package/dist/public/assets/{_B60HnTYs.js → _Cznq4Aee.js} +1 -1
- package/dist/public/assets/{_D67YJBwp.js → _D-6O7MKA.js} +1 -1
- package/dist/public/assets/_D-6O7MKA.js.br +0 -0
- package/dist/public/assets/_D-JhJZ2C.js +1 -0
- package/dist/public/assets/{_BtEy3x8_.js → _D-XHmBJj.js} +1 -1
- package/dist/public/assets/_D-XHmBJj.js.br +0 -0
- package/dist/public/assets/_D-neGx47.js +1 -0
- package/dist/public/assets/_D5VJGdAr.js +1 -0
- package/dist/public/assets/_D6u72i8c.js +1 -0
- package/dist/public/assets/_D8tbv6WM.js +1 -0
- package/dist/public/assets/{_DfZ3Abt5.js → _DA6CNMAS.js} +1 -1
- package/dist/public/assets/_DA6CNMAS.js.br +0 -0
- package/dist/public/assets/_DDD7aRxr.js +1 -0
- package/dist/public/assets/_DFCbdJTU.js +1 -0
- package/dist/public/assets/{_ZDh1oKQp.js → _DGyB0J_Z.js} +1 -1
- package/dist/public/assets/_DGyB0J_Z.js.br +0 -0
- package/dist/public/assets/{_BoQsdJdV.js → _DJNoam7G.js} +1 -1
- package/dist/public/assets/_DJNoam7G.js.br +0 -0
- package/dist/public/assets/{_F61IFRtr.js → _DKgv7Cyq.js} +1 -1
- package/dist/public/assets/_DKgv7Cyq.js.br +0 -0
- package/dist/public/assets/{_D9YIljl9.js → _DM2ZsY5Z.js} +1 -1
- package/dist/public/assets/_DM2ZsY5Z.js.br +0 -0
- package/dist/public/assets/{_DgHgR-hZ.js → _DO7dqRyj.js} +1 -1
- package/dist/public/assets/_DO7dqRyj.js.br +0 -0
- package/dist/public/assets/{_D-1h5Hss.js → _DORBDQxD.js} +1 -1
- package/dist/public/assets/_DORBDQxD.js.br +0 -0
- package/dist/public/assets/_DOsfhfso.js +1 -0
- package/dist/public/assets/_DRC6uiX0.js +1 -0
- package/dist/public/assets/_DSWmTo1L.js +1 -0
- package/dist/public/assets/{_C--f0OAN.js → _DU8DeX60.js} +1 -1
- package/dist/public/assets/_DU8DeX60.js.br +0 -0
- package/dist/public/assets/_DUKZkilh.js +1 -0
- package/dist/public/assets/{_CCAfK1VU.js → _DWCS2CFQ.js} +1 -1
- package/dist/public/assets/_DWCS2CFQ.js.br +0 -0
- package/dist/public/assets/_DWnX1Z3a.js +1 -0
- package/dist/public/assets/_DX71QHMR.js +1 -0
- package/dist/public/assets/{_pthxQoj7.js → _DZ0rqa0h.js} +1 -1
- package/dist/public/assets/_DZ0rqa0h.js.br +0 -0
- package/dist/public/assets/{_DDmNNj38.js → _D_TuAhnN.js} +1 -1
- package/dist/public/assets/_D_TuAhnN.js.br +0 -0
- package/dist/public/assets/_D_rLfkXR.js +1 -0
- package/dist/public/assets/_DeBbHTQf.js +1 -0
- package/dist/public/assets/_Dkm85KJF.js +1 -0
- package/dist/public/assets/{_DdnBcgjI.js → _Dml0472r.js} +1 -1
- package/dist/public/assets/_Dml0472r.js.br +0 -0
- package/dist/public/assets/{_BEhDrcww.js → _DouCdQ99.js} +1 -1
- package/dist/public/assets/{_CZa0gQzH.js → _DroY8_no.js} +1 -1
- package/dist/public/assets/_DroY8_no.js.br +0 -0
- package/dist/public/assets/_DtYahvpQ.js +1 -0
- package/dist/public/assets/{_Dzr8Nbyu.js → _DuaSYpQG.js} +1 -1
- package/dist/public/assets/_DuaSYpQG.js.br +0 -0
- package/dist/public/assets/{_SH68xtR9.js → _DuuP0rKI.js} +1 -1
- package/dist/public/assets/_DuuP0rKI.js.br +0 -0
- package/dist/public/assets/{_0L7GeCf8.js → _DyFziHLM.js} +1 -1
- package/dist/public/assets/_DyFziHLM.js.br +0 -0
- package/dist/public/assets/_Dz3s4MY0.js +1 -0
- package/dist/public/assets/_Dz3s4MY0.js.br +0 -0
- package/dist/public/assets/_DzZaUh6D.js +1 -0
- package/dist/public/assets/_DzhUXE8_.js +1 -0
- package/dist/public/assets/_GWc0eYhN.js +1 -0
- package/dist/public/assets/{_BL5Y2CUw.js → _H1xilHgC.js} +1 -1
- package/dist/public/assets/_H1xilHgC.js.br +0 -0
- package/dist/public/assets/{_Bd9f_2h4.js → _HNyiv6zs.js} +1 -1
- package/dist/public/assets/_HNyiv6zs.js.br +0 -0
- package/dist/public/assets/{_D-jzW1eS.js → _HlactPnQ.js} +1 -1
- package/dist/public/assets/_HlactPnQ.js.br +0 -0
- package/dist/public/assets/{_2xmggEiI.js → _JMrxKBGN.js} +1 -1
- package/dist/public/assets/_JMrxKBGN.js.br +0 -0
- package/dist/public/assets/{_DTQWFGgt.js → _JSiyuxRJ.js} +1 -1
- package/dist/public/assets/_JSiyuxRJ.js.br +0 -0
- package/dist/public/assets/{_DMsquaig.js → _JcvJ5ACW.js} +1 -1
- package/dist/public/assets/_JcvJ5ACW.js.br +0 -0
- package/dist/public/assets/{_PMnGojaw.js → _L2f5JNlj.js} +1 -1
- package/dist/public/assets/_L2f5JNlj.js.br +0 -0
- package/dist/public/assets/_LrU9RmZE.js +1 -0
- package/dist/public/assets/{_DAt5J6M_.js → _Mt6ebGGE.js} +10 -10
- package/dist/public/assets/_Mt6ebGGE.js.br +0 -0
- package/dist/public/assets/_Owc9jhpW.js +2 -0
- package/dist/public/assets/_Owc9jhpW.js.br +0 -0
- package/dist/public/assets/_PevhFQ5V.js +1 -0
- package/dist/public/assets/_R1tJA-Qg.js +1 -0
- package/dist/public/assets/{_DHQVtSUu.js → _REcALhmt.js} +1 -1
- package/dist/public/assets/_REcALhmt.js.br +0 -0
- package/dist/public/assets/{_BFlHBfEr.js → _TZpNJCj6.js} +1 -1
- package/dist/public/assets/_TZpNJCj6.js.br +0 -0
- package/dist/public/assets/_VDsjaeWW.js +1 -0
- package/dist/public/assets/{_DtsqwD_h.js → _VgS7WPcA.js} +1 -1
- package/dist/public/assets/_VgS7WPcA.js.br +0 -0
- package/dist/public/assets/_WekB6aHl.js +1 -0
- package/dist/public/assets/_X4dvLi1w.js +1 -0
- package/dist/public/assets/_XXcCKG6W.js +1 -0
- package/dist/public/assets/_Y4miPos6.js +1 -0
- package/dist/public/assets/{_CbkvJoJj.js → _YATrYiFD.js} +1 -1
- package/dist/public/assets/_YATrYiFD.js.br +0 -0
- package/dist/public/assets/{_DBn4INpY.js → _YC0QGp9j.js} +1 -1
- package/dist/public/assets/_YC0QGp9j.js.br +0 -0
- package/dist/public/assets/_YG1qePV2.js +1 -0
- package/dist/public/assets/_Yiwgrm_C.js +1 -0
- package/dist/public/assets/{_BSZnP2C1.js → __favRwtg.js} +1 -1
- package/dist/public/assets/__favRwtg.js.br +0 -0
- package/dist/public/assets/_b0whjSZe.js +1 -0
- package/dist/public/assets/_cw5fHxTz.js +1 -0
- package/dist/public/assets/_gSyGU-mq.js +1 -0
- package/dist/public/assets/_j5nRBBVa.js +1 -0
- package/dist/public/assets/{_8KVmX-ec.js → _jFGgKTYj.js} +1 -1
- package/dist/public/assets/_jFGgKTYj.js.br +0 -0
- package/dist/public/assets/{_BmhJ-bQi.js → _kkbInDpy.js} +1 -1
- package/dist/public/assets/_kkbInDpy.js.br +0 -0
- package/dist/public/assets/_mrvWutef.js +1 -0
- package/dist/public/assets/_nCxsopgT.js +1 -0
- package/dist/public/assets/_pwbytP5z.js +1 -0
- package/dist/public/assets/{_Be760Oeq.js → _sTT2iThd.js} +1 -1
- package/dist/public/assets/_sTT2iThd.js.br +0 -0
- package/dist/public/assets/{_Xei7jbG-.js → _tGE7SNww.js} +1 -1
- package/dist/public/assets/_tGE7SNww.js.br +0 -0
- package/dist/public/assets/_veyGCfhb.js +1 -0
- package/dist/public/assets/{_7kj3hOfH.js → _vfD02BWU.js} +1 -1
- package/dist/public/assets/_vfD02BWU.js.br +0 -0
- package/dist/public/assets/files-view-_b8IktQV.js +2 -0
- package/dist/public/assets/manage-workspace-Bu8_bkKy.js +2 -0
- package/dist/public/assets/new-CGbC3Rki.js +1 -0
- package/dist/public/assets/new-workspace-BPq4RG6p.js +2 -0
- package/dist/public/assets/review-view-Dwph1tIy.js +2 -0
- package/dist/public/assets/settings-CGbC3Rki.js +1 -0
- package/dist/public/assets/settings-page-DfjJBEV4.js +2 -0
- package/dist/public/assets/styles-DmUe5O9c.css +1 -0
- package/dist/public/assets/styles-DmUe5O9c.css.br +0 -0
- package/dist/public/assets/w-CGbC3Rki.js +1 -0
- package/dist/public/assets/w._-BdlGa_yr.js +1 -0
- package/dist/public/assets/w._-CGbC3Rki.js +1 -0
- package/dist/public/assets/w._-Cq1MaRMF.js +1 -0
- package/package.json +1 -1
- package/dist/_tFH4KiOy.js +0 -2
- package/dist/_xm4j4quQ.js +0 -2
- package/dist/public/assets/_-mM4yo3H.js.br +0 -0
- package/dist/public/assets/_0L7GeCf8.js.br +0 -0
- package/dist/public/assets/_2WOV-Xxm.js.br +0 -0
- package/dist/public/assets/_2xmggEiI.js.br +0 -0
- package/dist/public/assets/_5LaG-HZE.js +0 -1
- package/dist/public/assets/_7QNxfo9o.js +0 -1
- package/dist/public/assets/_7kj3hOfH.js.br +0 -0
- package/dist/public/assets/_8AEeEwwI.js +0 -1
- package/dist/public/assets/_8KVmX-ec.js.br +0 -0
- package/dist/public/assets/_B1J5kQMX.js +0 -1
- package/dist/public/assets/_B1ZJGMvk.js +0 -1
- package/dist/public/assets/_B3DCz1-b.js +0 -1
- package/dist/public/assets/_B3DCz1-b.js.br +0 -0
- package/dist/public/assets/_BAD_W-gb.js +0 -1
- package/dist/public/assets/_BByUXZCR.js.br +0 -0
- package/dist/public/assets/_BDJY1Xd1.js.br +0 -0
- package/dist/public/assets/_BFlHBfEr.js.br +0 -0
- package/dist/public/assets/_BG6nf7-6.js +0 -1
- package/dist/public/assets/_BG6nf7-6.js.br +0 -0
- package/dist/public/assets/_BHdwQo1r.js +0 -1
- package/dist/public/assets/_BJz1J7VL.js +0 -1
- package/dist/public/assets/_BKxZiX8Y.js.br +0 -0
- package/dist/public/assets/_BL5Y2CUw.js.br +0 -0
- package/dist/public/assets/_BOA9wu9y.js +0 -1
- package/dist/public/assets/_BQ6HGMiz.js +0 -1
- package/dist/public/assets/_BSZnP2C1.js.br +0 -0
- package/dist/public/assets/_BTK0j-x0.js.br +0 -0
- package/dist/public/assets/_BWZsCsQQ.js.br +0 -0
- package/dist/public/assets/_BWcGdDBZ.js.br +0 -0
- package/dist/public/assets/_BX6XuUUI.js +0 -1
- package/dist/public/assets/_BYImhKdQ.js +0 -1
- package/dist/public/assets/_Bcog8Mvw.js +0 -1
- package/dist/public/assets/_Bd9f_2h4.js.br +0 -0
- package/dist/public/assets/_BdViCDP-.js +0 -1
- package/dist/public/assets/_BdeQis2A.js.br +0 -0
- package/dist/public/assets/_Be760Oeq.js.br +0 -0
- package/dist/public/assets/_Bf8StQtP.js +0 -1
- package/dist/public/assets/_BgqsGerF.js +0 -1
- package/dist/public/assets/_BiHBXSk1.js.br +0 -0
- package/dist/public/assets/_Bic7QDJn.js +0 -1
- package/dist/public/assets/_Bje2UlWb.js +0 -1
- package/dist/public/assets/_BmgC95YK.js.br +0 -0
- package/dist/public/assets/_BmhJ-bQi.js.br +0 -0
- package/dist/public/assets/_BnQVcrhX.js +0 -1
- package/dist/public/assets/_BoQsdJdV.js.br +0 -0
- package/dist/public/assets/_BoTUkl_N.js +0 -1
- package/dist/public/assets/_BpDpZv1R.js.br +0 -0
- package/dist/public/assets/_BpGZbbmD.js +0 -1
- package/dist/public/assets/_BpXuBLlJ.js.br +0 -0
- package/dist/public/assets/_BsRfLR4Y.js +0 -1
- package/dist/public/assets/_BtEy3x8_.js.br +0 -0
- package/dist/public/assets/_BtZdp5Pb.js.br +0 -0
- package/dist/public/assets/_BxFn7bBG.js +0 -1
- package/dist/public/assets/_C--f0OAN.js.br +0 -0
- package/dist/public/assets/_C-_4KAMq.js +0 -1
- package/dist/public/assets/_C3lI_Twn.js +0 -1
- package/dist/public/assets/_C51h13b-.js +0 -1
- package/dist/public/assets/_C8Nimh8k.js.br +0 -0
- package/dist/public/assets/_C9UFsOy1.js +0 -1
- package/dist/public/assets/_CBK_SY_j.js +0 -1
- package/dist/public/assets/_CCAfK1VU.js.br +0 -0
- package/dist/public/assets/_CCw4Mih7.js +0 -1
- package/dist/public/assets/_CDUHEtRr.js.br +0 -0
- package/dist/public/assets/_CHy8Yzm5.js.br +0 -0
- package/dist/public/assets/_CHyLG_jb.js.br +0 -0
- package/dist/public/assets/_CI7eaQDi.js.br +0 -0
- package/dist/public/assets/_CIwfNMk3.js +0 -1
- package/dist/public/assets/_CJYGh-X3.js.br +0 -0
- package/dist/public/assets/_CLWpBKoo.js.br +0 -0
- package/dist/public/assets/_CPlovKCM.js +0 -1
- package/dist/public/assets/_CQDgAaDD.js +0 -1
- package/dist/public/assets/_CRd8czom.js.br +0 -0
- package/dist/public/assets/_CTwtnjHT.js.br +0 -0
- package/dist/public/assets/_CWUZ37Z2.js.br +0 -0
- package/dist/public/assets/_CWYdWpGf.js +0 -1
- package/dist/public/assets/_CWw2xrr5.js.br +0 -0
- package/dist/public/assets/_CZa0gQzH.js.br +0 -0
- package/dist/public/assets/_C_VkFQv_.js.br +0 -0
- package/dist/public/assets/_Cb5fameO.js +0 -1
- package/dist/public/assets/_Cb5znfXe.js +0 -1
- package/dist/public/assets/_CbkvJoJj.js.br +0 -0
- package/dist/public/assets/_CcA9L8Uv.js.br +0 -0
- package/dist/public/assets/_CcmYHRo2.js +0 -1
- package/dist/public/assets/_Cd0WqXuH.js.br +0 -0
- package/dist/public/assets/_Ci9OrA31.js +0 -1
- package/dist/public/assets/_CigEUN1Y.js +0 -1
- package/dist/public/assets/_CmCzrX8O.js +0 -1
- package/dist/public/assets/_Cn1d1sxS.js.br +0 -0
- package/dist/public/assets/_CpU0Rdtw.js.br +0 -0
- package/dist/public/assets/_CrHoYLWK.js.br +0 -0
- package/dist/public/assets/_CrLAwqeM.js +0 -1
- package/dist/public/assets/_Cs2Zd8pI.js.br +0 -0
- package/dist/public/assets/_Cs5YLsyh.js +0 -1
- package/dist/public/assets/_Cskv-lte.js +0 -1
- package/dist/public/assets/_CuZT7B5b.js +0 -1
- package/dist/public/assets/_Cv3jQpwd.js.br +0 -0
- package/dist/public/assets/_CzKQcLq6.js +0 -1
- package/dist/public/assets/_D-1h5Hss.js.br +0 -0
- package/dist/public/assets/_D-jzW1eS.js.br +0 -0
- package/dist/public/assets/_D3R3E-lW.js +0 -1
- package/dist/public/assets/_D3t8fBvV.js +0 -1
- package/dist/public/assets/_D46vZBR0.js.br +0 -0
- package/dist/public/assets/_D5_5gquy.js +0 -1
- package/dist/public/assets/_D624R74e.js +0 -1
- package/dist/public/assets/_D67YJBwp.js.br +0 -0
- package/dist/public/assets/_D7kyaI0s.js.br +0 -0
- package/dist/public/assets/_D8G71X2r.js.br +0 -0
- package/dist/public/assets/_D8mUHp4g.js +0 -1
- package/dist/public/assets/_D9YIljl9.js.br +0 -0
- package/dist/public/assets/_DA-5OGva.js.br +0 -0
- package/dist/public/assets/_DAt5J6M_.js.br +0 -0
- package/dist/public/assets/_DBn4INpY.js.br +0 -0
- package/dist/public/assets/_DBqrfSYd.js +0 -1
- package/dist/public/assets/_DDmNNj38.js.br +0 -0
- package/dist/public/assets/_DGF9MW5D.js +0 -1
- package/dist/public/assets/_DHOPvA0j.js.br +0 -0
- package/dist/public/assets/_DHQVtSUu.js.br +0 -0
- package/dist/public/assets/_DHTvNsC9.js +0 -1
- package/dist/public/assets/_DHafZUX3.js +0 -1
- package/dist/public/assets/_DM3cX6sN.js.br +0 -0
- package/dist/public/assets/_DMsquaig.js.br +0 -0
- package/dist/public/assets/_DNiHEIwz.js +0 -1
- package/dist/public/assets/_DPT6h_sp.js.br +0 -0
- package/dist/public/assets/_DQaRo0_Z.js +0 -1
- package/dist/public/assets/_DSjhAsHE.js +0 -1
- package/dist/public/assets/_DTQWFGgt.js.br +0 -0
- package/dist/public/assets/_DTseWZHC.js.br +0 -0
- package/dist/public/assets/_DULNepbq.js +0 -2
- package/dist/public/assets/_DULNepbq.js.br +0 -0
- package/dist/public/assets/_DVmk0cGb.js +0 -1
- package/dist/public/assets/_DVu8SG8S.js +0 -1
- package/dist/public/assets/_DWu6n0v3.js.br +0 -0
- package/dist/public/assets/_DYIJgXao.js +0 -1
- package/dist/public/assets/_DcDp1vYe.js +0 -1
- package/dist/public/assets/_DdnBcgjI.js.br +0 -0
- package/dist/public/assets/_DeqyAtmP.js +0 -1
- package/dist/public/assets/_DfZ3Abt5.js.br +0 -0
- package/dist/public/assets/_DgHgR-hZ.js.br +0 -0
- package/dist/public/assets/_Dhk4fgzB.js +0 -1
- package/dist/public/assets/_DiNKSmxI.js +0 -1
- package/dist/public/assets/_DiUWhWrq.js +0 -1
- package/dist/public/assets/_Dj1leKJH.js +0 -1
- package/dist/public/assets/_DjpGYd1p.js +0 -1
- package/dist/public/assets/_Dju_1f03.js.br +0 -0
- package/dist/public/assets/_DmGRSsUt.js +0 -1
- package/dist/public/assets/_Dqo4vWfH.js.br +0 -0
- package/dist/public/assets/_Dr-IU6HK.js.br +0 -0
- package/dist/public/assets/_DrqKhRAQ.js +0 -1
- package/dist/public/assets/_DtsqwD_h.js.br +0 -0
- package/dist/public/assets/_DyYt1xor.js.br +0 -0
- package/dist/public/assets/_DzFqbsGy.js +0 -1
- package/dist/public/assets/_Dzr8Nbyu.js.br +0 -0
- package/dist/public/assets/_EaUViMxr.js +0 -1
- package/dist/public/assets/_F61IFRtr.js.br +0 -0
- package/dist/public/assets/_JBpSIlgX.js +0 -1
- package/dist/public/assets/_JoAwMfkR.js +0 -1
- package/dist/public/assets/_LDz6VXdO.js.br +0 -0
- package/dist/public/assets/_Lop0HV3P.js +0 -1
- package/dist/public/assets/_Lop0HV3P.js.br +0 -0
- package/dist/public/assets/_Mg9GxHtB.js +0 -1
- package/dist/public/assets/_NwIYFT5B.js +0 -1
- package/dist/public/assets/_NwIYFT5B.js.br +0 -0
- package/dist/public/assets/_PMnGojaw.js.br +0 -0
- package/dist/public/assets/_RyUSIajb.js.br +0 -0
- package/dist/public/assets/_SH68xtR9.js.br +0 -0
- package/dist/public/assets/_TY_Pdc3F.js.br +0 -0
- package/dist/public/assets/_U6p2S3Z0.js +0 -1
- package/dist/public/assets/_V56TvjWJ.js +0 -1
- package/dist/public/assets/_Xei7jbG-.js.br +0 -0
- package/dist/public/assets/_ZDh1oKQp.js.br +0 -0
- package/dist/public/assets/__rjIklzT.js +0 -1
- package/dist/public/assets/_asNggv5C.js +0 -1
- package/dist/public/assets/_cSxqqciM.js +0 -1
- package/dist/public/assets/_hYHHWgXz.js +0 -1
- package/dist/public/assets/_kdC_mk_s.js.br +0 -0
- package/dist/public/assets/_pthxQoj7.js.br +0 -0
- package/dist/public/assets/_qss_F0VZ.js +0 -1
- package/dist/public/assets/_rKxafATp.js.br +0 -0
- package/dist/public/assets/_uwuCbs_Z.js.br +0 -0
- package/dist/public/assets/_wBNa2EL1.js +0 -1
- package/dist/public/assets/_wvT-w49n.js.br +0 -0
- package/dist/public/assets/files-view-D5Fv0SIK.js +0 -2
- package/dist/public/assets/manage-workspace-Cb9sMIjp.js +0 -2
- package/dist/public/assets/new-5AQb7ar3.js +0 -1
- package/dist/public/assets/new-workspace-o3VxyV3X.js +0 -2
- package/dist/public/assets/review-view-BNRZ1rgz.js +0 -2
- package/dist/public/assets/settings-5AQb7ar3.js +0 -1
- package/dist/public/assets/settings-page-6pXaU21j.js +0 -2
- package/dist/public/assets/styles-6nJ2WylG.css +0 -1
- package/dist/public/assets/styles-6nJ2WylG.css.br +0 -0
- package/dist/public/assets/w-5AQb7ar3.js +0 -1
- package/dist/public/assets/w._-5AQb7ar3.js +0 -1
- package/dist/public/assets/w._-6Uhhy1cN.js +0 -1
- package/dist/public/assets/w._-BdCzUYn6.js +0 -1
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
|
|
@@ -374,6 +397,7 @@ function topicsIn(ws, repo, foreign) {
|
|
|
374
397
|
// What `topic new` recorded for gh: the branch it stacks on, else the
|
|
375
398
|
// repo's base.
|
|
376
399
|
const recorded = mergeBases(repo.dir);
|
|
400
|
+
const dropped = droppedBranches(repo.dir);
|
|
377
401
|
const bases = new Map();
|
|
378
402
|
return [...branches].sort().map((branch) => {
|
|
379
403
|
const name = branch.slice(prefix.length);
|
|
@@ -389,6 +413,7 @@ function topicsIn(ws, repo, foreign) {
|
|
|
389
413
|
: { ahead: null, behind: null };
|
|
390
414
|
const worktree = trees.get(branch) || null;
|
|
391
415
|
const pr = prFor(repo, branch);
|
|
416
|
+
const contained = !!base && ahead === 0;
|
|
392
417
|
return {
|
|
393
418
|
topic: name,
|
|
394
419
|
repo: repo.worktree,
|
|
@@ -424,7 +449,12 @@ function topicsIn(ws, repo, foreign) {
|
|
|
424
449
|
// Nothing of its own past the base: either merged as it was, or a
|
|
425
450
|
// topic with no commits yet. Either way, nothing is lost by
|
|
426
451
|
// putting its worktree away.
|
|
427
|
-
contained
|
|
452
|
+
contained,
|
|
453
|
+
// Commits of its own, but none of its changes the base lacks.
|
|
454
|
+
landed: !!base && !contained && landedIn(repo.dir, base, tip),
|
|
455
|
+
// Dropped here (`topic drop`), its local branch gone: what is left is
|
|
456
|
+
// origin's copy, which drop leaves alone.
|
|
457
|
+
dropped: !local && dropped.has(branch),
|
|
428
458
|
link: link(ws, repo, name),
|
|
429
459
|
};
|
|
430
460
|
});
|
|
@@ -433,9 +463,11 @@ function topicsIn(ws, repo, foreign) {
|
|
|
433
463
|
async function topicList(ctx) {
|
|
434
464
|
const { ws, repos, foreign } = await context(ctx, ctx.has("--fresh"));
|
|
435
465
|
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
|
-
|
|
466
|
+
// Put away: merged (or nothing of it its base lacks) with no worktree
|
|
467
|
+
// left — its branch kept, as the after-merge chores leave it — or dropped
|
|
468
|
+
// here. Listed on asking.
|
|
469
|
+
const away = (t) =>
|
|
470
|
+
t.dropped || (!t.worktree && (t.merged || t.contained || t.landed));
|
|
439
471
|
const rows = ctx.has("--all") ? all : all.filter((t) => !away(t));
|
|
440
472
|
const hidden = all.length - rows.length;
|
|
441
473
|
ctx.out(rows, (list) => {
|
|
@@ -450,7 +482,9 @@ async function topicList(ctx) {
|
|
|
450
482
|
? `no ${t.baseBranch} or origin/${t.baseBranch} here to count against`
|
|
451
483
|
: t.contained
|
|
452
484
|
? `nothing past ${t.base}`
|
|
453
|
-
:
|
|
485
|
+
: t.landed
|
|
486
|
+
? `landed in ${t.base} (by other commits: ${t.ahead} of its own, none of its changes missing there)`
|
|
487
|
+
: `${t.ahead} ahead, ${t.behind} behind ${t.base}`;
|
|
454
488
|
const flags = [
|
|
455
489
|
t.dirty ? `${t.dirty} uncommitted` : null,
|
|
456
490
|
t.local && !t.onOrigin && t.ahead ? "not pushed" : null,
|
|
@@ -458,7 +492,8 @@ async function topicList(ctx) {
|
|
|
458
492
|
t.local && t.onOrigin && !t.unpushed && !t.pushed
|
|
459
493
|
? "origin has newer"
|
|
460
494
|
: null,
|
|
461
|
-
|
|
495
|
+
t.dropped ? "dropped here, origin keeps it" : null,
|
|
496
|
+
!t.local && !t.dropped ? "only on origin" : null,
|
|
462
497
|
].filter(Boolean);
|
|
463
498
|
const pr = t.pr
|
|
464
499
|
? ` #${t.pr.number} ${t.pr.state === "OPEN" ? (t.pr.draft ? "draft" : "open") : t.pr.state.toLowerCase()}`
|
|
@@ -471,7 +506,7 @@ async function topicList(ctx) {
|
|
|
471
506
|
}
|
|
472
507
|
if (hidden)
|
|
473
508
|
console.log(
|
|
474
|
-
`${hidden} put away (merged
|
|
509
|
+
`${hidden} put away (merged or landed with its worktree removed, or dropped): --all lists them`,
|
|
475
510
|
);
|
|
476
511
|
});
|
|
477
512
|
}
|
|
@@ -483,7 +518,7 @@ async function topicList(ctx) {
|
|
|
483
518
|
* PR's head, or past what origin has of it. */
|
|
484
519
|
function leftover(repo, t, pr) {
|
|
485
520
|
const local = oid(repo.dir, `refs/heads/${t.branch}`);
|
|
486
|
-
if (!local || t.contained) return null;
|
|
521
|
+
if (!local || t.contained || t.landed) return null;
|
|
487
522
|
let head = pr?.headRefOid || null;
|
|
488
523
|
if (head && !has(repo.dir, `${head}^{commit}`)) {
|
|
489
524
|
// A squash-merged PR's head lives on in GitHub's pull ref.
|
|
@@ -532,15 +567,18 @@ async function topicDone(ctx) {
|
|
|
532
567
|
const t = topicsIn(ws, repo, foreign).find((x) => x.branch === branch);
|
|
533
568
|
if (!t) continue;
|
|
534
569
|
const pr = prFor(repo, branch);
|
|
535
|
-
if (!t.merged && !t.contained) {
|
|
570
|
+
if (!t.merged && !t.contained && !t.landed) {
|
|
536
571
|
const prState = t.pr
|
|
537
572
|
? ` (#${t.pr.number} is ${t.pr.state.toLowerCase()})`
|
|
538
573
|
: "";
|
|
574
|
+
// An abandoned topic is never merged: say how it goes instead.
|
|
539
575
|
result.refused.push({
|
|
540
576
|
repo: repo.worktree,
|
|
541
|
-
why:
|
|
542
|
-
|
|
543
|
-
|
|
577
|
+
why: `${
|
|
578
|
+
t.base
|
|
579
|
+
? `${branch} is not merged${prState} and has changes in ${t.ahead} commit(s) ${t.base} lacks`
|
|
580
|
+
: `${branch} is not merged${prState}, and there is no ${t.baseBranch} or origin/${t.baseBranch} here to check it against`
|
|
581
|
+
} (to abandon it: work topic drop ${name})`,
|
|
544
582
|
});
|
|
545
583
|
continue;
|
|
546
584
|
}
|
|
@@ -603,7 +641,8 @@ async function topicDone(ctx) {
|
|
|
603
641
|
}
|
|
604
642
|
// Nothing of its own: left where it is, unless what it stacks on
|
|
605
643
|
// moved out from under it.
|
|
606
|
-
if (other.contained && !moved.has(other.baseBranch))
|
|
644
|
+
if ((other.contained || other.landed) && !moved.has(other.baseBranch))
|
|
645
|
+
continue;
|
|
607
646
|
const base = restack ? t.base : other.base;
|
|
608
647
|
if (!other.local || !base) continue;
|
|
609
648
|
const { behind } = aheadBehind(repo.dir, base, other.branch);
|
|
@@ -684,6 +723,307 @@ async function topicDone(ctx) {
|
|
|
684
723
|
process.exitCode = 1;
|
|
685
724
|
}
|
|
686
725
|
|
|
726
|
+
// -- drop --------------------------------------------------------------------
|
|
727
|
+
|
|
728
|
+
/** Where a dropped topic's last tip is kept, a ref per drop
|
|
729
|
+
* (`<branch>/<UTC stamp>`): outside `refs/work/<workspace>/`, whose
|
|
730
|
+
* snapshots the server prunes, and in no push. */
|
|
731
|
+
const DROPPED = "refs/work-dropped/";
|
|
732
|
+
/** How long a dropped topic can be brought back. */
|
|
733
|
+
const KEEP_DROPPED_DAYS = 30;
|
|
734
|
+
const DAY = 86_400_000;
|
|
735
|
+
|
|
736
|
+
const stampOf = (d) =>
|
|
737
|
+
d
|
|
738
|
+
.toISOString()
|
|
739
|
+
.replace(/[-:]/g, "")
|
|
740
|
+
.replace(/\.\d+Z$/, "Z");
|
|
741
|
+
|
|
742
|
+
function stampTime(stamp) {
|
|
743
|
+
const m = /^(\d{4})(\d\d)(\d\d)T(\d\d)(\d\d)(\d\d)Z$/.exec(stamp);
|
|
744
|
+
return m ? Date.UTC(+m[1], +m[2] - 1, +m[3], +m[4], +m[5], +m[6]) : null;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/** Each dropped ref: its branch, the time of its drop. */
|
|
748
|
+
function droppedRefs(dir) {
|
|
749
|
+
return git(dir, ["for-each-ref", "--format=%(refname)", DROPPED], {
|
|
750
|
+
allowFail: true,
|
|
751
|
+
})
|
|
752
|
+
.out.split("\n")
|
|
753
|
+
.filter(Boolean)
|
|
754
|
+
.map((ref) => {
|
|
755
|
+
const rest = ref.slice(DROPPED.length);
|
|
756
|
+
const cut = rest.lastIndexOf("/");
|
|
757
|
+
return {
|
|
758
|
+
ref,
|
|
759
|
+
branch: rest.slice(0, cut),
|
|
760
|
+
at: stampTime(rest.slice(cut + 1)),
|
|
761
|
+
};
|
|
762
|
+
})
|
|
763
|
+
.filter((r) => r.branch && r.at !== null);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/** The branches dropped here (within their keep). */
|
|
767
|
+
function droppedBranches(dir) {
|
|
768
|
+
return new Set(droppedRefs(dir).map((r) => r.branch));
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/** Dropped refs past their keep, gone: every workspace's on this repo,
|
|
772
|
+
* since its cache is shared and a deleted workspace drops nothing again. */
|
|
773
|
+
function pruneDropped(dir, now = Date.now()) {
|
|
774
|
+
const gone = droppedRefs(dir).filter(
|
|
775
|
+
(r) => r.at < now - KEEP_DROPPED_DAYS * DAY,
|
|
776
|
+
);
|
|
777
|
+
if (gone.length)
|
|
778
|
+
git(dir, ["update-ref", "--stdin"], {
|
|
779
|
+
allowFail: true,
|
|
780
|
+
input: gone.map((r) => `delete ${r.ref}\n`).join(""),
|
|
781
|
+
});
|
|
782
|
+
return gone.length;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/** A worktree as it is — uncommitted and untracked files too — as a commit
|
|
786
|
+
* on its HEAD, made through an index of its own so the worktree and its
|
|
787
|
+
* index are untouched: a forced drop keeps what it discards. */
|
|
788
|
+
function snapshotOf(worktree, message) {
|
|
789
|
+
const index = path.join(
|
|
790
|
+
os.tmpdir(),
|
|
791
|
+
`work-topic-drop-${process.pid}-${Date.now()}.index`,
|
|
792
|
+
);
|
|
793
|
+
// An identity of its own (a machine with none set still drops) and no
|
|
794
|
+
// signing (a key's passphrase prompt would hang a script).
|
|
795
|
+
const env = {
|
|
796
|
+
GIT_INDEX_FILE: index,
|
|
797
|
+
GIT_AUTHOR_NAME: "work",
|
|
798
|
+
GIT_AUTHOR_EMAIL: "work@localhost",
|
|
799
|
+
GIT_COMMITTER_NAME: "work",
|
|
800
|
+
GIT_COMMITTER_EMAIL: "work@localhost",
|
|
801
|
+
};
|
|
802
|
+
try {
|
|
803
|
+
git(worktree, ["read-tree", "HEAD"], { env });
|
|
804
|
+
git(worktree, ["add", "-A"], { env });
|
|
805
|
+
const tree = git(worktree, ["write-tree"], { env }).out;
|
|
806
|
+
return git(
|
|
807
|
+
worktree,
|
|
808
|
+
["commit-tree", "--no-gpg-sign", tree, "-p", "HEAD", "-m", message],
|
|
809
|
+
{ env },
|
|
810
|
+
).out;
|
|
811
|
+
} finally {
|
|
812
|
+
fs.rmSync(index, { force: true });
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
const real = (p) => {
|
|
817
|
+
try {
|
|
818
|
+
return fs.realpathSync(p);
|
|
819
|
+
} catch {
|
|
820
|
+
return path.resolve(p);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
const within = (dir, root) => dir === root || dir.startsWith(root + path.sep);
|
|
824
|
+
|
|
825
|
+
/** Everything about dropping the topic in one repo, before any of it is
|
|
826
|
+
* done: what goes, what would be lost, and what stands in the way —
|
|
827
|
+
* `blocks` give way to --yes, `stops` never do. */
|
|
828
|
+
function planDrop(ctx, ws, repo, t, sessions, topics) {
|
|
829
|
+
const plan = { repo, t, lost: [], blocks: [], stops: [], dirty: [] };
|
|
830
|
+
plan.local = oid(repo.dir, `refs/heads/${t.branch}`);
|
|
831
|
+
if (!plan.local) return plan;
|
|
832
|
+
if (t.worktree && real(t.worktree) === real(repo.dir))
|
|
833
|
+
plan.stops.push(
|
|
834
|
+
`${t.branch} is checked out in the workspace's own checkout (${repo.dir}): switch that off it first`,
|
|
835
|
+
);
|
|
836
|
+
if (t.worktree) {
|
|
837
|
+
plan.dirty = dirtyIn(t.worktree);
|
|
838
|
+
if (plan.dirty.length)
|
|
839
|
+
plan.blocks.push(
|
|
840
|
+
`${t.worktree} has ${plan.dirty.length} uncommitted change(s):\n ${plan.dirty.slice(0, 10).join("\n ")}`,
|
|
841
|
+
);
|
|
842
|
+
const here = real(t.worktree);
|
|
843
|
+
for (const s of sessions)
|
|
844
|
+
if (
|
|
845
|
+
s.state?.alive &&
|
|
846
|
+
s.launch_dir &&
|
|
847
|
+
within(real(path.resolve(ws.path, s.launch_dir)), here)
|
|
848
|
+
)
|
|
849
|
+
plan.blocks.push(
|
|
850
|
+
`session ${s.id}${s.title ? ` ("${s.title}")` : ""} is working in ${t.worktree}`,
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
// What the drop discards: none of it when its base holds every change.
|
|
854
|
+
const merged = t.merged && !leftover(repo, t, prFor(repo, t.branch));
|
|
855
|
+
if (!t.contained && !t.landed && !merged) {
|
|
856
|
+
if (!t.base)
|
|
857
|
+
plan.blocks.push(
|
|
858
|
+
`there is no ${t.baseBranch} or origin/${t.baseBranch} here to tell what of ${t.branch} would be lost`,
|
|
859
|
+
);
|
|
860
|
+
else {
|
|
861
|
+
plan.lost = git(repo.dir, [
|
|
862
|
+
"log",
|
|
863
|
+
"--format=%h %s",
|
|
864
|
+
`${t.base}..${plan.local}`,
|
|
865
|
+
]).out.split("\n");
|
|
866
|
+
plan.blocks.push(
|
|
867
|
+
`${t.branch} has ${plan.lost.length} commit(s) whose changes ${t.base} lacks${
|
|
868
|
+
t.unpushed
|
|
869
|
+
? `, ${t.onOrigin ? t.unpushed : "all"} of them on no remote`
|
|
870
|
+
: ""
|
|
871
|
+
}:\n ${plan.lost.slice(0, 10).join("\n ")}`,
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
if (t.pr?.state === "OPEN")
|
|
876
|
+
plan.blocks.push(
|
|
877
|
+
`#${t.pr.number} is open (the drop leaves the PR and origin's copy as they are)`,
|
|
878
|
+
);
|
|
879
|
+
plan.stacked = topics.filter(
|
|
880
|
+
(o) => o.branch !== t.branch && o.local && o.baseBranch === t.branch,
|
|
881
|
+
);
|
|
882
|
+
for (const o of plan.stacked)
|
|
883
|
+
plan.blocks.push(
|
|
884
|
+
`${o.branch} stacks on it (with --yes it is counted against ${t.baseBranch} instead, still carrying ${t.branch}'s commits)`,
|
|
885
|
+
);
|
|
886
|
+
return plan;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
async function topicDrop(ctx) {
|
|
890
|
+
const [name] = ctx.parse([]);
|
|
891
|
+
if (!name) ctx.die("usage: work topic drop <name> [--yes] [--json]");
|
|
892
|
+
const { ws, repos, foreign } = await context(ctx, false);
|
|
893
|
+
const branch = `${ws.branch}-${name}`;
|
|
894
|
+
const touched = repos.filter(
|
|
895
|
+
(r) =>
|
|
896
|
+
has(r.dir, `refs/heads/${branch}`) ||
|
|
897
|
+
has(r.dir, `refs/remotes/origin/${branch}`),
|
|
898
|
+
);
|
|
899
|
+
if (!touched.length)
|
|
900
|
+
ctx.die(`no topic ${name} in ${ws.name} (see: work topic list)`);
|
|
901
|
+
const sessions = await ctx.api
|
|
902
|
+
.get(`/api/workspaces/${ws.id}/sessions`)
|
|
903
|
+
.catch(() => []);
|
|
904
|
+
// Every repo is planned before any is touched: half a topic dropped is
|
|
905
|
+
// worse than none.
|
|
906
|
+
const plans = [];
|
|
907
|
+
for (const repo of touched) {
|
|
908
|
+
// A fetch that fails (offline) only leaves the base older, which can
|
|
909
|
+
// only find more to lose.
|
|
910
|
+
ctx.log(`fetching ${repo.full_name}…`);
|
|
911
|
+
if (
|
|
912
|
+
!git(repo.dir, ["fetch", "--prune", "--quiet", "origin"], {
|
|
913
|
+
allowFail: true,
|
|
914
|
+
}).ok
|
|
915
|
+
)
|
|
916
|
+
ctx.warn(
|
|
917
|
+
`${repo.worktree}: could not fetch origin; counting against what is here`,
|
|
918
|
+
);
|
|
919
|
+
const topics = topicsIn(ws, repo, foreign);
|
|
920
|
+
const t = topics.find((x) => x.branch === branch);
|
|
921
|
+
if (t) plans.push(planDrop(ctx, ws, repo, t, sessions, topics));
|
|
922
|
+
}
|
|
923
|
+
const result = {
|
|
924
|
+
topic: name,
|
|
925
|
+
dropped: [],
|
|
926
|
+
skipped: [],
|
|
927
|
+
refused: [],
|
|
928
|
+
restacked: [],
|
|
929
|
+
};
|
|
930
|
+
for (const p of plans) {
|
|
931
|
+
for (const why of p.stops)
|
|
932
|
+
result.refused.push({ repo: p.repo.worktree, why });
|
|
933
|
+
if (!ctx.yes)
|
|
934
|
+
for (const why of p.blocks)
|
|
935
|
+
result.refused.push({ repo: p.repo.worktree, why });
|
|
936
|
+
}
|
|
937
|
+
if (!result.refused.length) {
|
|
938
|
+
const at = new Date();
|
|
939
|
+
for (const p of plans) {
|
|
940
|
+
const { repo, t } = p;
|
|
941
|
+
if (!p.local) {
|
|
942
|
+
result.skipped.push({
|
|
943
|
+
repo: repo.worktree,
|
|
944
|
+
why: `${branch} is only on origin: nothing here to drop (git push origin --delete ${branch} removes it there)`,
|
|
945
|
+
});
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
pruneDropped(repo.dir, at.getTime());
|
|
949
|
+
const keep = p.dirty.length
|
|
950
|
+
? snapshotOf(
|
|
951
|
+
t.worktree,
|
|
952
|
+
`work topic drop: ${branch} with its uncommitted changes`,
|
|
953
|
+
)
|
|
954
|
+
: p.local;
|
|
955
|
+
const ref = `${DROPPED}${branch}/${stampOf(at)}`;
|
|
956
|
+
git(repo.dir, ["update-ref", ref, keep]);
|
|
957
|
+
if (t.worktree) {
|
|
958
|
+
git(repo.dir, [
|
|
959
|
+
"worktree",
|
|
960
|
+
"remove",
|
|
961
|
+
...(p.dirty.length ? ["--force"] : []),
|
|
962
|
+
t.worktree,
|
|
963
|
+
]);
|
|
964
|
+
// The topic's own folder, once its last repo's worktree is gone.
|
|
965
|
+
try {
|
|
966
|
+
fs.rmdirSync(path.dirname(t.worktree));
|
|
967
|
+
} catch {}
|
|
968
|
+
}
|
|
969
|
+
for (const o of p.stacked) {
|
|
970
|
+
git(repo.dir, [
|
|
971
|
+
"config",
|
|
972
|
+
`branch.${o.branch}.gh-merge-base`,
|
|
973
|
+
t.baseBranch,
|
|
974
|
+
]);
|
|
975
|
+
result.restacked.push({
|
|
976
|
+
repo: repo.worktree,
|
|
977
|
+
branch: o.branch,
|
|
978
|
+
base: t.baseBranch,
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
// Its config (the recorded base) goes with it.
|
|
982
|
+
git(repo.dir, ["branch", "-D", branch]);
|
|
983
|
+
result.dropped.push({
|
|
984
|
+
repo: repo.worktree,
|
|
985
|
+
branch,
|
|
986
|
+
worktree: t.worktree,
|
|
987
|
+
commits: p.lost.filter(Boolean).length,
|
|
988
|
+
unpushed: p.lost.length ? t.unpushed : 0,
|
|
989
|
+
uncommitted: p.dirty.length,
|
|
990
|
+
kept: ref,
|
|
991
|
+
keptDays: KEEP_DROPPED_DAYS,
|
|
992
|
+
restore: `git -C ${repo.dir} branch ${branch} ${ref}`,
|
|
993
|
+
onOrigin: t.onOrigin,
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
ctx.out(result, (r) => {
|
|
998
|
+
for (const x of r.dropped) {
|
|
999
|
+
const lost = [
|
|
1000
|
+
x.commits ? `${x.commits} commit(s) its base lacks` : null,
|
|
1001
|
+
x.uncommitted ? `${x.uncommitted} uncommitted change(s)` : null,
|
|
1002
|
+
].filter(Boolean);
|
|
1003
|
+
console.log(
|
|
1004
|
+
`${x.repo}: dropped ${x.branch}${lost.length ? ` (${lost.join(", ")})` : ""}`,
|
|
1005
|
+
);
|
|
1006
|
+
if (x.worktree) console.log(` removed ${x.worktree}`);
|
|
1007
|
+
console.log(
|
|
1008
|
+
` kept as ${x.kept} for ${x.keptDays} days; to bring it back: ${x.restore}${x.uncommitted ? " (its top commit holds the uncommitted changes)" : ""}`,
|
|
1009
|
+
);
|
|
1010
|
+
if (x.onOrigin)
|
|
1011
|
+
console.log(
|
|
1012
|
+
` origin/${x.branch} is still on origin (git push origin --delete ${x.branch} removes it)`,
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
for (const x of r.skipped) console.log(`${x.repo}: ${x.why}`);
|
|
1016
|
+
for (const x of r.restacked)
|
|
1017
|
+
console.log(`${x.repo}: ${x.branch} now counts against ${x.base}`);
|
|
1018
|
+
for (const x of r.refused) console.log(`${x.repo}: ${x.why}`);
|
|
1019
|
+
if (r.refused.length)
|
|
1020
|
+
console.log(
|
|
1021
|
+
`nothing dropped${ctx.yes ? "" : `: pass --yes to drop it anyway (its tip and uncommitted changes are kept ${KEEP_DROPPED_DAYS} days)`}`,
|
|
1022
|
+
);
|
|
1023
|
+
});
|
|
1024
|
+
if (result.refused.length) process.exitCode = 1;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
687
1027
|
// -- command -----------------------------------------------------------------
|
|
688
1028
|
|
|
689
1029
|
const HELP = `work topic new <name> [--repo <repo>]… [--from <ref>] [--install]
|
|
@@ -703,17 +1043,27 @@ work topic list [--all] [--fresh] [--json]
|
|
|
703
1043
|
answer.
|
|
704
1044
|
work topic done <name> [--rebase] [--json]
|
|
705
1045
|
after its PR merged, or once its base holds all of it (merged there
|
|
706
|
-
by hand, say)
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
1046
|
+
by hand, say) or all of its changes by other commits (squashed into
|
|
1047
|
+
another PR, cherry-picked): fetch --prune, remove its worktree (only
|
|
1048
|
+
if clean, and only if the merge took every commit), keep the branch,
|
|
1049
|
+
and list the other open topics to rebase, each onto its own base — one
|
|
1050
|
+
stacked on this topic onto this one's, which becomes its base.
|
|
1051
|
+
--rebase does it where the worktree is clean, aborting on conflict.
|
|
1052
|
+
Never touches the workspace's own checkout.
|
|
1053
|
+
work topic drop <name> [--yes] [--json]
|
|
1054
|
+
abandon a topic: remove its worktree and delete its local branch,
|
|
1055
|
+
keeping its tip (with any uncommitted changes) as
|
|
1056
|
+
refs/work-dropped/<branch>/<when> for ${KEEP_DROPPED_DAYS} days; the output says how to
|
|
1057
|
+
bring it back. Refuses, unless --yes, whatever would discard work:
|
|
1058
|
+
commits whose changes its base lacks (and which of them no remote has),
|
|
1059
|
+
uncommitted changes, a session working in it, a topic stacked on it, an
|
|
1060
|
+
open PR. Origin's copy and any PR are left as they are. Never touches
|
|
1061
|
+
the workspace's own checkout.`;
|
|
712
1062
|
|
|
713
1063
|
export const commands = [
|
|
714
1064
|
{
|
|
715
1065
|
name: "topic",
|
|
716
|
-
summary: "start, list
|
|
1066
|
+
summary: "start, list, put away and drop topic branches (work help topic)",
|
|
717
1067
|
help: HELP,
|
|
718
1068
|
async run(ctx) {
|
|
719
1069
|
const [verb] = ctx.positional;
|
|
@@ -725,11 +1075,12 @@ export const commands = [
|
|
|
725
1075
|
if (verb === "list" || verb === "ls" || !verb)
|
|
726
1076
|
return await topicList(sub);
|
|
727
1077
|
if (verb === "done") return await topicDone(sub);
|
|
1078
|
+
if (verb === "drop") return await topicDrop(sub);
|
|
728
1079
|
} catch (err) {
|
|
729
1080
|
ctx.die(err instanceof Error ? err.message : String(err));
|
|
730
1081
|
}
|
|
731
1082
|
ctx.die(
|
|
732
|
-
`no \`work topic ${verb}\`: new, list or
|
|
1083
|
+
`no \`work topic ${verb}\`: new, list, done or drop (see: work help topic)`,
|
|
733
1084
|
);
|
|
734
1085
|
},
|
|
735
1086
|
},
|