@shaohui_jin/git-cockpit-mcp-server 0.1.6 → 0.1.8
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/dist/{chunk-WCLC5KOG.js → chunk-HWDOOYER.js} +79 -2
- package/dist/chunk-HWDOOYER.js.map +1 -0
- package/dist/{chunk-4WZKRLKI.js → chunk-XCGHLAOY.js} +7 -5
- package/dist/chunk-XCGHLAOY.js.map +1 -0
- package/dist/{chunk-5CZ3BO3H.js → chunk-Y2UNG7RZ.js} +124 -5
- package/dist/chunk-Y2UNG7RZ.js.map +1 -0
- package/dist/cli-entry.js +3 -3
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.js +3 -3
- package/dist/mcpServer.js +1 -1
- package/dist/web/assets/{index-CNUTv7F2.css → index-DUymtENk.css} +1 -1
- package/dist/web/assets/index-MPCZvzsu.js +114 -0
- package/dist/web/index.html +2 -2
- package/dist/webServer.js +2 -2
- package/package.json +6 -2
- package/dist/chunk-4WZKRLKI.js.map +0 -1
- package/dist/chunk-5CZ3BO3H.js.map +0 -1
- package/dist/chunk-WCLC5KOG.js.map +0 -1
- package/dist/web/assets/index-XiZddJPB.js +0 -4
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import{az as Xe,c as G,G as Ce,d as Oe,w as ye,a6 as Pn,O as H,W as u,aj as R,aA as On,aB as ht,L as y,a0 as h,P as k,$ as O,u as K,M,F as ae,ae as he,_ as I,Y as Rn,k as Y,aq as mt,S as Be,ac as De,Z as j,i as Xt,e as ut,X as Je,ak as Ye,aC as An,aD as Fn,aw as Mn,aE as zn}from"./vue-CYNDxJyv.js";import{E as Z,a as gt,e as Bn}from"./element-plus-D8uC5V5h.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))e(l);new MutationObserver(l=>{for(const r of l)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&e(o)}).observe(document,{childList:!0,subtree:!0});function n(l){const r={};return l.integrity&&(r.integrity=l.integrity),l.referrerPolicy&&(r.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?r.credentials="include":l.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function e(l){if(l.ep)return;l.ep=!0;const r=n(l);fetch(l.href,r)}})();class dt extends Error{constructor(t,n,e,l){super(t),this.status=n,this.code=e,this.requiredApproval=l,this.name="ApiError"}}async function ce(s,t,n){let e;try{e=await fetch(t,{method:s,headers:n!==void 0?{"Content-Type":"application/json"}:void 0,body:n!==void 0?JSON.stringify(n):void 0})}catch(l){throw new dt(`无法连接后端服务(${t}):${l instanceof Error?l.message:String(l)}`,0)}if(!e.ok){let l=e.statusText,r,o;try{const f=await e.json();typeof f.error=="string"?(l=f.error,r=f.code,o=f.requiredApproval):f.error&&typeof f.error=="object"?(l=f.error.message??l,r=f.error.code??f.code,o=f.error.requiredApproval??f.requiredApproval):f.message&&(l=f.message,r=f.code,o=f.requiredApproval)}catch{}throw new dt(l,e.status,r,o)}return await e.json()}function Hn(){return ce("GET","/api/repos")}function Un(s){return ce("POST","/api/repos/open",{path:s})}function Wn(s){return ce("POST",`/api/repos/${s}/activate`)}function jn(s){return ce("DELETE",`/api/repos/${s}`)}function Gn(s){return ce("GET",`/api/repos/${s}/status`)}function qn(s,t={}){const n=new URLSearchParams;t.maxCount&&n.set("maxCount",String(t.maxCount)),t.all&&n.set("all","true"),t.path&&n.set("path",t.path),t.from&&n.set("from",t.from),t.to&&n.set("to",t.to),t.author&&n.set("author",t.author);const e=n.toString();return ce("GET",`/api/repos/${s}/log${e?`?${e}`:""}`)}function Kn(s,t={}){const n=new URLSearchParams;t.from&&n.set("from",t.from),t.to&&n.set("to",t.to),t.path&&n.set("path",t.path),t.staged&&n.set("staged","true");const e=n.toString();return ce("GET",`/api/repos/${s}/diff${e?`?${e}`:""}`)}function Xn(s,t){return ce("GET",`/api/repos/${s}/show/${encodeURIComponent(t)}`)}function Jn(s){return ce("GET",`/api/repos/${s}/branches`)}function Yn(s){return ce("GET",`/api/repos/${s}/stashes`)}function Qn(s){return ce("GET",`/api/repos/${s}/remotes`)}function qe(s,t,n={}){return ce("POST",`/api/repos/${s}/tools/${t}`,{params:n})}function Zn(s={}){const t=new URLSearchParams;s.limit&&t.set("limit",String(s.limit)),s.tool&&t.set("tool",s.tool);const n=t.toString();return ce("GET",`/api/logs${n?`?${n}`:""}`)}function es(){return ce("GET","/api/settings")}function ts(s){return ce("PUT","/api/settings",{permissions:s})}function ns(){return ce("GET","/api/health")}function ss(s){const t=new EventSource("/api/events");return s.onRepoChanged&&t.addEventListener("repo-changed",n=>{var e;return(e=s.onRepoChanged)==null?void 0:e.call(s,JSON.parse(n.data))}),s.onLog&&t.addEventListener("log",()=>{var n;return(n=s.onLog)==null?void 0:n.call(s)}),s.onError&&(t.onerror=n=>{var e;return(e=s.onError)==null?void 0:e.call(s,n)}),()=>t.close()}const ct="git-cockpit:currentRepoId";function At(){try{const s=Number(window.localStorage.getItem(ct));return Number.isInteger(s)&&s>0?s:null}catch{return null}}function lt(s){try{s===null?window.localStorage.removeItem(ct):window.localStorage.setItem(ct,String(s))}catch{}}const $e=Xe("repos",{state:()=>({repos:[],currentId:At(),loading:!1,error:null,healthOk:null}),getters:{current(s){return s.repos.find(t=>t.id===s.currentId)??null},currentPath(s){var t;return((t=s.repos.find(n=>n.id===s.currentId))==null?void 0:t.path)??null}},actions:{async checkHealth(){try{const s=await ns();this.healthOk=s.ok}catch{this.healthOk=!1}return this.healthOk===!0},async load(){var s;this.loading=!0,this.error=null;try{const{repos:t}=await Hn();this.repos=t;const n=At();n!==null&&t.some(e=>e.id===n)?this.currentId=n:(!this.currentId||!t.some(e=>e.id===this.currentId))&&(this.currentId=((s=t[0])==null?void 0:s.id)??null),lt(this.currentId)}catch(t){this.error=t instanceof Error?t.message:String(t)}finally{this.loading=!1}},async open(s){const{repo:t}=await Un(s);return await this.load(),t},async activate(s){const{repo:t}=await Wn(s);return this.currentId=s,lt(s),await this.load(),t},async remove(s){await jn(s),this.currentId===s&&(this.currentId=null),await this.load()},switchTo(s){this.currentId=s,lt(s)}}}),Jt=Xe("settings",{state:()=>({permissions:null,tools:[],loading:!1,saving:!1,error:null}),actions:{async load(){this.loading=!0,this.error=null;try{const s=await es();this.permissions=s.permissions,this.tools=s.tools}catch(s){this.error=s instanceof Error?s.message:String(s)}finally{this.loading=!1}},async save(s){if(this.permissions){this.saving=!0,this.error=null;try{await ts(s),this.permissions={...this.permissions,...s}}catch(t){throw this.error=t instanceof Error?t.message:String(t),t}finally{this.saving=!1}}}}});function ls(s,t="all"){return t==="local"?s.filter(n=>!n.remote):t==="remote"?s.filter(n=>n.remote):s}function Yt(s){s.sort((t,n)=>{const e=t.branch?1:0,l=n.branch?1:0;return e!==l?e-l:t.label.localeCompare(n.label)});for(const t of s)t.children&&Yt(t.children)}function Ft(s,t){const n=[];for(const{path:e,branch:l}of s){const r=e.split("/").filter(v=>v.length>0);if(r.length===0)continue;let o=n,f="";for(const[v,i]of r.entries()){f=f?`${f}/${i}`:i;const c=v===r.length-1,w=o.find(a=>a.label===i),m=w??{key:`${t}:${f}`,value:c?l.name:`${t}:${f}`,label:i,disabled:!c};w||o.push(m),c?(m.value=l.name,m.disabled=!1,m.branch=l,m.fullName=l.name,m.remote=l.remote):(m.children||(m.children=[]),o=m.children)}}return Yt(n),n}function Qt(s,t="all"){const n=ls(s,t),e=n.filter(f=>!f.remote),l=n.filter(f=>f.remote),r=new Map;for(const f of l){const v=f.name.indexOf("/"),i=v===-1?"":f.name.slice(0,v);if(!i)continue;const c=r.get(i)??[];c.push({path:f.name.slice(v+1),branch:f}),r.set(i,c)}const o=[];if(e.length&&t!=="remote"&&o.push({key:"local",title:`本地分支(${e.length})`,tree:Ft(e.map(f=>({path:f.name,branch:f})),"local")}),t!=="local")for(const[f,v]of r)o.push({key:`remote:${f}`,title:`远程 · ${f}(${v.length})`,tree:Ft(v,`remote:${f}`)});return o}function as(s,t=!1){return(t?[...s].reverse():s).map(e=>({key:`group:${e.key}`,value:`group:${e.key}`,label:e.title,disabled:!0,children:e.tree}))}let Fe=null;const He=Xe("branches",{state:()=>({list:[],remotes:[],repoId:null,loading:!1}),getters:{current(s){return s.list.find(t=>t.current)??null},locals(s){return s.list.filter(t=>!t.remote)},remoteBranches(s){return s.list.filter(t=>t.remote)},hasRemote(s){return s.remotes.length>0||s.list.some(t=>t.remote)},panes(s){return Qt(s.list,"all")}},actions:{async load(){if(!(Fe&&(await Fe,this.repoId===$e().currentId)))return Fe=this.fetch().finally(()=>{Fe=null}),Fe},async fetch(){const s=$e().currentId;if(s===null){this.list=[],this.remotes=[],this.repoId=null;return}this.repoId!==s&&(this.list=[],this.remotes=[]),this.loading=!0;try{const[{branches:t},n]=await Promise.all([Jn(s),Qn(s)]);if($e().currentId!==s)return;this.list=t,this.remotes=n,this.repoId=s}catch{$e().currentId===s&&this.repoId!==s&&(this.list=[],this.remotes=[])}finally{this.loading=!1}}}}),Zt=G(0),is=()=>{Zt.value+=1};function Qe(){return{revision:Zt,bump:is}}const os={class:"repo-box"},rs=["title"],us={class:"menu-icon"},ds={class:"aside-footer"},cs=Ce({__name:"App",setup(s){const t=$e(),n=Jt(),e=He(),l=On(),r=ht(),{bump:o,revision:f}=Qe(),v=[{path:"/status",label:"状态",icon:"◧"},{path:"/merge",label:"合并预演",icon:"⇄"},{path:"/history",label:"历史",icon:"◫"},{path:"/repos",label:"仓库管理",icon:"▤"},{path:"/logs",label:"操作日志",icon:"≡"},{path:"/settings",label:"设置",icon:"⚙"}],i=Y(()=>{if(!t.currentId)return"未选择仓库";const w=t.repos.find(m=>m.id===t.currentId);return(w==null?void 0:w.path)??"未选择仓库"});let c=null;return Oe(async()=>{await t.checkHealth(),await Promise.all([t.load(),n.load().catch(()=>{})]),await e.load(),c=ss({onRepoChanged:()=>o(),onLog:()=>o(),onError:()=>{}})}),ye(()=>t.currentId,()=>void e.load()),ye(f,()=>void e.load()),Pn(()=>{c==null||c()}),(w,m)=>{const a=R("el-menu-item"),p=R("el-menu"),b=R("el-tag"),g=R("el-aside"),E=R("router-view"),A=R("el-main"),N=R("el-container");return y(),H(N,{class:"app-shell"},{default:u(()=>[h(g,{width:"220px",class:"app-aside"},{default:u(()=>[m[4]||(m[4]=k("div",{class:"brand"},[k("span",{class:"brand-mark"},"⌘"),k("span",{class:"brand-name"},"Git Cockpit")],-1)),k("div",os,[m[0]||(m[0]=k("div",{class:"repo-box-label"},"当前仓库",-1)),k("div",{class:"repo-box-path mono",title:i.value},O(i.value),9,rs)]),h(p,{"default-active":K(l).path,class:"nav-menu"},{default:u(()=>[(y(),M(ae,null,he(v,x=>h(a,{key:x.path,index:x.path,onClick:V=>K(r).push(x.path)},{default:u(()=>[k("span",us,O(x.icon),1),k("span",null,O(x.label),1)]),_:2},1032,["index","onClick"])),64))]),_:1},8,["default-active"]),k("div",ds,[K(t).healthOk?(y(),H(b,{key:0,size:"small",type:"success"},{default:u(()=>[...m[1]||(m[1]=[I("后端已连接",-1)])]),_:1})):K(t).healthOk===!1?(y(),H(b,{key:1,size:"small",type:"danger"},{default:u(()=>[...m[2]||(m[2]=[I("后端离线",-1)])]),_:1})):(y(),H(b,{key:2,size:"small",type:"info"},{default:u(()=>[...m[3]||(m[3]=[I("连接中…",-1)])]),_:1}))])]),_:1}),h(N,{class:"app-main"},{default:u(()=>[h(A,{class:"main-content"},{default:u(()=>[h(E,null,{default:u(({Component:x})=>[(y(),H(Rn(x)))]),_:1})]),_:1})]),_:1})]),_:1})}}}),xe=(s,t)=>{const n=s.__vccOpts||s;for(const[e,l]of t)n[e]=l;return n},fs=xe(cs,[["__scopeId","data-v-53c06d14"]]),ps={class:"page"},hs={class:"open-row"},ms={class:"list-header"},gs={key:1,class:"tree-scroll"},bs=["title"],vs=["title","onDblclick"],ys={class:"node-name mono"},_s={class:"node-time"},ws={class:"node-actions"},ks=Ce({__name:"ReposView",setup(s){const t=$e(),n=ht(),e=G(""),l=G(!1),r=Y(()=>{const m=[],a=new Map;t.repos.forEach((b,g)=>a.set(b.id,g));for(const b of t.repos){const g=b.path.split(/[\\/]+/).filter(N=>N.length>0);if(g.length===0)continue;let E=m,A="";for(const[N,x]of g.entries()){A=A?`${A}/${x}`:x;const V=N===g.length-1,B=E.find(Q=>!Q.repo&&Q.label===x);if(V)E.push({key:"repo:"+b.path,label:x,fullPath:b.path,repo:b});else{const Q=B??{key:"dir:"+A,label:x,fullPath:A};B||E.push(Q),Q.children??(Q.children=[]),E=Q.children}}}const p=b=>{b.sort((g,E)=>{const A=g.repo?1:0,N=E.repo?1:0;return A!==N?A-N:A===1?(a.get(g.repo.id)??0)-(a.get(E.repo.id)??0):g.label.localeCompare(E.label)});for(const g of b)g.children&&p(g.children)};return p(m),m}),o=Y(()=>{const m=t.current;if(m){const p=m.path.split(/[\\/]+/).filter(E=>E.length>0),b=[];let g="";for(let E=0;E<p.length-1;E++)g=g?`${g}/${p[E]}`:p[E],b.push("dir:"+g);if(b.length>0)return b}const a=r.value[0];return a&&!a.repo?[a.key]:[]});async function f(){const m=e.value.trim();if(!m){Z.warning("请输入仓库路径");return}l.value=!0;try{const a=await t.open(m);Z.success(`已打开 ${a.path}`),t.switchTo(a.id),await n.push("/status")}catch(a){Z.error(a instanceof Error?a.message:String(a))}finally{l.value=!1}}async function v(m,a){try{await gt.confirm(`确定从列表移除 ${a}?注意:不会删除磁盘上的仓库文件。`,"移除仓库",{type:"warning",confirmButtonText:"移除",cancelButtonText:"取消"})}catch{return}try{await t.remove(m),Z.success("已移除")}catch(p){Z.error(p instanceof Error?p.message:String(p))}}async function i(m){try{await t.activate(m)}catch{t.switchTo(m)}n.push("/status")}function c(m){const a=new Date(m);return Number.isNaN(a.getTime())?m:a.toLocaleString()}function w(m){m.repo&&i(m.repo.id)}return Oe(()=>t.load()),(m,a)=>{const p=R("el-input"),b=R("el-button"),g=R("el-card"),E=R("el-empty"),A=R("el-tree");return y(),M("div",ps,[a[7]||(a[7]=k("h2",{class:"page-title"},"仓库管理",-1)),h(g,{class:"open-card",shadow:"never"},{header:u(()=>[...a[2]||(a[2]=[I("打开本地仓库",-1)])]),default:u(()=>[k("div",hs,[h(p,{modelValue:e.value,"onUpdate:modelValue":a[0]||(a[0]=N=>e.value=N),placeholder:"输入本地 Git 仓库路径,例如 D:\\project\\repo 或 /Users/me/code/app",clearable:"",onKeyup:mt(f,["enter"])},null,8,["modelValue"]),h(b,{type:"primary",loading:l.value,onClick:f},{default:u(()=>[...a[3]||(a[3]=[I("打开",-1)])]),_:1},8,["loading"])])]),_:1}),h(g,{shadow:"never",class:"list-card"},{header:u(()=>[k("div",ms,[k("span",null,"最近打开的仓库("+O(K(t).repos.length)+")",1),h(b,{text:"",type:"primary",loading:K(t).loading,onClick:a[1]||(a[1]=N=>K(t).load())},{default:u(()=>[...a[4]||(a[4]=[I("刷新",-1)])]),_:1},8,["loading"])])]),default:u(()=>[!K(t).loading&&K(t).repos.length===0?(y(),H(E,{key:0,description:"尚未打开任何仓库"})):(y(),M("div",gs,[h(A,{data:r.value,props:{label:"label",children:"children"},"node-key":"key",accordion:"","default-expanded-keys":o.value,indent:14,class:"repo-tree"},{default:u(({data:N})=>[N.repo?(y(),M("div",{key:1,class:Be(["repo-node",{current:N.repo.id===K(t).currentId}]),title:N.repo.path,onDblclick:x=>w(N)},[k("span",ys,O(N.label),1),k("span",_s,O(c(N.repo.lastOpenedAt)),1),k("span",ws,[h(b,{size:"small",text:"",type:"primary",onClick:De(x=>w(N),["stop"])},{default:u(()=>[...a[5]||(a[5]=[I("进入",-1)])]),_:1},8,["onClick"]),h(b,{size:"small",text:"",type:"danger",onClick:De(x=>v(N.repo.id,N.repo.path),["stop"])},{default:u(()=>[...a[6]||(a[6]=[I("移除",-1)])]),_:1},8,["onClick"])])],42,vs)):(y(),M("span",{key:0,class:"tree-dir",title:N.fullPath},O(N.label),9,bs))]),_:1},8,["data","default-expanded-keys"])]))]),_:1})])}}}),Cs=xe(ks,[["__scopeId","data-v-9d40cd16"]]);function en(s){const t=ht(),n=G(!1),e=G(null),l=G(!1),r=Y(()=>s()!==null);async function o(w,m={}){const a=s();if(a===null)return Z.warning("请先选择仓库"),!1;try{const p=await qe(a,w,{...m,dryRun:!0});return p.success?(e.value={tool:w,params:m,preview:p.preview??p.result},n.value=!0,!0):(i(p),!1)}catch(p){return c(p),!1}}async function f(){const w=s(),m=e.value;if(w===null||!m)return null;l.value=!0,n.value=!1;try{const a=await qe(w,m.tool,m.params);return a.success?(a.backupCreated?Z.success(`${m.tool} 执行成功(已自动备份:${a.backupCreated.branch??"分支"}${a.backupCreated.stashRef?` / ${a.backupCreated.stashRef}`:""})`):Z.success(`${m.tool} 执行成功`),a):(i(a),a)}catch(a){return c(a),null}finally{l.value=!1,e.value=null}}function v(){n.value=!1,e.value=null}function i(w){var m,a,p;if(((m=w.error)==null?void 0:m.code)==="PERMISSION_DENIED"){w.error.requiredApproval?gt.confirm(`操作 ${w.tool} 属于高风险操作,当前默认禁用,需要在设置中开启后才能执行。是否前往设置?`,"需要审批",{confirmButtonText:"去开启",cancelButtonText:"取消",type:"warning"}).then(()=>t.push("/settings")).catch(()=>{}):Z.error(((a=w.error)==null?void 0:a.message)??"操作被拒绝");return}Z.error(((p=w.error)==null?void 0:p.message)??"操作失败")}function c(w){const m=w instanceof Error?w.message:String(w);Z.error(m)}return{confirmVisible:n,pending:e,executing:l,canRun:r,previewAndConfirm:o,executeConfirmed:f,cancel:v}}const xs={key:2,class:"cmd-box"},Ts={class:"cmd-pre mono"},Ss={key:3,class:"files-box"},$s={class:"cmd-label"},Es={key:4,class:"note-text"},Ns={class:"risk-tag"},Ls=Ce({__name:"ConfirmDialog",props:{visible:{type:Boolean},tool:{},preview:{default:null},note:{default:""}},emits:["update:visible","confirm","cancel"],setup(s,{emit:t}){const n=s,e=t,l=Y(()=>{const c=n.preview;return c&&"command"in c&&typeof c.command=="string"?c.command:""}),r=Y(()=>{const c=n.preview,w=c&&"risk"in c&&typeof c.risk=="string"?String(c.risk):"write";return w==="dangerous"||w==="high"?"dangerous":w==="readonly"?"readonly":"write"}),o=Y(()=>{const c=n.preview;return c&&"affectedFiles"in c&&Array.isArray(c.affectedFiles)?c.affectedFiles:[]}),f=Y(()=>r.value==="dangerous"?{type:"danger",label:"高风险"}:r.value==="write"?{type:"warning",label:"写操作"}:{type:"info",label:"只读"});function v(){e("confirm")}function i(){e("cancel"),e("update:visible",!1),Z.info("操作已取消")}return(c,w)=>{const m=R("el-alert"),a=R("el-scrollbar"),p=R("el-tag"),b=R("el-button"),g=R("el-dialog");return y(),H(g,{"model-value":s.visible,title:`执行操作:${s.tool}`,width:"560px","close-on-click-modal":!1,onClosed:w[0]||(w[0]=E=>e("update:visible",!1))},{footer:u(()=>[k("span",Ns,[h(p,{type:f.value.type,size:"small",effect:"dark"},{default:u(()=>[I(O(f.value.label),1)]),_:1},8,["type"])]),h(b,{onClick:i},{default:u(()=>[...w[4]||(w[4]=[I("取消",-1)])]),_:1}),h(b,{type:"primary",danger:r.value==="dangerous",onClick:v},{default:u(()=>[...w[5]||(w[5]=[I("确认执行",-1)])]),_:1},8,["danger"])]),default:u(()=>[r.value==="dangerous"?(y(),H(m,{key:0,type:"error",closable:!1,"show-icon":"",class:"risk-alert"},{title:u(()=>[...w[1]||(w[1]=[I("这是",-1),k("b",null,"高风险",-1),I("操作,将自动创建备份(临时分支 + stash)",-1)])]),_:1})):r.value==="write"?(y(),H(m,{key:1,type:"warning",closable:!1,"show-icon":"",class:"risk-alert"},{title:u(()=>[...w[2]||(w[2]=[I("写操作:执行后将修改仓库状态",-1)])]),_:1})):j("",!0),l.value?(y(),M("div",xs,[w[3]||(w[3]=k("div",{class:"cmd-label"},"将执行的命令(dry-run 预览,未实际执行)",-1)),k("pre",Ts,O(l.value),1)])):j("",!0),o.value.length?(y(),M("div",Ss,[k("div",$s,"涉及文件("+O(o.value.length)+")",1),h(a,{"max-height":"140px"},{default:u(()=>[(y(!0),M(ae,null,he(o.value,E=>(y(),M("div",{key:E,class:"file-item mono"},O(E),1))),128))]),_:1})])):j("",!0),s.note?(y(),M("div",Es,O(s.note),1)):j("",!0)]),_:1},8,["model-value","title"])}}}),tn=xe(Ls,[["__scopeId","data-v-8484f9b1"]]);var oe;(function(s){s.INSERT="insert",s.DELETE="delete",s.CONTEXT="context"})(oe||(oe={}));const Is={LINE_BY_LINE:"line-by-line"},Vs={NONE:"none"},Ds={WORD:"word"};var Ve;(function(s){s.AUTO="auto",s.DARK="dark",s.LIGHT="light"})(Ve||(Ve={}));const Ps=["-","[","]","/","{","}","(",")","*","+","?",".","\\","^","$","|"],Os=RegExp("["+Ps.join("\\")+"]","g");function Rs(s){return s.replace(Os,"\\$&")}function Mt(s){return s&&s.replace(/\\/g,"/")}function As(s){let t,n,e,l=0;for(t=0,e=s.length;t<e;t++)n=s.charCodeAt(t),l=(l<<5)-l+n,l|=0;return l}function nn(s){const t=s.length;let n=-1/0;for(let e=0;e<t;e++)n=Math.max(n,s[e]);return n}function zt(s,t){const n=s.split(".");return n.length>1?n[n.length-1]:t}function Bt(s,t){return t.reduce((n,e)=>n||s.startsWith(e),!1)}const Ht=["a/","b/","i/","w/","c/","o/"];function Le(s,t,n){const e=n!==void 0?[...Ht,n]:Ht,l=t?new RegExp(`^${Rs(t)} "?(.+?)"?$`):new RegExp('^"?(.+?)"?$'),[,r=""]=l.exec(s)||[],o=e.find(v=>r.indexOf(v)===0);return(o?r.slice(o.length):r).replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [+-]\d{4}.*$/,"")}function Fs(s,t){return Le(s,"---",t)}function Ms(s,t){return Le(s,"+++",t)}function zs(s,t={}){const n=[];let e=null,l=null,r=null,o=null,f=null,v=null,i=null;const c="--- ",w="+++ ",m="@@",a=/^old mode (\d{6})/,p=/^new mode (\d{6})/,b=/^deleted file mode (\d{6})/,g=/^new file mode (\d{6})/,E=/^copy from "?(.+)"?/,A=/^copy to "?(.+)"?/,N=/^rename from "?(.+)"?/,x=/^rename to "?(.+)"?/,V=/^similarity index (\d+)%/,B=/^dissimilarity index (\d+)%/,Q=/^index ([\da-z]+)\.\.([\da-z]+)\s*(\d{6})?/,_=/^Binary files (.*) and (.*) differ/,$=/^GIT binary patch/,S=/^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/,L=/^mode (\d{6}),(\d{6})\.\.(\d{6})/,P=/^new file mode (\d{6})/,X=/^deleted file mode (\d{6}),(\d{6})/,J=s.replace(/\/g,"").replace(/\r\n?/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`);function W(){l!==null&&e!==null&&(e.blocks.push(l),l=null)}function te(){e!==null&&(!e.oldName&&v!==null&&(e.oldName=v),!e.newName&&i!==null&&(e.newName=i),e.newName&&(n.push(e),e=null)),v=null,i=null}function ue(){W(),te(),e={blocks:[],deletedLines:0,addedLines:0}}function ee(T){W();let U;e!==null&&((U=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@.*/.exec(T))?(e.isCombined=!1,r=parseInt(U[1],10),f=parseInt(U[2],10)):(U=/^@@@ -(\d+)(?:,\d+)? -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@@.*/.exec(T))?(e.isCombined=!0,r=parseInt(U[1],10),o=parseInt(U[2],10),f=parseInt(U[3],10)):(T.startsWith(m)&&console.error("Failed to parse lines, starting in 0!"),r=0,f=0,e.isCombined=!1)),l={lines:[],oldStartLine:r,oldStartLine2:o,newStartLine:f,header:T}}function ne(T){if(e===null||l===null||r===null||f===null)return;const U={content:T},D=e.isCombined?["+ "," +","++"]:["+"],de=e.isCombined?["- "," -","--"]:["-"];Bt(T,D)?(e.addedLines++,U.type=oe.INSERT,U.oldNumber=void 0,U.newNumber=f++):Bt(T,de)?(e.deletedLines++,U.type=oe.DELETE,U.oldNumber=r++,U.newNumber=void 0):(U.type=oe.CONTEXT,U.oldNumber=r++,U.newNumber=f++),l.lines.push(U)}function pe(T,U){let D=U;for(;D<J.length-3;){if(T.startsWith("diff"))return!1;if(J[D].startsWith(c)&&J[D+1].startsWith(w)&&J[D+2].startsWith(m))return!0;D++}return!1}return J.forEach((T,U)=>{if(!T||T.startsWith("*"))return;let D;const de=J[U-1],Ee=J[U+1],Te=J[U+2];if(T.startsWith("diff --git")||T.startsWith("diff --combined")){if(ue(),(D=/^diff --git "?([a-ciow]\/.+)"? "?([a-ciow]\/.+)"?/.exec(T))&&(v=Le(D[1],void 0,t.dstPrefix),i=Le(D[2],void 0,t.srcPrefix)),e===null)throw new Error("Where is my file !!!");e.isGitDiff=!0;return}if(T.startsWith("Binary files")&&!(e!=null&&e.isGitDiff)){if(ue(),(D=/^Binary files "?([a-ciow]\/.+)"? and "?([a-ciow]\/.+)"? differ/.exec(T))&&(v=Le(D[1],void 0,t.dstPrefix),i=Le(D[2],void 0,t.srcPrefix)),e===null)throw new Error("Where is my file !!!");e.isBinary=!0;return}if((!e||!e.isGitDiff&&e&&T.startsWith(c)&&Ee.startsWith(w)&&Te.startsWith(m))&&ue(),e!=null&&e.isTooBig)return;if(e&&(typeof t.diffMaxChanges=="number"&&e.addedLines+e.deletedLines>t.diffMaxChanges||typeof t.diffMaxLineLength=="number"&&T.length>t.diffMaxLineLength)){e.isTooBig=!0,e.addedLines=0,e.deletedLines=0,e.blocks=[],l=null;const Ie=typeof t.diffTooBigMessage=="function"?t.diffTooBigMessage(n.length):"Diff too big to be displayed";ee(Ie);return}if(T.startsWith(c)&&Ee.startsWith(w)||T.startsWith(w)&&de.startsWith(c)){if(e&&!e.oldName&&T.startsWith("--- ")&&(D=Fs(T,t.srcPrefix))){e.oldName=D,e.language=zt(e.oldName,e.language);return}if(e&&!e.newName&&T.startsWith("+++ ")&&(D=Ms(T,t.dstPrefix))){e.newName=D,e.language=zt(e.newName,e.language);return}}if(e&&(T.startsWith(m)||e.isGitDiff&&e.oldName&&e.newName&&!l)){ee(T);return}if(l&&(T.startsWith("+")||T.startsWith("-")||T.startsWith(" "))){ne(T);return}const se=!pe(T,U);if(e===null)throw new Error("Where is my file !!!");(D=a.exec(T))?e.oldMode=D[1]:(D=p.exec(T))?e.newMode=D[1]:(D=b.exec(T))?(e.deletedFileMode=D[1],e.isDeleted=!0):(D=g.exec(T))?(e.newFileMode=D[1],e.isNew=!0):(D=E.exec(T))?(se&&(e.oldName=D[1]),e.isCopy=!0):(D=A.exec(T))?(se&&(e.newName=D[1]),e.isCopy=!0):(D=N.exec(T))?(se&&(e.oldName=D[1]),e.isRename=!0):(D=x.exec(T))?(se&&(e.newName=D[1]),e.isRename=!0):(D=_.exec(T))?(e.isBinary=!0,e.oldName=Le(D[1],void 0,t.srcPrefix),e.newName=Le(D[2],void 0,t.dstPrefix),ee("Binary file")):$.test(T)?(e.isBinary=!0,ee(T)):(D=V.exec(T))?e.unchangedPercentage=parseInt(D[1],10):(D=B.exec(T))?e.changedPercentage=parseInt(D[1],10):(D=Q.exec(T))?(e.checksumBefore=D[1],e.checksumAfter=D[2],D[3]&&(e.mode=D[3])):(D=S.exec(T))?(e.checksumBefore=[D[2],D[3]],e.checksumAfter=D[1]):(D=L.exec(T))?(e.oldMode=[D[2],D[3]],e.newMode=D[1]):(D=P.exec(T))?(e.newFileMode=D[1],e.isNew=!0):(D=X.exec(T))&&(e.deletedFileMode=D[1],e.isDeleted=!0)}),W(),te(),n}class sn{diff(t,n,e={}){let l;typeof e=="function"?(l=e,e={}):"callback"in e&&(l=e.callback);const r=this.castInput(t,e),o=this.castInput(n,e),f=this.removeEmpty(this.tokenize(r,e)),v=this.removeEmpty(this.tokenize(o,e));return this.diffWithOptionsObj(f,v,e,l)}diffWithOptionsObj(t,n,e,l){var r;const o=A=>{if(A=this.postProcess(A,e),l){setTimeout(function(){l(A)},0);return}else return A},f=n.length,v=t.length;let i=1,c=f+v;e.maxEditLength!=null&&(c=Math.min(c,e.maxEditLength));const w=(r=e.timeout)!==null&&r!==void 0?r:1/0,m=Date.now()+w,a=[{oldPos:-1,lastComponent:void 0}];let p=this.extractCommon(a[0],n,t,0,e);if(a[0].oldPos+1>=v&&p+1>=f)return o(this.buildValues(a[0].lastComponent,n,t));let b=-1/0,g=1/0;const E=()=>{for(let A=Math.max(b,-i);A<=Math.min(g,i);A+=2){let N;const x=a[A-1],V=a[A+1];x&&(a[A-1]=void 0);let B=!1;if(V){const _=V.oldPos-A;B=V&&0<=_&&_<f}const Q=x&&x.oldPos+1<v;if(!B&&!Q){a[A]=void 0;continue}if(!Q||B&&x.oldPos<V.oldPos?N=this.addToPath(V,!0,!1,0,e):N=this.addToPath(x,!1,!0,1,e),p=this.extractCommon(N,n,t,A,e),N.oldPos+1>=v&&p+1>=f)return o(this.buildValues(N.lastComponent,n,t))||!0;a[A]=N,N.oldPos+1>=v&&(g=Math.min(g,A-1)),p+1>=f&&(b=Math.max(b,A+1))}i++};if(l)(function A(){setTimeout(function(){if(i>c||Date.now()>m)return l(void 0);E()||A()},0)})();else for(;i<=c&&Date.now()<=m;){const A=E();if(A)return A}}addToPath(t,n,e,l,r){const o=t.lastComponent;return o&&!r.oneChangePerToken&&o.added===n&&o.removed===e?{oldPos:t.oldPos+l,lastComponent:{count:o.count+1,added:n,removed:e,previousComponent:o.previousComponent}}:{oldPos:t.oldPos+l,lastComponent:{count:1,added:n,removed:e,previousComponent:o}}}extractCommon(t,n,e,l,r){const o=n.length,f=e.length;let v=t.oldPos,i=v-l,c=0;for(;i+1<o&&v+1<f&&this.equals(e[v+1],n[i+1],r);)i++,v++,c++,r.oneChangePerToken&&(t.lastComponent={count:1,previousComponent:t.lastComponent,added:!1,removed:!1});return c&&!r.oneChangePerToken&&(t.lastComponent={count:c,previousComponent:t.lastComponent,added:!1,removed:!1}),t.oldPos=v,i}equals(t,n,e){return e.comparator?e.comparator(t,n):t===n||!!e.ignoreCase&&t.toLowerCase()===n.toLowerCase()}removeEmpty(t){const n=[];for(let e=0;e<t.length;e++)t[e]&&n.push(t[e]);return n}castInput(t,n){return t}tokenize(t,n){return Array.from(t)}join(t){return t.join("")}postProcess(t,n){return t}get useLongestToken(){return!1}buildValues(t,n,e){const l=[];let r;for(;t;)l.push(t),r=t.previousComponent,delete t.previousComponent,t=r;l.reverse();const o=l.length;let f=0,v=0,i=0;for(;f<o;f++){const c=l[f];if(c.removed)c.value=this.join(e.slice(i,i+c.count)),i+=c.count;else{if(!c.added&&this.useLongestToken){let w=n.slice(v,v+c.count);w=w.map(function(m,a){const p=e[i+a];return p.length>m.length?p:m}),c.value=this.join(w)}else c.value=this.join(n.slice(v,v+c.count));v+=c.count,c.added||(i+=c.count)}}return l}}class Bs extends sn{}const Hs=new Bs;function Us(s,t,n){return Hs.diff(s,t,n)}const Ut="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";class Ws extends sn{tokenize(t){const n=new RegExp(`(\\r?\\n)|[${Ut}]+|[^\\S\\n\\r]+|[^${Ut}]`,"ug");return t.match(n)||[]}}const js=new Ws;function Gs(s,t,n){return js.diff(s,t,n)}function qs(s,t){if(s.length===0)return t.length;if(t.length===0)return s.length;const n=[];let e;for(e=0;e<=t.length;e++)n[e]=[e];let l;for(l=0;l<=s.length;l++)n[0][l]=l;for(e=1;e<=t.length;e++)for(l=1;l<=s.length;l++)t.charAt(e-1)===s.charAt(l-1)?n[e][l]=n[e-1][l-1]:n[e][l]=Math.min(n[e-1][l-1]+1,Math.min(n[e][l-1]+1,n[e-1][l]+1));return n[t.length][s.length]}function bt(s){return(t,n)=>{const e=s(t).trim(),l=s(n).trim();return qs(e,l)/(e.length+l.length)}}function vt(s){function t(e,l,r=new Map){let o=1/0,f;for(let v=0;v<e.length;++v)for(let i=0;i<l.length;++i){const c=JSON.stringify([e[v],l[i]]);let w;r.has(c)&&(w=r.get(c))||(w=s(e[v],l[i]),r.set(c,w)),w<o&&(o=w,f={indexA:v,indexB:i,score:o})}return f}function n(e,l,r=0,o=new Map){const f=t(e,l,o);if(!f||e.length+l.length<3)return[[e,l]];const v=e.slice(0,f.indexA),i=l.slice(0,f.indexB),c=[e[f.indexA]],w=[l[f.indexB]],m=f.indexA+1,a=f.indexB+1,p=e.slice(m),b=l.slice(a),g=n(v,i,r+1,o),E=n(c,w,r+1,o),A=n(p,b,r+1,o);let N=E;return(f.indexA>0||f.indexB>0)&&(N=g.concat(N)),(e.length>m||l.length>a)&&(N=N.concat(A)),N}return n}const fe={INSERTS:"d2h-ins",DELETES:"d2h-del",CONTEXT:"d2h-cntx",INFO:"d2h-info",INSERT_CHANGES:"d2h-ins d2h-change",DELETE_CHANGES:"d2h-del d2h-change"},Ze={matching:Vs.NONE,matchWordsThreshold:.25,maxLineLengthHighlight:1e4,diffStyle:Ds.WORD,colorScheme:Ve.LIGHT},we="/",ln=bt(s=>s.value),Ks=vt(ln);function at(s){return s.indexOf("dev/null")!==-1}function Xs(s){return s.replace(/(<ins[^>]*>((.|\n)*?)<\/ins>)/g,"")}function Js(s){return s.replace(/(<del[^>]*>((.|\n)*?)<\/del>)/g,"")}function Ke(s){switch(s){case oe.CONTEXT:return fe.CONTEXT;case oe.INSERT:return fe.INSERTS;case oe.DELETE:return fe.DELETES}}function yt(s){switch(s){case Ve.DARK:return"d2h-dark-color-scheme";case Ve.AUTO:return"d2h-auto-color-scheme";case Ve.LIGHT:default:return"d2h-light-color-scheme"}}function Ys(s){return s?2:1}function Pe(s){return s.slice(0).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}function ke(s,t,n=!0){const e=Ys(t);return{prefix:s.substring(0,e),content:n?Pe(s.substring(e)):s.substring(e)}}function et(s){const t=Mt(s.oldName),n=Mt(s.newName);if(t!==n&&!at(t)&&!at(n)){const e=[],l=[],r=t.split(we),o=n.split(we),f=r.length,v=o.length;let i=0,c=f-1,w=v-1;for(;i<c&&i<w&&r[i]===o[i];)e.push(o[i]),i+=1;for(;c>i&&w>i&&r[c]===o[w];)l.unshift(o[w]),c-=1,w-=1;const m=e.join(we),a=l.join(we),p=r.slice(i,c+1).join(we),b=o.slice(i,w+1).join(we);return m.length&&a.length?m+we+"{"+p+" → "+b+"}"+we+a:m.length?m+we+"{"+p+" → "+b+"}":a.length?"{"+p+" → "+b+"}"+we+a:t+" → "+n}else return at(n)?t:n}function _t(s){return`d2h-${As(et(s)).toString().slice(-6)}`}function wt(s){let t="file-changed";return s.isRename||s.isCopy?t="file-renamed":s.isNew?t="file-added":s.isDeleted?t="file-deleted":s.newName!==s.oldName&&(t="file-renamed"),t}function an(s,t,n,e={}){const{matching:l,maxLineLengthHighlight:r,matchWordsThreshold:o,diffStyle:f}=Object.assign(Object.assign({},Ze),e),v=ke(s,n,!1),i=ke(t,n,!1);if(v.content.length>r||i.content.length>r)return{oldLine:{prefix:v.prefix,content:Pe(v.content)},newLine:{prefix:i.prefix,content:Pe(i.content)}};const c=f==="char"?Us(v.content,i.content):Gs(v.content,i.content),w=[];if(f==="word"&&l==="words"){const a=c.filter(g=>g.removed),p=c.filter(g=>g.added);Ks(p,a).forEach(g=>{g[0].length===1&&g[1].length===1&&ln(g[0][0],g[1][0])<o&&(w.push(g[0][0]),w.push(g[1][0]))})}const m=c.reduce((a,p)=>{const b=p.added?"ins":p.removed?"del":null,g=w.indexOf(p)>-1?' class="d2h-change"':"",E=Pe(p.value);return b!==null?`${a}<${b}${g}>${E}</${b}>`:`${a}${E}`},"");return{oldLine:{prefix:v.prefix,content:Xs(m)},newLine:{prefix:i.prefix,content:Js(m)}}}const Wt="file-summary",Qs="icon",Zs={colorScheme:Ze.colorScheme};class el{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},Zs),n)}render(t){const n=t.map(e=>this.hoganUtils.render(Wt,"line",{fileHtmlId:_t(e),oldName:e.oldName,newName:e.newName,fileName:et(e),deletedLines:"-"+e.deletedLines,addedLines:"+"+e.addedLines},{fileIcon:this.hoganUtils.template(Qs,wt(e))})).join(`
|
|
4
|
+
`);return this.hoganUtils.render(Wt,"wrapper",{colorScheme:yt(this.config.colorScheme),filesNumber:t.length,files:n})}}const on=Object.assign(Object.assign({},Ze),{renderNothingWhenEmpty:!1,matchingMaxComparisons:2500,maxLineSizeInBlockForComparison:200}),Me="generic",jt="line-by-line",tl="icon",nl="tag";class sl{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},on),n)}render(t){const n=t.map(e=>{let l;return e.blocks.length?l=this.generateFileHtml(e):l=this.generateEmptyDiff(),this.makeFileDiffHtml(e,l)}).join(`
|
|
5
|
+
`);return this.hoganUtils.render(Me,"wrapper",{colorScheme:yt(this.config.colorScheme),content:n})}makeFileDiffHtml(t,n){if(this.config.renderNothingWhenEmpty&&Array.isArray(t.blocks)&&t.blocks.length===0)return"";const e=this.hoganUtils.template(jt,"file-diff"),l=this.hoganUtils.template(Me,"file-path"),r=this.hoganUtils.template(tl,"file"),o=this.hoganUtils.template(nl,wt(t));return e.render({file:t,fileHtmlId:_t(t),diffs:n,filePath:l.render({fileDiffName:et(t)},{fileIcon:r,fileTag:o})})}generateEmptyDiff(){return this.hoganUtils.render(Me,"empty-diff",{contentClass:"d2h-code-line",CSSLineClass:fe})}generateFileHtml(t){const n=vt(bt(e=>ke(e.content,t.isCombined).content));return t.blocks.map(e=>{let l=this.hoganUtils.render(Me,"block-header",{CSSLineClass:fe,blockHeader:t.isTooBig?e.header:Pe(e.header),lineClass:"d2h-code-linenumber",contentClass:"d2h-code-line"});return this.applyLineGroupping(e).forEach(([r,o,f])=>{if(o.length&&f.length&&!r.length)this.applyRematchMatching(o,f,n).map(([v,i])=>{const{left:c,right:w}=this.processChangedLines(t,t.isCombined,v,i);l+=c,l+=w});else if(r.length)r.forEach(v=>{const{prefix:i,content:c}=ke(v.content,t.isCombined);l+=this.generateSingleLineHtml(t,{type:fe.CONTEXT,prefix:i,content:c,oldNumber:v.oldNumber,newNumber:v.newNumber})});else if(o.length||f.length){const{left:v,right:i}=this.processChangedLines(t,t.isCombined,o,f);l+=v,l+=i}else console.error("Unknown state reached while processing groups of lines",r,o,f)}),l}).join(`
|
|
6
|
+
`)}applyLineGroupping(t){const n=[];let e=[],l=[];for(let r=0;r<t.lines.length;r++){const o=t.lines[r];(o.type!==oe.INSERT&&l.length||o.type===oe.CONTEXT&&e.length>0)&&(n.push([[],e,l]),e=[],l=[]),o.type===oe.CONTEXT?n.push([[o],[],[]]):o.type===oe.INSERT&&e.length===0?n.push([[],[],[o]]):o.type===oe.INSERT&&e.length>0?l.push(o):o.type===oe.DELETE&&e.push(o)}return(e.length||l.length)&&(n.push([[],e,l]),e=[],l=[]),n}applyRematchMatching(t,n,e){const l=t.length*n.length,r=nn(t.concat(n).map(f=>f.content.length));return l<this.config.matchingMaxComparisons&&r<this.config.maxLineSizeInBlockForComparison&&(this.config.matching==="lines"||this.config.matching==="words")?e(t,n):[[t,n]]}processChangedLines(t,n,e,l){const r={right:"",left:""},o=Math.max(e.length,l.length);for(let f=0;f<o;f++){const v=e[f],i=l[f],c=v!==void 0&&i!==void 0?an(v.content,i.content,n,this.config):void 0,w=v!==void 0&&v.oldNumber!==void 0?Object.assign(Object.assign({},c!==void 0?{prefix:c.oldLine.prefix,content:c.oldLine.content,type:fe.DELETE_CHANGES}:Object.assign(Object.assign({},ke(v.content,n)),{type:Ke(v.type)})),{oldNumber:v.oldNumber,newNumber:v.newNumber}):void 0,m=i!==void 0&&i.newNumber!==void 0?Object.assign(Object.assign({},c!==void 0?{prefix:c.newLine.prefix,content:c.newLine.content,type:fe.INSERT_CHANGES}:Object.assign(Object.assign({},ke(i.content,n)),{type:Ke(i.type)})),{oldNumber:i.oldNumber,newNumber:i.newNumber}):void 0,{left:a,right:p}=this.generateLineHtml(t,w,m);r.left+=a,r.right+=p}return r}generateLineHtml(t,n,e){return{left:this.generateSingleLineHtml(t,n),right:this.generateSingleLineHtml(t,e)}}generateSingleLineHtml(t,n){if(n===void 0)return"";const e=this.hoganUtils.render(jt,"numbers",{oldNumber:n.oldNumber||"",newNumber:n.newNumber||""});return this.hoganUtils.render(Me,"line",{type:n.type,lineClass:"d2h-code-linenumber",contentClass:"d2h-code-line",prefix:n.prefix===" "?" ":n.prefix,content:n.content,lineNumber:e,line:n,file:t})}}const rn=Object.assign(Object.assign({},Ze),{renderNothingWhenEmpty:!1,matchingMaxComparisons:2500,maxLineSizeInBlockForComparison:200}),ze="generic",ll="side-by-side",al="icon",il="tag";class ol{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},rn),n)}render(t){const n=t.map(e=>{let l;return e.blocks.length?l=this.generateFileHtml(e):l=this.generateEmptyDiff(),this.makeFileDiffHtml(e,l)}).join(`
|
|
7
|
+
`);return this.hoganUtils.render(ze,"wrapper",{colorScheme:yt(this.config.colorScheme),content:n})}makeFileDiffHtml(t,n){if(this.config.renderNothingWhenEmpty&&Array.isArray(t.blocks)&&t.blocks.length===0)return"";const e=this.hoganUtils.template(ll,"file-diff"),l=this.hoganUtils.template(ze,"file-path"),r=this.hoganUtils.template(al,"file"),o=this.hoganUtils.template(il,wt(t));return e.render({file:t,fileHtmlId:_t(t),diffs:n,filePath:l.render({fileDiffName:et(t)},{fileIcon:r,fileTag:o})})}generateEmptyDiff(){return{right:"",left:this.hoganUtils.render(ze,"empty-diff",{contentClass:"d2h-code-side-line",CSSLineClass:fe})}}generateFileHtml(t){const n=vt(bt(e=>ke(e.content,t.isCombined).content));return t.blocks.map(e=>{const l={left:this.makeHeaderHtml(e.header,t),right:this.makeHeaderHtml("")};return this.applyLineGroupping(e).forEach(([r,o,f])=>{if(o.length&&f.length&&!r.length)this.applyRematchMatching(o,f,n).map(([v,i])=>{const{left:c,right:w}=this.processChangedLines(t.isCombined,v,i);l.left+=c,l.right+=w});else if(r.length)r.forEach(v=>{const{prefix:i,content:c}=ke(v.content,t.isCombined),{left:w,right:m}=this.generateLineHtml({type:fe.CONTEXT,prefix:i,content:c,number:v.oldNumber},{type:fe.CONTEXT,prefix:i,content:c,number:v.newNumber});l.left+=w,l.right+=m});else if(o.length||f.length){const{left:v,right:i}=this.processChangedLines(t.isCombined,o,f);l.left+=v,l.right+=i}else console.error("Unknown state reached while processing groups of lines",r,o,f)}),l}).reduce((e,l)=>({left:e.left+l.left,right:e.right+l.right}),{left:"",right:""})}applyLineGroupping(t){const n=[];let e=[],l=[];for(let r=0;r<t.lines.length;r++){const o=t.lines[r];(o.type!==oe.INSERT&&l.length||o.type===oe.CONTEXT&&e.length>0)&&(n.push([[],e,l]),e=[],l=[]),o.type===oe.CONTEXT?n.push([[o],[],[]]):o.type===oe.INSERT&&e.length===0?n.push([[],[],[o]]):o.type===oe.INSERT&&e.length>0?l.push(o):o.type===oe.DELETE&&e.push(o)}return(e.length||l.length)&&(n.push([[],e,l]),e=[],l=[]),n}applyRematchMatching(t,n,e){const l=t.length*n.length,r=nn(t.concat(n).map(f=>f.content.length));return l<this.config.matchingMaxComparisons&&r<this.config.maxLineSizeInBlockForComparison&&(this.config.matching==="lines"||this.config.matching==="words")?e(t,n):[[t,n]]}makeHeaderHtml(t,n){return this.hoganUtils.render(ze,"block-header",{CSSLineClass:fe,blockHeader:n!=null&&n.isTooBig?t:Pe(t),lineClass:"d2h-code-side-linenumber",contentClass:"d2h-code-side-line"})}processChangedLines(t,n,e){const l={right:"",left:""},r=Math.max(n.length,e.length);for(let o=0;o<r;o++){const f=n[o],v=e[o],i=f!==void 0&&v!==void 0?an(f.content,v.content,t,this.config):void 0,c=f!==void 0&&f.oldNumber!==void 0?Object.assign(Object.assign({},i!==void 0?{prefix:i.oldLine.prefix,content:i.oldLine.content,type:fe.DELETE_CHANGES}:Object.assign(Object.assign({},ke(f.content,t)),{type:Ke(f.type)})),{number:f.oldNumber}):void 0,w=v!==void 0&&v.newNumber!==void 0?Object.assign(Object.assign({},i!==void 0?{prefix:i.newLine.prefix,content:i.newLine.content,type:fe.INSERT_CHANGES}:Object.assign(Object.assign({},ke(v.content,t)),{type:Ke(v.type)})),{number:v.newNumber}):void 0,{left:m,right:a}=this.generateLineHtml(c,w);l.left+=m,l.right+=a}return l}generateLineHtml(t,n){return{left:this.generateSingleHtml(t),right:this.generateSingleHtml(n)}}generateSingleHtml(t){const n="d2h-code-side-linenumber",e="d2h-code-side-line";return this.hoganUtils.render(ze,"line",{type:(t==null?void 0:t.type)||`${fe.CONTEXT} d2h-emptyplaceholder`,lineClass:t!==void 0?n:`${n} d2h-code-side-emptyplaceholder`,contentClass:t!==void 0?e:`${e} d2h-code-side-emptyplaceholder`,prefix:(t==null?void 0:t.prefix)===" "?" ":t==null?void 0:t.prefix,content:t==null?void 0:t.content,lineNumber:t==null?void 0:t.number})}}var it={},Gt;function rl(){return Gt||(Gt=1,(function(s){(function(t){var n=/\S/,e=/\"/g,l=/\n/g,r=/\r/g,o=/\\/g,f=/\u2028/,v=/\u2029/;t.tags={"#":1,"^":2,"<":3,$:4,"/":5,"!":6,">":7,"=":8,_v:9,"{":10,"&":11,_t:12},t.scan=function($,S){var L=$.length,P=0,X=1,J=2,W=P,te=null,ue=null,ee="",ne=[],pe=!1,T=0,U=0,D="{{",de="}}";function Ee(){ee.length>0&&(ne.push({tag:"_t",text:new String(ee)}),ee="")}function Te(){for(var me=!0,ge=U;ge<ne.length;ge++)if(me=t.tags[ne[ge].tag]<t.tags._v||ne[ge].tag=="_t"&&ne[ge].text.match(n)===null,!me)return!1;return me}function se(me,ge){if(Ee(),me&&Te())for(var ve=U,Ne;ve<ne.length;ve++)ne[ve].text&&((Ne=ne[ve+1])&&Ne.tag==">"&&(Ne.indent=ne[ve].text.toString()),ne.splice(ve,1));else ge||ne.push({tag:`
|
|
8
|
+
`});pe=!1,U=ne.length}function Ie(me,ge){var ve="="+de,Ne=me.indexOf(ve,ge),Re=c(me.substring(me.indexOf("=",ge)+1,Ne)).split(" ");return D=Re[0],de=Re[Re.length-1],Ne+ve.length-1}for(S&&(S=S.split(" "),D=S[0],de=S[1]),T=0;T<L;T++)W==P?w(D,$,T)?(--T,Ee(),W=X):$.charAt(T)==`
|
|
9
|
+
`?se(pe):ee+=$.charAt(T):W==X?(T+=D.length-1,ue=t.tags[$.charAt(T+1)],te=ue?$.charAt(T+1):"_v",te=="="?(T=Ie($,T),W=P):(ue&&T++,W=J),pe=T):w(de,$,T)?(ne.push({tag:te,n:c(ee),otag:D,ctag:de,i:te=="/"?pe-D.length:T+de.length}),ee="",T+=de.length-1,W=P,te=="{"&&(de=="}}"?T++:i(ne[ne.length-1]))):ee+=$.charAt(T);return se(pe,!0),ne};function i(_){_.n.substr(_.n.length-1)==="}"&&(_.n=_.n.substring(0,_.n.length-1))}function c(_){return _.trim?_.trim():_.replace(/^\s*|\s*$/g,"")}function w(_,$,S){if($.charAt(S)!=_.charAt(0))return!1;for(var L=1,P=_.length;L<P;L++)if($.charAt(S+L)!=_.charAt(L))return!1;return!0}var m={_t:!0,"\n":!0,$:!0,"/":!0};function a(_,$,S,L){var P=[],X=null,J=null,W=null;for(J=S[S.length-1];_.length>0;){if(W=_.shift(),J&&J.tag=="<"&&!(W.tag in m))throw new Error("Illegal content in < super tag.");if(t.tags[W.tag]<=t.tags.$||p(W,L))S.push(W),W.nodes=a(_,W.tag,S,L);else if(W.tag=="/"){if(S.length===0)throw new Error("Closing tag without opener: /"+W.n);if(X=S.pop(),W.n!=X.n&&!b(W.n,X.n,L))throw new Error("Nesting error: "+X.n+" vs. "+W.n);return X.end=W.i,P}else W.tag==`
|
|
10
|
+
`&&(W.last=_.length==0||_[0].tag==`
|
|
11
|
+
`);P.push(W)}if(S.length>0)throw new Error("missing closing tag: "+S.pop().n);return P}function p(_,$){for(var S=0,L=$.length;S<L;S++)if($[S].o==_.n)return _.tag="#",!0}function b(_,$,S){for(var L=0,P=S.length;L<P;L++)if(S[L].c==_&&S[L].o==$)return!0}function g(_){var $=[];for(var S in _)$.push('"'+N(S)+'": function(c,p,t,i) {'+_[S]+"}");return"{ "+$.join(",")+" }"}function E(_){var $=[];for(var S in _.partials)$.push('"'+N(S)+'":{name:"'+N(_.partials[S].name)+'", '+E(_.partials[S])+"}");return"partials: {"+$.join(",")+"}, subs: "+g(_.subs)}t.stringify=function(_,$,S){return"{code: function (c,p,i) { "+t.wrapMain(_.code)+" },"+E(_)+"}"};var A=0;t.generate=function(_,$,S){A=0;var L={code:"",subs:{},partials:{}};return t.walk(_,L),S.asString?this.stringify(L,$,S):this.makeTemplate(L,$,S)},t.wrapMain=function(_){return'var t=this;t.b(i=i||"");'+_+"return t.fl();"},t.template=t.Template,t.makeTemplate=function(_,$,S){var L=this.makePartials(_);return L.code=new Function("c","p","i",this.wrapMain(_.code)),new this.template(L,$,this,S)},t.makePartials=function(_){var $,S={subs:{},partials:_.partials,name:_.name};for($ in S.partials)S.partials[$]=this.makePartials(S.partials[$]);for($ in _.subs)S.subs[$]=new Function("c","p","t","i",_.subs[$]);return S};function N(_){return _.replace(o,"\\\\").replace(e,'\\"').replace(l,"\\n").replace(r,"\\r").replace(f,"\\u2028").replace(v,"\\u2029")}function x(_){return~_.indexOf(".")?"d":"f"}function V(_,$){var S="<"+($.prefix||""),L=S+_.n+A++;return $.partials[L]={name:_.n,partials:{}},$.code+='t.b(t.rp("'+N(L)+'",c,p,"'+(_.indent||"")+'"));',L}t.codegen={"#":function(_,$){$.code+="if(t.s(t."+x(_.n)+'("'+N(_.n)+'",c,p,1),c,p,0,'+_.i+","+_.end+',"'+_.otag+" "+_.ctag+'")){t.rs(c,p,function(c,p,t){',t.walk(_.nodes,$),$.code+="});c.pop();}"},"^":function(_,$){$.code+="if(!t.s(t."+x(_.n)+'("'+N(_.n)+'",c,p,1),c,p,1,0,0,"")){',t.walk(_.nodes,$),$.code+="};"},">":V,"<":function(_,$){var S={partials:{},code:"",subs:{},inPartial:!0};t.walk(_.nodes,S);var L=$.partials[V(_,$)];L.subs=S.subs,L.partials=S.partials},$:function(_,$){var S={subs:{},code:"",partials:$.partials,prefix:_.n};t.walk(_.nodes,S),$.subs[_.n]=S.code,$.inPartial||($.code+='t.sub("'+N(_.n)+'",c,p,i);')},"\n":function(_,$){$.code+=Q('"\\n"'+(_.last?"":" + i"))},_v:function(_,$){$.code+="t.b(t.v(t."+x(_.n)+'("'+N(_.n)+'",c,p,0)));'},_t:function(_,$){$.code+=Q('"'+N(_.text)+'"')},"{":B,"&":B};function B(_,$){$.code+="t.b(t.t(t."+x(_.n)+'("'+N(_.n)+'",c,p,0)));'}function Q(_){return"t.b("+_+");"}t.walk=function(_,$){for(var S,L=0,P=_.length;L<P;L++)S=t.codegen[_[L].tag],S&&S(_[L],$);return $},t.parse=function(_,$,S){return S=S||{},a(_,"",[],S.sectionTags||[])},t.cache={},t.cacheKey=function(_,$){return[_,!!$.asString,!!$.disableLambda,$.delimiters,!!$.modelGet].join("||")},t.compile=function(_,$){$=$||{};var S=t.cacheKey(_,$),L=this.cache[S];if(L){var P=L.partials;for(var X in P)delete P[X].instance;return L}return L=this.generate(this.parse(this.scan(_,$.delimiters),_,$),_,$),this.cache[S]=L}})(s)})(it)),it}var ot={},qt;function ul(){return qt||(qt=1,(function(s){(function(t){t.Template=function(a,p,b,g){a=a||{},this.r=a.code||this.r,this.c=b,this.options=g||{},this.text=p||"",this.partials=a.partials||{},this.subs=a.subs||{},this.buf=""},t.Template.prototype={r:function(a,p,b){return""},v:w,t:c,render:function(p,b,g){return this.ri([p],b||{},g)},ri:function(a,p,b){return this.r(a,p,b)},ep:function(a,p){var b=this.partials[a],g=p[b.name];if(b.instance&&b.base==g)return b.instance;if(typeof g=="string"){if(!this.c)throw new Error("No compiler available.");g=this.c.compile(g,this.options)}if(!g)return null;if(this.partials[a].base=g,b.subs){p.stackText||(p.stackText={});for(key in b.subs)p.stackText[key]||(p.stackText[key]=this.activeSub!==void 0&&p.stackText[this.activeSub]?p.stackText[this.activeSub]:this.text);g=e(g,b.subs,b.partials,this.stackSubs,this.stackPartials,p.stackText)}return this.partials[a].instance=g,g},rp:function(a,p,b,g){var E=this.ep(a,b);return E?E.ri(p,b,g):""},rs:function(a,p,b){var g=a[a.length-1];if(!m(g)){b(a,p,this);return}for(var E=0;E<g.length;E++)a.push(g[E]),b(a,p,this),a.pop()},s:function(a,p,b,g,E,A,N){var x;return m(a)&&a.length===0?!1:(typeof a=="function"&&(a=this.ms(a,p,b,g,E,A,N)),x=!!a,!g&&x&&p&&p.push(typeof a=="object"?a:p[p.length-1]),x)},d:function(a,p,b,g){var E,A=a.split("."),N=this.f(A[0],p,b,g),x=this.options.modelGet,V=null;if(a==="."&&m(p[p.length-2]))N=p[p.length-1];else for(var B=1;B<A.length;B++)E=n(A[B],N,x),E!==void 0?(V=N,N=E):N="";return g&&!N?!1:(!g&&typeof N=="function"&&(p.push(V),N=this.mv(N,p,b),p.pop()),N)},f:function(a,p,b,g){for(var E=!1,A=null,N=!1,x=this.options.modelGet,V=p.length-1;V>=0;V--)if(A=p[V],E=n(a,A,x),E!==void 0){N=!0;break}return N?(!g&&typeof E=="function"&&(E=this.mv(E,p,b)),E):g?!1:""},ls:function(a,p,b,g,E,A){var N=this.options.delimiters;return this.options.delimiters=A,this.b(this.ct(c(a.call(p,E,b)),p,g)),this.options.delimiters=N,!1},ct:function(a,p,b){if(this.options.disableLambda)throw new Error("Lambda features disabled.");return this.c.compile(a,this.options).render(p,b)},b:function(a){this.buf+=a},fl:function(){var a=this.buf;return this.buf="",a},ms:function(a,p,b,g,E,A,N){var x,V=p[p.length-1],B=a.call(V);return typeof B=="function"?g?!0:(x=this.activeSub&&this.subsText&&this.subsText[this.activeSub]?this.subsText[this.activeSub]:this.text,this.ls(B,V,p,b,x.substring(E,A),N)):B},mv:function(a,p,b){var g=p[p.length-1],E=a.call(g);return typeof E=="function"?this.ct(c(E.call(g)),g,b):E},sub:function(a,p,b,g){var E=this.subs[a];E&&(this.activeSub=a,E(p,b,this,g),this.activeSub=!1)}};function n(a,p,b){var g;return p&&typeof p=="object"&&(p[a]!==void 0?g=p[a]:b&&p.get&&typeof p.get=="function"&&(g=p.get(a))),g}function e(a,p,b,g,E,A){function N(){}N.prototype=a;function x(){}x.prototype=a.subs;var V,B=new N;B.subs=new x,B.subsText={},B.buf="",g=g||{},B.stackSubs=g,B.subsText=A;for(V in p)g[V]||(g[V]=p[V]);for(V in g)B.subs[V]=g[V];E=E||{},B.stackPartials=E;for(V in b)E[V]||(E[V]=b[V]);for(V in E)B.partials[V]=E[V];return B}var l=/&/g,r=/</g,o=/>/g,f=/\'/g,v=/\"/g,i=/[&<>\"\']/;function c(a){return String(a??"")}function w(a){return a=c(a),i.test(a)?a.replace(l,"&").replace(r,"<").replace(o,">").replace(f,"'").replace(v,"""):a}var m=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(s)})(ot)),ot}var rt,Kt;function dl(){if(Kt)return rt;Kt=1;var s=rl();return s.Template=ul().Template,s.template=s.Template,rt=s,rt}var ie=dl();const re={};re["file-summary-line"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<li class="d2h-file-list-line">'),e.b(`
|
|
12
|
+
`+n),e.b(' <span class="d2h-file-name-wrapper">'),e.b(`
|
|
13
|
+
`+n),e.b(e.rp("<fileIcon0",s,t," ")),e.b(' <a href="#'),e.b(e.v(e.f("fileHtmlId",s,t,0))),e.b('" class="d2h-file-name">'),e.b(e.v(e.f("fileName",s,t,0))),e.b("</a>"),e.b(`
|
|
14
|
+
`+n),e.b(' <span class="d2h-file-stats">'),e.b(`
|
|
15
|
+
`+n),e.b(' <span class="d2h-lines-added">'),e.b(e.v(e.f("addedLines",s,t,0))),e.b("</span>"),e.b(`
|
|
16
|
+
`+n),e.b(' <span class="d2h-lines-deleted">'),e.b(e.v(e.f("deletedLines",s,t,0))),e.b("</span>"),e.b(`
|
|
17
|
+
`+n),e.b(" </span>"),e.b(`
|
|
18
|
+
`+n),e.b(" </span>"),e.b(`
|
|
19
|
+
`+n),e.b("</li>"),e.fl()},partials:{"<fileIcon0":{name:"fileIcon",partials:{},subs:{}}},subs:{}});re["file-summary-wrapper"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<div class="d2h-file-list-wrapper '),e.b(e.v(e.f("colorScheme",s,t,0))),e.b('">'),e.b(`
|
|
20
|
+
`+n),e.b(' <div class="d2h-file-list-header">'),e.b(`
|
|
21
|
+
`+n),e.b(' <span class="d2h-file-list-title">Files changed ('),e.b(e.v(e.f("filesNumber",s,t,0))),e.b(")</span>"),e.b(`
|
|
22
|
+
`+n),e.b(' <a class="d2h-file-switch d2h-hide">hide</a>'),e.b(`
|
|
23
|
+
`+n),e.b(' <a class="d2h-file-switch d2h-show">show</a>'),e.b(`
|
|
24
|
+
`+n),e.b(" </div>"),e.b(`
|
|
25
|
+
`+n),e.b(' <ol class="d2h-file-list">'),e.b(`
|
|
26
|
+
`+n),e.b(" "),e.b(e.t(e.f("files",s,t,0))),e.b(`
|
|
27
|
+
`+n),e.b(" </ol>"),e.b(`
|
|
28
|
+
`+n),e.b("</div>"),e.fl()},partials:{},subs:{}});re["generic-block-header"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b("<tr>"),e.b(`
|
|
29
|
+
`+n),e.b(' <td class="'),e.b(e.v(e.f("lineClass",s,t,0))),e.b(" "),e.b(e.v(e.d("CSSLineClass.INFO",s,t,0))),e.b('"></td>'),e.b(`
|
|
30
|
+
`+n),e.b(' <td class="'),e.b(e.v(e.d("CSSLineClass.INFO",s,t,0))),e.b('">'),e.b(`
|
|
31
|
+
`+n),e.b(' <div class="'),e.b(e.v(e.f("contentClass",s,t,0))),e.b('">'),e.s(e.f("blockHeader",s,t,1),s,t,0,156,173,"{{ }}")&&(e.rs(s,t,function(l,r,o){o.b(o.t(o.f("blockHeader",l,r,0)))}),s.pop()),e.s(e.f("blockHeader",s,t,1),s,t,1,0,0,"")||e.b(" "),e.b("</div>"),e.b(`
|
|
32
|
+
`+n),e.b(" </td>"),e.b(`
|
|
33
|
+
`+n),e.b("</tr>"),e.fl()},partials:{},subs:{}});re["generic-empty-diff"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b("<tr>"),e.b(`
|
|
34
|
+
`+n),e.b(' <td class="'),e.b(e.v(e.d("CSSLineClass.INFO",s,t,0))),e.b('">'),e.b(`
|
|
35
|
+
`+n),e.b(' <div class="'),e.b(e.v(e.f("contentClass",s,t,0))),e.b('">'),e.b(`
|
|
36
|
+
`+n),e.b(" File without changes"),e.b(`
|
|
37
|
+
`+n),e.b(" </div>"),e.b(`
|
|
38
|
+
`+n),e.b(" </td>"),e.b(`
|
|
39
|
+
`+n),e.b("</tr>"),e.fl()},partials:{},subs:{}});re["generic-file-path"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<span class="d2h-file-name-wrapper">'),e.b(`
|
|
40
|
+
`+n),e.b(e.rp("<fileIcon0",s,t," ")),e.b(' <span class="d2h-file-name">'),e.b(e.v(e.f("fileDiffName",s,t,0))),e.b("</span>"),e.b(`
|
|
41
|
+
`+n),e.b(e.rp("<fileTag1",s,t," ")),e.b("</span>"),e.b(`
|
|
42
|
+
`+n),e.b('<label class="d2h-file-collapse">'),e.b(`
|
|
43
|
+
`+n),e.b(' <input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">'),e.b(`
|
|
44
|
+
`+n),e.b(" Viewed"),e.b(`
|
|
45
|
+
`+n),e.b("</label>"),e.fl()},partials:{"<fileIcon0":{name:"fileIcon",partials:{},subs:{}},"<fileTag1":{name:"fileTag",partials:{},subs:{}}},subs:{}});re["generic-line"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b("<tr>"),e.b(`
|
|
46
|
+
`+n),e.b(' <td class="'),e.b(e.v(e.f("lineClass",s,t,0))),e.b(" "),e.b(e.v(e.f("type",s,t,0))),e.b('">'),e.b(`
|
|
47
|
+
`+n),e.b(" "),e.b(e.t(e.f("lineNumber",s,t,0))),e.b(`
|
|
48
|
+
`+n),e.b(" </td>"),e.b(`
|
|
49
|
+
`+n),e.b(' <td class="'),e.b(e.v(e.f("type",s,t,0))),e.b('">'),e.b(`
|
|
50
|
+
`+n),e.b(' <div class="'),e.b(e.v(e.f("contentClass",s,t,0))),e.b('">'),e.b(`
|
|
51
|
+
`+n),e.s(e.f("prefix",s,t,1),s,t,0,162,238,"{{ }}")&&(e.rs(s,t,function(l,r,o){o.b(' <span class="d2h-code-line-prefix">'),o.b(o.t(o.f("prefix",l,r,0))),o.b("</span>"),o.b(`
|
|
52
|
+
`+n)}),s.pop()),e.s(e.f("prefix",s,t,1),s,t,1,0,0,"")||(e.b(' <span class="d2h-code-line-prefix"> </span>'),e.b(`
|
|
53
|
+
`+n)),e.s(e.f("content",s,t,1),s,t,0,371,445,"{{ }}")&&(e.rs(s,t,function(l,r,o){o.b(' <span class="d2h-code-line-ctn">'),o.b(o.t(o.f("content",l,r,0))),o.b("</span>"),o.b(`
|
|
54
|
+
`+n)}),s.pop()),e.s(e.f("content",s,t,1),s,t,1,0,0,"")||(e.b(' <span class="d2h-code-line-ctn"><br></span>'),e.b(`
|
|
55
|
+
`+n)),e.b(" </div>"),e.b(`
|
|
56
|
+
`+n),e.b(" </td>"),e.b(`
|
|
57
|
+
`+n),e.b("</tr>"),e.fl()},partials:{},subs:{}});re["generic-wrapper"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<div class="d2h-wrapper '),e.b(e.v(e.f("colorScheme",s,t,0))),e.b('">'),e.b(`
|
|
58
|
+
`+n),e.b(" "),e.b(e.t(e.f("content",s,t,0))),e.b(`
|
|
59
|
+
`+n),e.b("</div>"),e.fl()},partials:{},subs:{}});re["icon-file-added"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<svg aria-hidden="true" class="d2h-icon d2h-added" height="16" title="added" version="1.1" viewBox="0 0 14 16"'),e.b(`
|
|
60
|
+
`+n),e.b(' width="14">'),e.b(`
|
|
61
|
+
`+n),e.b(' <path d="M13 1H1C0.45 1 0 1.45 0 2v12c0 0.55 0.45 1 1 1h12c0.55 0 1-0.45 1-1V2c0-0.55-0.45-1-1-1z m0 13H1V2h12v12zM6 9H3V7h3V4h2v3h3v2H8v3H6V9z"></path>'),e.b(`
|
|
62
|
+
`+n),e.b("</svg>"),e.fl()},partials:{},subs:{}});re["icon-file-changed"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<svg aria-hidden="true" class="d2h-icon d2h-changed" height="16" title="modified" version="1.1"'),e.b(`
|
|
63
|
+
`+n),e.b(' viewBox="0 0 14 16" width="14">'),e.b(`
|
|
64
|
+
`+n),e.b(' <path d="M13 1H1C0.45 1 0 1.45 0 2v12c0 0.55 0.45 1 1 1h12c0.55 0 1-0.45 1-1V2c0-0.55-0.45-1-1-1z m0 13H1V2h12v12zM4 8c0-1.66 1.34-3 3-3s3 1.34 3 3-1.34 3-3 3-3-1.34-3-3z"></path>'),e.b(`
|
|
65
|
+
`+n),e.b("</svg>"),e.fl()},partials:{},subs:{}});re["icon-file-deleted"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<svg aria-hidden="true" class="d2h-icon d2h-deleted" height="16" title="removed" version="1.1"'),e.b(`
|
|
66
|
+
`+n),e.b(' viewBox="0 0 14 16" width="14">'),e.b(`
|
|
67
|
+
`+n),e.b(' <path d="M13 1H1C0.45 1 0 1.45 0 2v12c0 0.55 0.45 1 1 1h12c0.55 0 1-0.45 1-1V2c0-0.55-0.45-1-1-1z m0 13H1V2h12v12zM11 9H3V7h8v2z"></path>'),e.b(`
|
|
68
|
+
`+n),e.b("</svg>"),e.fl()},partials:{},subs:{}});re["icon-file-renamed"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<svg aria-hidden="true" class="d2h-icon d2h-moved" height="16" title="renamed" version="1.1"'),e.b(`
|
|
69
|
+
`+n),e.b(' viewBox="0 0 14 16" width="14">'),e.b(`
|
|
70
|
+
`+n),e.b(' <path d="M6 9H3V7h3V4l5 4-5 4V9z m8-7v12c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h12c0.55 0 1 0.45 1 1z m-1 0H1v12h12V2z"></path>'),e.b(`
|
|
71
|
+
`+n),e.b("</svg>"),e.fl()},partials:{},subs:{}});re["icon-file"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">'),e.b(`
|
|
72
|
+
`+n),e.b(' <path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>'),e.b(`
|
|
73
|
+
`+n),e.b("</svg>"),e.fl()},partials:{},subs:{}});re["line-by-line-file-diff"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<div id="'),e.b(e.v(e.f("fileHtmlId",s,t,0))),e.b('" class="d2h-file-wrapper" data-lang="'),e.b(e.v(e.d("file.language",s,t,0))),e.b('">'),e.b(`
|
|
74
|
+
`+n),e.b(' <div class="d2h-file-header">'),e.b(`
|
|
75
|
+
`+n),e.b(" "),e.b(e.t(e.f("filePath",s,t,0))),e.b(`
|
|
76
|
+
`+n),e.b(" </div>"),e.b(`
|
|
77
|
+
`+n),e.b(' <div class="d2h-file-diff">'),e.b(`
|
|
78
|
+
`+n),e.b(' <div class="d2h-code-wrapper">'),e.b(`
|
|
79
|
+
`+n),e.b(' <table class="d2h-diff-table">'),e.b(`
|
|
80
|
+
`+n),e.b(' <tbody class="d2h-diff-tbody">'),e.b(`
|
|
81
|
+
`+n),e.b(" "),e.b(e.t(e.f("diffs",s,t,0))),e.b(`
|
|
82
|
+
`+n),e.b(" </tbody>"),e.b(`
|
|
83
|
+
`+n),e.b(" </table>"),e.b(`
|
|
84
|
+
`+n),e.b(" </div>"),e.b(`
|
|
85
|
+
`+n),e.b(" </div>"),e.b(`
|
|
86
|
+
`+n),e.b("</div>"),e.fl()},partials:{},subs:{}});re["line-by-line-numbers"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<div class="line-num1">'),e.b(e.v(e.f("oldNumber",s,t,0))),e.b("</div>"),e.b(`
|
|
87
|
+
`+n),e.b('<div class="line-num2">'),e.b(e.v(e.f("newNumber",s,t,0))),e.b("</div>"),e.fl()},partials:{},subs:{}});re["side-by-side-file-diff"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<div id="'),e.b(e.v(e.f("fileHtmlId",s,t,0))),e.b('" class="d2h-file-wrapper" data-lang="'),e.b(e.v(e.d("file.language",s,t,0))),e.b('">'),e.b(`
|
|
88
|
+
`+n),e.b(' <div class="d2h-file-header">'),e.b(`
|
|
89
|
+
`+n),e.b(" "),e.b(e.t(e.f("filePath",s,t,0))),e.b(`
|
|
90
|
+
`+n),e.b(" </div>"),e.b(`
|
|
91
|
+
`+n),e.b(' <div class="d2h-files-diff">'),e.b(`
|
|
92
|
+
`+n),e.b(' <div class="d2h-file-side-diff">'),e.b(`
|
|
93
|
+
`+n),e.b(' <div class="d2h-code-wrapper">'),e.b(`
|
|
94
|
+
`+n),e.b(' <table class="d2h-diff-table">'),e.b(`
|
|
95
|
+
`+n),e.b(' <tbody class="d2h-diff-tbody">'),e.b(`
|
|
96
|
+
`+n),e.b(" "),e.b(e.t(e.d("diffs.left",s,t,0))),e.b(`
|
|
97
|
+
`+n),e.b(" </tbody>"),e.b(`
|
|
98
|
+
`+n),e.b(" </table>"),e.b(`
|
|
99
|
+
`+n),e.b(" </div>"),e.b(`
|
|
100
|
+
`+n),e.b(" </div>"),e.b(`
|
|
101
|
+
`+n),e.b(' <div class="d2h-file-side-diff">'),e.b(`
|
|
102
|
+
`+n),e.b(' <div class="d2h-code-wrapper">'),e.b(`
|
|
103
|
+
`+n),e.b(' <table class="d2h-diff-table">'),e.b(`
|
|
104
|
+
`+n),e.b(' <tbody class="d2h-diff-tbody">'),e.b(`
|
|
105
|
+
`+n),e.b(" "),e.b(e.t(e.d("diffs.right",s,t,0))),e.b(`
|
|
106
|
+
`+n),e.b(" </tbody>"),e.b(`
|
|
107
|
+
`+n),e.b(" </table>"),e.b(`
|
|
108
|
+
`+n),e.b(" </div>"),e.b(`
|
|
109
|
+
`+n),e.b(" </div>"),e.b(`
|
|
110
|
+
`+n),e.b(" </div>"),e.b(`
|
|
111
|
+
`+n),e.b("</div>"),e.fl()},partials:{},subs:{}});re["tag-file-added"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<span class="d2h-tag d2h-added d2h-added-tag">ADDED</span>'),e.fl()},partials:{},subs:{}});re["tag-file-changed"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<span class="d2h-tag d2h-changed d2h-changed-tag">CHANGED</span>'),e.fl()},partials:{},subs:{}});re["tag-file-deleted"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<span class="d2h-tag d2h-deleted d2h-deleted-tag">DELETED</span>'),e.fl()},partials:{},subs:{}});re["tag-file-renamed"]=new ie.Template({code:function(s,t,n){var e=this;return e.b(n=n||""),e.b('<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span>'),e.fl()},partials:{},subs:{}});class cl{constructor({compiledTemplates:t={},rawTemplates:n={}}){const e=Object.entries(n).reduce((l,[r,o])=>{const f=ie.compile(o,{asString:!1});return Object.assign(Object.assign({},l),{[r]:f})},{});this.preCompiledTemplates=Object.assign(Object.assign(Object.assign({},re),t),e)}static compile(t){return ie.compile(t,{asString:!1})}render(t,n,e,l,r){const o=this.templateKey(t,n);try{return this.preCompiledTemplates[o].render(e,l,r)}catch{throw new Error(`Could not find template to render '${o}'`)}}template(t,n){return this.preCompiledTemplates[this.templateKey(t,n)]}templateKey(t,n){return`${t}-${n}`}}const fl=Object.assign(Object.assign(Object.assign({},on),rn),{outputFormat:Is.LINE_BY_LINE,drawFileList:!0});function pl(s,t={}){const n=Object.assign(Object.assign({},fl),t),e=typeof s=="string"?zs(s,n):s,l=new cl(n),{colorScheme:r}=n,o={colorScheme:r},f=n.drawFileList?new el(l,o).render(e):"",v=n.outputFormat==="side-by-side"?new ol(l,n).render(e):new sl(l,n).render(e);return f+v}const hl={class:"diff-viewer"},ml=["innerHTML"],gl={key:1,class:"diff-fallback mono"},bl=Ce({__name:"DiffViewer",props:{patch:{}},setup(s){const t=s,n=Y(()=>{if(!t.patch.trim())return"";try{return pl(t.patch,{drawFileList:!1,outputFormat:"line-by-line",matching:"lines",colorScheme:Ve.DARK,renderNothingWhenEmpty:!0})}catch{return""}}),e=Y(()=>n.value===""?t.patch.split(`
|
|
112
|
+
`):[]);return(l,r)=>(y(),M("div",hl,[n.value?(y(),M("div",{key:0,class:"diff-html",innerHTML:n.value},null,8,ml)):e.value.length?(y(),M("pre",gl,[(y(!0),M(ae,null,he(e.value,(o,f)=>(y(),M(ae,{key:f},[I(O(o)+`
|
|
113
|
+
`,1)],64))),128))])):j("",!0)]))}}),ft=xe(bl,[["__scopeId","data-v-3ec3d3ee"]]),vl={class:"page status-page"},yl={class:"page-head"},_l={class:"head-branch"},wl={key:0,class:"tracking mono"},kl={key:1,class:"sync ahead"},Cl={key:2,class:"sync behind"},xl={class:"repo-path mono"},Tl={key:1,class:"empty-tip"},Sl={key:2,class:"status-layout"},$l={class:"panel-head"},El={class:"panel-actions"},Nl={class:"tree-scroll"},Ll={class:"group-label"},Il={key:0,class:"tree-dir"},Vl=["title","onDblclick"],Dl={class:"node-name"},Pl={class:"node-actions"},Ol={key:1,class:"pane-empty"},Rl={class:"status-content"},Al={class:"toolbar"},Fl={class:"toolbar-group"},Ml={class:"card-head"},zl={class:"card-actions"},Bl={class:"tab-label"},Hl={class:"tab-hint"},Ul={key:0,class:"file-empty"},Wl={key:1,class:"file-list"},jl=["title"],Gl={class:"card-head"},ql={class:"card-title"},Kl={class:"card-actions"},Xl={key:0,class:"file-empty"},Jl={key:1,class:"stash-list mono"},Yl={class:"stash-main"},Ql={class:"stash-ref"},Zl=["title"],ea={key:0,class:"stash-date"},ta={class:"stash-actions"},na={class:"diff-wrap"},sa={class:"diff-summary"},la={class:"add"},aa={class:"del"},ia={key:0,class:"warn"},oa={key:0,class:"file-empty"},ra={key:0,class:"stash-files"},ua={class:"stash-files-head"},da={class:"stash-files-title"},ca={class:"card-actions"},fa={class:"file-list compact"},pa={class:"file-path mono"},ha=Ce({__name:"StatusView",setup(s){const t=$e(),n=He(),{revision:e}=Qe(),l=()=>t.currentId,r=G(null),o=G([]),f=G(!1),v=G(""),i=ut({visible:!1,title:"",diff:null,patch:"",loading:!1}),c=G(!1),w=G(""),m=G(!1),a=G(""),p=G(""),b=G(!1),g=G(""),E=G(!1),A=G(!1),N=G(""),x=ut(new Set),V=Y(()=>x.size),B=G("unstaged"),{confirmVisible:Q,pending:_,canRun:$,previewAndConfirm:S,executeConfirmed:L,cancel:P}=en(l),X=Y(()=>{var C;return((C=t.current)==null?void 0:C.path)??""}),J=Y(()=>{var C,d;return((C=r.value)==null?void 0:C.currentShort)??((d=r.value)==null?void 0:d.current)??""}),W=Y(()=>{var C;return((C=r.value)==null?void 0:C.ahead)??0}),te=Y(()=>{var C;return((C=r.value)==null?void 0:C.behind)??0}),ue=Y(()=>n.panes),ee=Y(()=>{const C=r.value;if(!C)return{unstaged:[],staged:[],untracked:[],all:[]};const d=C.untracked.map(_e=>({path:_e,status:"??",indexStatus:"?",workTreeStatus:"?",staged:!1,untracked:!0,conflicted:!1})),le=[...C.staged,...C.unstaged,...d],z=new Set,be=le.filter(_e=>z.has(_e.path)?!1:(z.add(_e.path),_e.path!==""));return{unstaged:C.unstaged,staged:C.staged,untracked:d,all:be}}),ne=Y(()=>[{key:"unstaged",label:"未暂存",hint:"已修改,未 git add",count:ee.value.unstaged.length},{key:"staged",label:"已暂存",hint:"已 git add,未提交",count:ee.value.staged.length},{key:"untracked",label:"未跟踪",hint:"工作区新文件",count:ee.value.untracked.length},{key:"all",label:"全部",hint:"全部更改",count:ee.value.all.length}]),pe=Y(()=>ee.value[B.value]??[]),T=Y(()=>ee.value.all.length);function U(C){if(!C||C.remote||!C.upstream)return"";const d=[];return(C.ahead??0)>0&&d.push(`↑${C.ahead}`),(C.behind??0)>0&&d.push(`↓${C.behind}`),d.join(" ")}async function D(){const C=l();if(C!==null){f.value=!0,v.value="";try{r.value=await Gn(C)}catch(d){v.value=d instanceof Error?d.message:String(d),r.value=null}finally{f.value=!1}}}async function de(){await n.load()}async function Ee(){const C=l();if(C!==null)try{o.value=await Yn(C)}catch{}}async function Te(){await Promise.all([D(),de(),Ee()])}async function se(C,d={}){await S(C,d)&&Z.info("请在确认对话框中查看 dry-run 预览")}async function Ie(){const C=await L();C!=null&&C.success&&await Te()}function me(C){se("git_add",{paths:[C.path]})}function ge(C){se("git_unstage",{paths:[C.path]})}function ve(C){C.staged?ge(C):me(C)}function Ne(){se("git_add",{})}function Re(){var d;const C=((d=r.value)==null?void 0:d.staged.map(le=>le.path))??[];if(C.length===0){Z.info("没有已暂存的文件");return}se("git_unstage",{paths:C})}async function dn(C){const d=l();if(d!==null){i.title=`${C.path}(${C.staged?"已 git add":"工作区修改"})`,i.diff=null,i.patch="",i.visible=!0,i.loading=!0;try{i.diff=await Kn(d,{path:C.path,staged:C.staged})}catch(le){Z.error(le instanceof Error?le.message:String(le)),i.visible=!1}finally{i.loading=!1}}}async function cn(C){var le;const d=l();if(d!==null){i.title=`${C.ref} · ${C.message||"(无说明)"}`,i.diff=null,i.patch="",i.visible=!0,i.loading=!0;try{const z=await qe(d,"git_stash_show",{index:C.index});if(z.success){const be=z.result??{};i.patch=be.patch??""}else Z.error(((le=z.error)==null?void 0:le.message)??"查看差异失败"),i.visible=!1}catch(z){Z.error(z instanceof Error?z.message:String(z)),i.visible=!1}finally{i.loading=!1}}}function kt(C){x.has(C)?x.delete(C):x.add(C)}function Ct(C){return x.has(C)}function xt(){x.clear()}function fn(){for(const C of pe.value)x.add(C.path)}function pn(){for(const C of Ue.value)x.add(C)}const Ue=Y(()=>{const C=r.value;if(!C)return[];const d=new Set;return[...C.unstaged.map(le=>le.path),...C.untracked].filter(le=>d.has(le)?!1:(d.add(le),le!==""))});function hn(){b.value=!0}function mn(){const C=Ue.value,d=[...x].filter(be=>C.includes(be)),le=d.some(be=>{var _e;return((_e=r.value)==null?void 0:_e.untracked.includes(be))??!1}),z={};g.value.trim()&&(z.message=g.value.trim()),d.length&&(z.paths=d),(E.value||le)&&(z.includeUntracked=!0),b.value=!1,x.clear(),se("git_stash",z)}function gn(){se("git_stash",{})}function bn(C){se("git_stash_apply",{index:C.index})}function vn(C){se("git_stash_pop",{index:C.index})}function yn(C){gt.confirm(`确定删除 ${C.ref} 吗?删除后不可直接恢复。`,"删除 stash",{type:"warning",confirmButtonText:"继续",cancelButtonText:"取消"}).then(()=>void se("git_stash_drop",{index:C.index})).catch(()=>{})}function Tt(C){C.branch&&se("git_checkout",{branch:C.branch.name})}function _n(){se("git_pull")}function wn(){se("git_push")}function St(){const C=w.value.trim();if(!C){Z.warning("请输入提交信息");return}c.value=!1,se("git_commit",{message:C})}function kn(){const C=a.value.trim();if(!C){Z.warning("请输入分支名");return}m.value=!1,se("git_branch_create",p.value.trim()?{name:C,startPoint:p.value.trim()}:{name:C})}function Cn(){const C=N.value.trim()||"HEAD";A.value=!1,N.value="",se("git_reset_hard",{target:C})}function xn(C){return C.untracked?"?":C.staged?C.indexStatus||"M":C.workTreeStatus||"M"}function Tn(C){return C.untracked?"new":C.conflicted?"conflict":C.staged?"add":"mod"}function Sn(C){if(!C)return"";const d=new Date(C);return Number.isNaN(d.getTime())?C:d.toLocaleString()}function $n(C){return C.split(`
|
|
114
|
+
`)[0]??""}return ye(l,()=>{i.diff=null,i.patch="",i.visible=!1,x.clear(),Te()}),ye(e,()=>{Te()}),Oe(()=>{Te()}),(C,d)=>{var Lt,It,Vt,Dt,Pt;const le=R("el-tag"),z=R("el-button"),be=R("el-alert"),_e=R("el-tree"),$t=R("el-empty"),We=R("el-card"),Et=R("el-badge"),En=R("el-tooltip"),nt=R("el-checkbox"),Nn=R("el-tab-pane"),Ln=R("el-tabs"),In=R("el-drawer"),Ae=R("el-input"),je=R("el-dialog"),Ge=R("el-form-item"),Nt=R("el-form"),Vn=Ye("loading");return y(),M("div",vl,[k("div",yl,[d[26]||(d[26]=k("h2",{class:"page-title"},"仓库状态",-1)),k("div",_l,[h(le,{type:"primary",effect:"dark",class:"branch-tag"},{default:u(()=>[I(O(J.value||"—"),1)]),_:1}),(Lt=r.value)!=null&&Lt.tracking?(y(),M("span",wl,O(r.value.tracking),1)):j("",!0),W.value?(y(),M("span",kl,"↑"+O(W.value),1)):j("",!0),te.value?(y(),M("span",Cl,"↓"+O(te.value),1)):j("",!0),(It=r.value)!=null&&It.isClean?(y(),H(le,{key:3,type:"success",effect:"plain",size:"small"},{default:u(()=>[...d[24]||(d[24]=[I("工作区干净",-1)])]),_:1})):r.value?(y(),H(le,{key:4,type:"warning",effect:"plain",size:"small"},{default:u(()=>[I(O(T.value)+" 处更改",1)]),_:1})):j("",!0),k("span",xl,O(X.value),1)]),h(z,{loading:f.value,onClick:Te},{default:u(()=>[...d[25]||(d[25]=[I("刷新",-1)])]),_:1},8,["loading"])]),v.value?(y(),H(be,{key:0,title:v.value,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):j("",!0),K($)?(y(),M("div",Sl,[h(We,{shadow:"never",class:"branch-panel"},{header:u(()=>[k("div",$l,[d[29]||(d[29]=k("span",{class:"panel-title"},"分支 Branch",-1)),k("div",El,[h(z,{size:"small",text:"",onClick:de},{default:u(()=>[...d[27]||(d[27]=[I("刷新",-1)])]),_:1}),h(z,{size:"small",text:"",type:"primary",onClick:d[0]||(d[0]=F=>m.value=!0)},{default:u(()=>[...d[28]||(d[28]=[I("+ 新建",-1)])]),_:1})])])]),default:u(()=>[k("div",Nl,[(y(!0),M(ae,null,he(ue.value,F=>(y(),M(ae,{key:F.key},[k("div",Ll,O(F.title),1),F.tree.length?(y(),H(_e,{key:0,data:F.tree,props:{label:"label",children:"children"},"node-key":"key","default-expand-all":"",indent:14,class:"branch-tree"},{default:u(({data:q})=>{var Se,st,Ot;return[q.branch?(y(),M("div",{key:1,class:Be(["branch-node",{current:(Se=q.branch)==null?void 0:Se.current,remote:q.remote}]),title:q.fullName,onDblclick:Dn=>{var Rt;return((Rt=q.branch)==null?void 0:Rt.current)||Tt(q)}},[k("span",Dl,O(q.label),1),q.remote?j("",!0):(y(),M("span",{key:0,class:Be(["node-sync",{clean:!U(q.branch)&&((st=q.branch)==null?void 0:st.upstream)}])},O(U(q.branch)),3)),k("span",Pl,[(Ot=q.branch)!=null&&Ot.current?(y(),M(ae,{key:0},[h(z,{size:"small",text:"",type:"success",onClick:De(_n,["stop"])},{default:u(()=>[...d[30]||(d[30]=[I("拉取",-1)])]),_:1}),h(z,{size:"small",text:"",type:"primary",onClick:De(wn,["stop"])},{default:u(()=>[...d[31]||(d[31]=[I("推送",-1)])]),_:1})],64)):(y(),H(z,{key:1,size:"small",text:"",type:"primary",onClick:De(Dn=>Tt(q),["stop"])},{default:u(()=>[...d[32]||(d[32]=[I("切换",-1)])]),_:1},8,["onClick"]))])],42,Vl)):(y(),M("span",Il,O(q.label),1))]}),_:1},8,["data"])):(y(),M("div",Ol,"暂无分支"))],64))),128)),ue.value.length===0?(y(),H($t,{key:0,description:"暂无分支","image-size":60})):j("",!0)])]),_:1}),k("div",Rl,[h(We,{shadow:"never",class:"toolbar-card"},{default:u(()=>{var F;return[k("div",Al,[k("div",Fl,[h(z,{type:"primary",onClick:d[1]||(d[1]=q=>c.value=!0)},{default:u(()=>[...d[33]||(d[33]=[I("提交 Commit",-1)])]),_:1}),h(z,{plain:"",onClick:Ne},{default:u(()=>[...d[34]||(d[34]=[I("暂存全部",-1)])]),_:1}),h(z,{plain:"",disabled:(((F=r.value)==null?void 0:F.staged.length)??0)===0,onClick:Re},{default:u(()=>[...d[35]||(d[35]=[I("取消暂存全部",-1)])]),_:1},8,["disabled"]),h(Et,{value:V.value,hidden:V.value===0,offset:[2,4]},{default:u(()=>[h(z,{type:"success",plain:"",onClick:hn},{default:u(()=>[...d[36]||(d[36]=[I("暂存改动 Stash",-1)])]),_:1})]),_:1},8,["value","hidden"]),h(En,{content:"Shelve Silently:使用默认说明,一键暂存全部更改",placement:"top"},{default:u(()=>[h(z,{plain:"",onClick:gn},{default:u(()=>[...d[37]||(d[37]=[I("静默 Stash",-1)])]),_:1})]),_:1}),h(z,{type:"danger",plain:"",onClick:d[2]||(d[2]=q=>A.value=!0)},{default:u(()=>[...d[38]||(d[38]=[I("硬重置",-1)])]),_:1}),h(z,{type:"danger",plain:"",onClick:d[3]||(d[3]=q=>se("git_clean"))},{default:u(()=>[...d[39]||(d[39]=[I("清理未跟踪",-1)])]),_:1})])])]}),_:1}),(Vt=r.value)!=null&&Vt.conflicted.length?(y(),H(be,{key:0,title:"存在合并冲突,请先解决冲突(修改文件后重新 git add 并提交)",type:"error",closable:!1,"show-icon":"",class:"mb"})):j("",!0),h(We,{shadow:"never",class:"changes-card"},{header:u(()=>[k("div",Ml,[d[42]||(d[42]=k("span",{class:"card-title"},"更改 Changes",-1)),k("div",zl,[V.value?(y(),H(le,{key:0,size:"small",type:"primary",effect:"plain"},{default:u(()=>[I("已选 "+O(V.value),1)]),_:1})):j("",!0),h(z,{size:"small",text:"",onClick:fn},{default:u(()=>[...d[40]||(d[40]=[I("全选本组",-1)])]),_:1}),V.value?(y(),H(z,{key:1,size:"small",text:"",type:"danger",onClick:xt},{default:u(()=>[...d[41]||(d[41]=[I("清除选择",-1)])]),_:1})):j("",!0)])])]),default:u(()=>[h(Ln,{modelValue:B.value,"onUpdate:modelValue":d[4]||(d[4]=F=>B.value=F),class:"changes-tabs"},{default:u(()=>[(y(!0),M(ae,null,he(ne.value,F=>(y(),H(Nn,{key:F.key,name:F.key},{label:u(()=>[k("span",Bl,[I(O(F.label)+" ",1),h(Et,{value:F.count,hidden:F.count===0,type:"primary",class:"tab-badge"},null,8,["value","hidden"])])]),default:u(()=>[k("div",Hl,"「"+O(F.hint)+"」",1),F.count===0?(y(),M("div",Ul,"没有"+O(F.label)+"的文件",1)):(y(),M("div",Wl,[(y(!0),M(ae,null,he(ee.value[F.key],q=>(y(),M("div",{key:F.key+q.path,class:"file-row"},[h(nt,{"model-value":Ct(q.path),onChange:Se=>kt(q.path)},null,8,["model-value","onChange"]),k("span",{class:Be(["file-status",Tn(q)])},O(xn(q)),3),k("span",{class:"file-path mono",title:q.path},O(q.path),9,jl),h(z,{size:"small",text:"",type:"primary",onClick:Se=>dn(q)},{default:u(()=>[...d[43]||(d[43]=[I("查看差异",-1)])]),_:1},8,["onClick"]),q.conflicted?(y(),H(z,{key:0,size:"small",text:"",type:"warning",onClick:Se=>me(q)},{default:u(()=>[...d[44]||(d[44]=[I("标记已解决(git add)",-1)])]),_:1},8,["onClick"])):(y(),H(z,{key:1,size:"small",text:"",type:q.staged?"warning":"success",onClick:Se=>ve(q)},{default:u(()=>[I(O(q.staged?"取消暂存":"暂存"),1)]),_:2},1032,["type","onClick"]))]))),128))]))]),_:2},1032,["name"]))),128))]),_:1},8,["modelValue"])]),_:1}),h(We,{shadow:"never",class:"stash-card"},{header:u(()=>[k("div",Gl,[k("span",ql,"暂存列表 Stash("+O(o.value.length)+")",1),k("div",Kl,[h(z,{size:"small",text:"",onClick:Ee},{default:u(()=>[...d[45]||(d[45]=[I("刷新",-1)])]),_:1})])])]),default:u(()=>[o.value.length===0?(y(),M("div",Xl,"没有暂存的更改")):(y(),M("div",Jl,[(y(!0),M(ae,null,he(o.value,F=>(y(),M("div",{key:F.ref,class:"stash-row"},[k("div",Yl,[k("span",Ql,O(F.ref),1),k("span",{class:"stash-msg",title:F.message},O($n(F.message)||"(无说明)"),9,Zl),F.date?(y(),M("span",ea,O(Sn(F.date)),1)):j("",!0)]),k("div",ta,[h(z,{size:"small",text:"",type:"primary",onClick:q=>cn(F)},{default:u(()=>[...d[46]||(d[46]=[I("差异",-1)])]),_:1},8,["onClick"]),h(z,{size:"small",text:"",type:"success",onClick:q=>bn(F)},{default:u(()=>[...d[47]||(d[47]=[I("应用",-1)])]),_:1},8,["onClick"]),h(z,{size:"small",text:"",type:"warning",onClick:q=>vn(F)},{default:u(()=>[...d[48]||(d[48]=[I("恢复",-1)])]),_:1},8,["onClick"]),h(z,{size:"small",text:"",type:"danger",onClick:q=>yn(F)},{default:u(()=>[...d[49]||(d[49]=[I("删除",-1)])]),_:1},8,["onClick"])])]))),128))]))]),_:1})])])):(y(),M("div",Tl,"请先在「仓库管理」中打开一个仓库")),h(tn,{visible:K(Q),"onUpdate:visible":d[5]||(d[5]=F=>Xt(Q)?Q.value=F:null),tool:((Dt=K(_))==null?void 0:Dt.tool)??"",preview:((Pt=K(_))==null?void 0:Pt.preview)??null,onConfirm:Ie,onCancel:K(P)},null,8,["visible","tool","preview","onCancel"]),h(In,{modelValue:i.visible,"onUpdate:modelValue":d[6]||(d[6]=F=>i.visible=F),title:i.title,size:"56%","destroy-on-close":""},{default:u(()=>[Je((y(),M("div",na,[i.diff?(y(),M(ae,{key:0},[k("div",sa,[k("span",null,O(i.diff.files.length)+" 个文件",1),k("span",la,"+"+O(i.diff.insertions),1),k("span",aa,"-"+O(i.diff.deletions),1),i.diff.truncated?(y(),M("span",ia,"(已截断)")):j("",!0)]),h(ft,{patch:i.diff.rawPatch},null,8,["patch"])],64)):i.patch?(y(),M(ae,{key:1},[i.patch?(y(),H(ft,{key:1,patch:i.patch},null,8,["patch"])):(y(),M("div",oa,"无差异"))],64)):i.loading?j("",!0):(y(),H($t,{key:2,description:"无差异","image-size":60}))])),[[Vn,i.loading]])]),_:1},8,["modelValue","title"]),h(je,{modelValue:c.value,"onUpdate:modelValue":d[9]||(d[9]=F=>c.value=F),title:"提交 Commit",width:"520px",onClosed:d[10]||(d[10]=F=>w.value="")},{footer:u(()=>[h(z,{onClick:d[8]||(d[8]=F=>c.value=!1)},{default:u(()=>[...d[50]||(d[50]=[I("取消",-1)])]),_:1}),h(z,{type:"primary",onClick:St},{default:u(()=>[...d[51]||(d[51]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:u(()=>[h(Ae,{modelValue:w.value,"onUpdate:modelValue":d[7]||(d[7]=F=>w.value=F),type:"textarea",rows:5,placeholder:"输入提交信息(message)",onKeydown:mt(De(St,["ctrl"]),["enter"])},null,8,["modelValue","onKeydown"])]),_:1},8,["modelValue"]),h(je,{modelValue:m.value,"onUpdate:modelValue":d[14]||(d[14]=F=>m.value=F),title:"新建分支",width:"480px",onClosed:d[15]||(d[15]=F=>{a.value="",p.value=""})},{footer:u(()=>[h(z,{onClick:d[13]||(d[13]=F=>m.value=!1)},{default:u(()=>[...d[52]||(d[52]=[I("取消",-1)])]),_:1}),h(z,{type:"primary",onClick:kn},{default:u(()=>[...d[53]||(d[53]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:u(()=>[h(Nt,{"label-width":"100px"},{default:u(()=>[h(Ge,{label:"分支名"},{default:u(()=>[h(Ae,{modelValue:a.value,"onUpdate:modelValue":d[11]||(d[11]=F=>a.value=F),placeholder:"feature/xxx"},null,8,["modelValue"])]),_:1}),h(Ge,{label:"起点(可选)"},{default:u(()=>[h(Ae,{modelValue:p.value,"onUpdate:modelValue":d[12]||(d[12]=F=>p.value=F),placeholder:"默认当前 HEAD,如 main 或 commit hash"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"]),h(je,{modelValue:b.value,"onUpdate:modelValue":d[19]||(d[19]=F=>b.value=F),title:"暂存改动 Stash",width:"560px"},{footer:u(()=>[h(z,{onClick:d[18]||(d[18]=F=>b.value=!1)},{default:u(()=>[...d[57]||(d[57]=[I("取消",-1)])]),_:1}),h(z,{type:"primary",onClick:mn},{default:u(()=>[...d[58]||(d[58]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:u(()=>[h(be,{class:"stash-tip",title:"可勾选左侧更改列表的文件随本次 stash 一起保存;不勾选则保存全部更改。",type:"info",closable:!1,"show-icon":""}),h(Nt,{"label-width":"90px"},{default:u(()=>[h(Ge,{label:"说明(可选)"},{default:u(()=>[h(Ae,{modelValue:g.value,"onUpdate:modelValue":d[16]||(d[16]=F=>g.value=F),placeholder:"留空则使用默认说明(WIP on 分支: 提交)"},null,8,["modelValue"])]),_:1}),h(Ge,{label:"包含未跟踪"},{default:u(()=>[h(nt,{modelValue:E.value,"onUpdate:modelValue":d[17]||(d[17]=F=>E.value=F)},{default:u(()=>[...d[54]||(d[54]=[I("包含未跟踪文件(-u)。勾选文件后会自动包含其中的未跟踪文件",-1)])]),_:1},8,["modelValue"])]),_:1})]),_:1}),Ue.value.length?(y(),M("div",ra,[k("div",ua,[k("span",da,"选择文件(已选 "+O(V.value)+")",1),k("div",ca,[h(z,{size:"small",text:"",onClick:pn},{default:u(()=>[...d[55]||(d[55]=[I("全选",-1)])]),_:1}),h(z,{size:"small",text:"",onClick:xt},{default:u(()=>[...d[56]||(d[56]=[I("清除选择",-1)])]),_:1})])]),k("div",fa,[(y(!0),M(ae,null,he(Ue.value,F=>{var q,Se;return y(),M("div",{key:F,class:"file-row"},[h(nt,{"model-value":Ct(F),onChange:st=>kt(F)},null,8,["model-value","onChange"]),k("span",{class:Be(["file-status",(q=r.value)!=null&&q.untracked.includes(F)?"new":"mod"])},O((Se=r.value)!=null&&Se.untracked.includes(F)?"?":"M"),3),k("span",pa,O(F),1)])}),128))])])):j("",!0)]),_:1},8,["modelValue"]),h(je,{modelValue:A.value,"onUpdate:modelValue":d[22]||(d[22]=F=>A.value=F),title:"硬重置(高风险)",width:"480px",onClosed:d[23]||(d[23]=F=>N.value="")},{footer:u(()=>[h(z,{onClick:d[21]||(d[21]=F=>A.value=!1)},{default:u(()=>[...d[59]||(d[59]=[I("取消",-1)])]),_:1}),h(z,{type:"danger",onClick:Cn},{default:u(()=>[...d[60]||(d[60]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:u(()=>[h(be,{title:"将丢弃索引与工作区所有更改(不可逆),执行前会自动创建备份",type:"error",closable:!1,"show-icon":"",class:"mb"}),h(Ae,{modelValue:N.value,"onUpdate:modelValue":d[20]||(d[20]=F=>N.value=F),placeholder:"重置目标,默认 HEAD,如 HEAD~1 / commit hash / main"},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),ma=xe(ha,[["__scopeId","data-v-f003fc68"]]),ga=Ce({__name:"BranchTreeSelect",props:{modelValue:{},placeholder:{default:"选择分支"},scope:{default:"all"},remoteFirst:{type:Boolean,default:!1}},emits:["update:modelValue"],setup(s,{emit:t}){const n=s,e=t,l=He(),r=Y(()=>as(Qt(l.list,n.scope),n.remoteFirst));function o(f,v){if(!f)return!0;const i=f.toLowerCase();return(v.label??"").toLowerCase().includes(i)||(v.value??"").toLowerCase().includes(i)}return(f,v)=>{const i=R("el-tree-select");return y(),H(i,{"model-value":s.modelValue,data:r.value,filterable:"","filter-node-method":o,"check-strictly":"","default-expand-all":"","render-after-expand":!1,placeholder:s.placeholder,class:"branch-tree-select","onUpdate:modelValue":v[0]||(v[0]=c=>e("update:modelValue",c))},null,8,["model-value","data","placeholder"])}}}),pt=xe(ga,[["__scopeId","data-v-fc71d58d"]]),ba={class:"page"},va={class:"page-head"},ya={key:1,class:"empty-tip"},_a={class:"filter-bar"},wa={class:"field"},ka={class:"field"},Ca={class:"field field-switch"},xa={class:"result-head"},Ta={class:"mono sha"},Sa={class:"mono"},$a={key:5,class:"messages"},Ea={class:"tip"},Na={class:"mono"},La={class:"mono"},Ia={key:0,class:"tip"},Va=["href"],Da=Ce({__name:"MergeView",setup(s){const t=$e(),n=He(),e=()=>t.currentId,{confirmVisible:l,pending:r,canRun:o,previewAndConfirm:f,executeConfirmed:v,cancel:i}=en(e),c=G(""),w=G(""),m=G(!0),a=G(!1),p=G(""),b=G(null),g=G(null),E=Y(()=>n.hasRemote),A=Y(()=>{var P;const L=(P=b.value)==null?void 0:P.outcome;return L==="clean"?"success":L==="unrelated"?"warning":L==="conflicts"?"danger":"info"}),N=Y(()=>{var P;const L=(P=b.value)==null?void 0:P.outcome;return L==="clean"?"可干净合并":L==="unrelated"?"无关历史":L==="conflicts"?"存在冲突":""}),x=Y(()=>{var L;return!!((L=b.value)!=null&&L.clean)&&o.value});function V(L){var W;const P=L.filter(te=>te.remote),X=["origin/main","origin/master","origin/develop"];for(const te of X)if(P.some(ue=>ue.name===te))return te;if(P[0])return P[0].name;const J=L.find(te=>te.current);return(J==null?void 0:J.name)??((W=L[0])==null?void 0:W.name)??""}function B(L,P){const X=L.find(W=>W.current&&!W.remote);if(X&&X.name!==P)return X.name;const J=L.find(W=>!W.remote&&W.name!==P);return(J==null?void 0:J.name)??""}function Q(L){(!c.value||!L.some(P=>P.name===c.value))&&(c.value=V(L)),(!w.value||!L.some(P=>P.name===w.value))&&(w.value=B(L,c.value))}async function _(){var P;const L=e();if(L===null){Z.warning("请先选择仓库");return}if(!c.value||!w.value){Z.warning("请选择合入目标与我的分支");return}a.value=!0,p.value="",b.value=null,g.value=null;try{const X=await qe(L,"git_merge_preview",{into:c.value,from:w.value,fetch:m.value,dryRun:!1});if(!X.success){p.value=((P=X.error)==null?void 0:P.message)??"预演失败";return}b.value=X.result}catch(X){p.value=X instanceof Error?X.message:String(X)}finally{a.value=!1}}async function $(){if(!x.value)return;const L={into:c.value,from:w.value,files:[],push:E.value};await f("git_apply_resolve",L)}async function S(){const L=await v();L!=null&&L.success&&L.result&&typeof L.result=="object"&&(g.value=L.result,Z.success(g.value.pushed?"已落盘并推送临时分支":"已落盘到本地临时分支"))}return ye(()=>t.currentId,()=>{b.value=null,g.value=null,c.value="",w.value=""}),ye(()=>[n.repoId,n.list],([L,P])=>{L===t.currentId&&Q(P)},{deep:!0,immediate:!0}),(L,P)=>{var T,U;const X=R("el-button"),J=R("el-alert"),W=R("el-switch"),te=R("el-card"),ue=R("el-tag"),ee=R("el-table-column"),ne=R("el-table"),pe=R("el-empty");return y(),M("div",ba,[k("div",va,[P[5]||(P[5]=k("h2",{class:"page-title"},"合并预演",-1)),h(X,{loading:a.value,disabled:!K(o),type:"primary",onClick:_},{default:u(()=>[...P[4]||(P[4]=[I("预演",-1)])]),_:1},8,["loading","disabled"])]),p.value?(y(),H(J,{key:0,title:p.value,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):j("",!0),K(o)?(y(),M(ae,{key:2},[h(te,{shadow:"never",class:"mb"},{default:u(()=>[k("div",_a,[k("div",wa,[P[6]||(P[6]=k("span",{class:"field-label"},"合入目标 into(线上 / ours)",-1)),h(pt,{modelValue:c.value,"onUpdate:modelValue":P[0]||(P[0]=D=>c.value=D),"remote-first":"",placeholder:"选择合入目标"},null,8,["modelValue"])]),k("div",ka,[P[7]||(P[7]=k("span",{class:"field-label"},"我的分支 from(theirs)",-1)),h(pt,{modelValue:w.value,"onUpdate:modelValue":P[1]||(P[1]=D=>w.value=D),placeholder:"选择我的分支"},null,8,["modelValue"])]),k("div",Ca,[P[8]||(P[8]=k("span",{class:"field-label"},"先 fetch",-1)),h(W,{modelValue:m.value,"onUpdate:modelValue":P[2]||(P[2]=D=>m.value=D)},null,8,["modelValue"])])]),P[9]||(P[9]=k("p",{class:"tip"},[I(" 预演使用 "),k("span",{class:"mono"},"git merge-tree"),I(",不会改工作区,也不会执行 "),k("span",{class:"mono"},"git merge"),I("。 方向:把「我的分支」合入「合入目标」。 ")],-1))]),_:1}),b.value?(y(),H(te,{key:0,shadow:"never",class:"mb"},{header:u(()=>[k("div",xa,[h(ue,{type:A.value,effect:"dark"},{default:u(()=>[I(O(N.value),1)]),_:1},8,["type"]),k("span",Ta,O(b.value.into)+" ("+O(b.value.intoSha.slice(0,7))+") ← "+O(b.value.from)+" ("+O(b.value.fromSha.slice(0,7))+")",1),b.value.fetchAttempted&&!b.value.fetched?(y(),H(ue,{key:0,type:"warning",effect:"plain",size:"small"},{default:u(()=>[...P[10]||(P[10]=[I("远程未更新",-1)])]),_:1})):j("",!0),x.value?(y(),H(X,{key:1,type:"primary",onClick:$},{default:u(()=>[...P[11]||(P[11]=[I("落盘并推送",-1)])]),_:1})):j("",!0)])]),default:u(()=>[b.value.outcome==="conflicts"?(y(),H(J,{key:0,type:"warning",closable:!1,"show-icon":"",class:"mb",title:"网页暂不能逐文件选边。请在 Cursor 对话里让 Agent 调用 git_merge_rehearse,选边后用 git_apply_resolve 落盘。"})):b.value.outcome==="unrelated"?(y(),H(J,{key:1,type:"warning",closable:!1,"show-icon":"",class:"mb",title:"两条历史没有共同祖先,不能当作干净合并落盘。"})):b.value.clean?(y(),H(J,{key:2,type:"success",closable:!1,"show-icon":"",class:"mb",title:"可干净合并。落盘会在独立 worktree 提交到临时分支,主工作区保持不变。"})):j("",!0),b.value.conflictFiles.length?(y(),H(ne,{key:3,data:b.value.conflictFiles,stripe:"",class:"conflict-table"},{default:u(()=>[h(ee,{prop:"path",label:"冲突文件","min-width":"280"},{default:u(({row:D})=>[k("span",Sa,O(D.path),1)]),_:1}),h(ee,{label:"类型",width:"120"},{default:u(()=>[h(ue,{size:"small",type:"danger",effect:"plain"},{default:u(()=>[...P[12]||(P[12]=[I("内容冲突",-1)])]),_:1})]),_:1})]),_:1},8,["data"])):b.value.clean?(y(),H(pe,{key:4,description:"没有冲突文件"})):j("",!0),b.value.messages.length?(y(),M("div",$a,[(y(!0),M(ae,null,he(b.value.messages.slice(0,8),(D,de)=>(y(),M("div",{key:de,class:"msg-line mono"},O(D),1))),128))])):j("",!0)]),_:1})):j("",!0),g.value?(y(),H(te,{key:1,shadow:"never"},{header:u(()=>[...P[13]||(P[13]=[I("落盘结果",-1)])]),default:u(()=>[k("p",Ea,[P[14]||(P[14]=I("临时分支 ",-1)),k("span",Na,O(g.value.tempBranch),1),P[15]||(P[15]=I(" · 提交 ",-1)),k("span",La,O(g.value.commitSha.slice(0,7)),1)]),g.value.createMrUrl?(y(),M("p",Ia,[k("a",{href:g.value.createMrUrl,target:"_blank",rel:"noreferrer"},"打开创建 MR/PR 页面",8,Va)])):j("",!0),(y(!0),M(ae,null,he(g.value.messages,(D,de)=>(y(),M("div",{key:de,class:"msg-line mono"},O(D),1))),128))]),_:1})):j("",!0)],64)):(y(),M("div",ya,"请先在「仓库管理」中打开一个仓库")),h(tn,{visible:K(l),"onUpdate:visible":P[3]||(P[3]=D=>Xt(l)?l.value=D:null),tool:((T=K(r))==null?void 0:T.tool)??"",preview:((U=K(r))==null?void 0:U.preview)??null,onConfirm:S,onCancel:K(i)},null,8,["visible","tool","preview","onCancel"])])}}}),Pa=xe(Da,[["__scopeId","data-v-34013775"]]),Oa={class:"page"},Ra={class:"filter-bar"},Aa={class:"mono hash"},Fa={class:"subject"},Ma={key:0,class:"refs"},za={class:"sub"},Ba={class:"commit-head"},Ha={class:"mono commit-hash"},Ua={class:"commit-subject"},Wa={class:"commit-meta"},ja={key:0},Ga={key:0,class:"commit-body"},qa={class:"diff-wrap"},Ka={class:"diff-summary"},Xa={class:"add"},Ja={class:"del"},Ya={key:0,class:"warn"},Qa=Ce({__name:"HistoryView",setup(s){const t=$e(),n=He(),{revision:e}=Qe(),l=()=>t.currentId,r=G([]),o=G(!1),f=G(""),v=G("head"),i=G(""),c=G(""),w=G(50),m=G(!1),a=G(null),p=G(null),b=Y(()=>{var x;return((x=n.current)==null?void 0:x.name)??""});async function g(){const x=l();if(x!==null){o.value=!0,f.value="";try{const V={maxCount:w.value};v.value==="all"?V.all=!0:v.value==="branch"&&i.value&&(V.from=i.value),c.value.trim()&&(V.path=c.value.trim()),r.value=await qn(x,V)}catch(V){f.value=V instanceof Error?V.message:String(V),r.value=[]}finally{o.value=!1}}}async function E(){await g()}async function A(x){const V=l();if(V!==null){o.value=!0;try{const{diff:B}=await Xn(V,x.hash);a.value=x,console.log(B),p.value=B,m.value=!0}catch(B){B instanceof dt&&B.code==="COMMIT_NOT_FOUND"?Z.warning(`提交不存在(${x.shortHash}),可能已被清理,请刷新列表`):Z.error(B instanceof Error?B.message:String(B))}finally{o.value=!1}}}function N(x){const V=new Date(x);return Number.isNaN(V.getTime())?x:V.toLocaleString()}return ye(l,()=>{i.value="",E()}),ye(e,()=>void g()),ye([v,i,w],()=>void g()),Oe(()=>void E()),(x,V)=>{const B=R("el-alert"),Q=R("el-radio-button"),_=R("el-radio-group"),$=R("el-input"),S=R("el-option"),L=R("el-select"),P=R("el-button"),X=R("el-card"),J=R("el-table-column"),W=R("el-tag"),te=R("el-table"),ue=R("el-empty"),ee=R("el-divider"),ne=R("el-drawer"),pe=Ye("loading");return y(),M("div",Oa,[V[8]||(V[8]=k("h2",{class:"page-title"},"提交历史",-1)),f.value?(y(),H(B,{key:0,title:f.value,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):j("",!0),h(X,{shadow:"never",class:"mb"},{default:u(()=>[k("div",Ra,[h(_,{modelValue:v.value,"onUpdate:modelValue":V[0]||(V[0]=T=>v.value=T)},{default:u(()=>[h(Q,{value:"head"},{default:u(()=>[I("当前分支("+O(b.value)+")",1)]),_:1}),h(Q,{value:"all"},{default:u(()=>[...V[5]||(V[5]=[I("全部分支",-1)])]),_:1}),h(Q,{value:"branch"},{default:u(()=>[...V[6]||(V[6]=[I("指定分支",-1)])]),_:1})]),_:1},8,["modelValue"]),v.value==="branch"?(y(),H(pt,{key:0,modelValue:i.value,"onUpdate:modelValue":V[1]||(V[1]=T=>i.value=T),placeholder:"选择分支"},null,8,["modelValue"])):j("",!0),h($,{modelValue:c.value,"onUpdate:modelValue":V[2]||(V[2]=T=>c.value=T),clearable:"",placeholder:"按路径过滤(可选)",class:"path-input",onKeyup:mt(g,["enter"])},null,8,["modelValue"]),h(L,{modelValue:w.value,"onUpdate:modelValue":V[3]||(V[3]=T=>w.value=T),class:"count-select"},{default:u(()=>[h(S,{label:"20 条",value:20}),h(S,{label:"50 条",value:50}),h(S,{label:"100 条",value:100})]),_:1},8,["modelValue"]),h(P,{loading:o.value,onClick:g},{default:u(()=>[...V[7]||(V[7]=[I("刷新",-1)])]),_:1},8,["loading"])])]),_:1}),h(X,{shadow:"never"},{default:u(()=>[Je((y(),H(te,{data:r.value,size:"default","highlight-current-row":"",onRowClick:A},{default:u(()=>[h(J,{label:"提交",width:"100"},{default:u(({row:T})=>[k("span",Aa,O(T.shortHash),1)]),_:1}),h(J,{label:"信息","min-width":"300"},{default:u(({row:T})=>[k("div",Fa,O(T.subject),1),T.refs?(y(),M("div",Ma,[(y(!0),M(ae,null,he(T.refs.split(",").map(U=>U.trim()).filter(Boolean),U=>(y(),H(W,{key:U,size:"small",effect:"plain",class:"ref-tag"},{default:u(()=>[I(O(U.startsWith("tag: ")?U:U.includes("/")&&!U.startsWith("HEAD")?U.split("/").pop():U),1)]),_:2},1024))),128))])):j("",!0)]),_:1}),h(J,{label:"作者",width:"170"},{default:u(({row:T})=>[k("div",null,O(T.authorName),1),k("div",za,O(T.authorEmail),1)]),_:1}),h(J,{label:"时间",width:"180"},{default:u(({row:T})=>[I(O(N(T.authorDate)),1)]),_:1})]),_:1},8,["data"])),[[pe,o.value]]),!o.value&&r.value.length===0?(y(),H(ue,{key:0,description:"暂无提交记录"})):j("",!0)]),_:1}),h(ne,{modelValue:m.value,"onUpdate:modelValue":V[4]||(V[4]=T=>m.value=T),size:"60%","destroy-on-close":""},{default:u(()=>[a.value?(y(),M(ae,{key:0},[k("div",Ba,[k("div",Ha,O(a.value.hash),1),k("h3",Ua,O(a.value.subject),1),k("div",Wa,[k("span",null,O(a.value.authorName)+" <"+O(a.value.authorEmail)+">",1),k("span",null,O(N(a.value.authorDate)),1),a.value.refs?(y(),M("span",ja,"refs: "+O(a.value.refs),1)):j("",!0)]),a.value.body?(y(),M("pre",Ga,O(a.value.body),1)):j("",!0)]),h(ee),k("div",qa,[p.value?(y(),M(ae,{key:0},[k("div",Ka,[k("span",null,O(p.value.files.length)+" 个文件",1),k("span",Xa,"+"+O(p.value.insertions),1),k("span",Ja,"-"+O(p.value.deletions),1),p.value.truncated?(y(),M("span",Ya,"(已截断)")):j("",!0)]),h(ft,{patch:p.value.rawPatch},null,8,["patch"])],64)):(y(),H(ue,{key:1,description:"无差异","image-size":60}))])],64)):j("",!0)]),_:1},8,["modelValue"])])}}}),Za=xe(Qa,[["__scopeId","data-v-851d8cb3"]]),ei=Xe("logs",{state:()=>({logs:[],loading:!1,error:null,limit:50,toolFilter:""}),actions:{async load(){this.loading=!0,this.error=null;try{const{logs:s}=await Zn({limit:this.limit,tool:this.toolFilter||void 0});this.logs=s}catch(s){this.error=s instanceof Error?s.message:String(s)}finally{this.loading=!1}}}}),ti={class:"page"},ni={class:"filter-bar"},si={class:"tool-cell"},li={class:"mono repo-path"},ai=["title"],ii=["title"],oi=["title"],ri=Ce({__name:"LogsView",setup(s){const t=ei(),{revision:n}=Qe(),e=Y(()=>{const i=new Set;for(const c of t.logs)i.add(c.tool);return[...i].sort()}),l=i=>i.includes("reset")||i.includes("clean")||i.includes("force")||i.includes("rebase")?"dangerous":"write";function r(i){return l(i)==="dangerous"?"danger":i.startsWith("git_")?"primary":"success"}function o(i){const c=new Date(i);return Number.isNaN(c.getTime())?i:c.toLocaleString()}function f(i){return i==="mcp"?"primary":i==="web"?"success":"warning"}function v(i){if(i==null)return"";if(typeof i=="string")return i;try{const c=JSON.stringify(i);return c===void 0?"":c}catch{return String(i)}}return ye(n,()=>{t.load()}),Oe(()=>{t.load()}),(i,c)=>{const w=R("el-option"),m=R("el-select"),a=R("el-button"),p=R("el-card"),b=R("el-table-column"),g=R("el-tag"),E=R("el-table"),A=R("el-empty"),N=Ye("loading");return y(),M("div",ti,[c[7]||(c[7]=k("h2",{class:"page-title"},"操作日志",-1)),h(p,{shadow:"never",class:"mb"},{default:u(()=>[k("div",ni,[h(m,{modelValue:K(t).toolFilter,"onUpdate:modelValue":c[0]||(c[0]=x=>K(t).toolFilter=x),clearable:"",placeholder:"按工具过滤",class:"tool-select",onChange:K(t).load},{default:u(()=>[(y(!0),M(ae,null,he(e.value,x=>(y(),H(w,{key:x,label:x,value:x},null,8,["label","value"]))),128))]),_:1},8,["modelValue","onChange"]),h(m,{modelValue:K(t).limit,"onUpdate:modelValue":c[1]||(c[1]=x=>K(t).limit=x),class:"limit-select",onChange:K(t).load},{default:u(()=>[h(w,{label:"最近 20 条",value:20}),h(w,{label:"最近 50 条",value:50}),h(w,{label:"最近 100 条",value:100})]),_:1},8,["modelValue","onChange"]),h(a,{loading:K(t).loading,onClick:K(t).load},{default:u(()=>[...c[2]||(c[2]=[I("刷新",-1)])]),_:1},8,["loading","onClick"]),c[3]||(c[3]=k("span",{class:"tip"},"记录来源:Web / MCP / CLI 全部写入操作(只读操作不记录)",-1))])]),_:1}),h(p,{shadow:"never"},{default:u(()=>[Je((y(),H(E,{data:K(t).logs,size:"default"},{default:u(()=>[h(b,{label:"时间",width:"180"},{default:u(({row:x})=>[I(O(o(x.timestamp)),1)]),_:1}),h(b,{label:"来源",width:"90"},{default:u(({row:x})=>[h(g,{type:f(x.source),size:"small",effect:"plain"},{default:u(()=>[I(O(x.source.toUpperCase()),1)]),_:2},1032,["type"])]),_:1}),h(b,{label:"工具",width:"200"},{default:u(({row:x})=>[k("div",si,[h(g,{type:r(x.tool),size:"small",effect:"dark"},{default:u(()=>[I(O(x.tool),1)]),_:2},1032,["type"]),x.dryRun?(y(),H(g,{key:0,size:"small",type:"info",effect:"plain",class:"dry-tag"},{default:u(()=>[...c[4]||(c[4]=[I("dry-run",-1)])]),_:1})):j("",!0)])]),_:1}),h(b,{label:"仓库","min-width":"200"},{default:u(({row:x})=>[k("span",li,O(x.repoPath??"—"),1)]),_:1}),h(b,{label:"参数(脱敏)","min-width":"180"},{default:u(({row:x})=>[k("span",{class:"mono params",title:v(x.params)},O(v(x.params)||"—"),9,ai)]),_:1}),h(b,{label:"结果","min-width":"150"},{default:u(({row:x})=>[x.error?(y(),M(ae,{key:0},[h(g,{type:"danger",size:"small",effect:"plain",class:"result-tag"},{default:u(()=>[...c[5]||(c[5]=[I("失败",-1)])]),_:1}),k("div",{class:"err-text",title:x.error},O(x.error),9,ii)],64)):(y(),M(ae,{key:1},[h(g,{type:"success",size:"small",effect:"plain",class:"result-tag"},{default:u(()=>[...c[6]||(c[6]=[I("成功",-1)])]),_:1}),k("div",{class:"ok-text",title:x.result},O(x.result),9,oi)],64))]),_:1}),h(b,{label:"耗时",width:"90"},{default:u(({row:x})=>[I(O(x.durationMs)+" ms",1)]),_:1})]),_:1},8,["data"])),[[N,K(t).loading]]),!K(t).loading&&K(t).logs.length===0?(y(),H(A,{key:0,description:"暂无操作日志"})):j("",!0)]),_:1})])}}}),ui=xe(ri,[["__scopeId","data-v-79ac665b"]]),di={class:"page"},ci={class:"card-head"},fi={class:"mono"},pi={class:"desc"},hi={key:1,class:"action-bar"},mi=Ce({__name:"SettingsView",setup(s){const t=Jt(),n=ut({disabledTools:[],requireApprovalFor:[],dryRunDefault:!1}),e=G(!1),l=Y(()=>{const m=t.permissions;return m?JSON.stringify([...n.disabledTools].sort())!==JSON.stringify([...m.disabledTools].sort())||JSON.stringify([...n.requireApprovalFor].sort())!==JSON.stringify([...m.requireApprovalFor].sort())||n.dryRunDefault!==m.dryRunDefault:!1}),r=Y(()=>t.tools.filter(m=>m.riskLevel==="dangerous")),o=Y(()=>r.value.map(m=>m.name));function f(){const m=t.permissions;m&&(n.disabledTools=[...m.disabledTools],n.requireApprovalFor=[...m.requireApprovalFor],n.dryRunDefault=m.dryRunDefault,e.value=!0)}ye(()=>t.permissions,m=>{m&&!l.value&&f()});async function v(m,a){a?n.disabledTools=n.disabledTools.filter(p=>p!==m.name):(n.disabledTools.includes(m.name)||n.disabledTools.push(m.name),n.requireApprovalFor=n.requireApprovalFor.filter(p=>p!==m.name))}function i(m){return m==="readonly"?"success":m==="write"?"primary":"danger"}function c(m){return m==="readonly"?"只读":m==="write"?"写操作":"高风险"}async function w(){try{await t.save({disabledTools:[...n.disabledTools],requireApprovalFor:[...n.requireApprovalFor],dryRunDefault:n.dryRunDefault}),Z.success("设置已保存")}catch(m){Z.error(m instanceof Error?m.message:String(m))}}return Oe(async()=>{await t.load(),f()}),(m,a)=>{const p=R("el-alert"),b=R("el-switch"),g=R("el-form-item"),E=R("el-form"),A=R("el-card"),N=R("el-tag"),x=R("el-table-column"),V=R("el-table"),B=R("el-option"),Q=R("el-select"),_=R("el-button"),$=Ye("loading");return y(),M("div",di,[a[10]||(a[10]=k("h2",{class:"page-title"},"设置",-1)),K(t).error?(y(),H(p,{key:0,title:K(t).error,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):j("",!0),h(A,{shadow:"never",class:"mb"},{header:u(()=>[...a[2]||(a[2]=[I("默认行为",-1)])]),default:u(()=>[h(E,{"label-width":"180px","label-position":"left"},{default:u(()=>[h(g,{label:"写操作默认 dry-run 预览"},{default:u(()=>[h(b,{modelValue:n.dryRunDefault,"onUpdate:modelValue":a[0]||(a[0]=S=>n.dryRunDefault=S)},null,8,["modelValue"]),a[3]||(a[3]=k("span",{class:"form-tip"},"开启后所有写操作(MCP/CLI)默认只生成预览,不真正执行",-1))]),_:1})]),_:1})]),_:1}),h(A,{shadow:"never",class:"mb"},{header:u(()=>[k("div",ci,[a[5]||(a[5]=k("span",null,"工具开关与风险等级",-1)),h(N,{size:"small",type:"warning",effect:"plain"},{default:u(()=>[...a[4]||(a[4]=[I("高危工具默认禁用,需在下方开启",-1)])]),_:1})])]),default:u(()=>[Je((y(),H(V,{data:K(t).tools,size:"default"},{default:u(()=>[h(x,{label:"工具",width:"230"},{default:u(({row:S})=>[k("span",fi,O(S.name),1)]),_:1}),h(x,{label:"风险",width:"90"},{default:u(({row:S})=>[h(N,{type:i(S.riskLevel),size:"small",effect:"dark"},{default:u(()=>[I(O(c(S.riskLevel)),1)]),_:2},1032,["type"])]),_:1}),h(x,{label:"描述","min-width":"240"},{default:u(({row:S})=>[k("span",pi,O(S.description),1)]),_:1}),h(x,{label:"启用",width:"100",align:"center"},{default:u(({row:S})=>[h(b,{"model-value":!n.disabledTools.includes(S.name),onChange:L=>v(S,L===!0)},null,8,["model-value","onChange"])]),_:1})]),_:1},8,["data"])),[[$,K(t).loading]])]),_:1}),h(A,{shadow:"never",class:"mb"},{header:u(()=>[...a[6]||(a[6]=[I("审批规则",-1)])]),default:u(()=>[h(E,{"label-position":"top"},{default:u(()=>[h(g,{label:"执行前需要审批的工具(勾选后,执行时需在确认框中手工确认)"},{default:u(()=>[h(Q,{modelValue:n.requireApprovalFor,"onUpdate:modelValue":a[1]||(a[1]=S=>n.requireApprovalFor=S),multiple:"",filterable:"","collapse-tags":"",placeholder:"选择需要审批的工具",style:{width:"100%"}},{default:u(()=>[(y(!0),M(ae,null,he(o.value,S=>(y(),H(B,{key:S,label:S,value:S,disabled:n.disabledTools.includes(S)},null,8,["label","value","disabled"]))),128))]),_:1},8,["modelValue"]),a[7]||(a[7]=k("span",{class:"form-tip"},"审批仅对已启用的高危工具生效;禁用后自动移除",-1))]),_:1})]),_:1})]),_:1}),e.value?(y(),M("div",hi,[h(_,{type:"primary",loading:K(t).saving,disabled:!l.value,onClick:w},{default:u(()=>[...a[8]||(a[8]=[I("保存设置",-1)])]),_:1},8,["loading","disabled"]),h(_,{disabled:!l.value,onClick:f},{default:u(()=>[...a[9]||(a[9]=[I("放弃修改",-1)])]),_:1},8,["disabled"])])):j("",!0)])}}}),gi=xe(mi,[["__scopeId","data-v-eb3ae411"]]),un=An({history:Fn(),routes:[{path:"/",redirect:"/status"},{path:"/repos",name:"repos",component:Cs,meta:{title:"仓库管理"}},{path:"/status",name:"status",component:ma,meta:{title:"状态"}},{path:"/merge",name:"merge",component:Pa,meta:{title:"合并预演"}},{path:"/history",name:"history",component:Za,meta:{title:"历史"}},{path:"/logs",name:"logs",component:ui,meta:{title:"操作日志"}},{path:"/settings",name:"settings",component:gi,meta:{title:"设置"}}]});un.afterEach(s=>{const t=s.meta.title;document.title=t?`${t} · Git Cockpit`:"Git Cockpit"});document.documentElement.classList.add("dark");const tt=Mn(fs);tt.use(zn());tt.use(un);tt.use(Bn,{size:"default"});tt.mount("#app");
|
package/dist/web/index.html
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Git Cockpit</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-MPCZvzsu.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/vue-CYNDxJyv.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/element-plus-D8uC5V5h.js">
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DUymtENk.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="app"></div>
|
package/dist/webServer.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shaohui_jin/git-cockpit-mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Git Cockpit - 基于 MCP 的 Git 可视化操作工具(MCP Server + Web 服务 + CLI)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,10 +27,13 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@fastify/cors": "^10.0.2",
|
|
29
29
|
"@fastify/static": "^8.0.3",
|
|
30
|
+
"@fastify/swagger": "^9.8.1",
|
|
31
|
+
"@fastify/swagger-ui": "^5.2.6",
|
|
30
32
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
31
33
|
"fastify": "^5.2.1",
|
|
32
34
|
"zod": "^3.24.1",
|
|
33
|
-
"
|
|
35
|
+
"zod-to-json-schema": "^3.25.2",
|
|
36
|
+
"@shaohui_jin/git-cockpit-core": "^0.1.8"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
39
|
"simple-git": "^3.27.0",
|
|
@@ -41,6 +44,7 @@
|
|
|
41
44
|
"scripts": {
|
|
42
45
|
"build": "tsup",
|
|
43
46
|
"dev": "tsup --watch",
|
|
47
|
+
"start": "node dist/cli-entry.js start",
|
|
44
48
|
"test": "vitest run",
|
|
45
49
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
46
50
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/**\n * CLI:`git-cockpit` 入口。\n * - git-cockpit start 启动常驻 daemon(Web 服务 + MCP Streamable HTTP),默认端口 3000;\n * - git-cockpit mcp 以 stdio 模式运行 MCP Server(供客户端直接拉起);\n * - git-cockpit version / --help。\n */\nimport { createRuntime, disposeRuntime } from './runtime.js';\nimport { createWebServer } from './webServer.js';\nimport { startMcpStdio } from './mcpServer.js';\n\nfunction printHelp(): void {\n console.log(`Git Cockpit - 基于 MCP 的 Git 可视化操作工具\n\n用法:\n git-cockpit start 启动 daemon:Web 界面 + MCP Server(Streamable HTTP)\n git-cockpit mcp 以 stdio 模式运行 MCP Server(供 Claude Desktop / Cursor 配置)\n git-cockpit version 输出版本号\n git-cockpit help 显示帮助\n\n环境变量:\n GIT_COCKPIT_DATA_DIR 数据目录(默认 ~/.git-cockpit)\n GIT_COCKPIT_PORT 端口(默认 3000)\n GIT_COCKPIT_HOST 监听地址(默认 localhost)\n`);\n}\n\nexport async function main(argv: string[]): Promise<number> {\n const args = argv.slice(2);\n const command = args[0] ?? 'start';\n\n if (command === 'help' || command === '--help' || command === '-h') {\n printHelp();\n return 0;\n }\n if (command === 'version' || command === '--version' || command === '-v') {\n console.log('0.1.0');\n return 0;\n }\n\n const dataDir = process.env.GIT_COCKPIT_DATA_DIR ?? '~/.git-cockpit';\n const runtime = createRuntime({ dataDir });\n\n if (command === 'mcp') {\n await startMcpStdio(runtime);\n return 0;\n }\n\n if (command === 'start') {\n const port = Number(process.env.GIT_COCKPIT_PORT) || runtime.config.server.port;\n const host = process.env.GIT_COCKPIT_HOST ?? runtime.config.server.host;\n const server = await createWebServer(runtime, { host, port });\n console.log(`[git-cockpit] Web UI: http://${host}:${port}`);\n console.log(`[git-cockpit] MCP (HTTP): http://${host}:${port}/mcp`);\n console.log(`[git-cockpit] 数据目录: ${dataDir}`);\n console.log(`[git-cockpit] Ctrl+C 退出`);\n return await new Promise<number>((resolve) => {\n const shutdown = () => {\n void server.close().then(() => resolve(0));\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n }\n\n console.error(`未知命令: ${command}`);\n printHelp();\n return 1;\n}\n\nexport { createRuntime, disposeRuntime };"],"mappings":";;;;;;;;;;AAUA,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAYb;AACD;AAEA,eAAsB,KAAK,MAAiC;AAC1D,QAAM,OAAO,KAAK,MAAM,CAAC;AACzB,QAAM,UAAU,KAAK,CAAC,KAAK;AAE3B,MAAI,YAAY,UAAU,YAAY,YAAY,YAAY,MAAM;AAClE,cAAU;AACV,WAAO;AAAA,EACT;AACA,MAAI,YAAY,aAAa,YAAY,eAAe,YAAY,MAAM;AACxE,YAAQ,IAAI,OAAO;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,QAAQ,IAAI,wBAAwB;AACpD,QAAM,UAAU,cAAc,EAAE,QAAQ,CAAC;AAEzC,MAAI,YAAY,OAAO;AACrB,UAAM,cAAc,OAAO;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,YAAY,SAAS;AACvB,UAAM,OAAO,OAAO,QAAQ,IAAI,gBAAgB,KAAK,QAAQ,OAAO,OAAO;AAC3E,UAAM,OAAO,QAAQ,IAAI,oBAAoB,QAAQ,OAAO,OAAO;AACnE,UAAM,SAAS,MAAM,gBAAgB,SAAS,EAAE,MAAM,KAAK,CAAC;AAC5D,YAAQ,IAAI,qCAAqC,IAAI,IAAI,IAAI,EAAE;AAC/D,YAAQ,IAAI,qCAAqC,IAAI,IAAI,IAAI,MAAM;AACnE,YAAQ,IAAI,gDAA4B,OAAO,EAAE;AACjD,YAAQ,IAAI,mCAAyB;AACrC,WAAO,MAAM,IAAI,QAAgB,CAAC,YAAY;AAC5C,YAAM,WAAW,MAAM;AACrB,aAAK,OAAO,MAAM,EAAE,KAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC3C;AACA,cAAQ,GAAG,UAAU,QAAQ;AAC7B,cAAQ,GAAG,WAAW,QAAQ;AAAA,IAChC,CAAC;AAAA,EACH;AAEA,UAAQ,MAAM,6BAAS,OAAO,EAAE;AAChC,YAAU;AACV,SAAO;AACT;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/webServer.ts","../src/runtime.ts","../src/config.ts","../src/repoManager.ts"],"sourcesContent":["/**\n * Fastify Web 服务:\n * - REST API 供 Web 前端调用(仓库管理、状态/历史/差异/branch 等只读查询、通用写操作入口);\n * - SSE(GET /api/events)推送仓库变化事件;\n * - 挂载 MCP Streamable HTTP 传输(/mcp),供 AI 客户端(Cursor/Claude Desktop)连接;\n * - 托管 Web 前端构建产物(packages/web/dist,若存在)。\n */\nimport * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport Fastify from 'fastify';\nimport type { FastifyInstance, FastifyReply } from 'fastify';\nimport cors from '@fastify/cors';\nimport fastifyStatic from '@fastify/static';\nimport {\n GitOperationError,\n GitService,\n PermissionManager,\n RepoNotFoundError\n} from '@shaohui_jin/git-cockpit-core';\nimport type { OpenedRepo } from '@shaohui_jin/git-cockpit-core';\nimport { disposeRuntime } from './runtime.js';\nimport type { Runtime } from './runtime.js';\nimport { McpHttpHandler } from './mcpServer.js';\nimport { executeTool } from './tools/handlers.js';\nimport { TOOL_DEF_MAP, toolSummaries } from './tools/index.js';\n\nexport interface WebServerHandle {\n app: FastifyInstance;\n /** 关闭 HTTP 服务与相关资源 */\n close: () => Promise<void>;\n}\n\n/** 静态资源目录:优先 Web 构建产物;不存在则仅提供 API。\n * 解析基于脚本自身位置(而非 process.cwd()),保证任意启动目录都能找到前端。 */\nfunction resolveWebDist(): string | null {\n // 源码布局下脚本位于 packages/mcp-server/dist,../.. 回到 packages,再进 web/dist\n const here = path.resolve(path.dirname(fileURLToPath(import.meta.url)));\n const candidates = [\n path.resolve(here, '..', '..', 'web', 'dist'), // 源码布局:packages/mcp-server/dist → packages/web/dist\n path.resolve(here, 'web'), // 发布布局:产物由 copy-web.mjs 打入 dist/web(含 index.html)\n path.resolve(here, 'web', 'dist'), // 兼容旧式 dist/web/dist 布局\n path.resolve(here, '..', 'web', 'dist'), // 兼容 npm 全局安装目录的旧式布局\n path.resolve(process.cwd(), 'dist', 'web'),\n path.resolve(process.cwd(), '..', 'web', 'dist'),\n path.resolve(process.cwd(), 'node_modules', '@shaohui_jin', 'git-cockpit-web', 'dist')\n ];\n for (const c of candidates) {\n if (fs.existsSync(path.join(c, 'index.html'))) return c;\n }\n return null;\n}\n\nexport async function createWebServer(\n runtime: Runtime,\n options: { host?: string; port?: number; staticDir?: string | null; noListen?: boolean } = {}\n): Promise<WebServerHandle> {\n const app = Fastify({ logger: false, bodyLimit: 2 * 1024 * 1024 });\n\n await app.register(cors, {\n origin: true,\n methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n allowedHeaders: ['Content-Type', 'Mcp-Session-Id', 'Authorization']\n });\n\n const staticDir = options.staticDir !== undefined ? options.staticDir : resolveWebDist();\n if (staticDir && fs.existsSync(staticDir)) {\n await app.register(fastifyStatic, { root: staticDir, prefix: '/' });\n }\n\n const mcpHttp = new McpHttpHandler(runtime);\n\n // Health\n app.get('/api/health', async () => ({\n ok: true,\n service: 'git-cockpit',\n version: '0.1.6',\n uptimeMs: process.uptime() * 1000\n }));\n\n // ---------------------------------------------------------------------------\n // 仓库管理\n // ---------------------------------------------------------------------------\n app.get('/api/repos', async () => ({\n repos: runtime.repoManager.list()\n }));\n\n app.post<{ Body: { path?: string } }>('/api/repos/open', async (req, reply) => {\n const target = req.body?.path?.trim();\n if (!target) {\n return reply.code(400).send({ error: '缺少 path 参数' } as never);\n }\n try {\n const handle = await runtime.repoManager.open(target);\n return { repo: handle.record };\n } catch (err) {\n return reply.code(400).send({ error: toError(err) } as never);\n }\n });\n\n app.delete<{ Params: { id: string } }>('/api/repos/:id', async (req, reply) => {\n const id = Number(req.params.id);\n if (!Number.isInteger(id)) {\n return reply.code(400).send({ error: '非法仓库 id' } as never);\n }\n runtime.repoManager.remove(id);\n return { ok: true };\n });\n\n /** 激活/进入仓库:刷新最近打开排序,并记录一条操作日志(source=web) */\n app.post<{ Params: { id: string } }>('/api/repos/:id/activate', async (req, reply) => {\n const id = Number(req.params.id);\n if (!Number.isInteger(id)) {\n return reply.code(400).send({ error: '非法仓库 id' } as never);\n }\n const t0 = Date.now();\n const repo = runtime.repoManager.activate(id);\n if (!repo) {\n return reply.code(404).send({ error: '仓库不存在或已失效' } as never);\n }\n runtime.auditLogger.log({\n timestamp: new Date().toISOString(),\n source: 'web',\n tool: 'repo_activate',\n repoPath: repo.path,\n params: { id: repo.id, path: repo.path },\n result: 'success',\n error: null,\n durationMs: Date.now() - t0,\n dryRun: false\n });\n runtime.eventBus.emit('log', { tool: 'repo_activate', result: 'success', at: new Date().toISOString() });\n return { repo };\n });\n\n // ---------------------------------------------------------------------------\n // 只读查询(按仓库 id)\n // ---------------------------------------------------------------------------\n async function withRepo<T>(\n req: { params: { id: string } },\n reply: FastifyReply,\n fn: (handle: { service: GitService; record: OpenedRepo }) => Promise<T>\n ): Promise<T | void> {\n const id = Number(req.params.id);\n const handle = await runtime.repoManager.getById(id);\n if (!handle) {\n await reply.code(404).send({ error: '仓库不存在或已失效' });\n return undefined;\n }\n try {\n return await fn(handle);\n } catch (err) {\n await reply.code(400).send({ error: toError(err) });\n return undefined;\n }\n }\n\n app.get<{ Params: { id: string } }>('/api/repos/:id/status', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.getStatus())\n );\n\n app.get<{ Params: { id: string }; Querystring: Record<string, string | undefined> }>('/api/repos/:id/log', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => {\n const q = req.query;\n return service.getLog({\n maxCount: q.maxCount ? Math.min(Number(q.maxCount) || 100, 10000) : undefined,\n from: q.from,\n to: q.to,\n author: q.author,\n path: q.path,\n all: q.all === 'true'\n });\n })\n );\n\n app.get<{ Params: { id: string }; Querystring: Record<string, string | undefined> }>('/api/repos/:id/diff', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => {\n const q = req.query;\n return service.getDiff({\n from: q.from,\n to: q.to,\n path: q.path,\n staged: q.staged === 'true',\n maxPatchBytes: q.maxPatchBytes ? Number(q.maxPatchBytes) : undefined\n });\n })\n );\n\n app.get<{ Params: { id: string; commit: string }; Querystring: Record<string, string | undefined> }>(\n '/api/repos/:id/show/:commit',\n async (req, reply) =>\n withRepo(req, reply, async ({ service }) =>\n service.getShow(req.params.commit, {\n path: req.query.path,\n maxPatchBytes: req.query.maxPatchBytes ? Number(req.query.maxPatchBytes) : undefined\n })\n )\n );\n\n app.get<{ Params: { id: string } }>('/api/repos/:id/branches', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.listBranches())\n );\n\n app.get<{ Params: { id: string } }>('/api/repos/:id/tags', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.listTags())\n );\n\n app.get<{ Params: { id: string } }>('/api/repos/:id/remotes', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.listRemotes())\n );\n\n app.get<{ Params: { id: string }; Querystring: Record<string, string | undefined> }>('/api/repos/:id/graph', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.getGraph(req.query.maxCount ? Number(req.query.maxCount) : 500))\n );\n\n app.get<{ Params: { id: string }; Querystring: { commit?: string; path?: string } }>('/api/repos/:id/file', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => {\n if (!req.query.commit || !req.query.path) {\n return { error: '需要 commit 与 path 参数' };\n }\n return service.getFileContent(req.query.commit, req.query.path);\n })\n );\n\n app.get<{ Params: { id: string } }>('/api/repos/:id/stashes', async (req, reply) =>\n withRepo(req, reply, async ({ service }) => service.listStashes())\n );\n\n // ---------------------------------------------------------------------------\n // 通用写操作入口(复用 MCP 同款安全链路)\n // ---------------------------------------------------------------------------\n app.post<{ Params: { id: string; tool: string }; Body: { params?: Record<string, unknown> } }>(\n '/api/repos/:id/tools/:tool',\n async (req, reply) => {\n const def = TOOL_DEF_MAP.get(req.params.tool);\n if (!def) return reply.code(404).send({ error: `未知工具: ${req.params.tool}` });\n const params = req.body?.params ?? {};\n const exec = await executeTool(def, params, {\n runtime,\n source: 'web',\n repoId: Number(req.params.id)\n });\n if (!exec.success) {\n const status = exec.error?.requiredApproval ? 403 : 400;\n return reply\n .code(status)\n .send({ error: exec.error?.message, requiredApproval: exec.error?.requiredApproval, code: exec.error?.code });\n }\n return { ...exec };\n }\n );\n\n // ---------------------------------------------------------------------------\n // 工具注册表信息(供前端渲染可操作按钮)\n // ---------------------------------------------------------------------------\n app.get('/api/tools', async () => ({\n tools: toolSummaries().map((t) => ({\n ...t,\n riskLevel: runtime.permissions.getRiskLevel(t.name),\n enabled: runtime.permissions.isEnabled(t.name)\n }))\n }));\n\n // ---------------------------------------------------------------------------\n // 操作日志\n // ---------------------------------------------------------------------------\n app.get<{ Querystring: Record<string, string | undefined> }>('/api/logs', async (req) => {\n const q = req.query;\n return {\n logs: runtime.auditLogger.list({\n limit: q.limit ? Number(q.limit) : undefined,\n offset: q.offset ? Number(q.offset) : undefined,\n tool: q.tool,\n source: (q.source as 'mcp' | 'web' | 'cli' | undefined) ?? undefined\n })\n };\n });\n\n // ---------------------------------------------------------------------------\n // 配置 / 权限\n // ---------------------------------------------------------------------------\n app.get('/api/settings', async () => ({\n config: runtime.configStore.snapshot(),\n permissions: {\n disabledTools: runtime.config.permissions.disabledTools,\n requireApprovalFor: runtime.config.permissions.requireApprovalFor,\n dryRunDefault: runtime.config.permissions.dryRunDefault\n },\n tools: toolSummaries().map((t) => ({\n name: t.name,\n description: t.description,\n riskLevel: runtime.permissions.getRiskLevel(t.name),\n enabled: runtime.permissions.isEnabled(t.name)\n }))\n }));\n\n app.put<{\n Body: { permissions?: { disabledTools?: string[]; requireApprovalFor?: string[]; dryRunDefault?: boolean } };\n }>('/api/settings', async (req, reply) => {\n const patch = req.body ?? {};\n if (patch.permissions === undefined) {\n return reply.code(400).send({ error: '仅支持更新 permissions 段' });\n }\n runtime.configStore.update({ permissions: patch.permissions });\n runtime.config = runtime.configStore.get();\n runtime.permissions = new PermissionManager(runtime.config);\n return { ok: true, config: runtime.configStore.snapshot() };\n });\n\n // ---------------------------------------------------------------------------\n // SSE:仓库变化推送\n // ---------------------------------------------------------------------------\n app.get('/api/events', async (req, reply) => {\n reply.hijack();\n const raw = reply.raw;\n raw.writeHead(200, {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n 'X-Accel-Buffering': 'no'\n });\n raw.write(': connected\\n\\n');\n\n const listener = (payload: unknown) => {\n raw.write(`event: repo-changed\\ndata: ${JSON.stringify(payload)}\\n\\n`);\n };\n const logListener = () => {\n raw.write('event: log\\ndata: {}\\n\\n');\n };\n runtime.eventBus.on('repo-changed', listener);\n runtime.eventBus.on('log', logListener);\n\n const keepAlive = setInterval(() => raw.write(': ping\\n\\n'), 15_000);\n\n req.raw.on('close', () => {\n clearInterval(keepAlive);\n runtime.eventBus.off('repo-changed', listener);\n runtime.eventBus.off('log', logListener);\n });\n });\n\n // ---------------------------------------------------------------------------\n // MCP Streamable HTTP\n // ---------------------------------------------------------------------------\n app.get('/mcp', async (req, reply) => {\n reply.hijack();\n await mcpHttp.handle(req.raw, reply.raw, undefined);\n });\n app.post('/mcp', async (req, reply) => {\n // fastify 预读并解析了请求体(req.body);SDK transport 需要 parsedBody 透传\n // (handleRequest(req, res, parsedBody)),否则它再读 req.raw 时流已空,initialize 无响应。\n reply.hijack();\n await mcpHttp.handle(req.raw, reply.raw, req.body);\n });\n\n // SPA fallback(静态托管存在时)\n if (staticDir) {\n app.setNotFoundHandler(async (req, reply) => {\n if (req.url.startsWith('/api') || req.url.startsWith('/mcp')) {\n return reply.code(404).send({ error: 'Not Found' });\n }\n const index = path.join(staticDir, 'index.html');\n if (fs.existsSync(index)) {\n reply.type('text/html').send(fs.readFileSync(index, 'utf8'));\n return;\n }\n return reply.code(404).send({ error: 'Not Found' });\n });\n }\n\n const port = options.port ?? runtime.config.server.port;\n const host = options.host ?? runtime.config.server.host;\n if (!options.noListen) {\n await app.listen({ port, host });\n }\n\n return {\n app,\n close: async () => {\n mcpHttp.dispose();\n await app.close();\n disposeRuntime(runtime);\n }\n };\n}\n\nfunction toError(err: unknown): { code: string; message: string; requiredApproval?: boolean } {\n if (err instanceof GitOperationError) return { code: err.code, message: err.message };\n if (err instanceof RepoNotFoundError) return { code: 'REPO_NOT_FOUND', message: err.message };\n if (err instanceof Error) return { code: 'INTERNAL_ERROR', message: err.message.slice(0, 500) };\n return { code: 'INTERNAL_ERROR', message: String(err) };\n}","/**\n * Runtime:mcp-server 共享运行时上下文。\n * - 唯一数据库实例、审计日志、权限管理器、仓库存储与其管理模式;\n * - eventBus 承载 Git 变更事件(changed / log),被 Web SSE 与订阅者消费。\n */\nimport { EventEmitter } from 'node:events';\nimport type { DatabaseSync } from 'node:sqlite';\nimport {\n AuditLogger,\n PermissionManager,\n RepoStore,\n openDatabase\n} from '@shaohui_jin/git-cockpit-core';\nimport type { GitCockpitConfig } from '@shaohui_jin/git-cockpit-core';\nimport { ConfigStore } from './config.js';\nimport { RepoManager } from './repoManager.js';\n\nexport interface RuntimeOptions {\n dataDir?: string;\n configOverrides?: ConstructorParameters<typeof ConfigStore>[1];\n db?: DatabaseSync;\n}\n\nexport interface Runtime {\n configStore: ConfigStore;\n config: GitCockpitConfig;\n db: DatabaseSync;\n auditLogger: AuditLogger;\n permissions: PermissionManager;\n repoStore: RepoStore;\n repoManager: RepoManager;\n /** 全局事件总线:'repo-changed' | 'log' */\n eventBus: EventEmitter;\n}\n\n/** 创建运行时(唯一后端共享);须在进程生命周期内调用一次 */\nexport function createRuntime(options: RuntimeOptions = {}): Runtime {\n const configStore = new ConfigStore(options.dataDir ?? '~/.git-cockpit', options.configOverrides);\n const config = configStore.get();\n const db = options.db ?? openDatabase(config.storage.dataDir);\n const eventBus = new EventEmitter();\n eventBus.setMaxListeners(200);\n\n const auditLogger = new AuditLogger(db, config.logging);\n const permissions = new PermissionManager(config);\n const repoStore = new RepoStore(db);\n const repoManager = new RepoManager({ repoStore, eventBus, config });\n\n return {\n configStore,\n config,\n db,\n auditLogger,\n permissions,\n repoStore,\n repoManager,\n eventBus\n };\n}\n\n/** 关闭运行时占用的资源(数据库等) */\nexport function disposeRuntime(runtime: Runtime): void {\n try {\n runtime.eventBus.removeAllListeners();\n runtime.repoManager.dispose();\n } catch {\n /* ignore */\n }\n try {\n runtime.db.close();\n } catch {\n /* ignore */\n }\n}","/**\n * 配置管理:默认值 <- 配置文件(config.json)合并(浅/深合并)。\n * 运行时通过 ConfigStore 读写,权限配置界面直接修改其内部状态并持久化。\n */\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { DEFAULT_CONFIG, expandHome } from '@shaohui_jin/git-cockpit-core';\nimport type { GitCockpitConfig } from '@shaohui_jin/git-cockpit-core';\n\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];\n};\n\n/** 递归合并:target 上已存在的值优先保留,仅用 source 填充缺失字段与新增对象 */\nfunction deepMerge<T>(target: T, source: unknown): T {\n if (source === null || source === undefined) return target;\n if (Array.isArray(source)) {\n return (source as unknown[]) as T;\n }\n if (typeof source === 'object' && typeof target === 'object' && target !== null) {\n const out = { ...(target as Record<string, unknown>) } as Record<string, unknown>;\n for (const [k, v] of Object.entries(source as Record<string, unknown>)) {\n if (v !== undefined) out[k] = deepMerge(out[k], v);\n }\n return out as T;\n }\n return source as T;\n}\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * ConfigStore:\n * - 配置存储在 <dataDir>/config.json;\n * - 数据目录默认 ~/.git-cockpit(支持 ~ 展开)。\n */\nexport class ConfigStore {\n private config: GitCockpitConfig;\n\n constructor(\n private readonly dataDir: string,\n overrides?: DeepPartial<GitCockpitConfig>\n ) {\n const dir = expandHome(dataDir);\n const file = path.join(dir, 'config.json');\n // 数据目录同时写入 storage.dataDir,保证数据库与配置存放在同一目录\n this.config = {\n ...this.load(file, overrides),\n storage: { dataDir: dir }\n };\n }\n\n private load(file: string, overrides?: DeepPartial<GitCockpitConfig>): GitCockpitConfig {\n let fileConfig: unknown = {};\n try {\n if (fs.existsSync(file)) {\n fileConfig = JSON.parse(fs.readFileSync(file, 'utf8'));\n }\n } catch (err) {\n // 配置文件损坏时回退默认(不阻断启动)\n console.warn(`[git-cockpit] 配置文件 ${file} 无法解析,已使用默认配置:`, (err as Error).message);\n }\n let merged = deepMerge(structuredClone(DEFAULT_CONFIG), fileConfig);\n if (overrides) merged = deepMerge(merged, overrides);\n return merged;\n }\n\n get(): GitCockpitConfig {\n return this.config;\n }\n\n /** 合并并持久化;返回新配置 */\n update(patch: DeepPartial<GitCockpitConfig>): GitCockpitConfig {\n this.config = deepMerge(this.config, patch);\n this.save();\n return this.config;\n }\n\n save(): void {\n const dir = expandHome(this.config.storage.dataDir);\n fs.mkdirSync(dir, { recursive: true });\n const file = path.join(dir, 'config.json');\n fs.writeFileSync(file, JSON.stringify(this.config, null, 2), 'utf8');\n }\n\n /** 供日志/调试:仅返回脱敏后的配置快照(隐藏敏感键名) */\n snapshot(): Record<string, unknown> {\n const copy = structuredClone(this.config);\n const redact = (v: unknown): unknown => {\n if (isPlainObject(v)) {\n const out: Record<string, unknown> = {};\n for (const [k, val] of Object.entries(v)) {\n const lower = k.toLowerCase();\n if (/password|token|secret|authorization|url/i.test(lower)) out[k] = '[REDACTED]';\n else out[k] = redact(val);\n }\n return out;\n }\n if (Array.isArray(v)) return v.map(redact);\n return v;\n };\n return redact(copy) as Record<string, unknown>;\n }\n}","/**\n * RepoManager:GitService 实例池 + 已打开仓库存储。\n * - 每个仓库根路径对应一个 GitService 实例(内含串行队列),Web 与 MCP 共用,\n * 保证\"唯一后端\"与锁全局有效;\n * - 打开仓库时校验合法性(GitService.open),并在 SQLite 中记录最近列表;\n * - 监听 Git 变更事件并转发到全局 eventBus,驱动前端实时刷新。\n */\nimport { EventEmitter } from 'node:events';\nimport * as path from 'node:path';\nimport {\n GitService,\n RepoNotFoundError,\n RepoStore\n} from '@shaohui_jin/git-cockpit-core';\nimport type { GitCockpitConfig, OpenedRepo } from '@shaohui_jin/git-cockpit-core';\n\nexport interface RepoHandle {\n service: GitService;\n record: OpenedRepo;\n}\n\nexport interface RepoManagerOptions {\n repoStore: RepoStore;\n eventBus: EventEmitter;\n config: GitCockpitConfig;\n}\n\nexport class RepoManager {\n /** repo 根路径(规范化绝对路径) -> repoId */\n private readonly pathToId = new Map<string, number>();\n private readonly idToService = new Map<number, GitService>();\n private readonly eventBus: EventEmitter;\n\n constructor(private readonly options: RepoManagerOptions) {\n this.eventBus = options.eventBus;\n // 为历史记录建立 路径->id 索引(服务实例懒创建)\n for (const repo of options.repoStore.list()) {\n this.pathToId.set(normalizePath(repo.path), repo.id);\n }\n }\n\n list(): (OpenedRepo & { available: boolean })[] {\n return this.options.repoStore.list().map((r) => ({\n ...r,\n available: r.path === '' || true\n }));\n }\n\n /** 取最近打开的仓库(懒创建服务) */\n async getCurrent(): Promise<RepoHandle | null> {\n const record = this.options.repoStore.list()[0];\n return record ? this.getByRecord(record) : null;\n }\n\n /** 按 id 取仓库(懒创建服务) */\n async getById(id: number): Promise<RepoHandle | null> {\n const record = this.options.repoStore.getById(id);\n if (!record) return null;\n try {\n return await this.getByRecord(record);\n } catch (err) {\n if (err instanceof Error && /NOT_A_GIT_REPO|REPO_NOT_FOUND/.test(err.message)) {\n return null;\n }\n throw err;\n }\n }\n\n /** 打开仓库:校验并记录;重复打开返回既有实例 */\n async open(repoPath: string): Promise<RepoHandle> {\n const service = await GitService.open(repoPath);\n const root = service.repoPath;\n const key = normalizePath(root);\n const existingId = this.pathToId.get(key);\n if (existingId !== undefined && existingId !== 0) {\n const record = this.options.repoStore.getById(existingId);\n if (record) {\n this.options.repoStore.open(root); // 刷新最近打开时间\n this.idToService.set(record.id, service);\n this.attach(service);\n return { service, record: this.options.repoStore.getById(record.id) ?? record };\n }\n }\n const record = this.options.repoStore.open(root);\n this.pathToId.set(key, record.id);\n this.idToService.set(record.id, service);\n this.attach(service);\n return { service, record };\n }\n\n /** 激活仓库:刷新最近打开时间,驱动「最近打开」列表重排到首位;仓库不存在返回 null */\n activate(id: number): OpenedRepo | null {\n const record = this.options.repoStore.getById(id);\n if (!record) return null;\n this.options.repoStore.open(record.path); // 同路径 open 仅更新 last_opened_at\n return this.options.repoStore.getById(id) ?? record;\n }\n\n /** 按路径取服务,未打开则报错(避免隐式副作用) */\n getByPath(repoPath: string): RepoHandle {\n const key = normalizePath(repoPath);\n const id = this.pathToId.get(key);\n if (id !== undefined && id !== 0) {\n const record = this.options.repoStore.getById(id);\n if (record) {\n const service = this.idToService.get(id);\n if (service) return { service, record };\n }\n }\n throw new RepoNotFoundError(`仓库未打开: ${repoPath}。请先打开仓库(POST /api/repos/open)。`);\n }\n\n /** 关闭:仅从内存服务池移除;保留历史记录 */\n close(id: number): void {\n const record = this.options.repoStore.getById(id);\n if (record) this.pathToId.delete(normalizePath(record.path));\n const svc = this.idToService.get(id);\n if (svc) svc.removeAllListeners('changed');\n this.idToService.delete(id);\n }\n\n /** 从历史记录中删除并关闭 */\n remove(id: number): void {\n this.close(id);\n this.options.repoStore.remove(id);\n }\n\n dispose(): void {\n for (const id of [...this.idToService.keys()]) this.close(id);\n }\n\n /** 按记录取句柄;服务缺失时(合法)创建并缓存 */\n private async getByRecord(record: OpenedRepo): Promise<RepoHandle> {\n let service = this.idToService.get(record.id);\n if (!service) {\n service = await GitService.open(record.path);\n this.pathToId.set(normalizePath(service.repoPath), record.id);\n this.idToService.set(record.id, service);\n this.attach(service);\n }\n return { service, record };\n }\n\n private attach(service: GitService): void {\n service.on('changed', (payload: { repoPath: string; command: string[] }) => {\n this.eventBus.emit('repo-changed', {\n repoPath: payload.repoPath,\n command: payload.command,\n at: new Date().toISOString()\n });\n });\n }\n}\n\nfunction normalizePath(p: string): string {\n let normalized = path.resolve(p);\n if (process.platform === 'win32') normalized = normalized.toLowerCase();\n return normalized;\n}"],"mappings":"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","names":["path","fs","PermissionManager","RepoNotFoundError","EventEmitter","RepoStore","path","record","EventEmitter","RepoStore","PermissionManager","RepoNotFoundError"]}
|