@shaohui_jin/git-cockpit-mcp-server 0.1.5 → 0.1.7
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-ASBVWOQY.js → chunk-5CZ3BO3H.js} +33 -2
- package/dist/chunk-5CZ3BO3H.js.map +1 -0
- package/dist/{chunk-4QEU6AVI.js → chunk-CLCT6P3U.js} +6 -3
- package/dist/chunk-CLCT6P3U.js.map +1 -0
- package/dist/cli-entry.js +2 -2
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/mcpServer.d.ts +1 -1
- package/dist/{runtime-CmdOmv60.d.ts → runtime-BzkM1IAj.d.ts} +2 -0
- package/dist/web/assets/{index-CBdX3yjE.css → index-BrQ29WGx.css} +1 -1
- package/dist/web/assets/index-rh3DXMef.js +114 -0
- package/dist/web/index.html +2 -2
- package/dist/webServer.d.ts +1 -1
- package/dist/webServer.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-4QEU6AVI.js.map +0 -1
- package/dist/chunk-ASBVWOQY.js.map +0 -1
- package/dist/web/assets/index-CSq1S2W2.js +0 -4
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import{az as ht,c as q,G as Le,d as Fe,a6 as $n,O as W,W as d,aj as O,aA as Ln,aB as mt,L as w,a0 as p,P as T,$ as P,u as X,M as A,F as se,ae as be,_ as I,Y as Dn,k as Q,aq as gt,S as Ue,ac as Oe,Z as J,w as Ve,i as In,e as dt,X as Xe,ak as Je,aC as Vn,aD as Pn,aw as On,aE as An}from"./vue-CYNDxJyv.js";import{E as ne,a as bt,e as Fn}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 f of l)if(f.type==="childList")for(const r of f.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&e(r)}).observe(document,{childList:!0,subtree:!0});function n(l){const f={};return l.integrity&&(f.integrity=l.integrity),l.referrerPolicy&&(f.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?f.credentials="include":l.crossOrigin==="anonymous"?f.credentials="omit":f.credentials="same-origin",f}function e(l){if(l.ep)return;l.ep=!0;const f=n(l);fetch(l.href,f)}})();class ct extends Error{constructor(t,n,e,l){super(t),this.status=n,this.code=e,this.requiredApproval=l,this.name="ApiError"}}async function me(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 ct(`无法连接后端服务(${t}):${l instanceof Error?l.message:String(l)}`,0)}if(!e.ok){let l=e.statusText,f,r;try{const h=await e.json();typeof h.error=="string"?(l=h.error,f=h.code,r=h.requiredApproval):h.error&&typeof h.error=="object"?(l=h.error.message??l,f=h.error.code??h.code,r=h.error.requiredApproval??h.requiredApproval):h.message&&(l=h.message,f=h.code,r=h.requiredApproval)}catch{}throw new ct(l,e.status,f,r)}return await e.json()}function Rn(){return me("GET","/api/repos")}function Mn(s){return me("POST","/api/repos/open",{path:s})}function zn(s){return me("POST",`/api/repos/${s}/activate`)}function Hn(s){return me("DELETE",`/api/repos/${s}`)}function Bn(s){return me("GET",`/api/repos/${s}/status`)}function Un(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 me("GET",`/api/repos/${s}/log${e?`?${e}`:""}`)}function Wn(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 me("GET",`/api/repos/${s}/diff${e?`?${e}`:""}`)}function jn(s,t){return me("GET",`/api/repos/${s}/show/${encodeURIComponent(t)}`)}function qt(s){return me("GET",`/api/repos/${s}/branches`)}function Gn(s){return me("GET",`/api/repos/${s}/stashes`)}function ut(s,t,n={}){return me("POST",`/api/repos/${s}/tools/${t}`,{params:n})}function qn(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 me("GET",`/api/logs${n?`?${n}`:""}`)}function Kn(){return me("GET","/api/settings")}function Xn(s){return me("PUT","/api/settings",{permissions:s})}function Jn(){return me("GET","/api/health")}function Yn(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 ft="git-cockpit:currentRepoId";function At(){try{const s=Number(window.localStorage.getItem(ft));return Number.isInteger(s)&&s>0?s:null}catch{return null}}function lt(s){try{s===null?window.localStorage.removeItem(ft):window.localStorage.setItem(ft,String(s))}catch{}}const Ye=ht("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 Jn();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 Rn();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 Mn(s);return await this.load(),t},async activate(s){const{repo:t}=await zn(s);return this.currentId=s,lt(s),await this.load(),t},async remove(s){await Hn(s),this.currentId===s&&(this.currentId=null),await this.load()},switchTo(s){this.currentId=s,lt(s)}}}),Kt=ht("settings",{state:()=>({permissions:null,tools:[],loading:!1,saving:!1,error:null}),actions:{async load(){this.loading=!0,this.error=null;try{const s=await Kn();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 Xn(s),this.permissions={...this.permissions,...s}}catch(t){throw this.error=t instanceof Error?t.message:String(t),t}finally{this.saving=!1}}}}}),Xt=q(0),Qn=()=>{Xt.value+=1};function Qe(){return{revision:Xt,bump:Qn}}const Zn={class:"repo-box"},es=["title"],ts={class:"menu-icon"},ns={class:"aside-footer"},ss=Le({__name:"App",setup(s){const t=Ye(),n=Kt(),e=Ln(),l=mt(),{bump:f}=Qe(),r=[{path:"/status",label:"状态",icon:"◧"},{path:"/history",label:"历史",icon:"◫"},{path:"/repos",label:"仓库管理",icon:"▤"},{path:"/logs",label:"操作日志",icon:"≡"},{path:"/settings",label:"设置",icon:"⚙"}],h=Q(()=>{if(!t.currentId)return"未选择仓库";const o=t.repos.find(c=>c.id===t.currentId);return(o==null?void 0:o.path)??"未选择仓库"});let y=null;return Fe(async()=>{await t.checkHealth(),await Promise.all([t.load(),n.load().catch(()=>{})]),y=Yn({onRepoChanged:()=>f(),onLog:()=>f(),onError:()=>{}})}),$n(()=>{y==null||y()}),(o,c)=>{const k=O("el-menu-item"),b=O("el-menu"),a=O("el-tag"),u=O("el-aside"),_=O("router-view"),v=O("el-main"),N=O("el-container");return w(),W(N,{class:"app-shell"},{default:d(()=>[p(u,{width:"220px",class:"app-aside"},{default:d(()=>[c[4]||(c[4]=T("div",{class:"brand"},[T("span",{class:"brand-mark"},"⌘"),T("span",{class:"brand-name"},"Git Cockpit")],-1)),T("div",Zn,[c[0]||(c[0]=T("div",{class:"repo-box-label"},"当前仓库",-1)),T("div",{class:"repo-box-path mono",title:h.value},P(h.value),9,es)]),p(b,{"default-active":X(e).path,class:"nav-menu"},{default:d(()=>[(w(),A(se,null,be(r,L=>p(k,{key:L.path,index:L.path,onClick:E=>X(l).push(L.path)},{default:d(()=>[T("span",ts,P(L.icon),1),T("span",null,P(L.label),1)]),_:2},1032,["index","onClick"])),64))]),_:1},8,["default-active"]),T("div",ns,[X(t).healthOk?(w(),W(a,{key:0,size:"small",type:"success"},{default:d(()=>[...c[1]||(c[1]=[I("后端已连接",-1)])]),_:1})):X(t).healthOk===!1?(w(),W(a,{key:1,size:"small",type:"danger"},{default:d(()=>[...c[2]||(c[2]=[I("后端离线",-1)])]),_:1})):(w(),W(a,{key:2,size:"small",type:"info"},{default:d(()=>[...c[3]||(c[3]=[I("连接中…",-1)])]),_:1}))])]),_:1}),p(N,{class:"app-main"},{default:d(()=>[p(v,{class:"main-content"},{default:d(()=>[p(_,null,{default:d(({Component:L})=>[(w(),W(Dn(L)))]),_:1})]),_:1})]),_:1})]),_:1})}}}),De=(s,t)=>{const n=s.__vccOpts||s;for(const[e,l]of t)n[e]=l;return n},ls=De(ss,[["__scopeId","data-v-17b27ba6"]]),as={class:"page"},is={class:"open-row"},os={class:"list-header"},rs={key:1,class:"tree-scroll"},ds=["title"],cs=["title","onDblclick"],us={class:"node-name mono"},fs={class:"node-time"},ps={class:"node-actions"},hs=Le({__name:"ReposView",setup(s){const t=Ye(),n=mt(),e=q(""),l=q(!1),f=Q(()=>{const b=[],a=new Map;t.repos.forEach((_,v)=>a.set(_.id,v));for(const _ of t.repos){const v=_.path.split(/[\\/]+/).filter(E=>E.length>0);if(v.length===0)continue;let N=b,L="";for(const[E,$]of v.entries()){L=L?`${L}/${$}`:$;const H=E===v.length-1,M=N.find(F=>!F.repo&&F.label===$);if(H)N.push({key:"repo:"+_.path,label:$,fullPath:_.path,repo:_});else{const F=M??{key:"dir:"+L,label:$,fullPath:L};M||N.push(F),F.children??(F.children=[]),N=F.children}}}const u=_=>{_.sort((v,N)=>{const L=v.repo?1:0,E=N.repo?1:0;return L!==E?L-E:L===1?(a.get(v.repo.id)??0)-(a.get(N.repo.id)??0):v.label.localeCompare(N.label)});for(const v of _)v.children&&u(v.children)};return u(b),b}),r=Q(()=>{const b=t.current;if(b){const u=b.path.split(/[\\/]+/).filter(N=>N.length>0),_=[];let v="";for(let N=0;N<u.length-1;N++)v=v?`${v}/${u[N]}`:u[N],_.push("dir:"+v);if(_.length>0)return _}const a=f.value[0];return a&&!a.repo?[a.key]:[]});async function h(){const b=e.value.trim();if(!b){ne.warning("请输入仓库路径");return}l.value=!0;try{const a=await t.open(b);ne.success(`已打开 ${a.path}`),t.switchTo(a.id),await n.push("/status")}catch(a){ne.error(a instanceof Error?a.message:String(a))}finally{l.value=!1}}async function y(b,a){try{await bt.confirm(`确定从列表移除 ${a}?注意:不会删除磁盘上的仓库文件。`,"移除仓库",{type:"warning",confirmButtonText:"移除",cancelButtonText:"取消"})}catch{return}try{await t.remove(b),ne.success("已移除")}catch(u){ne.error(u instanceof Error?u.message:String(u))}}async function o(b){try{await t.activate(b)}catch{t.switchTo(b)}n.push("/status")}function c(b){const a=new Date(b);return Number.isNaN(a.getTime())?b:a.toLocaleString()}function k(b){b.repo&&o(b.repo.id)}return Fe(()=>t.load()),(b,a)=>{const u=O("el-input"),_=O("el-button"),v=O("el-card"),N=O("el-empty"),L=O("el-tree");return w(),A("div",as,[a[7]||(a[7]=T("h2",{class:"page-title"},"仓库管理",-1)),p(v,{class:"open-card",shadow:"never"},{header:d(()=>[...a[2]||(a[2]=[I("打开本地仓库",-1)])]),default:d(()=>[T("div",is,[p(u,{modelValue:e.value,"onUpdate:modelValue":a[0]||(a[0]=E=>e.value=E),placeholder:"输入本地 Git 仓库路径,例如 D:\\project\\repo 或 /Users/me/code/app",clearable:"",onKeyup:gt(h,["enter"])},null,8,["modelValue"]),p(_,{type:"primary",loading:l.value,onClick:h},{default:d(()=>[...a[3]||(a[3]=[I("打开",-1)])]),_:1},8,["loading"])])]),_:1}),p(v,{shadow:"never",class:"list-card"},{header:d(()=>[T("div",os,[T("span",null,"最近打开的仓库("+P(X(t).repos.length)+")",1),p(_,{text:"",type:"primary",loading:X(t).loading,onClick:a[1]||(a[1]=E=>X(t).load())},{default:d(()=>[...a[4]||(a[4]=[I("刷新",-1)])]),_:1},8,["loading"])])]),default:d(()=>[!X(t).loading&&X(t).repos.length===0?(w(),W(N,{key:0,description:"尚未打开任何仓库"})):(w(),A("div",rs,[p(L,{data:f.value,props:{label:"label",children:"children"},"node-key":"key",accordion:"","default-expanded-keys":r.value,indent:14,class:"repo-tree"},{default:d(({data:E})=>[E.repo?(w(),A("div",{key:1,class:Ue(["repo-node",{current:E.repo.id===X(t).currentId}]),title:E.repo.path,onDblclick:$=>k(E)},[T("span",us,P(E.label),1),T("span",fs,P(c(E.repo.lastOpenedAt)),1),T("span",ps,[p(_,{size:"small",text:"",type:"primary",onClick:Oe($=>k(E),["stop"])},{default:d(()=>[...a[5]||(a[5]=[I("进入",-1)])]),_:1},8,["onClick"]),p(_,{size:"small",text:"",type:"danger",onClick:Oe($=>y(E.repo.id,E.repo.path),["stop"])},{default:d(()=>[...a[6]||(a[6]=[I("移除",-1)])]),_:1},8,["onClick"])])],42,cs)):(w(),A("span",{key:0,class:"tree-dir",title:E.fullPath},P(E.label),9,ds))]),_:1},8,["data","default-expanded-keys"])]))]),_:1})])}}}),ms=De(hs,[["__scopeId","data-v-9d40cd16"]]);function gs(s){const t=mt(),n=q(!1),e=q(null),l=q(!1),f=Q(()=>s()!==null);async function r(k,b={}){const a=s();if(a===null)return ne.warning("请先选择仓库"),!1;try{const u=await ut(a,k,{...b,dryRun:!0});return u.success?(e.value={tool:k,params:b,preview:u.preview??u.result},n.value=!0,!0):(o(u),!1)}catch(u){return c(u),!1}}async function h(){const k=s(),b=e.value;if(k===null||!b)return null;l.value=!0,n.value=!1;try{const a=await ut(k,b.tool,b.params);return a.success?(a.backupCreated?ne.success(`${b.tool} 执行成功(已自动备份:${a.backupCreated.branch??"分支"}${a.backupCreated.stashRef?` / ${a.backupCreated.stashRef}`:""})`):ne.success(`${b.tool} 执行成功`),a):(o(a),a)}catch(a){return c(a),null}finally{l.value=!1,e.value=null}}function y(){n.value=!1,e.value=null}function o(k){var b,a,u;if(((b=k.error)==null?void 0:b.code)==="PERMISSION_DENIED"){k.error.requiredApproval?bt.confirm(`操作 ${k.tool} 属于高风险操作,当前默认禁用,需要在设置中开启后才能执行。是否前往设置?`,"需要审批",{confirmButtonText:"去开启",cancelButtonText:"取消",type:"warning"}).then(()=>t.push("/settings")).catch(()=>{}):ne.error(((a=k.error)==null?void 0:a.message)??"操作被拒绝");return}ne.error(((u=k.error)==null?void 0:u.message)??"操作失败")}function c(k){const b=k instanceof Error?k.message:String(k);ne.error(b)}return{confirmVisible:n,pending:e,executing:l,canRun:f,previewAndConfirm:r,executeConfirmed:h,cancel:y}}const bs={key:2,class:"cmd-box"},vs={class:"cmd-pre mono"},ys={key:3,class:"files-box"},_s={class:"cmd-label"},ws={key:4,class:"note-text"},ks={class:"risk-tag"},Cs=Le({__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=Q(()=>{const c=n.preview;return c&&"command"in c&&typeof c.command=="string"?c.command:""}),f=Q(()=>{const c=n.preview;return c&&"risk"in c&&typeof c.risk=="string"?c.risk:"write"}),r=Q(()=>{const c=n.preview;return c&&"affectedFiles"in c&&Array.isArray(c.affectedFiles)?c.affectedFiles:[]}),h=Q(()=>f.value==="dangerous"?{type:"danger",label:"高风险"}:f.value==="write"?{type:"warning",label:"写操作"}:{type:"info",label:"只读"});function y(){e("confirm")}function o(){e("cancel"),e("update:visible",!1),ne.info("操作已取消")}return(c,k)=>{const b=O("el-alert"),a=O("el-scrollbar"),u=O("el-tag"),_=O("el-button"),v=O("el-dialog");return w(),W(v,{"model-value":s.visible,title:`执行操作:${s.tool}`,width:"560px","close-on-click-modal":!1,onClosed:k[0]||(k[0]=N=>e("update:visible",!1))},{footer:d(()=>[T("span",ks,[p(u,{type:h.value.type,size:"small",effect:"dark"},{default:d(()=>[I(P(h.value.label),1)]),_:1},8,["type"])]),p(_,{onClick:o},{default:d(()=>[...k[4]||(k[4]=[I("取消",-1)])]),_:1}),p(_,{type:"primary",danger:f.value==="dangerous",onClick:y},{default:d(()=>[...k[5]||(k[5]=[I("确认执行",-1)])]),_:1},8,["danger"])]),default:d(()=>[f.value==="dangerous"?(w(),W(b,{key:0,type:"error",closable:!1,"show-icon":"",class:"risk-alert"},{title:d(()=>[...k[1]||(k[1]=[I("这是",-1),T("b",null,"高风险",-1),I("操作,将自动创建备份(临时分支 + stash)",-1)])]),_:1})):f.value==="write"?(w(),W(b,{key:1,type:"warning",closable:!1,"show-icon":"",class:"risk-alert"},{title:d(()=>[...k[2]||(k[2]=[I("写操作:执行后将修改仓库状态",-1)])]),_:1})):J("",!0),l.value?(w(),A("div",bs,[k[3]||(k[3]=T("div",{class:"cmd-label"},"将执行的命令(dry-run 预览,未实际执行)",-1)),T("pre",vs,P(l.value),1)])):J("",!0),r.value.length?(w(),A("div",ys,[T("div",_s,"涉及文件("+P(r.value.length)+")",1),p(a,{"max-height":"140px"},{default:d(()=>[(w(!0),A(se,null,be(r.value,N=>(w(),A("div",{key:N,class:"file-item mono"},P(N),1))),128))]),_:1})])):J("",!0),s.note?(w(),A("div",ws,P(s.note),1)):J("",!0)]),_:1},8,["model-value","title"])}}}),xs=De(Cs,[["__scopeId","data-v-5d42c09b"]]);var ie;(function(s){s.INSERT="insert",s.DELETE="delete",s.CONTEXT="context"})(ie||(ie={}));const Ts={LINE_BY_LINE:"line-by-line"},Ss={NONE:"none"},Ns={WORD:"word"};var Pe;(function(s){s.AUTO="auto",s.DARK="dark",s.LIGHT="light"})(Pe||(Pe={}));const Es=["-","[","]","/","{","}","(",")","*","+","?",".","\\","^","$","|"],$s=RegExp("["+Es.join("\\")+"]","g");function Ls(s){return s.replace($s,"\\$&")}function Ft(s){return s&&s.replace(/\\/g,"/")}function Ds(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 Jt(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 Rt(s,t){const n=s.split(".");return n.length>1?n[n.length-1]:t}function Mt(s,t){return t.reduce((n,e)=>n||s.startsWith(e),!1)}const zt=["a/","b/","i/","w/","c/","o/"];function $e(s,t,n){const e=n!==void 0?[...zt,n]:zt,l=t?new RegExp(`^${Ls(t)} "?(.+?)"?$`):new RegExp('^"?(.+?)"?$'),[,f=""]=l.exec(s)||[],r=e.find(y=>f.indexOf(y)===0);return(r?f.slice(r.length):f).replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [+-]\d{4}.*$/,"")}function Is(s,t){return $e(s,"---",t)}function Vs(s,t){return $e(s,"+++",t)}function Ps(s,t={}){const n=[];let e=null,l=null,f=null,r=null,h=null,y=null,o=null;const c="--- ",k="+++ ",b="@@",a=/^old mode (\d{6})/,u=/^new mode (\d{6})/,_=/^deleted file mode (\d{6})/,v=/^new file mode (\d{6})/,N=/^copy from "?(.+)"?/,L=/^copy to "?(.+)"?/,E=/^rename from "?(.+)"?/,$=/^rename to "?(.+)"?/,H=/^similarity index (\d+)%/,M=/^dissimilarity index (\d+)%/,F=/^index ([\da-z]+)\.\.([\da-z]+)\s*(\d{6})?/,m=/^Binary files (.*) and (.*) differ/,x=/^GIT binary patch/,S=/^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/,z=/^mode (\d{6}),(\d{6})\.\.(\d{6})/,ee=/^new file mode (\d{6})/,ce=/^deleted file mode (\d{6}),(\d{6})/,re=s.replace(/\/g,"").replace(/\r\n?/g,`
|
|
2
|
+
`).split(`
|
|
3
|
+
`);function K(){l!==null&&e!==null&&(e.blocks.push(l),l=null)}function ue(){e!==null&&(!e.oldName&&y!==null&&(e.oldName=y),!e.newName&&o!==null&&(e.newName=o),e.newName&&(n.push(e),e=null)),y=null,o=null}function de(){K(),ue(),e={blocks:[],deletedLines:0,addedLines:0}}function fe(D){K();let j;e!==null&&((j=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@.*/.exec(D))?(e.isCombined=!1,f=parseInt(j[1],10),h=parseInt(j[2],10)):(j=/^@@@ -(\d+)(?:,\d+)? -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@@.*/.exec(D))?(e.isCombined=!0,f=parseInt(j[1],10),r=parseInt(j[2],10),h=parseInt(j[3],10)):(D.startsWith(b)&&console.error("Failed to parse lines, starting in 0!"),f=0,h=0,e.isCombined=!1)),l={lines:[],oldStartLine:f,oldStartLine2:r,newStartLine:h,header:D}}function te(D){if(e===null||l===null||f===null||h===null)return;const j={content:D},C=e.isCombined?["+ "," +","++"]:["+"],Z=e.isCombined?["- "," -","--"]:["-"];Mt(D,C)?(e.addedLines++,j.type=ie.INSERT,j.oldNumber=void 0,j.newNumber=h++):Mt(D,Z)?(e.deletedLines++,j.type=ie.DELETE,j.oldNumber=f++,j.newNumber=void 0):(j.type=ie.CONTEXT,j.oldNumber=f++,j.newNumber=h++),l.lines.push(j)}function ve(D,j){let C=j;for(;C<re.length-3;){if(D.startsWith("diff"))return!1;if(re[C].startsWith(c)&&re[C+1].startsWith(k)&&re[C+2].startsWith(b))return!0;C++}return!1}return re.forEach((D,j)=>{if(!D||D.startsWith("*"))return;let C;const Z=re[j-1],Ne=re[j+1],Re=re[j+2];if(D.startsWith("diff --git")||D.startsWith("diff --combined")){if(de(),(C=/^diff --git "?([a-ciow]\/.+)"? "?([a-ciow]\/.+)"?/.exec(D))&&(y=$e(C[1],void 0,t.dstPrefix),o=$e(C[2],void 0,t.srcPrefix)),e===null)throw new Error("Where is my file !!!");e.isGitDiff=!0;return}if(D.startsWith("Binary files")&&!(e!=null&&e.isGitDiff)){if(de(),(C=/^Binary files "?([a-ciow]\/.+)"? and "?([a-ciow]\/.+)"? differ/.exec(D))&&(y=$e(C[1],void 0,t.dstPrefix),o=$e(C[2],void 0,t.srcPrefix)),e===null)throw new Error("Where is my file !!!");e.isBinary=!0;return}if((!e||!e.isGitDiff&&e&&D.startsWith(c)&&Ne.startsWith(k)&&Re.startsWith(b))&&de(),e!=null&&e.isTooBig)return;if(e&&(typeof t.diffMaxChanges=="number"&&e.addedLines+e.deletedLines>t.diffMaxChanges||typeof t.diffMaxLineLength=="number"&&D.length>t.diffMaxLineLength)){e.isTooBig=!0,e.addedLines=0,e.deletedLines=0,e.blocks=[],l=null;const Ee=typeof t.diffTooBigMessage=="function"?t.diffTooBigMessage(n.length):"Diff too big to be displayed";fe(Ee);return}if(D.startsWith(c)&&Ne.startsWith(k)||D.startsWith(k)&&Z.startsWith(c)){if(e&&!e.oldName&&D.startsWith("--- ")&&(C=Is(D,t.srcPrefix))){e.oldName=C,e.language=Rt(e.oldName,e.language);return}if(e&&!e.newName&&D.startsWith("+++ ")&&(C=Vs(D,t.dstPrefix))){e.newName=C,e.language=Rt(e.newName,e.language);return}}if(e&&(D.startsWith(b)||e.isGitDiff&&e.oldName&&e.newName&&!l)){fe(D);return}if(l&&(D.startsWith("+")||D.startsWith("-")||D.startsWith(" "))){te(D);return}const ke=!ve(D,j);if(e===null)throw new Error("Where is my file !!!");(C=a.exec(D))?e.oldMode=C[1]:(C=u.exec(D))?e.newMode=C[1]:(C=_.exec(D))?(e.deletedFileMode=C[1],e.isDeleted=!0):(C=v.exec(D))?(e.newFileMode=C[1],e.isNew=!0):(C=N.exec(D))?(ke&&(e.oldName=C[1]),e.isCopy=!0):(C=L.exec(D))?(ke&&(e.newName=C[1]),e.isCopy=!0):(C=E.exec(D))?(ke&&(e.oldName=C[1]),e.isRename=!0):(C=$.exec(D))?(ke&&(e.newName=C[1]),e.isRename=!0):(C=m.exec(D))?(e.isBinary=!0,e.oldName=$e(C[1],void 0,t.srcPrefix),e.newName=$e(C[2],void 0,t.dstPrefix),fe("Binary file")):x.test(D)?(e.isBinary=!0,fe(D)):(C=H.exec(D))?e.unchangedPercentage=parseInt(C[1],10):(C=M.exec(D))?e.changedPercentage=parseInt(C[1],10):(C=F.exec(D))?(e.checksumBefore=C[1],e.checksumAfter=C[2],C[3]&&(e.mode=C[3])):(C=S.exec(D))?(e.checksumBefore=[C[2],C[3]],e.checksumAfter=C[1]):(C=z.exec(D))?(e.oldMode=[C[2],C[3]],e.newMode=C[1]):(C=ee.exec(D))?(e.newFileMode=C[1],e.isNew=!0):(C=ce.exec(D))&&(e.deletedFileMode=C[1],e.isDeleted=!0)}),K(),ue(),n}class Yt{diff(t,n,e={}){let l;typeof e=="function"?(l=e,e={}):"callback"in e&&(l=e.callback);const f=this.castInput(t,e),r=this.castInput(n,e),h=this.removeEmpty(this.tokenize(f,e)),y=this.removeEmpty(this.tokenize(r,e));return this.diffWithOptionsObj(h,y,e,l)}diffWithOptionsObj(t,n,e,l){var f;const r=L=>{if(L=this.postProcess(L,e),l){setTimeout(function(){l(L)},0);return}else return L},h=n.length,y=t.length;let o=1,c=h+y;e.maxEditLength!=null&&(c=Math.min(c,e.maxEditLength));const k=(f=e.timeout)!==null&&f!==void 0?f:1/0,b=Date.now()+k,a=[{oldPos:-1,lastComponent:void 0}];let u=this.extractCommon(a[0],n,t,0,e);if(a[0].oldPos+1>=y&&u+1>=h)return r(this.buildValues(a[0].lastComponent,n,t));let _=-1/0,v=1/0;const N=()=>{for(let L=Math.max(_,-o);L<=Math.min(v,o);L+=2){let E;const $=a[L-1],H=a[L+1];$&&(a[L-1]=void 0);let M=!1;if(H){const m=H.oldPos-L;M=H&&0<=m&&m<h}const F=$&&$.oldPos+1<y;if(!M&&!F){a[L]=void 0;continue}if(!F||M&&$.oldPos<H.oldPos?E=this.addToPath(H,!0,!1,0,e):E=this.addToPath($,!1,!0,1,e),u=this.extractCommon(E,n,t,L,e),E.oldPos+1>=y&&u+1>=h)return r(this.buildValues(E.lastComponent,n,t))||!0;a[L]=E,E.oldPos+1>=y&&(v=Math.min(v,L-1)),u+1>=h&&(_=Math.max(_,L+1))}o++};if(l)(function L(){setTimeout(function(){if(o>c||Date.now()>b)return l(void 0);N()||L()},0)})();else for(;o<=c&&Date.now()<=b;){const L=N();if(L)return L}}addToPath(t,n,e,l,f){const r=t.lastComponent;return r&&!f.oneChangePerToken&&r.added===n&&r.removed===e?{oldPos:t.oldPos+l,lastComponent:{count:r.count+1,added:n,removed:e,previousComponent:r.previousComponent}}:{oldPos:t.oldPos+l,lastComponent:{count:1,added:n,removed:e,previousComponent:r}}}extractCommon(t,n,e,l,f){const r=n.length,h=e.length;let y=t.oldPos,o=y-l,c=0;for(;o+1<r&&y+1<h&&this.equals(e[y+1],n[o+1],f);)o++,y++,c++,f.oneChangePerToken&&(t.lastComponent={count:1,previousComponent:t.lastComponent,added:!1,removed:!1});return c&&!f.oneChangePerToken&&(t.lastComponent={count:c,previousComponent:t.lastComponent,added:!1,removed:!1}),t.oldPos=y,o}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 f;for(;t;)l.push(t),f=t.previousComponent,delete t.previousComponent,t=f;l.reverse();const r=l.length;let h=0,y=0,o=0;for(;h<r;h++){const c=l[h];if(c.removed)c.value=this.join(e.slice(o,o+c.count)),o+=c.count;else{if(!c.added&&this.useLongestToken){let k=n.slice(y,y+c.count);k=k.map(function(b,a){const u=e[o+a];return u.length>b.length?u:b}),c.value=this.join(k)}else c.value=this.join(n.slice(y,y+c.count));y+=c.count,c.added||(o+=c.count)}}return l}}class Os extends Yt{}const As=new Os;function Fs(s,t,n){return As.diff(s,t,n)}const Ht="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 Rs extends Yt{tokenize(t){const n=new RegExp(`(\\r?\\n)|[${Ht}]+|[^\\S\\n\\r]+|[^${Ht}]`,"ug");return t.match(n)||[]}}const Ms=new Rs;function zs(s,t,n){return Ms.diff(s,t,n)}function Hs(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 vt(s){return(t,n)=>{const e=s(t).trim(),l=s(n).trim();return Hs(e,l)/(e.length+l.length)}}function yt(s){function t(e,l,f=new Map){let r=1/0,h;for(let y=0;y<e.length;++y)for(let o=0;o<l.length;++o){const c=JSON.stringify([e[y],l[o]]);let k;f.has(c)&&(k=f.get(c))||(k=s(e[y],l[o]),f.set(c,k)),k<r&&(r=k,h={indexA:y,indexB:o,score:r})}return h}function n(e,l,f=0,r=new Map){const h=t(e,l,r);if(!h||e.length+l.length<3)return[[e,l]];const y=e.slice(0,h.indexA),o=l.slice(0,h.indexB),c=[e[h.indexA]],k=[l[h.indexB]],b=h.indexA+1,a=h.indexB+1,u=e.slice(b),_=l.slice(a),v=n(y,o,f+1,r),N=n(c,k,f+1,r),L=n(u,_,f+1,r);let E=N;return(h.indexA>0||h.indexB>0)&&(E=v.concat(E)),(e.length>b||l.length>a)&&(E=E.concat(L)),E}return n}const he={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:Ss.NONE,matchWordsThreshold:.25,maxLineLengthHighlight:1e4,diffStyle:Ns.WORD,colorScheme:Pe.LIGHT},Ce="/",Qt=vt(s=>s.value),Bs=yt(Qt);function at(s){return s.indexOf("dev/null")!==-1}function Us(s){return s.replace(/(<ins[^>]*>((.|\n)*?)<\/ins>)/g,"")}function Ws(s){return s.replace(/(<del[^>]*>((.|\n)*?)<\/del>)/g,"")}function Ke(s){switch(s){case ie.CONTEXT:return he.CONTEXT;case ie.INSERT:return he.INSERTS;case ie.DELETE:return he.DELETES}}function _t(s){switch(s){case Pe.DARK:return"d2h-dark-color-scheme";case Pe.AUTO:return"d2h-auto-color-scheme";case Pe.LIGHT:default:return"d2h-light-color-scheme"}}function js(s){return s?2:1}function Ae(s){return s.slice(0).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")}function xe(s,t,n=!0){const e=js(t);return{prefix:s.substring(0,e),content:n?Ae(s.substring(e)):s.substring(e)}}function et(s){const t=Ft(s.oldName),n=Ft(s.newName);if(t!==n&&!at(t)&&!at(n)){const e=[],l=[],f=t.split(Ce),r=n.split(Ce),h=f.length,y=r.length;let o=0,c=h-1,k=y-1;for(;o<c&&o<k&&f[o]===r[o];)e.push(r[o]),o+=1;for(;c>o&&k>o&&f[c]===r[k];)l.unshift(r[k]),c-=1,k-=1;const b=e.join(Ce),a=l.join(Ce),u=f.slice(o,c+1).join(Ce),_=r.slice(o,k+1).join(Ce);return b.length&&a.length?b+Ce+"{"+u+" → "+_+"}"+Ce+a:b.length?b+Ce+"{"+u+" → "+_+"}":a.length?"{"+u+" → "+_+"}"+Ce+a:t+" → "+n}else return at(n)?t:n}function wt(s){return`d2h-${Ds(et(s)).toString().slice(-6)}`}function kt(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 Zt(s,t,n,e={}){const{matching:l,maxLineLengthHighlight:f,matchWordsThreshold:r,diffStyle:h}=Object.assign(Object.assign({},Ze),e),y=xe(s,n,!1),o=xe(t,n,!1);if(y.content.length>f||o.content.length>f)return{oldLine:{prefix:y.prefix,content:Ae(y.content)},newLine:{prefix:o.prefix,content:Ae(o.content)}};const c=h==="char"?Fs(y.content,o.content):zs(y.content,o.content),k=[];if(h==="word"&&l==="words"){const a=c.filter(v=>v.removed),u=c.filter(v=>v.added);Bs(u,a).forEach(v=>{v[0].length===1&&v[1].length===1&&Qt(v[0][0],v[1][0])<r&&(k.push(v[0][0]),k.push(v[1][0]))})}const b=c.reduce((a,u)=>{const _=u.added?"ins":u.removed?"del":null,v=k.indexOf(u)>-1?' class="d2h-change"':"",N=Ae(u.value);return _!==null?`${a}<${_}${v}>${N}</${_}>`:`${a}${N}`},"");return{oldLine:{prefix:y.prefix,content:Us(b)},newLine:{prefix:o.prefix,content:Ws(b)}}}const Bt="file-summary",Gs="icon",qs={colorScheme:Ze.colorScheme};class Ks{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},qs),n)}render(t){const n=t.map(e=>this.hoganUtils.render(Bt,"line",{fileHtmlId:wt(e),oldName:e.oldName,newName:e.newName,fileName:et(e),deletedLines:"-"+e.deletedLines,addedLines:"+"+e.addedLines},{fileIcon:this.hoganUtils.template(Gs,kt(e))})).join(`
|
|
4
|
+
`);return this.hoganUtils.render(Bt,"wrapper",{colorScheme:_t(this.config.colorScheme),filesNumber:t.length,files:n})}}const en=Object.assign(Object.assign({},Ze),{renderNothingWhenEmpty:!1,matchingMaxComparisons:2500,maxLineSizeInBlockForComparison:200}),He="generic",Ut="line-by-line",Xs="icon",Js="tag";class Ys{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},en),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(He,"wrapper",{colorScheme:_t(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(Ut,"file-diff"),l=this.hoganUtils.template(He,"file-path"),f=this.hoganUtils.template(Xs,"file"),r=this.hoganUtils.template(Js,kt(t));return e.render({file:t,fileHtmlId:wt(t),diffs:n,filePath:l.render({fileDiffName:et(t)},{fileIcon:f,fileTag:r})})}generateEmptyDiff(){return this.hoganUtils.render(He,"empty-diff",{contentClass:"d2h-code-line",CSSLineClass:he})}generateFileHtml(t){const n=yt(vt(e=>xe(e.content,t.isCombined).content));return t.blocks.map(e=>{let l=this.hoganUtils.render(He,"block-header",{CSSLineClass:he,blockHeader:t.isTooBig?e.header:Ae(e.header),lineClass:"d2h-code-linenumber",contentClass:"d2h-code-line"});return this.applyLineGroupping(e).forEach(([f,r,h])=>{if(r.length&&h.length&&!f.length)this.applyRematchMatching(r,h,n).map(([y,o])=>{const{left:c,right:k}=this.processChangedLines(t,t.isCombined,y,o);l+=c,l+=k});else if(f.length)f.forEach(y=>{const{prefix:o,content:c}=xe(y.content,t.isCombined);l+=this.generateSingleLineHtml(t,{type:he.CONTEXT,prefix:o,content:c,oldNumber:y.oldNumber,newNumber:y.newNumber})});else if(r.length||h.length){const{left:y,right:o}=this.processChangedLines(t,t.isCombined,r,h);l+=y,l+=o}else console.error("Unknown state reached while processing groups of lines",f,r,h)}),l}).join(`
|
|
6
|
+
`)}applyLineGroupping(t){const n=[];let e=[],l=[];for(let f=0;f<t.lines.length;f++){const r=t.lines[f];(r.type!==ie.INSERT&&l.length||r.type===ie.CONTEXT&&e.length>0)&&(n.push([[],e,l]),e=[],l=[]),r.type===ie.CONTEXT?n.push([[r],[],[]]):r.type===ie.INSERT&&e.length===0?n.push([[],[],[r]]):r.type===ie.INSERT&&e.length>0?l.push(r):r.type===ie.DELETE&&e.push(r)}return(e.length||l.length)&&(n.push([[],e,l]),e=[],l=[]),n}applyRematchMatching(t,n,e){const l=t.length*n.length,f=Jt(t.concat(n).map(h=>h.content.length));return l<this.config.matchingMaxComparisons&&f<this.config.maxLineSizeInBlockForComparison&&(this.config.matching==="lines"||this.config.matching==="words")?e(t,n):[[t,n]]}processChangedLines(t,n,e,l){const f={right:"",left:""},r=Math.max(e.length,l.length);for(let h=0;h<r;h++){const y=e[h],o=l[h],c=y!==void 0&&o!==void 0?Zt(y.content,o.content,n,this.config):void 0,k=y!==void 0&&y.oldNumber!==void 0?Object.assign(Object.assign({},c!==void 0?{prefix:c.oldLine.prefix,content:c.oldLine.content,type:he.DELETE_CHANGES}:Object.assign(Object.assign({},xe(y.content,n)),{type:Ke(y.type)})),{oldNumber:y.oldNumber,newNumber:y.newNumber}):void 0,b=o!==void 0&&o.newNumber!==void 0?Object.assign(Object.assign({},c!==void 0?{prefix:c.newLine.prefix,content:c.newLine.content,type:he.INSERT_CHANGES}:Object.assign(Object.assign({},xe(o.content,n)),{type:Ke(o.type)})),{oldNumber:o.oldNumber,newNumber:o.newNumber}):void 0,{left:a,right:u}=this.generateLineHtml(t,k,b);f.left+=a,f.right+=u}return f}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(Ut,"numbers",{oldNumber:n.oldNumber||"",newNumber:n.newNumber||""});return this.hoganUtils.render(He,"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 tn=Object.assign(Object.assign({},Ze),{renderNothingWhenEmpty:!1,matchingMaxComparisons:2500,maxLineSizeInBlockForComparison:200}),Be="generic",Qs="side-by-side",Zs="icon",el="tag";class tl{constructor(t,n={}){this.hoganUtils=t,this.config=Object.assign(Object.assign({},tn),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(Be,"wrapper",{colorScheme:_t(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(Qs,"file-diff"),l=this.hoganUtils.template(Be,"file-path"),f=this.hoganUtils.template(Zs,"file"),r=this.hoganUtils.template(el,kt(t));return e.render({file:t,fileHtmlId:wt(t),diffs:n,filePath:l.render({fileDiffName:et(t)},{fileIcon:f,fileTag:r})})}generateEmptyDiff(){return{right:"",left:this.hoganUtils.render(Be,"empty-diff",{contentClass:"d2h-code-side-line",CSSLineClass:he})}}generateFileHtml(t){const n=yt(vt(e=>xe(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(([f,r,h])=>{if(r.length&&h.length&&!f.length)this.applyRematchMatching(r,h,n).map(([y,o])=>{const{left:c,right:k}=this.processChangedLines(t.isCombined,y,o);l.left+=c,l.right+=k});else if(f.length)f.forEach(y=>{const{prefix:o,content:c}=xe(y.content,t.isCombined),{left:k,right:b}=this.generateLineHtml({type:he.CONTEXT,prefix:o,content:c,number:y.oldNumber},{type:he.CONTEXT,prefix:o,content:c,number:y.newNumber});l.left+=k,l.right+=b});else if(r.length||h.length){const{left:y,right:o}=this.processChangedLines(t.isCombined,r,h);l.left+=y,l.right+=o}else console.error("Unknown state reached while processing groups of lines",f,r,h)}),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 f=0;f<t.lines.length;f++){const r=t.lines[f];(r.type!==ie.INSERT&&l.length||r.type===ie.CONTEXT&&e.length>0)&&(n.push([[],e,l]),e=[],l=[]),r.type===ie.CONTEXT?n.push([[r],[],[]]):r.type===ie.INSERT&&e.length===0?n.push([[],[],[r]]):r.type===ie.INSERT&&e.length>0?l.push(r):r.type===ie.DELETE&&e.push(r)}return(e.length||l.length)&&(n.push([[],e,l]),e=[],l=[]),n}applyRematchMatching(t,n,e){const l=t.length*n.length,f=Jt(t.concat(n).map(h=>h.content.length));return l<this.config.matchingMaxComparisons&&f<this.config.maxLineSizeInBlockForComparison&&(this.config.matching==="lines"||this.config.matching==="words")?e(t,n):[[t,n]]}makeHeaderHtml(t,n){return this.hoganUtils.render(Be,"block-header",{CSSLineClass:he,blockHeader:n!=null&&n.isTooBig?t:Ae(t),lineClass:"d2h-code-side-linenumber",contentClass:"d2h-code-side-line"})}processChangedLines(t,n,e){const l={right:"",left:""},f=Math.max(n.length,e.length);for(let r=0;r<f;r++){const h=n[r],y=e[r],o=h!==void 0&&y!==void 0?Zt(h.content,y.content,t,this.config):void 0,c=h!==void 0&&h.oldNumber!==void 0?Object.assign(Object.assign({},o!==void 0?{prefix:o.oldLine.prefix,content:o.oldLine.content,type:he.DELETE_CHANGES}:Object.assign(Object.assign({},xe(h.content,t)),{type:Ke(h.type)})),{number:h.oldNumber}):void 0,k=y!==void 0&&y.newNumber!==void 0?Object.assign(Object.assign({},o!==void 0?{prefix:o.newLine.prefix,content:o.newLine.content,type:he.INSERT_CHANGES}:Object.assign(Object.assign({},xe(y.content,t)),{type:Ke(y.type)})),{number:y.newNumber}):void 0,{left:b,right:a}=this.generateLineHtml(c,k);l.left+=b,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(Be,"line",{type:(t==null?void 0:t.type)||`${he.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={},Wt;function nl(){return Wt||(Wt=1,(function(s){(function(t){var n=/\S/,e=/\"/g,l=/\n/g,f=/\r/g,r=/\\/g,h=/\u2028/,y=/\u2029/;t.tags={"#":1,"^":2,"<":3,$:4,"/":5,"!":6,">":7,"=":8,_v:9,"{":10,"&":11,_t:12},t.scan=function(x,S){var z=x.length,ee=0,ce=1,re=2,K=ee,ue=null,de=null,fe="",te=[],ve=!1,D=0,j=0,C="{{",Z="}}";function Ne(){fe.length>0&&(te.push({tag:"_t",text:new String(fe)}),fe="")}function Re(){for(var pe=!0,Y=j;Y<te.length;Y++)if(pe=t.tags[te[Y].tag]<t.tags._v||te[Y].tag=="_t"&&te[Y].text.match(n)===null,!pe)return!1;return pe}function ke(pe,Y){if(Ne(),pe&&Re())for(var ye=j,Te;ye<te.length;ye++)te[ye].text&&((Te=te[ye+1])&&Te.tag==">"&&(Te.indent=te[ye].text.toString()),te.splice(ye,1));else Y||te.push({tag:`
|
|
8
|
+
`});ve=!1,j=te.length}function Ee(pe,Y){var ye="="+Z,Te=pe.indexOf(ye,Y),Me=c(pe.substring(pe.indexOf("=",Y)+1,Te)).split(" ");return C=Me[0],Z=Me[Me.length-1],Te+ye.length-1}for(S&&(S=S.split(" "),C=S[0],Z=S[1]),D=0;D<z;D++)K==ee?k(C,x,D)?(--D,Ne(),K=ce):x.charAt(D)==`
|
|
9
|
+
`?ke(ve):fe+=x.charAt(D):K==ce?(D+=C.length-1,de=t.tags[x.charAt(D+1)],ue=de?x.charAt(D+1):"_v",ue=="="?(D=Ee(x,D),K=ee):(de&&D++,K=re),ve=D):k(Z,x,D)?(te.push({tag:ue,n:c(fe),otag:C,ctag:Z,i:ue=="/"?ve-C.length:D+Z.length}),fe="",D+=Z.length-1,K=ee,ue=="{"&&(Z=="}}"?D++:o(te[te.length-1]))):fe+=x.charAt(D);return ke(ve,!0),te};function o(m){m.n.substr(m.n.length-1)==="}"&&(m.n=m.n.substring(0,m.n.length-1))}function c(m){return m.trim?m.trim():m.replace(/^\s*|\s*$/g,"")}function k(m,x,S){if(x.charAt(S)!=m.charAt(0))return!1;for(var z=1,ee=m.length;z<ee;z++)if(x.charAt(S+z)!=m.charAt(z))return!1;return!0}var b={_t:!0,"\n":!0,$:!0,"/":!0};function a(m,x,S,z){var ee=[],ce=null,re=null,K=null;for(re=S[S.length-1];m.length>0;){if(K=m.shift(),re&&re.tag=="<"&&!(K.tag in b))throw new Error("Illegal content in < super tag.");if(t.tags[K.tag]<=t.tags.$||u(K,z))S.push(K),K.nodes=a(m,K.tag,S,z);else if(K.tag=="/"){if(S.length===0)throw new Error("Closing tag without opener: /"+K.n);if(ce=S.pop(),K.n!=ce.n&&!_(K.n,ce.n,z))throw new Error("Nesting error: "+ce.n+" vs. "+K.n);return ce.end=K.i,ee}else K.tag==`
|
|
10
|
+
`&&(K.last=m.length==0||m[0].tag==`
|
|
11
|
+
`);ee.push(K)}if(S.length>0)throw new Error("missing closing tag: "+S.pop().n);return ee}function u(m,x){for(var S=0,z=x.length;S<z;S++)if(x[S].o==m.n)return m.tag="#",!0}function _(m,x,S){for(var z=0,ee=S.length;z<ee;z++)if(S[z].c==m&&S[z].o==x)return!0}function v(m){var x=[];for(var S in m)x.push('"'+E(S)+'": function(c,p,t,i) {'+m[S]+"}");return"{ "+x.join(",")+" }"}function N(m){var x=[];for(var S in m.partials)x.push('"'+E(S)+'":{name:"'+E(m.partials[S].name)+'", '+N(m.partials[S])+"}");return"partials: {"+x.join(",")+"}, subs: "+v(m.subs)}t.stringify=function(m,x,S){return"{code: function (c,p,i) { "+t.wrapMain(m.code)+" },"+N(m)+"}"};var L=0;t.generate=function(m,x,S){L=0;var z={code:"",subs:{},partials:{}};return t.walk(m,z),S.asString?this.stringify(z,x,S):this.makeTemplate(z,x,S)},t.wrapMain=function(m){return'var t=this;t.b(i=i||"");'+m+"return t.fl();"},t.template=t.Template,t.makeTemplate=function(m,x,S){var z=this.makePartials(m);return z.code=new Function("c","p","i",this.wrapMain(m.code)),new this.template(z,x,this,S)},t.makePartials=function(m){var x,S={subs:{},partials:m.partials,name:m.name};for(x in S.partials)S.partials[x]=this.makePartials(S.partials[x]);for(x in m.subs)S.subs[x]=new Function("c","p","t","i",m.subs[x]);return S};function E(m){return m.replace(r,"\\\\").replace(e,'\\"').replace(l,"\\n").replace(f,"\\r").replace(h,"\\u2028").replace(y,"\\u2029")}function $(m){return~m.indexOf(".")?"d":"f"}function H(m,x){var S="<"+(x.prefix||""),z=S+m.n+L++;return x.partials[z]={name:m.n,partials:{}},x.code+='t.b(t.rp("'+E(z)+'",c,p,"'+(m.indent||"")+'"));',z}t.codegen={"#":function(m,x){x.code+="if(t.s(t."+$(m.n)+'("'+E(m.n)+'",c,p,1),c,p,0,'+m.i+","+m.end+',"'+m.otag+" "+m.ctag+'")){t.rs(c,p,function(c,p,t){',t.walk(m.nodes,x),x.code+="});c.pop();}"},"^":function(m,x){x.code+="if(!t.s(t."+$(m.n)+'("'+E(m.n)+'",c,p,1),c,p,1,0,0,"")){',t.walk(m.nodes,x),x.code+="};"},">":H,"<":function(m,x){var S={partials:{},code:"",subs:{},inPartial:!0};t.walk(m.nodes,S);var z=x.partials[H(m,x)];z.subs=S.subs,z.partials=S.partials},$:function(m,x){var S={subs:{},code:"",partials:x.partials,prefix:m.n};t.walk(m.nodes,S),x.subs[m.n]=S.code,x.inPartial||(x.code+='t.sub("'+E(m.n)+'",c,p,i);')},"\n":function(m,x){x.code+=F('"\\n"'+(m.last?"":" + i"))},_v:function(m,x){x.code+="t.b(t.v(t."+$(m.n)+'("'+E(m.n)+'",c,p,0)));'},_t:function(m,x){x.code+=F('"'+E(m.text)+'"')},"{":M,"&":M};function M(m,x){x.code+="t.b(t.t(t."+$(m.n)+'("'+E(m.n)+'",c,p,0)));'}function F(m){return"t.b("+m+");"}t.walk=function(m,x){for(var S,z=0,ee=m.length;z<ee;z++)S=t.codegen[m[z].tag],S&&S(m[z],x);return x},t.parse=function(m,x,S){return S=S||{},a(m,"",[],S.sectionTags||[])},t.cache={},t.cacheKey=function(m,x){return[m,!!x.asString,!!x.disableLambda,x.delimiters,!!x.modelGet].join("||")},t.compile=function(m,x){x=x||{};var S=t.cacheKey(m,x),z=this.cache[S];if(z){var ee=z.partials;for(var ce in ee)delete ee[ce].instance;return z}return z=this.generate(this.parse(this.scan(m,x.delimiters),m,x),m,x),this.cache[S]=z}})(s)})(it)),it}var ot={},jt;function sl(){return jt||(jt=1,(function(s){(function(t){t.Template=function(a,u,_,v){a=a||{},this.r=a.code||this.r,this.c=_,this.options=v||{},this.text=u||"",this.partials=a.partials||{},this.subs=a.subs||{},this.buf=""},t.Template.prototype={r:function(a,u,_){return""},v:k,t:c,render:function(u,_,v){return this.ri([u],_||{},v)},ri:function(a,u,_){return this.r(a,u,_)},ep:function(a,u){var _=this.partials[a],v=u[_.name];if(_.instance&&_.base==v)return _.instance;if(typeof v=="string"){if(!this.c)throw new Error("No compiler available.");v=this.c.compile(v,this.options)}if(!v)return null;if(this.partials[a].base=v,_.subs){u.stackText||(u.stackText={});for(key in _.subs)u.stackText[key]||(u.stackText[key]=this.activeSub!==void 0&&u.stackText[this.activeSub]?u.stackText[this.activeSub]:this.text);v=e(v,_.subs,_.partials,this.stackSubs,this.stackPartials,u.stackText)}return this.partials[a].instance=v,v},rp:function(a,u,_,v){var N=this.ep(a,_);return N?N.ri(u,_,v):""},rs:function(a,u,_){var v=a[a.length-1];if(!b(v)){_(a,u,this);return}for(var N=0;N<v.length;N++)a.push(v[N]),_(a,u,this),a.pop()},s:function(a,u,_,v,N,L,E){var $;return b(a)&&a.length===0?!1:(typeof a=="function"&&(a=this.ms(a,u,_,v,N,L,E)),$=!!a,!v&&$&&u&&u.push(typeof a=="object"?a:u[u.length-1]),$)},d:function(a,u,_,v){var N,L=a.split("."),E=this.f(L[0],u,_,v),$=this.options.modelGet,H=null;if(a==="."&&b(u[u.length-2]))E=u[u.length-1];else for(var M=1;M<L.length;M++)N=n(L[M],E,$),N!==void 0?(H=E,E=N):E="";return v&&!E?!1:(!v&&typeof E=="function"&&(u.push(H),E=this.mv(E,u,_),u.pop()),E)},f:function(a,u,_,v){for(var N=!1,L=null,E=!1,$=this.options.modelGet,H=u.length-1;H>=0;H--)if(L=u[H],N=n(a,L,$),N!==void 0){E=!0;break}return E?(!v&&typeof N=="function"&&(N=this.mv(N,u,_)),N):v?!1:""},ls:function(a,u,_,v,N,L){var E=this.options.delimiters;return this.options.delimiters=L,this.b(this.ct(c(a.call(u,N,_)),u,v)),this.options.delimiters=E,!1},ct:function(a,u,_){if(this.options.disableLambda)throw new Error("Lambda features disabled.");return this.c.compile(a,this.options).render(u,_)},b:function(a){this.buf+=a},fl:function(){var a=this.buf;return this.buf="",a},ms:function(a,u,_,v,N,L,E){var $,H=u[u.length-1],M=a.call(H);return typeof M=="function"?v?!0:($=this.activeSub&&this.subsText&&this.subsText[this.activeSub]?this.subsText[this.activeSub]:this.text,this.ls(M,H,u,_,$.substring(N,L),E)):M},mv:function(a,u,_){var v=u[u.length-1],N=a.call(v);return typeof N=="function"?this.ct(c(N.call(v)),v,_):N},sub:function(a,u,_,v){var N=this.subs[a];N&&(this.activeSub=a,N(u,_,this,v),this.activeSub=!1)}};function n(a,u,_){var v;return u&&typeof u=="object"&&(u[a]!==void 0?v=u[a]:_&&u.get&&typeof u.get=="function"&&(v=u.get(a))),v}function e(a,u,_,v,N,L){function E(){}E.prototype=a;function $(){}$.prototype=a.subs;var H,M=new E;M.subs=new $,M.subsText={},M.buf="",v=v||{},M.stackSubs=v,M.subsText=L;for(H in u)v[H]||(v[H]=u[H]);for(H in v)M.subs[H]=v[H];N=N||{},M.stackPartials=N;for(H in _)N[H]||(N[H]=_[H]);for(H in N)M.partials[H]=N[H];return M}var l=/&/g,f=/</g,r=/>/g,h=/\'/g,y=/\"/g,o=/[&<>\"\']/;function c(a){return String(a??"")}function k(a){return a=c(a),o.test(a)?a.replace(l,"&").replace(f,"<").replace(r,">").replace(h,"'").replace(y,"""):a}var b=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"}})(s)})(ot)),ot}var rt,Gt;function ll(){if(Gt)return rt;Gt=1;var s=nl();return s.Template=sl().Template,s.template=s.Template,rt=s,rt}var le=ll();const oe={};oe["file-summary-line"]=new le.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:{}});oe["file-summary-wrapper"]=new le.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:{}});oe["generic-block-header"]=new le.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,f,r){r.b(r.t(r.f("blockHeader",l,f,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:{}});oe["generic-empty-diff"]=new le.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:{}});oe["generic-file-path"]=new le.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:{}});oe["generic-line"]=new le.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,f,r){r.b(' <span class="d2h-code-line-prefix">'),r.b(r.t(r.f("prefix",l,f,0))),r.b("</span>"),r.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,f,r){r.b(' <span class="d2h-code-line-ctn">'),r.b(r.t(r.f("content",l,f,0))),r.b("</span>"),r.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:{}});oe["generic-wrapper"]=new le.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:{}});oe["icon-file-added"]=new le.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:{}});oe["icon-file-changed"]=new le.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:{}});oe["icon-file-deleted"]=new le.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:{}});oe["icon-file-renamed"]=new le.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:{}});oe["icon-file"]=new le.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:{}});oe["line-by-line-file-diff"]=new le.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:{}});oe["line-by-line-numbers"]=new le.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:{}});oe["side-by-side-file-diff"]=new le.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:{}});oe["tag-file-added"]=new le.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:{}});oe["tag-file-changed"]=new le.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:{}});oe["tag-file-deleted"]=new le.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:{}});oe["tag-file-renamed"]=new le.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 al{constructor({compiledTemplates:t={},rawTemplates:n={}}){const e=Object.entries(n).reduce((l,[f,r])=>{const h=le.compile(r,{asString:!1});return Object.assign(Object.assign({},l),{[f]:h})},{});this.preCompiledTemplates=Object.assign(Object.assign(Object.assign({},oe),t),e)}static compile(t){return le.compile(t,{asString:!1})}render(t,n,e,l,f){const r=this.templateKey(t,n);try{return this.preCompiledTemplates[r].render(e,l,f)}catch{throw new Error(`Could not find template to render '${r}'`)}}template(t,n){return this.preCompiledTemplates[this.templateKey(t,n)]}templateKey(t,n){return`${t}-${n}`}}const il=Object.assign(Object.assign(Object.assign({},en),tn),{outputFormat:Ts.LINE_BY_LINE,drawFileList:!0});function ol(s,t={}){const n=Object.assign(Object.assign({},il),t),e=typeof s=="string"?Ps(s,n):s,l=new al(n),{colorScheme:f}=n,r={colorScheme:f},h=n.drawFileList?new Ks(l,r).render(e):"",y=n.outputFormat==="side-by-side"?new tl(l,n).render(e):new Ys(l,n).render(e);return h+y}const rl={class:"diff-viewer"},dl=["innerHTML"],cl={key:1,class:"diff-fallback mono"},ul=Le({__name:"DiffViewer",props:{patch:{}},setup(s){const t=s,n=Q(()=>{if(!t.patch.trim())return"";try{return ol(t.patch,{drawFileList:!1,outputFormat:"line-by-line",matching:"lines",colorScheme:Pe.DARK,renderNothingWhenEmpty:!0})}catch{return""}}),e=Q(()=>n.value===""?t.patch.split(`
|
|
112
|
+
`):[]);return(l,f)=>(w(),A("div",rl,[n.value?(w(),A("div",{key:0,class:"diff-html",innerHTML:n.value},null,8,dl)):e.value.length?(w(),A("pre",cl,[(w(!0),A(se,null,be(e.value,(r,h)=>(w(),A(se,{key:h},[I(P(r)+`
|
|
113
|
+
`,1)],64))),128))])):J("",!0)]))}}),pt=De(ul,[["__scopeId","data-v-3ec3d3ee"]]),fl={class:"page status-page"},pl={class:"page-head"},hl={class:"head-branch"},ml={key:0,class:"tracking mono"},gl={key:1,class:"sync ahead"},bl={key:2,class:"sync behind"},vl={class:"repo-path mono"},yl={key:1,class:"empty-tip"},_l={key:2,class:"status-layout"},wl={class:"panel-head"},kl={class:"panel-actions"},Cl={class:"tree-scroll"},xl={class:"group-label"},Tl={key:0,class:"tree-dir"},Sl=["title","onDblclick"],Nl={class:"node-name"},El={class:"node-actions"},$l={key:1,class:"pane-empty"},Ll={class:"status-content"},Dl={class:"toolbar"},Il={class:"toolbar-group"},Vl={class:"card-head"},Pl={class:"card-actions"},Ol={class:"tab-label"},Al={class:"tab-hint"},Fl={key:0,class:"file-empty"},Rl={key:1,class:"file-list"},Ml=["title"],zl={class:"card-head"},Hl={class:"card-title"},Bl={class:"card-actions"},Ul={key:0,class:"file-empty"},Wl={key:1,class:"stash-list mono"},jl={class:"stash-main"},Gl={class:"stash-ref"},ql=["title"],Kl={key:0,class:"stash-date"},Xl={class:"stash-actions"},Jl={class:"diff-wrap"},Yl={class:"diff-summary"},Ql={class:"add"},Zl={class:"del"},ea={key:0,class:"warn"},ta={key:0,class:"file-empty"},na={key:0,class:"stash-files"},sa={class:"stash-files-head"},la={class:"stash-files-title"},aa={class:"card-actions"},ia={class:"file-list compact"},oa={class:"file-path mono"},ra=Le({__name:"StatusView",setup(s){const t=Ye(),{revision:n}=Qe(),e=()=>t.currentId,l=q(null),f=q([]),r=q([]),h=q(!1),y=q(""),o=dt({visible:!1,title:"",diff:null,patch:"",loading:!1}),c=q(!1),k=q(""),b=q(!1),a=q(""),u=q(""),_=q(!1),v=q(""),N=q(!1),L=q(!1),E=q(""),$=dt(new Set),H=Q(()=>$.size),M=q("unstaged"),{confirmVisible:F,pending:m,canRun:x,previewAndConfirm:S,executeConfirmed:z,cancel:ee}=gs(e),ce=Q(()=>{var g;return((g=t.current)==null?void 0:g.path)??""}),re=Q(()=>{var g,i;return((g=l.value)==null?void 0:g.currentShort)??((i=l.value)==null?void 0:i.current)??""}),K=Q(()=>{var g;return((g=l.value)==null?void 0:g.ahead)??0}),ue=Q(()=>{var g;return((g=l.value)==null?void 0:g.behind)??0}),de=Q(()=>{const g=l.value;if(!g)return{unstaged:[],staged:[],untracked:[],all:[]};const i=g.untracked.map(ae=>({path:ae,status:"??",indexStatus:"?",workTreeStatus:"?",staged:!1,untracked:!0,conflicted:!1})),U=[...g.staged,...g.unstaged,...i],R=new Set,G=U.filter(ae=>R.has(ae.path)?!1:(R.add(ae.path),ae.path!==""));return{unstaged:g.unstaged,staged:g.staged,untracked:i,all:G}}),fe=Q(()=>[{key:"unstaged",label:"未暂存",hint:"已修改,未 git add",count:de.value.unstaged.length},{key:"staged",label:"已暂存",hint:"已 git add,未提交",count:de.value.staged.length},{key:"untracked",label:"未跟踪",hint:"工作区新文件",count:de.value.untracked.length},{key:"all",label:"全部",hint:"全部更改",count:de.value.all.length}]),te=Q(()=>de.value[M.value]??[]),ve=Q(()=>de.value.all.length);function D(g){const i=[];for(const{name:U,branch:R}of g){const G=U.split("/").filter(_e=>_e.length>0);if(G.length===0)continue;let ae=i,ge="";for(const[_e,Ie]of G.entries()){ge=ge?`${ge}/${Ie}`:Ie;const je=ae.find(nt=>nt.label===Ie),we=je??{key:"node:"+ge,label:Ie};je||ae.push(we),_e===G.length-1?(we.branch=R,we.fullName=U,we.remote=R.remote):(we.children||(we.children=[]),ae=we.children)}}return j(i),i}function j(g){g.sort((i,U)=>{const R=i.branch?1:0,G=U.branch?1:0;return R!==G?R-G:i.label.localeCompare(U.label)});for(const i of g)i.children&&j(i.children)}function C(g){let i=0;for(const U of g)i+=U.branch?1:C(U.children??[]);return i}const Z=Q(()=>{const g=f.value.filter(G=>!G.remote),i=f.value.filter(G=>G.remote),U=new Map;for(const G of i){const ae=G.name.indexOf("/"),ge=ae===-1?"":G.name.slice(0,ae);if(!ge)continue;const _e=U.get(ge)??[];_e.push({name:G.name.slice(ae+1),branch:G}),U.set(ge,_e)}const R=[];g.length&&R.push({key:"local",title:`本地分支(${g.length})`,tree:D(g.map(G=>({name:G.name,branch:G})))});for(const[G,ae]of U){const ge=D(ae);R.push({key:"remote:"+G,title:`远程 · ${G}(${C(ge)})`,tree:ge})}return R});function Ne(g){if(!g||g.remote||!g.upstream)return"";const i=[];return(g.ahead??0)>0&&i.push(`↑${g.ahead}`),(g.behind??0)>0&&i.push(`↓${g.behind}`),i.join(" ")}async function Re(){const g=e();if(g!==null){h.value=!0,y.value="";try{l.value=await Bn(g)}catch(i){y.value=i instanceof Error?i.message:String(i),l.value=null}finally{h.value=!1}}}async function ke(){const g=e();if(g!==null)try{const{branches:i}=await qt(g);f.value=i}catch{}}async function Ee(){const g=e();if(g!==null)try{r.value=await Gn(g)}catch{}}async function pe(){await Promise.all([Re(),ke(),Ee()])}async function Y(g,i={}){await S(g,i)&&ne.info("请在确认对话框中查看 dry-run 预览")}async function ye(){const g=await z();g!=null&&g.success&&await pe()}function Te(g){Y("git_add",{paths:[g.path]})}function Me(g){Y("git_unstage",{paths:[g.path]})}function sn(g){g.staged?Me(g):Te(g)}function ln(){Y("git_add",{})}function an(){var i;const g=((i=l.value)==null?void 0:i.staged.map(U=>U.path))??[];if(g.length===0){ne.info("没有已暂存的文件");return}Y("git_unstage",{paths:g})}async function on(g){const i=e();if(i!==null){o.title=`${g.path}(${g.staged?"已 git add":"工作区修改"})`,o.diff=null,o.patch="",o.visible=!0,o.loading=!0;try{o.diff=await Wn(i,{path:g.path,staged:g.staged})}catch(U){ne.error(U instanceof Error?U.message:String(U)),o.visible=!1}finally{o.loading=!1}}}async function rn(g){var U;const i=e();if(i!==null){o.title=`${g.ref} · ${g.message||"(无说明)"}`,o.diff=null,o.patch="",o.visible=!0,o.loading=!0;try{const R=await ut(i,"git_stash_show",{index:g.index});if(R.success){const G=R.result??{};o.patch=G.patch??""}else ne.error(((U=R.error)==null?void 0:U.message)??"查看差异失败"),o.visible=!1}catch(R){ne.error(R instanceof Error?R.message:String(R)),o.visible=!1}finally{o.loading=!1}}}function Ct(g){$.has(g)?$.delete(g):$.add(g)}function xt(g){return $.has(g)}function Tt(){$.clear()}function dn(){for(const g of te.value)$.add(g.path)}function cn(){for(const g of We.value)$.add(g)}const We=Q(()=>{const g=l.value;if(!g)return[];const i=new Set;return[...g.unstaged.map(U=>U.path),...g.untracked].filter(U=>i.has(U)?!1:(i.add(U),U!==""))});function un(){_.value=!0}function fn(){const g=We.value,i=[...$].filter(G=>g.includes(G)),U=i.some(G=>{var ae;return((ae=l.value)==null?void 0:ae.untracked.includes(G))??!1}),R={};v.value.trim()&&(R.message=v.value.trim()),i.length&&(R.paths=i),(N.value||U)&&(R.includeUntracked=!0),_.value=!1,$.clear(),Y("git_stash",R)}function pn(){Y("git_stash",{})}function hn(g){Y("git_stash_apply",{index:g.index})}function mn(g){Y("git_stash_pop",{index:g.index})}function gn(g){bt.confirm(`确定删除 ${g.ref} 吗?删除后不可直接恢复。`,"删除 stash",{type:"warning",confirmButtonText:"继续",cancelButtonText:"取消"}).then(()=>void Y("git_stash_drop",{index:g.index})).catch(()=>{})}function St(g){g.branch&&Y("git_checkout",{branch:g.branch.name})}function bn(){Y("git_pull")}function vn(){Y("git_push")}function Nt(){const g=k.value.trim();if(!g){ne.warning("请输入提交信息");return}c.value=!1,Y("git_commit",{message:g})}function yn(){const g=a.value.trim();if(!g){ne.warning("请输入分支名");return}b.value=!1,Y("git_branch_create",u.value.trim()?{name:g,startPoint:u.value.trim()}:{name:g})}function _n(){const g=E.value.trim()||"HEAD";L.value=!1,E.value="",Y("git_reset_hard",{target:g})}function wn(g){return g.untracked?"?":g.staged?g.indexStatus||"M":g.workTreeStatus||"M"}function kn(g){return g.untracked?"new":g.conflicted?"conflict":g.staged?"add":"mod"}function Cn(g){if(!g)return"";const i=new Date(g);return Number.isNaN(i.getTime())?g:i.toLocaleString()}function xn(g){return g.split(`
|
|
114
|
+
`)[0]??""}return Ve(e,()=>{o.diff=null,o.patch="",o.visible=!1,$.clear(),pe()}),Ve(n,()=>{pe()}),Fe(()=>{pe()}),(g,i)=>{var $t,Lt,Dt,It,Vt;const U=O("el-tag"),R=O("el-button"),G=O("el-alert"),ae=O("el-tree"),ge=O("el-empty"),_e=O("el-card"),Ie=O("el-badge"),je=O("el-tooltip"),we=O("el-checkbox"),nt=O("el-tab-pane"),Tn=O("el-tabs"),Sn=O("el-drawer"),ze=O("el-input"),Ge=O("el-dialog"),qe=O("el-form-item"),Et=O("el-form"),Nn=Je("loading");return w(),A("div",fl,[T("div",pl,[i[26]||(i[26]=T("h2",{class:"page-title"},"仓库状态",-1)),T("div",hl,[p(U,{type:"primary",effect:"dark",class:"branch-tag"},{default:d(()=>[I(P(re.value||"—"),1)]),_:1}),($t=l.value)!=null&&$t.tracking?(w(),A("span",ml,P(l.value.tracking),1)):J("",!0),K.value?(w(),A("span",gl,"↑"+P(K.value),1)):J("",!0),ue.value?(w(),A("span",bl,"↓"+P(ue.value),1)):J("",!0),(Lt=l.value)!=null&&Lt.isClean?(w(),W(U,{key:3,type:"success",effect:"plain",size:"small"},{default:d(()=>[...i[24]||(i[24]=[I("工作区干净",-1)])]),_:1})):l.value?(w(),W(U,{key:4,type:"warning",effect:"plain",size:"small"},{default:d(()=>[I(P(ve.value)+" 处更改",1)]),_:1})):J("",!0),T("span",vl,P(ce.value),1)]),p(R,{loading:h.value,onClick:pe},{default:d(()=>[...i[25]||(i[25]=[I("刷新",-1)])]),_:1},8,["loading"])]),y.value?(w(),W(G,{key:0,title:y.value,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):J("",!0),X(x)?(w(),A("div",_l,[p(_e,{shadow:"never",class:"branch-panel"},{header:d(()=>[T("div",wl,[i[29]||(i[29]=T("span",{class:"panel-title"},"分支 Branch",-1)),T("div",kl,[p(R,{size:"small",text:"",onClick:ke},{default:d(()=>[...i[27]||(i[27]=[I("刷新",-1)])]),_:1}),p(R,{size:"small",text:"",type:"primary",onClick:i[0]||(i[0]=V=>b.value=!0)},{default:d(()=>[...i[28]||(i[28]=[I("+ 新建",-1)])]),_:1})])])]),default:d(()=>[T("div",Cl,[(w(!0),A(se,null,be(Z.value,V=>(w(),A(se,{key:V.key},[T("div",xl,P(V.title),1),V.tree.length?(w(),W(ae,{key:0,data:V.tree,props:{label:"label",children:"children"},"node-key":"key","default-expand-all":"",indent:14,class:"branch-tree"},{default:d(({data:B})=>{var Se,st,Pt;return[B.branch?(w(),A("div",{key:1,class:Ue(["branch-node",{current:(Se=B.branch)==null?void 0:Se.current,remote:B.remote}]),title:B.fullName,onDblclick:En=>{var Ot;return((Ot=B.branch)==null?void 0:Ot.current)||St(B)}},[T("span",Nl,P(B.label),1),B.remote?J("",!0):(w(),A("span",{key:0,class:Ue(["node-sync",{clean:!Ne(B.branch)&&((st=B.branch)==null?void 0:st.upstream)}])},P(Ne(B.branch)),3)),T("span",El,[(Pt=B.branch)!=null&&Pt.current?(w(),A(se,{key:0},[p(R,{size:"small",text:"",type:"success",onClick:Oe(bn,["stop"])},{default:d(()=>[...i[30]||(i[30]=[I("拉取",-1)])]),_:1}),p(R,{size:"small",text:"",type:"primary",onClick:Oe(vn,["stop"])},{default:d(()=>[...i[31]||(i[31]=[I("推送",-1)])]),_:1})],64)):(w(),W(R,{key:1,size:"small",text:"",type:"primary",onClick:Oe(En=>St(B),["stop"])},{default:d(()=>[...i[32]||(i[32]=[I("切换",-1)])]),_:1},8,["onClick"]))])],42,Sl)):(w(),A("span",Tl,P(B.label),1))]}),_:1},8,["data"])):(w(),A("div",$l,"暂无分支"))],64))),128)),Z.value.length===0?(w(),W(ge,{key:0,description:"暂无分支","image-size":60})):J("",!0)])]),_:1}),T("div",Ll,[p(_e,{shadow:"never",class:"toolbar-card"},{default:d(()=>{var V;return[T("div",Dl,[T("div",Il,[p(R,{type:"primary",onClick:i[1]||(i[1]=B=>c.value=!0)},{default:d(()=>[...i[33]||(i[33]=[I("提交 Commit",-1)])]),_:1}),p(R,{plain:"",onClick:ln},{default:d(()=>[...i[34]||(i[34]=[I("暂存全部",-1)])]),_:1}),p(R,{plain:"",disabled:(((V=l.value)==null?void 0:V.staged.length)??0)===0,onClick:an},{default:d(()=>[...i[35]||(i[35]=[I("取消暂存全部",-1)])]),_:1},8,["disabled"]),p(Ie,{value:H.value,hidden:H.value===0,offset:[2,4]},{default:d(()=>[p(R,{type:"success",plain:"",onClick:un},{default:d(()=>[...i[36]||(i[36]=[I("暂存改动 Stash",-1)])]),_:1})]),_:1},8,["value","hidden"]),p(je,{content:"Shelve Silently:使用默认说明,一键暂存全部更改",placement:"top"},{default:d(()=>[p(R,{plain:"",onClick:pn},{default:d(()=>[...i[37]||(i[37]=[I("静默 Stash",-1)])]),_:1})]),_:1}),p(R,{type:"danger",plain:"",onClick:i[2]||(i[2]=B=>L.value=!0)},{default:d(()=>[...i[38]||(i[38]=[I("硬重置",-1)])]),_:1}),p(R,{type:"danger",plain:"",onClick:i[3]||(i[3]=B=>Y("git_clean"))},{default:d(()=>[...i[39]||(i[39]=[I("清理未跟踪",-1)])]),_:1})])])]}),_:1}),(Dt=l.value)!=null&&Dt.conflicted.length?(w(),W(G,{key:0,title:"存在合并冲突,请先解决冲突(修改文件后重新 git add 并提交)",type:"error",closable:!1,"show-icon":"",class:"mb"})):J("",!0),p(_e,{shadow:"never",class:"changes-card"},{header:d(()=>[T("div",Vl,[i[42]||(i[42]=T("span",{class:"card-title"},"更改 Changes",-1)),T("div",Pl,[H.value?(w(),W(U,{key:0,size:"small",type:"primary",effect:"plain"},{default:d(()=>[I("已选 "+P(H.value),1)]),_:1})):J("",!0),p(R,{size:"small",text:"",onClick:dn},{default:d(()=>[...i[40]||(i[40]=[I("全选本组",-1)])]),_:1}),H.value?(w(),W(R,{key:1,size:"small",text:"",type:"danger",onClick:Tt},{default:d(()=>[...i[41]||(i[41]=[I("清除选择",-1)])]),_:1})):J("",!0)])])]),default:d(()=>[p(Tn,{modelValue:M.value,"onUpdate:modelValue":i[4]||(i[4]=V=>M.value=V),class:"changes-tabs"},{default:d(()=>[(w(!0),A(se,null,be(fe.value,V=>(w(),W(nt,{key:V.key,name:V.key},{label:d(()=>[T("span",Ol,[I(P(V.label)+" ",1),p(Ie,{value:V.count,hidden:V.count===0,type:"primary",class:"tab-badge"},null,8,["value","hidden"])])]),default:d(()=>[T("div",Al,"「"+P(V.hint)+"」",1),V.count===0?(w(),A("div",Fl,"没有"+P(V.label)+"的文件",1)):(w(),A("div",Rl,[(w(!0),A(se,null,be(de.value[V.key],B=>(w(),A("div",{key:V.key+B.path,class:"file-row"},[p(we,{"model-value":xt(B.path),onChange:Se=>Ct(B.path)},null,8,["model-value","onChange"]),T("span",{class:Ue(["file-status",kn(B)])},P(wn(B)),3),T("span",{class:"file-path mono",title:B.path},P(B.path),9,Ml),p(R,{size:"small",text:"",type:"primary",onClick:Se=>on(B)},{default:d(()=>[...i[43]||(i[43]=[I("查看差异",-1)])]),_:1},8,["onClick"]),B.conflicted?(w(),W(R,{key:0,size:"small",text:"",type:"warning",onClick:Se=>Te(B)},{default:d(()=>[...i[44]||(i[44]=[I("标记已解决(git add)",-1)])]),_:1},8,["onClick"])):(w(),W(R,{key:1,size:"small",text:"",type:B.staged?"warning":"success",onClick:Se=>sn(B)},{default:d(()=>[I(P(B.staged?"取消暂存":"暂存"),1)]),_:2},1032,["type","onClick"]))]))),128))]))]),_:2},1032,["name"]))),128))]),_:1},8,["modelValue"])]),_:1}),p(_e,{shadow:"never",class:"stash-card"},{header:d(()=>[T("div",zl,[T("span",Hl,"暂存列表 Stash("+P(r.value.length)+")",1),T("div",Bl,[p(R,{size:"small",text:"",onClick:Ee},{default:d(()=>[...i[45]||(i[45]=[I("刷新",-1)])]),_:1})])])]),default:d(()=>[r.value.length===0?(w(),A("div",Ul,"没有暂存的更改")):(w(),A("div",Wl,[(w(!0),A(se,null,be(r.value,V=>(w(),A("div",{key:V.ref,class:"stash-row"},[T("div",jl,[T("span",Gl,P(V.ref),1),T("span",{class:"stash-msg",title:V.message},P(xn(V.message)||"(无说明)"),9,ql),V.date?(w(),A("span",Kl,P(Cn(V.date)),1)):J("",!0)]),T("div",Xl,[p(R,{size:"small",text:"",type:"primary",onClick:B=>rn(V)},{default:d(()=>[...i[46]||(i[46]=[I("差异",-1)])]),_:1},8,["onClick"]),p(R,{size:"small",text:"",type:"success",onClick:B=>hn(V)},{default:d(()=>[...i[47]||(i[47]=[I("应用",-1)])]),_:1},8,["onClick"]),p(R,{size:"small",text:"",type:"warning",onClick:B=>mn(V)},{default:d(()=>[...i[48]||(i[48]=[I("恢复",-1)])]),_:1},8,["onClick"]),p(R,{size:"small",text:"",type:"danger",onClick:B=>gn(V)},{default:d(()=>[...i[49]||(i[49]=[I("删除",-1)])]),_:1},8,["onClick"])])]))),128))]))]),_:1})])])):(w(),A("div",yl,"请先在「仓库管理」中打开一个仓库")),p(xs,{visible:X(F),"onUpdate:visible":i[5]||(i[5]=V=>In(F)?F.value=V:null),tool:((It=X(m))==null?void 0:It.tool)??"",preview:((Vt=X(m))==null?void 0:Vt.preview)??null,onConfirm:ye,onCancel:X(ee)},null,8,["visible","tool","preview","onCancel"]),p(Sn,{modelValue:o.visible,"onUpdate:modelValue":i[6]||(i[6]=V=>o.visible=V),title:o.title,size:"56%","destroy-on-close":""},{default:d(()=>[Xe((w(),A("div",Jl,[o.diff?(w(),A(se,{key:0},[T("div",Yl,[T("span",null,P(o.diff.files.length)+" 个文件",1),T("span",Ql,"+"+P(o.diff.insertions),1),T("span",Zl,"-"+P(o.diff.deletions),1),o.diff.truncated?(w(),A("span",ea,"(已截断)")):J("",!0)]),p(pt,{patch:o.diff.rawPatch},null,8,["patch"])],64)):o.patch?(w(),A(se,{key:1},[o.patch?(w(),W(pt,{key:1,patch:o.patch},null,8,["patch"])):(w(),A("div",ta,"无差异"))],64)):o.loading?J("",!0):(w(),W(ge,{key:2,description:"无差异","image-size":60}))])),[[Nn,o.loading]])]),_:1},8,["modelValue","title"]),p(Ge,{modelValue:c.value,"onUpdate:modelValue":i[9]||(i[9]=V=>c.value=V),title:"提交 Commit",width:"520px",onClosed:i[10]||(i[10]=V=>k.value="")},{footer:d(()=>[p(R,{onClick:i[8]||(i[8]=V=>c.value=!1)},{default:d(()=>[...i[50]||(i[50]=[I("取消",-1)])]),_:1}),p(R,{type:"primary",onClick:Nt},{default:d(()=>[...i[51]||(i[51]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:d(()=>[p(ze,{modelValue:k.value,"onUpdate:modelValue":i[7]||(i[7]=V=>k.value=V),type:"textarea",rows:5,placeholder:"输入提交信息(message)",onKeydown:gt(Oe(Nt,["ctrl"]),["enter"])},null,8,["modelValue","onKeydown"])]),_:1},8,["modelValue"]),p(Ge,{modelValue:b.value,"onUpdate:modelValue":i[14]||(i[14]=V=>b.value=V),title:"新建分支",width:"480px",onClosed:i[15]||(i[15]=V=>{a.value="",u.value=""})},{footer:d(()=>[p(R,{onClick:i[13]||(i[13]=V=>b.value=!1)},{default:d(()=>[...i[52]||(i[52]=[I("取消",-1)])]),_:1}),p(R,{type:"primary",onClick:yn},{default:d(()=>[...i[53]||(i[53]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:d(()=>[p(Et,{"label-width":"100px"},{default:d(()=>[p(qe,{label:"分支名"},{default:d(()=>[p(ze,{modelValue:a.value,"onUpdate:modelValue":i[11]||(i[11]=V=>a.value=V),placeholder:"feature/xxx"},null,8,["modelValue"])]),_:1}),p(qe,{label:"起点(可选)"},{default:d(()=>[p(ze,{modelValue:u.value,"onUpdate:modelValue":i[12]||(i[12]=V=>u.value=V),placeholder:"默认当前 HEAD,如 main 或 commit hash"},null,8,["modelValue"])]),_:1})]),_:1})]),_:1},8,["modelValue"]),p(Ge,{modelValue:_.value,"onUpdate:modelValue":i[19]||(i[19]=V=>_.value=V),title:"暂存改动 Stash",width:"560px"},{footer:d(()=>[p(R,{onClick:i[18]||(i[18]=V=>_.value=!1)},{default:d(()=>[...i[57]||(i[57]=[I("取消",-1)])]),_:1}),p(R,{type:"primary",onClick:fn},{default:d(()=>[...i[58]||(i[58]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:d(()=>[p(G,{class:"stash-tip",title:"可勾选左侧更改列表的文件随本次 stash 一起保存;不勾选则保存全部更改。",type:"info",closable:!1,"show-icon":""}),p(Et,{"label-width":"90px"},{default:d(()=>[p(qe,{label:"说明(可选)"},{default:d(()=>[p(ze,{modelValue:v.value,"onUpdate:modelValue":i[16]||(i[16]=V=>v.value=V),placeholder:"留空则使用默认说明(WIP on 分支: 提交)"},null,8,["modelValue"])]),_:1}),p(qe,{label:"包含未跟踪"},{default:d(()=>[p(we,{modelValue:N.value,"onUpdate:modelValue":i[17]||(i[17]=V=>N.value=V)},{default:d(()=>[...i[54]||(i[54]=[I("包含未跟踪文件(-u)。勾选文件后会自动包含其中的未跟踪文件",-1)])]),_:1},8,["modelValue"])]),_:1})]),_:1}),We.value.length?(w(),A("div",na,[T("div",sa,[T("span",la,"选择文件(已选 "+P(H.value)+")",1),T("div",aa,[p(R,{size:"small",text:"",onClick:cn},{default:d(()=>[...i[55]||(i[55]=[I("全选",-1)])]),_:1}),p(R,{size:"small",text:"",onClick:Tt},{default:d(()=>[...i[56]||(i[56]=[I("清除选择",-1)])]),_:1})])]),T("div",ia,[(w(!0),A(se,null,be(We.value,V=>{var B,Se;return w(),A("div",{key:V,class:"file-row"},[p(we,{"model-value":xt(V),onChange:st=>Ct(V)},null,8,["model-value","onChange"]),T("span",{class:Ue(["file-status",(B=l.value)!=null&&B.untracked.includes(V)?"new":"mod"])},P((Se=l.value)!=null&&Se.untracked.includes(V)?"?":"M"),3),T("span",oa,P(V),1)])}),128))])])):J("",!0)]),_:1},8,["modelValue"]),p(Ge,{modelValue:L.value,"onUpdate:modelValue":i[22]||(i[22]=V=>L.value=V),title:"硬重置(高风险)",width:"480px",onClosed:i[23]||(i[23]=V=>E.value="")},{footer:d(()=>[p(R,{onClick:i[21]||(i[21]=V=>L.value=!1)},{default:d(()=>[...i[59]||(i[59]=[I("取消",-1)])]),_:1}),p(R,{type:"danger",onClick:_n},{default:d(()=>[...i[60]||(i[60]=[I("下一步(dry-run 预览)",-1)])]),_:1})]),default:d(()=>[p(G,{title:"将丢弃索引与工作区所有更改(不可逆),执行前会自动创建备份",type:"error",closable:!1,"show-icon":"",class:"mb"}),p(ze,{modelValue:E.value,"onUpdate:modelValue":i[20]||(i[20]=V=>E.value=V),placeholder:"重置目标,默认 HEAD,如 HEAD~1 / commit hash / main"},null,8,["modelValue"])]),_:1},8,["modelValue"])])}}}),da=De(ra,[["__scopeId","data-v-889338b7"]]),ca={class:"page"},ua={class:"filter-bar"},fa={class:"mono hash"},pa={class:"subject"},ha={key:0,class:"refs"},ma={class:"sub"},ga={class:"commit-head"},ba={class:"mono commit-hash"},va={class:"commit-subject"},ya={class:"commit-meta"},_a={key:0},wa={key:0,class:"commit-body"},ka={class:"diff-wrap"},Ca={class:"diff-summary"},xa={class:"add"},Ta={class:"del"},Sa={key:0,class:"warn"},Na=Le({__name:"HistoryView",setup(s){const t=Ye(),{revision:n}=Qe(),e=()=>t.currentId,l=q([]),f=q([]),r=q(!1),h=q(""),y=q("head"),o=q(""),c=q(""),k=q(50),b=q(!1),a=q(null),u=q(null),_=Q(()=>f.value.filter(M=>!M.remote)),v=Q(()=>{var M;return((M=f.value.find(F=>F.current))==null?void 0:M.name)??""});async function N(){const M=e();if(M!==null)try{const{branches:F}=await qt(M);f.value=F}catch{}}async function L(){const M=e();if(M!==null){r.value=!0,h.value="";try{const F={maxCount:k.value};y.value==="all"?F.all=!0:y.value==="branch"&&o.value&&(F.from=o.value),c.value.trim()&&(F.path=c.value.trim()),l.value=await Un(M,F)}catch(F){h.value=F instanceof Error?F.message:String(F),l.value=[]}finally{r.value=!1}}}async function E(){await Promise.all([N(),L()])}async function $(M){const F=e();if(F!==null){r.value=!0;try{const{diff:m}=await jn(F,M.hash);a.value=M,console.log(m),u.value=m,b.value=!0}catch(m){m instanceof ct&&m.code==="COMMIT_NOT_FOUND"?ne.warning(`提交不存在(${M.shortHash}),可能已被清理,请刷新列表`):ne.error(m instanceof Error?m.message:String(m))}finally{r.value=!1}}}function H(M){const F=new Date(M);return Number.isNaN(F.getTime())?M:F.toLocaleString()}return Ve(e,()=>void E()),Ve(n,()=>void L()),Ve([y,o,k],()=>void L()),Fe(()=>void E()),(M,F)=>{const m=O("el-alert"),x=O("el-radio-button"),S=O("el-radio-group"),z=O("el-option"),ee=O("el-select"),ce=O("el-input"),re=O("el-button"),K=O("el-card"),ue=O("el-table-column"),de=O("el-tag"),fe=O("el-table"),te=O("el-empty"),ve=O("el-divider"),D=O("el-drawer"),j=Je("loading");return w(),A("div",ca,[F[8]||(F[8]=T("h2",{class:"page-title"},"提交历史",-1)),h.value?(w(),W(m,{key:0,title:h.value,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):J("",!0),p(K,{shadow:"never",class:"mb"},{default:d(()=>[T("div",ua,[p(S,{modelValue:y.value,"onUpdate:modelValue":F[0]||(F[0]=C=>y.value=C)},{default:d(()=>[p(x,{value:"head"},{default:d(()=>[I("当前分支("+P(v.value)+")",1)]),_:1}),p(x,{value:"all"},{default:d(()=>[...F[5]||(F[5]=[I("全部分支",-1)])]),_:1}),p(x,{value:"branch"},{default:d(()=>[...F[6]||(F[6]=[I("指定分支",-1)])]),_:1})]),_:1},8,["modelValue"]),y.value==="branch"?(w(),W(ee,{key:0,modelValue:o.value,"onUpdate:modelValue":F[1]||(F[1]=C=>o.value=C),filterable:"",placeholder:"选择分支",class:"branch-select"},{default:d(()=>[(w(!0),A(se,null,be(_.value,C=>(w(),W(z,{key:C.name,label:C.name,value:C.name},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])):J("",!0),p(ce,{modelValue:c.value,"onUpdate:modelValue":F[2]||(F[2]=C=>c.value=C),clearable:"",placeholder:"按路径过滤(可选)",class:"path-input",onKeyup:gt(L,["enter"])},null,8,["modelValue"]),p(ee,{modelValue:k.value,"onUpdate:modelValue":F[3]||(F[3]=C=>k.value=C),class:"count-select"},{default:d(()=>[p(z,{label:"20 条",value:20}),p(z,{label:"50 条",value:50}),p(z,{label:"100 条",value:100})]),_:1},8,["modelValue"]),p(re,{loading:r.value,onClick:L},{default:d(()=>[...F[7]||(F[7]=[I("刷新",-1)])]),_:1},8,["loading"])])]),_:1}),p(K,{shadow:"never"},{default:d(()=>[Xe((w(),W(fe,{data:l.value,size:"default","highlight-current-row":"",onRowClick:$},{default:d(()=>[p(ue,{label:"提交",width:"100"},{default:d(({row:C})=>[T("span",fa,P(C.shortHash),1)]),_:1}),p(ue,{label:"信息","min-width":"300"},{default:d(({row:C})=>[T("div",pa,P(C.subject),1),C.refs?(w(),A("div",ha,[(w(!0),A(se,null,be(C.refs.split(",").map(Z=>Z.trim()).filter(Boolean),Z=>(w(),W(de,{key:Z,size:"small",effect:"plain",class:"ref-tag"},{default:d(()=>[I(P(Z.startsWith("tag: ")?Z:Z.includes("/")&&!Z.startsWith("HEAD")?Z.split("/").pop():Z),1)]),_:2},1024))),128))])):J("",!0)]),_:1}),p(ue,{label:"作者",width:"170"},{default:d(({row:C})=>[T("div",null,P(C.authorName),1),T("div",ma,P(C.authorEmail),1)]),_:1}),p(ue,{label:"时间",width:"180"},{default:d(({row:C})=>[I(P(H(C.authorDate)),1)]),_:1})]),_:1},8,["data"])),[[j,r.value]]),!r.value&&l.value.length===0?(w(),W(te,{key:0,description:"暂无提交记录"})):J("",!0)]),_:1}),p(D,{modelValue:b.value,"onUpdate:modelValue":F[4]||(F[4]=C=>b.value=C),size:"60%","destroy-on-close":""},{default:d(()=>[a.value?(w(),A(se,{key:0},[T("div",ga,[T("div",ba,P(a.value.hash),1),T("h3",va,P(a.value.subject),1),T("div",ya,[T("span",null,P(a.value.authorName)+" <"+P(a.value.authorEmail)+">",1),T("span",null,P(H(a.value.authorDate)),1),a.value.refs?(w(),A("span",_a,"refs: "+P(a.value.refs),1)):J("",!0)]),a.value.body?(w(),A("pre",wa,P(a.value.body),1)):J("",!0)]),p(ve),T("div",ka,[u.value?(w(),A(se,{key:0},[T("div",Ca,[T("span",null,P(u.value.files.length)+" 个文件",1),T("span",xa,"+"+P(u.value.insertions),1),T("span",Ta,"-"+P(u.value.deletions),1),u.value.truncated?(w(),A("span",Sa,"(已截断)")):J("",!0)]),p(pt,{patch:u.value.rawPatch},null,8,["patch"])],64)):(w(),W(te,{key:1,description:"无差异","image-size":60}))])],64)):J("",!0)]),_:1},8,["modelValue"])])}}}),Ea=De(Na,[["__scopeId","data-v-409543e4"]]),$a=ht("logs",{state:()=>({logs:[],loading:!1,error:null,limit:50,toolFilter:""}),actions:{async load(){this.loading=!0,this.error=null;try{const{logs:s}=await qn({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}}}}),La={class:"page"},Da={class:"filter-bar"},Ia={class:"tool-cell"},Va={class:"mono repo-path"},Pa=["title"],Oa=["title"],Aa=["title"],Fa=Le({__name:"LogsView",setup(s){const t=$a(),{revision:n}=Qe(),e=Q(()=>{const o=new Set;for(const c of t.logs)o.add(c.tool);return[...o].sort()}),l=o=>o.includes("reset")||o.includes("clean")||o.includes("force")||o.includes("rebase")?"dangerous":"write";function f(o){return l(o)==="dangerous"?"danger":o.startsWith("git_")?"primary":"success"}function r(o){const c=new Date(o);return Number.isNaN(c.getTime())?o:c.toLocaleString()}function h(o){return o==="mcp"?"primary":o==="web"?"success":"warning"}function y(o){if(o==null)return"";if(typeof o=="string")return o;try{const c=JSON.stringify(o);return c===void 0?"":c}catch{return String(o)}}return Ve(n,()=>{t.load()}),Fe(()=>{t.load()}),(o,c)=>{const k=O("el-option"),b=O("el-select"),a=O("el-button"),u=O("el-card"),_=O("el-table-column"),v=O("el-tag"),N=O("el-table"),L=O("el-empty"),E=Je("loading");return w(),A("div",La,[c[7]||(c[7]=T("h2",{class:"page-title"},"操作日志",-1)),p(u,{shadow:"never",class:"mb"},{default:d(()=>[T("div",Da,[p(b,{modelValue:X(t).toolFilter,"onUpdate:modelValue":c[0]||(c[0]=$=>X(t).toolFilter=$),clearable:"",placeholder:"按工具过滤",class:"tool-select",onChange:X(t).load},{default:d(()=>[(w(!0),A(se,null,be(e.value,$=>(w(),W(k,{key:$,label:$,value:$},null,8,["label","value"]))),128))]),_:1},8,["modelValue","onChange"]),p(b,{modelValue:X(t).limit,"onUpdate:modelValue":c[1]||(c[1]=$=>X(t).limit=$),class:"limit-select",onChange:X(t).load},{default:d(()=>[p(k,{label:"最近 20 条",value:20}),p(k,{label:"最近 50 条",value:50}),p(k,{label:"最近 100 条",value:100})]),_:1},8,["modelValue","onChange"]),p(a,{loading:X(t).loading,onClick:X(t).load},{default:d(()=>[...c[2]||(c[2]=[I("刷新",-1)])]),_:1},8,["loading","onClick"]),c[3]||(c[3]=T("span",{class:"tip"},"记录来源:Web / MCP / CLI 全部写入操作(只读操作不记录)",-1))])]),_:1}),p(u,{shadow:"never"},{default:d(()=>[Xe((w(),W(N,{data:X(t).logs,size:"default"},{default:d(()=>[p(_,{label:"时间",width:"180"},{default:d(({row:$})=>[I(P(r($.timestamp)),1)]),_:1}),p(_,{label:"来源",width:"90"},{default:d(({row:$})=>[p(v,{type:h($.source),size:"small",effect:"plain"},{default:d(()=>[I(P($.source.toUpperCase()),1)]),_:2},1032,["type"])]),_:1}),p(_,{label:"工具",width:"200"},{default:d(({row:$})=>[T("div",Ia,[p(v,{type:f($.tool),size:"small",effect:"dark"},{default:d(()=>[I(P($.tool),1)]),_:2},1032,["type"]),$.dryRun?(w(),W(v,{key:0,size:"small",type:"info",effect:"plain",class:"dry-tag"},{default:d(()=>[...c[4]||(c[4]=[I("dry-run",-1)])]),_:1})):J("",!0)])]),_:1}),p(_,{label:"仓库","min-width":"200"},{default:d(({row:$})=>[T("span",Va,P($.repoPath??"—"),1)]),_:1}),p(_,{label:"参数(脱敏)","min-width":"180"},{default:d(({row:$})=>[T("span",{class:"mono params",title:y($.params)},P(y($.params)||"—"),9,Pa)]),_:1}),p(_,{label:"结果","min-width":"150"},{default:d(({row:$})=>[$.error?(w(),A(se,{key:0},[p(v,{type:"danger",size:"small",effect:"plain",class:"result-tag"},{default:d(()=>[...c[5]||(c[5]=[I("失败",-1)])]),_:1}),T("div",{class:"err-text",title:$.error},P($.error),9,Oa)],64)):(w(),A(se,{key:1},[p(v,{type:"success",size:"small",effect:"plain",class:"result-tag"},{default:d(()=>[...c[6]||(c[6]=[I("成功",-1)])]),_:1}),T("div",{class:"ok-text",title:$.result},P($.result),9,Aa)],64))]),_:1}),p(_,{label:"耗时",width:"90"},{default:d(({row:$})=>[I(P($.durationMs)+" ms",1)]),_:1})]),_:1},8,["data"])),[[E,X(t).loading]]),!X(t).loading&&X(t).logs.length===0?(w(),W(L,{key:0,description:"暂无操作日志"})):J("",!0)]),_:1})])}}}),Ra=De(Fa,[["__scopeId","data-v-79ac665b"]]),Ma={class:"page"},za={class:"card-head"},Ha={class:"mono"},Ba={class:"desc"},Ua={key:1,class:"action-bar"},Wa=Le({__name:"SettingsView",setup(s){const t=Kt(),n=dt({disabledTools:[],requireApprovalFor:[],dryRunDefault:!1}),e=q(!1),l=Q(()=>{const b=t.permissions;return b?JSON.stringify([...n.disabledTools].sort())!==JSON.stringify([...b.disabledTools].sort())||JSON.stringify([...n.requireApprovalFor].sort())!==JSON.stringify([...b.requireApprovalFor].sort())||n.dryRunDefault!==b.dryRunDefault:!1}),f=Q(()=>t.tools.filter(b=>b.riskLevel==="dangerous")),r=Q(()=>f.value.map(b=>b.name));function h(){const b=t.permissions;b&&(n.disabledTools=[...b.disabledTools],n.requireApprovalFor=[...b.requireApprovalFor],n.dryRunDefault=b.dryRunDefault,e.value=!0)}Ve(()=>t.permissions,b=>{b&&!l.value&&h()});async function y(b,a){a?n.disabledTools=n.disabledTools.filter(u=>u!==b.name):(n.disabledTools.includes(b.name)||n.disabledTools.push(b.name),n.requireApprovalFor=n.requireApprovalFor.filter(u=>u!==b.name))}function o(b){return b==="readonly"?"success":b==="write"?"primary":"danger"}function c(b){return b==="readonly"?"只读":b==="write"?"写操作":"高风险"}async function k(){try{await t.save({disabledTools:[...n.disabledTools],requireApprovalFor:[...n.requireApprovalFor],dryRunDefault:n.dryRunDefault}),ne.success("设置已保存")}catch(b){ne.error(b instanceof Error?b.message:String(b))}}return Fe(async()=>{await t.load(),h()}),(b,a)=>{const u=O("el-alert"),_=O("el-switch"),v=O("el-form-item"),N=O("el-form"),L=O("el-card"),E=O("el-tag"),$=O("el-table-column"),H=O("el-table"),M=O("el-option"),F=O("el-select"),m=O("el-button"),x=Je("loading");return w(),A("div",Ma,[a[10]||(a[10]=T("h2",{class:"page-title"},"设置",-1)),X(t).error?(w(),W(u,{key:0,title:X(t).error,type:"error",closable:!1,"show-icon":"",class:"mb"},null,8,["title"])):J("",!0),p(L,{shadow:"never",class:"mb"},{header:d(()=>[...a[2]||(a[2]=[I("默认行为",-1)])]),default:d(()=>[p(N,{"label-width":"180px","label-position":"left"},{default:d(()=>[p(v,{label:"写操作默认 dry-run 预览"},{default:d(()=>[p(_,{modelValue:n.dryRunDefault,"onUpdate:modelValue":a[0]||(a[0]=S=>n.dryRunDefault=S)},null,8,["modelValue"]),a[3]||(a[3]=T("span",{class:"form-tip"},"开启后所有写操作(MCP/CLI)默认只生成预览,不真正执行",-1))]),_:1})]),_:1})]),_:1}),p(L,{shadow:"never",class:"mb"},{header:d(()=>[T("div",za,[a[5]||(a[5]=T("span",null,"工具开关与风险等级",-1)),p(E,{size:"small",type:"warning",effect:"plain"},{default:d(()=>[...a[4]||(a[4]=[I("高危工具默认禁用,需在下方开启",-1)])]),_:1})])]),default:d(()=>[Xe((w(),W(H,{data:X(t).tools,size:"default"},{default:d(()=>[p($,{label:"工具",width:"230"},{default:d(({row:S})=>[T("span",Ha,P(S.name),1)]),_:1}),p($,{label:"风险",width:"90"},{default:d(({row:S})=>[p(E,{type:o(S.riskLevel),size:"small",effect:"dark"},{default:d(()=>[I(P(c(S.riskLevel)),1)]),_:2},1032,["type"])]),_:1}),p($,{label:"描述","min-width":"240"},{default:d(({row:S})=>[T("span",Ba,P(S.description),1)]),_:1}),p($,{label:"启用",width:"100",align:"center"},{default:d(({row:S})=>[p(_,{"model-value":!n.disabledTools.includes(S.name),onChange:z=>y(S,z===!0)},null,8,["model-value","onChange"])]),_:1})]),_:1},8,["data"])),[[x,X(t).loading]])]),_:1}),p(L,{shadow:"never",class:"mb"},{header:d(()=>[...a[6]||(a[6]=[I("审批规则",-1)])]),default:d(()=>[p(N,{"label-position":"top"},{default:d(()=>[p(v,{label:"执行前需要审批的工具(勾选后,执行时需在确认框中手工确认)"},{default:d(()=>[p(F,{modelValue:n.requireApprovalFor,"onUpdate:modelValue":a[1]||(a[1]=S=>n.requireApprovalFor=S),multiple:"",filterable:"","collapse-tags":"",placeholder:"选择需要审批的工具",style:{width:"100%"}},{default:d(()=>[(w(!0),A(se,null,be(r.value,S=>(w(),W(M,{key:S,label:S,value:S,disabled:n.disabledTools.includes(S)},null,8,["label","value","disabled"]))),128))]),_:1},8,["modelValue"]),a[7]||(a[7]=T("span",{class:"form-tip"},"审批仅对已启用的高危工具生效;禁用后自动移除",-1))]),_:1})]),_:1})]),_:1}),e.value?(w(),A("div",Ua,[p(m,{type:"primary",loading:X(t).saving,disabled:!l.value,onClick:k},{default:d(()=>[...a[8]||(a[8]=[I("保存设置",-1)])]),_:1},8,["loading","disabled"]),p(m,{disabled:!l.value,onClick:h},{default:d(()=>[...a[9]||(a[9]=[I("放弃修改",-1)])]),_:1},8,["disabled"])])):J("",!0)])}}}),ja=De(Wa,[["__scopeId","data-v-eb3ae411"]]),nn=Vn({history:Pn(),routes:[{path:"/",redirect:"/status"},{path:"/repos",name:"repos",component:ms,meta:{title:"仓库管理"}},{path:"/status",name:"status",component:da,meta:{title:"状态"}},{path:"/history",name:"history",component:Ea,meta:{title:"历史"}},{path:"/logs",name:"logs",component:Ra,meta:{title:"操作日志"}},{path:"/settings",name:"settings",component:ja,meta:{title:"设置"}}]});nn.afterEach(s=>{const t=s.meta.title;document.title=t?`${t} · Git Cockpit`:"Git Cockpit"});document.documentElement.classList.add("dark");const tt=On(ls);tt.use(An());tt.use(nn);tt.use(Fn,{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-rh3DXMef.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-BrQ29WGx.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="app"></div>
|
package/dist/webServer.d.ts
CHANGED
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.7",
|
|
4
4
|
"description": "Git Cockpit - 基于 MCP 的 Git 可视化操作工具(MCP Server + Web 服务 + CLI)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
31
31
|
"fastify": "^5.2.1",
|
|
32
32
|
"zod": "^3.24.1",
|
|
33
|
-
"@shaohui_jin/git-cockpit-core": "^0.1.
|
|
33
|
+
"@shaohui_jin/git-cockpit-core": "^0.1.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"simple-git": "^3.27.0",
|
|
@@ -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.0',\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 // ---------------------------------------------------------------------------\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 /** 按路径取服务,未打开则报错(避免隐式副作用) */\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":";;;;;;;;;AAOA,YAAYA,WAAU;AACtB,YAAYC,SAAQ;AACpB,SAAS,qBAAqB;AAC9B,OAAO,aAAa;AAEpB,OAAO,UAAU;AACjB,OAAO,mBAAmB;AAC1B;AAAA,EACE;AAAA,EAEA,qBAAAC;AAAA,EACA,qBAAAC;AAAA,OACK;;;ACdP,SAAS,gBAAAC,qBAAoB;AAE7B;AAAA,EACE;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,OACK;;;ACRP,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,gBAAgB,kBAAkB;AAQ3C,SAAS,UAAa,QAAW,QAAoB;AACnD,MAAI,WAAW,QAAQ,WAAW,OAAW,QAAO;AACpD,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAQ;AAAA,EACV;AACA,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,YAAY,WAAW,MAAM;AAC/E,UAAM,MAAM,EAAE,GAAI,OAAmC;AACrD,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAiC,GAAG;AACtE,UAAI,MAAM,OAAW,KAAI,CAAC,IAAI,UAAU,IAAI,CAAC,GAAG,CAAC;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,cAAc,GAA0C;AAC/D,SAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAChE;AAOO,IAAM,cAAN,MAAkB;AAAA,EAGvB,YACmB,SACjB,WACA;AAFiB;AAGjB,UAAM,MAAM,WAAW,OAAO;AAC9B,UAAM,OAAY,UAAK,KAAK,aAAa;AAEzC,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK,KAAK,MAAM,SAAS;AAAA,MAC5B,SAAS,EAAE,SAAS,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAVmB;AAAA,EAHX;AAAA,EAeA,KAAK,MAAc,WAA6D;AACtF,QAAI,aAAsB,CAAC;AAC3B,QAAI;AACF,UAAO,cAAW,IAAI,GAAG;AACvB,qBAAa,KAAK,MAAS,gBAAa,MAAM,MAAM,CAAC;AAAA,MACvD;AAAA,IACF,SAAS,KAAK;AAEZ,cAAQ,KAAK,0CAAsB,IAAI,8EAAmB,IAAc,OAAO;AAAA,IACjF;AACA,QAAI,SAAS,UAAU,gBAAgB,cAAc,GAAG,UAAU;AAClE,QAAI,UAAW,UAAS,UAAU,QAAQ,SAAS;AACnD,WAAO;AAAA,EACT;AAAA,EAEA,MAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,OAAO,OAAwD;AAC7D,SAAK,SAAS,UAAU,KAAK,QAAQ,KAAK;AAC1C,SAAK,KAAK;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAa;AACX,UAAM,MAAM,WAAW,KAAK,OAAO,QAAQ,OAAO;AAClD,IAAG,aAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,OAAY,UAAK,KAAK,aAAa;AACzC,IAAG,iBAAc,MAAM,KAAK,UAAU,KAAK,QAAQ,MAAM,CAAC,GAAG,MAAM;AAAA,EACrE;AAAA;AAAA,EAGA,WAAoC;AAClC,UAAM,OAAO,gBAAgB,KAAK,MAAM;AACxC,UAAM,SAAS,CAAC,MAAwB;AACtC,UAAI,cAAc,CAAC,GAAG;AACpB,cAAM,MAA+B,CAAC;AACtC,mBAAW,CAAC,GAAG,GAAG,KAAK,OAAO,QAAQ,CAAC,GAAG;AACxC,gBAAM,QAAQ,EAAE,YAAY;AAC5B,cAAI,2CAA2C,KAAK,KAAK,EAAG,KAAI,CAAC,IAAI;AAAA,cAChE,KAAI,CAAC,IAAI,OAAO,GAAG;AAAA,QAC1B;AACA,eAAO;AAAA,MACT;AACA,UAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,IAAI,MAAM;AACzC,aAAO;AAAA,IACT;AACA,WAAO,OAAO,IAAI;AAAA,EACpB;AACF;;;AClGA,OAA6B;AAC7B,YAAYC,WAAU;AACtB;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAcA,IAAM,cAAN,MAAkB;AAAA,EAMvB,YAA6B,SAA6B;AAA7B;AAC3B,SAAK,WAAW,QAAQ;AAExB,eAAW,QAAQ,QAAQ,UAAU,KAAK,GAAG;AAC3C,WAAK,SAAS,IAAI,cAAc,KAAK,IAAI,GAAG,KAAK,EAAE;AAAA,IACrD;AAAA,EACF;AAAA,EAN6B;AAAA;AAAA,EAJZ,WAAW,oBAAI,IAAoB;AAAA,EACnC,cAAc,oBAAI,IAAwB;AAAA,EAC1C;AAAA,EAUjB,OAAgD;AAC9C,WAAO,KAAK,QAAQ,UAAU,KAAK,EAAE,IAAI,CAAC,OAAO;AAAA,MAC/C,GAAG;AAAA,MACH,WAAW,EAAE,SAAS,MAAM;AAAA,IAC9B,EAAE;AAAA,EACJ;AAAA;AAAA,EAGA,MAAM,aAAyC;AAC7C,UAAM,SAAS,KAAK,QAAQ,UAAU,KAAK,EAAE,CAAC;AAC9C,WAAO,SAAS,KAAK,YAAY,MAAM,IAAI;AAAA,EAC7C;AAAA;AAAA,EAGA,MAAM,QAAQ,IAAwC;AACpD,UAAM,SAAS,KAAK,QAAQ,UAAU,QAAQ,EAAE;AAChD,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AACF,aAAO,MAAM,KAAK,YAAY,MAAM;AAAA,IACtC,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,gCAAgC,KAAK,IAAI,OAAO,GAAG;AAC7E,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAK,UAAuC;AAChD,UAAM,UAAU,MAAM,WAAW,KAAK,QAAQ;AAC9C,UAAM,OAAO,QAAQ;AACrB,UAAM,MAAM,cAAc,IAAI;AAC9B,UAAM,aAAa,KAAK,SAAS,IAAI,GAAG;AACxC,QAAI,eAAe,UAAa,eAAe,GAAG;AAChD,YAAMC,UAAS,KAAK,QAAQ,UAAU,QAAQ,UAAU;AACxD,UAAIA,SAAQ;AACV,aAAK,QAAQ,UAAU,KAAK,IAAI;AAChC,aAAK,YAAY,IAAIA,QAAO,IAAI,OAAO;AACvC,aAAK,OAAO,OAAO;AACnB,eAAO,EAAE,SAAS,QAAQ,KAAK,QAAQ,UAAU,QAAQA,QAAO,EAAE,KAAKA,QAAO;AAAA,MAChF;AAAA,IACF;AACA,UAAM,SAAS,KAAK,QAAQ,UAAU,KAAK,IAAI;AAC/C,SAAK,SAAS,IAAI,KAAK,OAAO,EAAE;AAChC,SAAK,YAAY,IAAI,OAAO,IAAI,OAAO;AACvC,SAAK,OAAO,OAAO;AACnB,WAAO,EAAE,SAAS,OAAO;AAAA,EAC3B;AAAA;AAAA,EAGA,UAAU,UAA8B;AACtC,UAAM,MAAM,cAAc,QAAQ;AAClC,UAAM,KAAK,KAAK,SAAS,IAAI,GAAG;AAChC,QAAI,OAAO,UAAa,OAAO,GAAG;AAChC,YAAM,SAAS,KAAK,QAAQ,UAAU,QAAQ,EAAE;AAChD,UAAI,QAAQ;AACV,cAAM,UAAU,KAAK,YAAY,IAAI,EAAE;AACvC,YAAI,QAAS,QAAO,EAAE,SAAS,OAAO;AAAA,MACxC;AAAA,IACF;AACA,UAAM,IAAI,kBAAkB,mCAAU,QAAQ,kFAAgC;AAAA,EAChF;AAAA;AAAA,EAGA,MAAM,IAAkB;AACtB,UAAM,SAAS,KAAK,QAAQ,UAAU,QAAQ,EAAE;AAChD,QAAI,OAAQ,MAAK,SAAS,OAAO,cAAc,OAAO,IAAI,CAAC;AAC3D,UAAM,MAAM,KAAK,YAAY,IAAI,EAAE;AACnC,QAAI,IAAK,KAAI,mBAAmB,SAAS;AACzC,SAAK,YAAY,OAAO,EAAE;AAAA,EAC5B;AAAA;AAAA,EAGA,OAAO,IAAkB;AACvB,SAAK,MAAM,EAAE;AACb,SAAK,QAAQ,UAAU,OAAO,EAAE;AAAA,EAClC;AAAA,EAEA,UAAgB;AACd,eAAW,MAAM,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,EAAG,MAAK,MAAM,EAAE;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAc,YAAY,QAAyC;AACjE,QAAI,UAAU,KAAK,YAAY,IAAI,OAAO,EAAE;AAC5C,QAAI,CAAC,SAAS;AACZ,gBAAU,MAAM,WAAW,KAAK,OAAO,IAAI;AAC3C,WAAK,SAAS,IAAI,cAAc,QAAQ,QAAQ,GAAG,OAAO,EAAE;AAC5D,WAAK,YAAY,IAAI,OAAO,IAAI,OAAO;AACvC,WAAK,OAAO,OAAO;AAAA,IACrB;AACA,WAAO,EAAE,SAAS,OAAO;AAAA,EAC3B;AAAA,EAEQ,OAAO,SAA2B;AACxC,YAAQ,GAAG,WAAW,CAAC,YAAqD;AAC1E,WAAK,SAAS,KAAK,gBAAgB;AAAA,QACjC,UAAU,QAAQ;AAAA,QAClB,SAAS,QAAQ;AAAA,QACjB,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC7B,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEA,SAAS,cAAc,GAAmB;AACxC,MAAI,aAAkB,cAAQ,CAAC;AAC/B,MAAI,QAAQ,aAAa,QAAS,cAAa,WAAW,YAAY;AACtE,SAAO;AACT;;;AFlHO,SAAS,cAAc,UAA0B,CAAC,GAAY;AACnE,QAAM,cAAc,IAAI,YAAY,QAAQ,WAAW,kBAAkB,QAAQ,eAAe;AAChG,QAAM,SAAS,YAAY,IAAI;AAC/B,QAAM,KAAK,QAAQ,MAAM,aAAa,OAAO,QAAQ,OAAO;AAC5D,QAAM,WAAW,IAAIC,cAAa;AAClC,WAAS,gBAAgB,GAAG;AAE5B,QAAM,cAAc,IAAI,YAAY,IAAI,OAAO,OAAO;AACtD,QAAM,cAAc,IAAI,kBAAkB,MAAM;AAChD,QAAM,YAAY,IAAIC,WAAU,EAAE;AAClC,QAAM,cAAc,IAAI,YAAY,EAAE,WAAW,UAAU,OAAO,CAAC;AAEnE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,eAAe,SAAwB;AACrD,MAAI;AACF,YAAQ,SAAS,mBAAmB;AACpC,YAAQ,YAAY,QAAQ;AAAA,EAC9B,QAAQ;AAAA,EAER;AACA,MAAI;AACF,YAAQ,GAAG,MAAM;AAAA,EACnB,QAAQ;AAAA,EAER;AACF;;;ADtCA,SAAS,iBAAgC;AAEvC,QAAM,OAAY,cAAa,cAAQ,cAAc,YAAY,GAAG,CAAC,CAAC;AACtE,QAAM,aAAa;AAAA,IACZ,cAAQ,MAAM,MAAM,MAAM,OAAO,MAAM;AAAA;AAAA,IACvC,cAAQ,MAAM,KAAK;AAAA;AAAA,IACnB,cAAQ,MAAM,OAAO,MAAM;AAAA;AAAA,IAC3B,cAAQ,MAAM,MAAM,OAAO,MAAM;AAAA;AAAA,IACjC,cAAQ,QAAQ,IAAI,GAAG,QAAQ,KAAK;AAAA,IACpC,cAAQ,QAAQ,IAAI,GAAG,MAAM,OAAO,MAAM;AAAA,IAC1C,cAAQ,QAAQ,IAAI,GAAG,gBAAgB,gBAAgB,mBAAmB,MAAM;AAAA,EACvF;AACA,aAAW,KAAK,YAAY;AAC1B,QAAO,eAAgB,WAAK,GAAG,YAAY,CAAC,EAAG,QAAO;AAAA,EACxD;AACA,SAAO;AACT;AAEA,eAAsB,gBACpB,SACA,UAA2F,CAAC,GAClE;AAC1B,QAAM,MAAM,QAAQ,EAAE,QAAQ,OAAO,WAAW,IAAI,OAAO,KAAK,CAAC;AAEjE,QAAM,IAAI,SAAS,MAAM;AAAA,IACvB,QAAQ;AAAA,IACR,SAAS,CAAC,OAAO,QAAQ,OAAO,UAAU,SAAS;AAAA,IACnD,gBAAgB,CAAC,gBAAgB,kBAAkB,eAAe;AAAA,EACpE,CAAC;AAED,QAAM,YAAY,QAAQ,cAAc,SAAY,QAAQ,YAAY,eAAe;AACvF,MAAI,aAAgB,eAAW,SAAS,GAAG;AACzC,UAAM,IAAI,SAAS,eAAe,EAAE,MAAM,WAAW,QAAQ,IAAI,CAAC;AAAA,EACpE;AAEA,QAAM,UAAU,IAAI,eAAe,OAAO;AAG1C,MAAI,IAAI,eAAe,aAAa;AAAA,IAClC,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU,QAAQ,OAAO,IAAI;AAAA,EAC/B,EAAE;AAKF,MAAI,IAAI,cAAc,aAAa;AAAA,IACjC,OAAO,QAAQ,YAAY,KAAK;AAAA,EAClC,EAAE;AAEF,MAAI,KAAkC,mBAAmB,OAAO,KAAK,UAAU;AAC7E,UAAM,SAAS,IAAI,MAAM,MAAM,KAAK;AACpC,QAAI,CAAC,QAAQ;AACX,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,iCAAa,CAAU;AAAA,IAC9D;AACA,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,YAAY,KAAK,MAAM;AACpD,aAAO,EAAE,MAAM,OAAO,OAAO;AAAA,IAC/B,SAAS,KAAK;AACZ,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,CAAU;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,MAAI,OAAmC,kBAAkB,OAAO,KAAK,UAAU;AAC7E,UAAM,KAAK,OAAO,IAAI,OAAO,EAAE;AAC/B,QAAI,CAAC,OAAO,UAAU,EAAE,GAAG;AACzB,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,8BAAU,CAAU;AAAA,IAC3D;AACA,YAAQ,YAAY,OAAO,EAAE;AAC7B,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB,CAAC;AAKD,iBAAe,SACb,KACA,OACA,IACmB;AACnB,UAAM,KAAK,OAAO,IAAI,OAAO,EAAE;AAC/B,UAAM,SAAS,MAAM,QAAQ,YAAY,QAAQ,EAAE;AACnD,QAAI,CAAC,QAAQ;AACX,YAAM,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,yDAAY,CAAC;AACjD,aAAO;AAAA,IACT;AACA,QAAI;AACF,aAAO,MAAM,GAAG,MAAM;AAAA,IACxB,SAAS,KAAK;AACZ,YAAM,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,QAAQ,GAAG,EAAE,CAAC;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI;AAAA,IAAgC;AAAA,IAAyB,OAAO,KAAK,UACvE,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,UAAU,CAAC;AAAA,EACjE;AAEA,MAAI;AAAA,IAAiF;AAAA,IAAsB,OAAO,KAAK,UACrH,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM;AAC1C,YAAM,IAAI,IAAI;AACd,aAAO,QAAQ,OAAO;AAAA,QACpB,UAAU,EAAE,WAAW,KAAK,IAAI,OAAO,EAAE,QAAQ,KAAK,KAAK,GAAK,IAAI;AAAA,QACpE,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,MAAM,EAAE;AAAA,QACR,KAAK,EAAE,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,MAAI;AAAA,IAAiF;AAAA,IAAuB,OAAO,KAAK,UACtH,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM;AAC1C,YAAM,IAAI,IAAI;AACd,aAAO,QAAQ,QAAQ;AAAA,QACrB,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE,WAAW;AAAA,QACrB,eAAe,EAAE,gBAAgB,OAAO,EAAE,aAAa,IAAI;AAAA,MAC7D,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAEA,MAAI;AAAA,IACF;AAAA,IACA,OAAO,KAAK,UACV;AAAA,MAAS;AAAA,MAAK;AAAA,MAAO,OAAO,EAAE,QAAQ,MACpC,QAAQ,QAAQ,IAAI,OAAO,QAAQ;AAAA,QACjC,MAAM,IAAI,MAAM;AAAA,QAChB,eAAe,IAAI,MAAM,gBAAgB,OAAO,IAAI,MAAM,aAAa,IAAI;AAAA,MAC7E,CAAC;AAAA,IACH;AAAA,EACJ;AAEA,MAAI;AAAA,IAAgC;AAAA,IAA2B,OAAO,KAAK,UACzE,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,aAAa,CAAC;AAAA,EACpE;AAEA,MAAI;AAAA,IAAgC;AAAA,IAAuB,OAAO,KAAK,UACrE,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,SAAS,CAAC;AAAA,EAChE;AAEA,MAAI;AAAA,IAAgC;AAAA,IAA0B,OAAO,KAAK,UACxE,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,YAAY,CAAC;AAAA,EACnE;AAEA,MAAI;AAAA,IAAiF;AAAA,IAAwB,OAAO,KAAK,UACvH,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,SAAS,IAAI,MAAM,WAAW,OAAO,IAAI,MAAM,QAAQ,IAAI,GAAG,CAAC;AAAA,EACrH;AAEA,MAAI;AAAA,IAAiF;AAAA,IAAuB,OAAO,KAAK,UACtH,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM;AAC1C,UAAI,CAAC,IAAI,MAAM,UAAU,CAAC,IAAI,MAAM,MAAM;AACxC,eAAO,EAAE,OAAO,+CAAsB;AAAA,MACxC;AACA,aAAO,QAAQ,eAAe,IAAI,MAAM,QAAQ,IAAI,MAAM,IAAI;AAAA,IAChE,CAAC;AAAA,EACH;AAEA,MAAI;AAAA,IAAgC;AAAA,IAA0B,OAAO,KAAK,UACxE,SAAS,KAAK,OAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,YAAY,CAAC;AAAA,EACnE;AAKA,MAAI;AAAA,IACF;AAAA,IACA,OAAO,KAAK,UAAU;AACpB,YAAM,MAAM,aAAa,IAAI,IAAI,OAAO,IAAI;AAC5C,UAAI,CAAC,IAAK,QAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,6BAAS,IAAI,OAAO,IAAI,GAAG,CAAC;AAC3E,YAAM,SAAS,IAAI,MAAM,UAAU,CAAC;AACpC,YAAM,OAAO,MAAM,YAAY,KAAK,QAAQ;AAAA,QAC1C;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ,OAAO,IAAI,OAAO,EAAE;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,KAAK,SAAS;AACjB,cAAM,SAAS,KAAK,OAAO,mBAAmB,MAAM;AACpD,eAAO,MACJ,KAAK,MAAM,EACX,KAAK,EAAE,OAAO,KAAK,OAAO,SAAS,kBAAkB,KAAK,OAAO,kBAAkB,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,MAChH;AACA,aAAO,EAAE,GAAG,KAAK;AAAA,IACnB;AAAA,EACF;AAKA,MAAI,IAAI,cAAc,aAAa;AAAA,IACjC,OAAO,cAAc,EAAE,IAAI,CAAC,OAAO;AAAA,MACjC,GAAG;AAAA,MACH,WAAW,QAAQ,YAAY,aAAa,EAAE,IAAI;AAAA,MAClD,SAAS,QAAQ,YAAY,UAAU,EAAE,IAAI;AAAA,IAC/C,EAAE;AAAA,EACJ,EAAE;AAKF,MAAI,IAAyD,aAAa,OAAO,QAAQ;AACvF,UAAM,IAAI,IAAI;AACd,WAAO;AAAA,MACL,MAAM,QAAQ,YAAY,KAAK;AAAA,QAC7B,OAAO,EAAE,QAAQ,OAAO,EAAE,KAAK,IAAI;AAAA,QACnC,QAAQ,EAAE,SAAS,OAAO,EAAE,MAAM,IAAI;AAAA,QACtC,MAAM,EAAE;AAAA,QACR,QAAS,EAAE,UAAgD;AAAA,MAC7D,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAKD,MAAI,IAAI,iBAAiB,aAAa;AAAA,IACpC,QAAQ,QAAQ,YAAY,SAAS;AAAA,IACrC,aAAa;AAAA,MACX,eAAe,QAAQ,OAAO,YAAY;AAAA,MAC1C,oBAAoB,QAAQ,OAAO,YAAY;AAAA,MAC/C,eAAe,QAAQ,OAAO,YAAY;AAAA,IAC5C;AAAA,IACA,OAAO,cAAc,EAAE,IAAI,CAAC,OAAO;AAAA,MACjC,MAAM,EAAE;AAAA,MACR,aAAa,EAAE;AAAA,MACf,WAAW,QAAQ,YAAY,aAAa,EAAE,IAAI;AAAA,MAClD,SAAS,QAAQ,YAAY,UAAU,EAAE,IAAI;AAAA,IAC/C,EAAE;AAAA,EACJ,EAAE;AAEF,MAAI,IAED,iBAAiB,OAAO,KAAK,UAAU;AACxC,UAAM,QAAQ,IAAI,QAAQ,CAAC;AAC3B,QAAI,MAAM,gBAAgB,QAAW;AACnC,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,oDAAsB,CAAC;AAAA,IAC9D;AACA,YAAQ,YAAY,OAAO,EAAE,aAAa,MAAM,YAAY,CAAC;AAC7D,YAAQ,SAAS,QAAQ,YAAY,IAAI;AACzC,YAAQ,cAAc,IAAIC,mBAAkB,QAAQ,MAAM;AAC1D,WAAO,EAAE,IAAI,MAAM,QAAQ,QAAQ,YAAY,SAAS,EAAE;AAAA,EAC5D,CAAC;AAKD,MAAI,IAAI,eAAe,OAAO,KAAK,UAAU;AAC3C,UAAM,OAAO;AACb,UAAM,MAAM,MAAM;AAClB,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,qBAAqB;AAAA,IACvB,CAAC;AACD,QAAI,MAAM,iBAAiB;AAE3B,UAAM,WAAW,CAAC,YAAqB;AACrC,UAAI,MAAM;AAAA,QAA8B,KAAK,UAAU,OAAO,CAAC;AAAA;AAAA,CAAM;AAAA,IACvE;AACA,UAAM,cAAc,MAAM;AACxB,UAAI,MAAM,0BAA0B;AAAA,IACtC;AACA,YAAQ,SAAS,GAAG,gBAAgB,QAAQ;AAC5C,YAAQ,SAAS,GAAG,OAAO,WAAW;AAEtC,UAAM,YAAY,YAAY,MAAM,IAAI,MAAM,YAAY,GAAG,IAAM;AAEnE,QAAI,IAAI,GAAG,SAAS,MAAM;AACxB,oBAAc,SAAS;AACvB,cAAQ,SAAS,IAAI,gBAAgB,QAAQ;AAC7C,cAAQ,SAAS,IAAI,OAAO,WAAW;AAAA,IACzC,CAAC;AAAA,EACH,CAAC;AAKD,MAAI,IAAI,QAAQ,OAAO,KAAK,UAAU;AACpC,UAAM,OAAO;AACb,UAAM,QAAQ,OAAO,IAAI,KAAK,MAAM,KAAK,MAAS;AAAA,EACpD,CAAC;AACD,MAAI,KAAK,QAAQ,OAAO,KAAK,UAAU;AAGrC,UAAM,OAAO;AACb,UAAM,QAAQ,OAAO,IAAI,KAAK,MAAM,KAAK,IAAI,IAAI;AAAA,EACnD,CAAC;AAGD,MAAI,WAAW;AACb,QAAI,mBAAmB,OAAO,KAAK,UAAU;AAC3C,UAAI,IAAI,IAAI,WAAW,MAAM,KAAK,IAAI,IAAI,WAAW,MAAM,GAAG;AAC5D,eAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,MACpD;AACA,YAAM,QAAa,WAAK,WAAW,YAAY;AAC/C,UAAO,eAAW,KAAK,GAAG;AACxB,cAAM,KAAK,WAAW,EAAE,KAAQ,iBAAa,OAAO,MAAM,CAAC;AAC3D;AAAA,MACF;AACA,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IACpD,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,QAAQ,QAAQ,QAAQ,OAAO,OAAO;AACnD,QAAM,OAAO,QAAQ,QAAQ,QAAQ,OAAO,OAAO;AACnD,MAAI,CAAC,QAAQ,UAAU;AACrB,UAAM,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC;AAAA,EACjC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,YAAY;AACjB,cAAQ,QAAQ;AAChB,YAAM,IAAI,MAAM;AAChB,qBAAe,OAAO;AAAA,IACxB;AAAA,EACF;AACF;AAEA,SAAS,QAAQ,KAA6E;AAC5F,MAAI,eAAe,kBAAmB,QAAO,EAAE,MAAM,IAAI,MAAM,SAAS,IAAI,QAAQ;AACpF,MAAI,eAAeC,mBAAmB,QAAO,EAAE,MAAM,kBAAkB,SAAS,IAAI,QAAQ;AAC5F,MAAI,eAAe,MAAO,QAAO,EAAE,MAAM,kBAAkB,SAAS,IAAI,QAAQ,MAAM,GAAG,GAAG,EAAE;AAC9F,SAAO,EAAE,MAAM,kBAAkB,SAAS,OAAO,GAAG,EAAE;AACxD;","names":["path","fs","PermissionManager","RepoNotFoundError","EventEmitter","RepoStore","path","record","EventEmitter","RepoStore","PermissionManager","RepoNotFoundError"]}
|