nuwax-file-server 1.5.4 → 1.5.5

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/cli.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{Command as ee}from"commander";import{createRequire as te}from"module";import f from"path";import U from"os";import c from"fs-extra";import{spawn as E}from"cross-spawn";import V from"tree-kill";import{fileURLToPath as q}from"url";import{execFileSync as R}from"child_process";import M from"http";import{createRequire as G}from"module";var I=f.dirname(q(import.meta.url)),H=G(import.meta.url),n={name:"nuwax-file-server",pidDir:f.join(U.tmpdir(),"nuwax-file-server"),pidFileName:"server.pid",lockFileName:"start.lock",defaultStopTimeout:3e4,defaultStartTimeout:3e4,staleLockTimeout:12e4,checkInterval:500};function $(){return f.join(n.pidDir,n.pidFileName)}function F(){return f.join(n.pidDir,n.lockFileName)}function J(){let e=[f.join(I,"..","server.js"),f.join(I,"server.js")];for(let t of e)if(c.existsSync(t))return t;return e[0]}function W(){let e=["../../package.json","../package.json"];for(let t of e)try{let o=H(t);if(o?.version)return o.version}catch{}return"unknown"}function x(){try{let e=$();if(!c.existsSync(e))return null;let t=c.readFileSync(e,"utf8"),o=JSON.parse(t);return!o||typeof o.pid!="number"?null:o}catch(e){return e.code!=="ENOENT"&&console.error(`Read PID file failed: ${e.message}`),null}}function B(e){try{let t=$();c.ensureDirSync(n.pidDir),c.writeFileSync(t,JSON.stringify(e,null,2)),console.debug(`PID file written: ${t}`)}catch(t){throw console.error(`Write PID file failed: ${t.message}`),t}}function v(){try{let e=$();c.existsSync(e)&&(c.removeSync(e),console.debug(`PID file deleted: ${e}`))}catch(e){console.error(`Delete PID file failed: ${e.message}`)}}function g(e){try{return process.kill(e,0),!0}catch(t){return t.code!=="ESRCH"}}function K(e){try{return k()?R("powershell",["-NoProfile","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim():R("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return""}}function X(e){if(!g(e))return!1;let t=K(e);if(!t)return!1;let o=t.toLowerCase(),s=f.basename(f.join(I,"..","server.js")).toLowerCase(),i=n.name.toLowerCase();return o.includes(s)||o.includes(i)}function z(){c.ensureDirSync(n.pidDir);let e=F(),t=`${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,10)}`,o=JSON.stringify({pid:process.pid,token:t,createdAt:new Date().toISOString()},null,2);try{let s=c.openSync(e,"wx");return c.writeSync(s,o),{fd:s,token:t}}catch(s){if(s.code!=="EEXIST")throw s;try{let i=c.readFileSync(e,"utf8"),r=JSON.parse(i),a=Number(r?.pid),u=r?.createdAt?new Date(r.createdAt).getTime():0,l=Date.now()-u,C=Number.isFinite(a)&&a>0&&g(a),p=!u||Number.isNaN(l)||l>n.staleLockTimeout;if(!C||p){c.removeSync(e);let S=c.openSync(e,"wx");return c.writeSync(S,o),console.warn("Detected stale start lock, auto cleaned"),{fd:S,token:t}}}catch{c.removeSync(e);let r=c.openSync(e,"wx");return c.writeSync(r,o),console.warn("Detected invalid start lock, auto cleaned"),{fd:r,token:t}}throw s}}function Q(e){let t=e?.fd,o=e?.token;try{t!=null&&c.closeSync(t)}catch{}try{let s=F();if(c.existsSync(s)){let i=!1;if(!o)i=!0;else try{let r=c.readFileSync(s,"utf8");i=JSON.parse(r)?.token===o}catch{i=!0}i&&c.removeSync(s)}}catch{}}function k(){return process.platform==="win32"}async function Y(e=n.defaultStopTimeout){let t=x();return t?X(t.pid)?(console.log(`Existing service process detected (PID: ${t.pid}), stopping before start...`),await h(t.pid,!1)&&await D(t.pid,e)?(v(),{success:!0,message:`Existing process ${t.pid} stopped gracefully`}):(console.warn(`Graceful stop timeout or failed for PID ${t.pid}, force stop...`),await h(t.pid,!0)?await D(t.pid,e)?(v(),{success:!0,message:`Existing process ${t.pid} stopped forcibly`}):{success:!1,message:`Existing process ${t.pid} did not exit after force stop`}:{success:!1,message:`Failed to stop existing process ${t.pid}`})):(console.log(`Found stale PID file (PID: ${t.pid}), clean it...`),v(),{success:!0,message:"Stale PID file cleaned"}):{success:!0,message:"No existing service process"}}async function h(e,t=!1){return new Promise(o=>{if(!g(e)){console.debug(`Process ${e} does not exist, already stopped`),o(!0);return}let s=t?"SIGKILL":"SIGTERM",i=k()?"taskkill":"tree-kill";if(console.debug(`Use ${i} to stop process ${e} (signal: ${s})`),k()){let r=t?["/F","/PID",String(e)]:["/PID",String(e)],a=E("taskkill",r,{stdio:["ignore","pipe","pipe"],windowsHide:!0}),u="";a.stdout.on("data",l=>{u+=l.toString()}),a.stderr.on("data",l=>{u+=l.toString()}),a.on("error",l=>{console.error(`Stop process failed: ${l.message}`),o(!1)}),a.on("close",l=>{l===0?(console.debug(`Process ${e} stopped`),o(!0)):(console.warn(`taskkill exit code: ${l}, output: ${u}`),t?o(!1):h(e,!0).then(o))})}else V(e,s,r=>{r?r.code==="ESRCH"?(console.debug(`Process ${e} does not exist`),o(!0)):(console.error(`Stop process failed: ${r.message}`),o(!1)):(console.debug(`Process ${e} stopped`),o(!0))})})}async function D(e,t=n.defaultStopTimeout){let o=Date.now();for(;g(e);){if(Date.now()-o>t)return console.warn(`Wait for process ${e} to stop timeout (${t}ms)`),!1;await new Promise(i=>setTimeout(i,n.checkInterval))}let s=Date.now()-o;return console.debug(`Process ${e} stopped after ${s}ms`),!0}async function Z(e,t=n.defaultStartTimeout){let o=Number(e);if(!Number.isFinite(o)||o<=0)return!1;let s=Date.now();for(;Date.now()-s<=t;){if(await new Promise(r=>{let a=M.get({host:"127.0.0.1",port:o,path:"/health",timeout:Math.min(2e3,n.checkInterval*4)},u=>{r(u.statusCode>=200&&u.statusCode<300),u.resume()});a.on("timeout",()=>{a.destroy(),r(!1)}),a.on("error",()=>r(!1))}))return!0;await new Promise(r=>setTimeout(r,n.checkInterval))}return!1}async function N(e={}){let{env:t,port:o,config:s}=e,i=null;console.log(`Start service ${n.name}...`);try{i=z()}catch(r){return r.code==="EEXIST"?{success:!1,pid:null,message:"Another start operation is in progress, please retry later"}:{success:!1,pid:null,message:`Acquire start lock failed: ${r.message}`}}try{let r=Number(e.timeout)||n.defaultStopTimeout,a=await Y(r);if(!a.success)return{success:!1,pid:null,message:`Service start blocked: ${a.message}`};let u={...process.env};t&&(u.NODE_ENV=t,console.log(`Environment: ${t}`)),o&&(u.PORT=o,console.log(`Port: ${o}`)),s&&(u.CONFIG_FILE=s,console.log(`Configuration file: ${s}`));let l=J(),p=E("node",[l,...[]],{env:u,stdio:["pipe","pipe","pipe"],detached:!0,cwd:process.cwd()});if(p.stdout.on("data",m=>{process.stdout.write(m)}),p.stderr.on("data",m=>{process.stderr.write(m)}),p.on("error",m=>{console.error(`Start service failed: ${m.message}`)}),await new Promise(m=>setTimeout(m,2e3)),!g(p.pid))return{success:!1,pid:null,message:"Service start failed"};let S={pid:p.pid,startedAt:new Date().toISOString(),env:t||process.env.NODE_ENV||"production",port:o||process.env.PORT||"60000",version:W(),platform:process.platform};B(S);let P=Number(e.startTimeout)||n.defaultStartTimeout;return await Z(S.port,P)?(p.unref(),console.log(`Service started (PID: ${p.pid})`),console.log(`Service address: http://localhost:${S.port}`),{success:!0,pid:p.pid,message:"Service started successfully"}):(console.error(`Service health check timeout (${P}ms), stop failed instance...`),await h(p.pid,!0),v(),{success:!1,pid:null,message:`Service health check timeout (${P}ms)`})}finally{Q(i)}}async function T(e={}){let{force:t=!1,timeout:o=n.defaultStopTimeout}=e;console.log(`Stop service ${n.name}...`);let s=x();if(!s)return{success:!1,message:"Service not found"};if(!g(s.pid))return console.log("Service process has stopped, clean PID file..."),v(),{success:!0,message:"Service has stopped (process has exited)"};if(!await h(s.pid,t))return{success:!1,message:"Stop service failed"};let r=await D(s.pid,o);return v(),r?{success:!0,message:"Service has stopped"}:{success:!1,message:"Service stop timeout"}}async function O(e={}){console.log(`Restart service ${n.name}...`);let t=await T(e);!t.success&&t.message!=="Service not found"&&console.warn(`Stop service failed: ${t.message}`),await new Promise(s=>setTimeout(s,2e3));let o=await N(e);return o.success?{success:!0,pid:o.pid,message:"Service has restarted"}:{success:!1,pid:null,message:`Restart failed: ${o.message}`}}function _(){let e=x();return e?g(e.pid)?{running:!0,pidInfo:e,message:"Service running"}:{running:!1,pidInfo:e,message:"Service process does not exist"}:{running:!1,pidInfo:null,message:"Service not running"}}function L(e){try{let t=new Date(e),o=new Date;if(isNaN(t.getTime()))return"unknown";let s=Math.floor((o-t)/1e3),i=Math.floor(s/3600),r=Math.floor(s%3600/60),a=s%60;return i>0?`${i} hours ${r} minutes ${a} seconds`:r>0?`${r} minutes ${a} seconds`:`${a} seconds`}catch{return"unknown"}}var Pe=te(import.meta.url),A="1.5.4",d=new ee,w={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",cyan:"\x1B[36m"};function j(e){console.error(`${w.red}ERROR: ${e}${w.reset}`)}function b(e){console.log(`${w.green}${e}${w.reset}`)}function oe(e){console.log(`${w.blue}${e}${w.reset}`)}function y(e){return async(...t)=>{try{let o=await e(...t);o&&o.success===!1?(j(o.message||"Command failed"),process.exitCode=1):process.exitCode=0}catch(o){j(o?.message||"Command failed with unexpected error"),process.exitCode=1}}}async function se(e){let t=await N({env:e.env,port:e.port,config:e.config,timeout:Number(e.timeout),startTimeout:Number(e.startTimeout)});return t.success&&b(`Service started (PID: ${t.pid})`),t}async function re(e){let t=await T({force:e.force,timeout:Number(e.timeout)});return t.success&&b(t.message||"Service stopped"),t}async function ne(e){let t=await O({env:e.env,port:e.port,config:e.config,timeout:Number(e.timeout),startTimeout:Number(e.startTimeout)});return t.success&&b(t.message||"Service restarted"),t}function ie(){let e=_();return oe(`${n.name} service status:`),console.log(""),console.log(` Service name: ${n.name}`),console.log(` Running status: ${e.running?"Running":"Stopped"}`),console.log(` Message: ${e.message}`),console.log(` PID file: ${$()}`),e.pidInfo&&(console.log(` Process ID: ${e.pidInfo.pid}`),console.log(` Environment: ${e.pidInfo.env||"Unknown"}`),console.log(` Port: ${e.pidInfo.port||"Unknown"}`),console.log(` Version: ${e.pidInfo.version||A}`),console.log(` Platform: ${e.pidInfo.platform||process.platform}`),console.log(` Started at: ${e.pidInfo.startedAt||"Unknown"}`),console.log(` Uptime: ${L(e.pidInfo.startedAt)}`)),console.log(""),{success:e.running,message:e.message}}function ce(){d.name("nuwax-file-server").description("Cross-platform file service deployment tool, supporting start/stop/restart/status").version(A,"-v, --version","Display version number").helpOption("-h, --help","Display help information"),d.command("start").allowUnknownOption().description("Start service").option("--env <environment>","\u73AF\u5883: development|production|test","production").option("--port <port>","Service port").option("--config <path>","Custom configuration file path").option("--timeout <ms>","\u505C\u6B62\u65E7\u8FDB\u7A0B\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).option("--start-timeout <ms>","\u542F\u52A8\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStartTimeout}`).action(y(se)),d.command("stop").description("Stop service").option("--force","Force stop").option("--timeout <ms>","\u505C\u6B62\u670D\u52A1\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).action(y(re)),d.command("restart").allowUnknownOption().description("Restart service").option("--env <environment>","\u73AF\u5883: development|production|test","production").option("--port <port>","Service port").option("--config <path>","Custom configuration file path").option("--timeout <ms>","\u505C\u6B62\u65E7\u8FDB\u7A0B\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).option("--start-timeout <ms>","\u542F\u52A8\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStartTimeout}`).action(y(ne)),d.command("status").description("View service status").action(y(ie)),d.command("help").description("Display help information").action(()=>{d.outputHelp()}),d.parse(process.argv),process.argv.slice(2).length||(d.outputHelp(),process.exitCode=0)}ce();
2
+ import{Command as ee}from"commander";import{createRequire as te}from"module";import f from"path";import U from"os";import c from"fs-extra";import{spawn as E}from"cross-spawn";import V from"tree-kill";import{fileURLToPath as q}from"url";import{execFileSync as R}from"child_process";import M from"http";import{createRequire as G}from"module";var I=f.dirname(q(import.meta.url)),H=G(import.meta.url),n={name:"nuwax-file-server",pidDir:f.join(U.tmpdir(),"nuwax-file-server"),pidFileName:"server.pid",lockFileName:"start.lock",defaultStopTimeout:3e4,defaultStartTimeout:3e4,staleLockTimeout:12e4,checkInterval:500};function $(){return f.join(n.pidDir,n.pidFileName)}function F(){return f.join(n.pidDir,n.lockFileName)}function J(){let e=[f.join(I,"..","server.js"),f.join(I,"server.js")];for(let t of e)if(c.existsSync(t))return t;return e[0]}function W(){let e=["../../package.json","../package.json"];for(let t of e)try{let o=H(t);if(o?.version)return o.version}catch{}return"unknown"}function x(){try{let e=$();if(!c.existsSync(e))return null;let t=c.readFileSync(e,"utf8"),o=JSON.parse(t);return!o||typeof o.pid!="number"?null:o}catch(e){return e.code!=="ENOENT"&&console.error(`Read PID file failed: ${e.message}`),null}}function B(e){try{let t=$();c.ensureDirSync(n.pidDir),c.writeFileSync(t,JSON.stringify(e,null,2)),console.debug(`PID file written: ${t}`)}catch(t){throw console.error(`Write PID file failed: ${t.message}`),t}}function v(){try{let e=$();c.existsSync(e)&&(c.removeSync(e),console.debug(`PID file deleted: ${e}`))}catch(e){console.error(`Delete PID file failed: ${e.message}`)}}function g(e){try{return process.kill(e,0),!0}catch(t){return t.code!=="ESRCH"}}function K(e){try{return k()?R("powershell",["-NoProfile","-Command",`(Get-CimInstance Win32_Process -Filter "ProcessId = ${e}").CommandLine`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim():R("ps",["-p",String(e),"-o","command="],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return""}}function X(e){if(!g(e))return!1;let t=K(e);if(!t)return!1;let o=t.toLowerCase(),s=f.basename(f.join(I,"..","server.js")).toLowerCase(),i=n.name.toLowerCase();return o.includes(s)||o.includes(i)}function z(){c.ensureDirSync(n.pidDir);let e=F(),t=`${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,10)}`,o=JSON.stringify({pid:process.pid,token:t,createdAt:new Date().toISOString()},null,2);try{let s=c.openSync(e,"wx");return c.writeSync(s,o),{fd:s,token:t}}catch(s){if(s.code!=="EEXIST")throw s;try{let i=c.readFileSync(e,"utf8"),r=JSON.parse(i),a=Number(r?.pid),u=r?.createdAt?new Date(r.createdAt).getTime():0,l=Date.now()-u,C=Number.isFinite(a)&&a>0&&g(a),p=!u||Number.isNaN(l)||l>n.staleLockTimeout;if(!C||p){c.removeSync(e);let S=c.openSync(e,"wx");return c.writeSync(S,o),console.warn("Detected stale start lock, auto cleaned"),{fd:S,token:t}}}catch{c.removeSync(e);let r=c.openSync(e,"wx");return c.writeSync(r,o),console.warn("Detected invalid start lock, auto cleaned"),{fd:r,token:t}}throw s}}function Q(e){let t=e?.fd,o=e?.token;try{t!=null&&c.closeSync(t)}catch{}try{let s=F();if(c.existsSync(s)){let i=!1;if(!o)i=!0;else try{let r=c.readFileSync(s,"utf8");i=JSON.parse(r)?.token===o}catch{i=!0}i&&c.removeSync(s)}}catch{}}function k(){return process.platform==="win32"}async function Y(e=n.defaultStopTimeout){let t=x();return t?X(t.pid)?(console.log(`Existing service process detected (PID: ${t.pid}), stopping before start...`),await h(t.pid,!1)&&await D(t.pid,e)?(v(),{success:!0,message:`Existing process ${t.pid} stopped gracefully`}):(console.warn(`Graceful stop timeout or failed for PID ${t.pid}, force stop...`),await h(t.pid,!0)?await D(t.pid,e)?(v(),{success:!0,message:`Existing process ${t.pid} stopped forcibly`}):{success:!1,message:`Existing process ${t.pid} did not exit after force stop`}:{success:!1,message:`Failed to stop existing process ${t.pid}`})):(console.log(`Found stale PID file (PID: ${t.pid}), clean it...`),v(),{success:!0,message:"Stale PID file cleaned"}):{success:!0,message:"No existing service process"}}async function h(e,t=!1){return new Promise(o=>{if(!g(e)){console.debug(`Process ${e} does not exist, already stopped`),o(!0);return}let s=t?"SIGKILL":"SIGTERM",i=k()?"taskkill":"tree-kill";if(console.debug(`Use ${i} to stop process ${e} (signal: ${s})`),k()){let r=t?["/F","/PID",String(e)]:["/PID",String(e)],a=E("taskkill",r,{stdio:["ignore","pipe","pipe"],windowsHide:!0}),u="";a.stdout.on("data",l=>{u+=l.toString()}),a.stderr.on("data",l=>{u+=l.toString()}),a.on("error",l=>{console.error(`Stop process failed: ${l.message}`),o(!1)}),a.on("close",l=>{l===0?(console.debug(`Process ${e} stopped`),o(!0)):(console.warn(`taskkill exit code: ${l}, output: ${u}`),t?o(!1):h(e,!0).then(o))})}else V(e,s,r=>{r?r.code==="ESRCH"?(console.debug(`Process ${e} does not exist`),o(!0)):(console.error(`Stop process failed: ${r.message}`),o(!1)):(console.debug(`Process ${e} stopped`),o(!0))})})}async function D(e,t=n.defaultStopTimeout){let o=Date.now();for(;g(e);){if(Date.now()-o>t)return console.warn(`Wait for process ${e} to stop timeout (${t}ms)`),!1;await new Promise(i=>setTimeout(i,n.checkInterval))}let s=Date.now()-o;return console.debug(`Process ${e} stopped after ${s}ms`),!0}async function Z(e,t=n.defaultStartTimeout){let o=Number(e);if(!Number.isFinite(o)||o<=0)return!1;let s=Date.now();for(;Date.now()-s<=t;){if(await new Promise(r=>{let a=M.get({host:"127.0.0.1",port:o,path:"/health",timeout:Math.min(2e3,n.checkInterval*4)},u=>{r(u.statusCode>=200&&u.statusCode<300),u.resume()});a.on("timeout",()=>{a.destroy(),r(!1)}),a.on("error",()=>r(!1))}))return!0;await new Promise(r=>setTimeout(r,n.checkInterval))}return!1}async function N(e={}){let{env:t,port:o,config:s}=e,i=null;console.log(`Start service ${n.name}...`);try{i=z()}catch(r){return r.code==="EEXIST"?{success:!1,pid:null,message:"Another start operation is in progress, please retry later"}:{success:!1,pid:null,message:`Acquire start lock failed: ${r.message}`}}try{let r=Number(e.timeout)||n.defaultStopTimeout,a=await Y(r);if(!a.success)return{success:!1,pid:null,message:`Service start blocked: ${a.message}`};let u={...process.env};t&&(u.NODE_ENV=t,console.log(`Environment: ${t}`)),o&&(u.PORT=o,console.log(`Port: ${o}`)),s&&(u.CONFIG_FILE=s,console.log(`Configuration file: ${s}`));let l=J(),p=E("node",[l,...[]],{env:u,stdio:["pipe","pipe","pipe"],detached:!0,cwd:process.cwd()});if(p.stdout.on("data",m=>{process.stdout.write(m)}),p.stderr.on("data",m=>{process.stderr.write(m)}),p.on("error",m=>{console.error(`Start service failed: ${m.message}`)}),await new Promise(m=>setTimeout(m,2e3)),!g(p.pid))return{success:!1,pid:null,message:"Service start failed"};let S={pid:p.pid,startedAt:new Date().toISOString(),env:t||process.env.NODE_ENV||"production",port:o||process.env.PORT||"60000",version:W(),platform:process.platform};B(S);let P=Number(e.startTimeout)||n.defaultStartTimeout;return await Z(S.port,P)?(p.unref(),console.log(`Service started (PID: ${p.pid})`),console.log(`Service address: http://localhost:${S.port}`),{success:!0,pid:p.pid,message:"Service started successfully"}):(console.error(`Service health check timeout (${P}ms), stop failed instance...`),await h(p.pid,!0),v(),{success:!1,pid:null,message:`Service health check timeout (${P}ms)`})}finally{Q(i)}}async function T(e={}){let{force:t=!1,timeout:o=n.defaultStopTimeout}=e;console.log(`Stop service ${n.name}...`);let s=x();if(!s)return{success:!1,message:"Service not found"};if(!g(s.pid))return console.log("Service process has stopped, clean PID file..."),v(),{success:!0,message:"Service has stopped (process has exited)"};if(!await h(s.pid,t))return{success:!1,message:"Stop service failed"};let r=await D(s.pid,o);return v(),r?{success:!0,message:"Service has stopped"}:{success:!1,message:"Service stop timeout"}}async function O(e={}){console.log(`Restart service ${n.name}...`);let t=await T(e);!t.success&&t.message!=="Service not found"&&console.warn(`Stop service failed: ${t.message}`),await new Promise(s=>setTimeout(s,2e3));let o=await N(e);return o.success?{success:!0,pid:o.pid,message:"Service has restarted"}:{success:!1,pid:null,message:`Restart failed: ${o.message}`}}function _(){let e=x();return e?g(e.pid)?{running:!0,pidInfo:e,message:"Service running"}:{running:!1,pidInfo:e,message:"Service process does not exist"}:{running:!1,pidInfo:null,message:"Service not running"}}function L(e){try{let t=new Date(e),o=new Date;if(isNaN(t.getTime()))return"unknown";let s=Math.floor((o-t)/1e3),i=Math.floor(s/3600),r=Math.floor(s%3600/60),a=s%60;return i>0?`${i} hours ${r} minutes ${a} seconds`:r>0?`${r} minutes ${a} seconds`:`${a} seconds`}catch{return"unknown"}}var Pe=te(import.meta.url),A="1.5.5",d=new ee,w={reset:"\x1B[0m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",cyan:"\x1B[36m"};function j(e){console.error(`${w.red}ERROR: ${e}${w.reset}`)}function b(e){console.log(`${w.green}${e}${w.reset}`)}function oe(e){console.log(`${w.blue}${e}${w.reset}`)}function y(e){return async(...t)=>{try{let o=await e(...t);o&&o.success===!1?(j(o.message||"Command failed"),process.exitCode=1):process.exitCode=0}catch(o){j(o?.message||"Command failed with unexpected error"),process.exitCode=1}}}async function se(e){let t=await N({env:e.env,port:e.port,config:e.config,timeout:Number(e.timeout),startTimeout:Number(e.startTimeout)});return t.success&&b(`Service started (PID: ${t.pid})`),t}async function re(e){let t=await T({force:e.force,timeout:Number(e.timeout)});return t.success&&b(t.message||"Service stopped"),t}async function ne(e){let t=await O({env:e.env,port:e.port,config:e.config,timeout:Number(e.timeout),startTimeout:Number(e.startTimeout)});return t.success&&b(t.message||"Service restarted"),t}function ie(){let e=_();return oe(`${n.name} service status:`),console.log(""),console.log(` Service name: ${n.name}`),console.log(` Running status: ${e.running?"Running":"Stopped"}`),console.log(` Message: ${e.message}`),console.log(` PID file: ${$()}`),e.pidInfo&&(console.log(` Process ID: ${e.pidInfo.pid}`),console.log(` Environment: ${e.pidInfo.env||"Unknown"}`),console.log(` Port: ${e.pidInfo.port||"Unknown"}`),console.log(` Version: ${e.pidInfo.version||A}`),console.log(` Platform: ${e.pidInfo.platform||process.platform}`),console.log(` Started at: ${e.pidInfo.startedAt||"Unknown"}`),console.log(` Uptime: ${L(e.pidInfo.startedAt)}`)),console.log(""),{success:e.running,message:e.message}}function ce(){d.name("nuwax-file-server").description("Cross-platform file service deployment tool, supporting start/stop/restart/status").version(A,"-v, --version","Display version number").helpOption("-h, --help","Display help information"),d.command("start").allowUnknownOption().description("Start service").option("--env <environment>","\u73AF\u5883: development|production|test","production").option("--port <port>","Service port").option("--config <path>","Custom configuration file path").option("--timeout <ms>","\u505C\u6B62\u65E7\u8FDB\u7A0B\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).option("--start-timeout <ms>","\u542F\u52A8\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStartTimeout}`).action(y(se)),d.command("stop").description("Stop service").option("--force","Force stop").option("--timeout <ms>","\u505C\u6B62\u670D\u52A1\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).action(y(re)),d.command("restart").allowUnknownOption().description("Restart service").option("--env <environment>","\u73AF\u5883: development|production|test","production").option("--port <port>","Service port").option("--config <path>","Custom configuration file path").option("--timeout <ms>","\u505C\u6B62\u65E7\u8FDB\u7A0B\u7B49\u5F85\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStopTimeout}`).option("--start-timeout <ms>","\u542F\u52A8\u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",`${n.defaultStartTimeout}`).action(y(ne)),d.command("status").description("View service status").action(y(ie)),d.command("help").description("Display help information").action(()=>{d.outputHelp()}),d.parse(process.argv),process.argv.slice(2).length||(d.outputHelp(),process.exitCode=0)}ce();
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import A from"express";import"json-bigint";import C from"swagger-ui-express";import R from"./config/swagger.js";import a from"./appConfig/index.js";import{log as c,logger as S}from"./utils/log/logUtils.js";import w from"./utils/log/logCacheManager.js";import{errorHandler as P,notFoundHandler as y}from"./utils/error/errorHandler.js";import N from"./routes/router.js";import{cleanupInitProjectOnStartup as D}from"./utils/project/initProjectCleanupUtils.js";import{resolveServiceContext as H,resolveWorkspaceDir as F}from"./utils/computer/workspaceContext.js";import{startScheduler as v,stopScheduler as x}from"./scheduler/pnpmPruneScheduler.js";import f from"path";const o=A();o.use(A.json({limit:a.REQUEST_BODY_LIMIT,reviver:(t,e)=>typeof e=="number"&&!Number.isSafeInteger(e)?e.toString():e})),o.use(A.urlencoded({extended:!0,limit:a.REQUEST_BODY_LIMIT})),o.use(S);const T=t=>{let e=t;try{for(;;){const n=decodeURIComponent(e);if(n===e)break;e=n}}catch{}return e};o.use("/api/page/static/:projectId",(t,e,n)=>{const{projectId:d}=t.params;let s=t.path||"/";if(!d||s==="/")return e.status(404).send("Not Found");const r=t.headers.origin,l=r||"*";if(e.header("Access-Control-Allow-Origin",l),e.header("Access-Control-Allow-Methods","HEAD,GET,POST,PUT,DELETE,OPTIONS"),e.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Fragment"),e.header("Access-Control-Expose-Headers","Content-Type"),r&&(e.header("Access-Control-Allow-Credentials","true"),e.header("Vary","Origin")),t.method==="OPTIONS")return e.sendStatus(200);s=s.replace(/^\/+/,"");const p=T(s),g=f.join(a.PROJECT_SOURCE_DIR,d,p),i={"Access-Control-Allow-Origin":l,"Access-Control-Allow-Methods":"HEAD,GET,POST,PUT,DELETE,OPTIONS","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Fragment"};return r&&(i["Access-Control-Allow-Credentials"]="true",i.Vary="Origin"),e.sendFile(g,{dotfiles:"allow",headers:i},h=>{if(h)return n()})}),o.use("/api/computer/static/:userId/:cId",(t,e,n)=>{const{userId:d,cId:s}=t.params;let r=t.path||"/";if(!d||!s||r==="/")return e.status(404).send("Not Found");const l=t.headers.origin,p=l||"*";if(e.header("Access-Control-Allow-Origin",p),e.header("Access-Control-Allow-Methods","HEAD,GET,POST,PUT,DELETE,OPTIONS"),e.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Range, If-Range"),e.header("Access-Control-Expose-Headers","Content-Type, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified"),l&&(e.header("Access-Control-Allow-Credentials","true"),e.header("Vary","Origin")),t.method==="OPTIONS")return e.sendStatus(200);r=r.replace(/^\/+/,"");const g=T(r),{customTargetDir:i}=t.query,h=H(t),E=i&&i.trim()?f.join(i,g):f.join(F(h,d,s),g),m={"Access-Control-Allow-Origin":p,"Access-Control-Allow-Methods":"HEAD,GET,POST,PUT,DELETE,OPTIONS","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Range, If-Range","Access-Control-Expose-Headers":"Content-Type, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified"};return l&&(m["Access-Control-Allow-Credentials"]="true",m.Vary="Origin"),e.sendFile(E,{dotfiles:"allow",headers:m},I=>{if(I)return n()})}),o.use("/api-docs",C.serve,C.setup(R,{customCss:".swagger-ui .topbar { display: none }",customSiteTitle:"nuwax-file-server API Documentation"})),o.use(N),o.use(y),o.use(P);const u=o.listen(a.PORT,async()=>{c("default","INFO",`Server is running on port ${a.PORT} (${a.NODE_ENV} mode)`),await D(a);try{v()}catch(t){c("default","ERROR",`pnpm prune scheduled task failed to start: ${t.message}`)}});u.timeout=6e5,u.keepAliveTimeout=61e4,u.headersTimeout=62e4,u.requestTimeout=63e4;const O=t=>{c("default","INFO",`Received ${t} signal, preparing graceful exit...`),x();try{w.destroy(),c("default","INFO","Log cache manager cleared")}catch(e){c("default","ERROR",`Failed to clear log cache manager: ${e.message}`)}u.close(()=>{c("default","INFO","Server closed"),process.exit(0)}),setTimeout(()=>{c("default","ERROR","Force exit (timeout)"),process.exit(1)},3e4)};process.on("SIGTERM",()=>O("SIGTERM")),process.on("SIGINT",()=>O("SIGINT"));
1
+ import f from"express";import"json-bigint";import T from"swagger-ui-express";import R from"./config/swagger.js";import a from"./appConfig/index.js";import{log as c,logger as w}from"./utils/log/logUtils.js";import P from"./utils/log/logCacheManager.js";import{errorHandler as y,notFoundHandler as F}from"./utils/error/errorHandler.js";import N from"./routes/router.js";import{cleanupInitProjectOnStartup as H}from"./utils/project/initProjectCleanupUtils.js";import{resolveServiceContext as D,resolveWorkspaceDir as v}from"./utils/computer/workspaceContext.js";import{startScheduler as x,stopScheduler as L}from"./scheduler/pnpmPruneScheduler.js";import A from"path";import M from"fs/promises";const r=f();r.use(f.json({limit:a.REQUEST_BODY_LIMIT,reviver:(t,e)=>typeof e=="number"&&!Number.isSafeInteger(e)?e.toString():e})),r.use(f.urlencoded({extended:!0,limit:a.REQUEST_BODY_LIMIT})),r.use(w);const O=t=>{let e=t;try{for(;;){const o=decodeURIComponent(e);if(o===e)break;e=o}}catch{}return e},E=async(t,e)=>{try{const o=await M.stat(e);o.isFile()&&t.setHeader("X-File-Size",o.size)}catch{}};r.use("/api/page/static/:projectId",async(t,e,o)=>{const{projectId:d}=t.params;let s=t.path||"/";if(!d||s==="/")return e.status(404).send("Not Found");const n=t.headers.origin,l=n||"*";if(e.header("Access-Control-Allow-Origin",l),e.header("Access-Control-Allow-Methods","HEAD,GET,POST,PUT,DELETE,OPTIONS"),e.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Fragment"),e.header("Access-Control-Expose-Headers","Content-Type, X-File-Size"),n&&(e.header("Access-Control-Allow-Credentials","true"),e.header("Vary","Origin")),t.method==="OPTIONS")return e.sendStatus(200);s=s.replace(/^\/+/,"");const g=O(s),u=A.join(a.PROJECT_SOURCE_DIR,d,g);await E(e,u);const i={"Access-Control-Allow-Origin":l,"Access-Control-Allow-Methods":"HEAD,GET,POST,PUT,DELETE,OPTIONS","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Fragment"};return n&&(i["Access-Control-Allow-Credentials"]="true",i.Vary="Origin"),e.sendFile(u,{dotfiles:"allow",headers:i},h=>{if(h)return o()})}),r.use("/api/computer/static/:userId/:cId",async(t,e,o)=>{const{userId:d,cId:s}=t.params;let n=t.path||"/";if(!d||!s||n==="/")return e.status(404).send("Not Found");const l=t.headers.origin,g=l||"*";if(e.header("Access-Control-Allow-Origin",g),e.header("Access-Control-Allow-Methods","HEAD,GET,POST,PUT,DELETE,OPTIONS"),e.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Range, If-Range"),e.header("Access-Control-Expose-Headers","Content-Type, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-File-Size"),l&&(e.header("Access-Control-Allow-Credentials","true"),e.header("Vary","Origin")),t.method==="OPTIONS")return e.sendStatus(200);n=n.replace(/^\/+/,"");const u=O(n),{customTargetDir:i}=t.query,h=D(t),C=i&&i.trim()?A.join(i,u):A.join(v(h,d,s),u);await E(e,C);const m={"Access-Control-Allow-Origin":g,"Access-Control-Allow-Methods":"HEAD,GET,POST,PUT,DELETE,OPTIONS","Access-Control-Allow-Headers":"Origin, X-Requested-With, Content-Type, Accept, Authorization, Cache-Control, Range, If-Range","Access-Control-Expose-Headers":"Content-Type, Content-Length, Content-Range, Accept-Ranges, ETag, Last-Modified, X-File-Size"};return l&&(m["Access-Control-Allow-Credentials"]="true",m.Vary="Origin"),e.sendFile(C,{dotfiles:"allow",headers:m},I=>{if(I)return o()})}),r.use("/api-docs",T.serve,T.setup(R,{customCss:".swagger-ui .topbar { display: none }",customSiteTitle:"nuwax-file-server API Documentation"})),r.use(N),r.use(F),r.use(y);const p=r.listen(a.PORT,async()=>{c("default","INFO",`Server is running on port ${a.PORT} (${a.NODE_ENV} mode)`),await H(a);try{x()}catch(t){c("default","ERROR",`pnpm prune scheduled task failed to start: ${t.message}`)}});p.timeout=6e5,p.keepAliveTimeout=61e4,p.headersTimeout=62e4,p.requestTimeout=63e4;const S=t=>{c("default","INFO",`Received ${t} signal, preparing graceful exit...`),L();try{P.destroy(),c("default","INFO","Log cache manager cleared")}catch(e){c("default","ERROR",`Failed to clear log cache manager: ${e.message}`)}p.close(()=>{c("default","INFO","Server closed"),process.exit(0)}),setTimeout(()=>{c("default","ERROR","Force exit (timeout)"),process.exit(1)},3e4)};process.on("SIGTERM",()=>S("SIGTERM")),process.on("SIGINT",()=>S("SIGINT"));
@@ -1,8 +1,8 @@
1
- import C from"path";import e from"fs";import L from"crypto";import i from"isomorphic-git";import{createPatch as O}from"diff";import P from"../../appConfig/index.js";import{cleanEmptyParentDirs as N}from"./nativeGitUtils.js";function T(t,s){return{name:t||P.GIT_DEFAULT_AUTHOR_NAME,email:s||P.GIT_DEFAULT_AUTHOR_EMAIL}}function M(t){for(let s=0;s<Math.min(t.length,8e3);s++)if(t[s]===0)return!0;return!1}function W(t){const s=Buffer.from(`blob ${t.length}\0`);return L.createHash("sha1").update(Buffer.concat([s,t])).digest("hex")}async function D(t){return i.resolveRef({fs:e,dir:t,ref:"HEAD"})}async function I(t){try{return await i.resolveRef({fs:e,dir:t,ref:"HEAD"}),!0}catch{return!1}}async function B(t,s,o){try{const{blob:a}=await i.readBlob({fs:e,dir:t,oid:s,filepath:o}),n=Buffer.from(a);return{content:n.toString("utf8"),buf:n}}catch{return null}}function G(t,s,o,a,n,r,f){const w=O(t,a?s:"",n?o:"",a?`a/${t}`:"/dev/null",n?`b/${t}`:"/dev/null").split(`
2
- `).slice(4);w.length>0&&w[w.length-1]===""&&w.pop();const u=[];let d=0,g=0;for(const m of w){if(m.startsWith("@@")){const x=m.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);if(x){const H=x[1],E=x[2]!==void 0?parseInt(x[2],10):1,F=x[3],v=x[4]!==void 0?parseInt(x[4],10):1,A=E===1?H:`${H},${E}`,$=v===1?F:`${F},${v}`;u.push(`@@ -${A} +${$} @@`);continue}}m.startsWith("+")&&!m.startsWith("+++")?d++:m.startsWith("-")&&!m.startsWith("---")&&g++,u.push(m)}const p=a&&s!==""&&!s.endsWith(`
1
+ import A from"path";import e from"fs";import j from"crypto";import r from"isomorphic-git";import{createPatch as U}from"diff";import P from"../../appConfig/index.js";import{cleanEmptyParentDirs as D}from"./nativeGitUtils.js";function $(t,s){return{name:t||P.GIT_DEFAULT_AUTHOR_NAME,email:s||P.GIT_DEFAULT_AUTHOR_EMAIL}}function M(t){for(let s=0;s<Math.min(t.length,8e3);s++)if(t[s]===0)return!0;return!1}function B(t){const s=Buffer.from(`blob ${t.length}\0`);return j.createHash("sha1").update(Buffer.concat([s,t])).digest("hex")}async function W(t){return r.resolveRef({fs:e,dir:t,ref:"HEAD"})}async function T(t){try{return await r.resolveRef({fs:e,dir:t,ref:"HEAD"}),!0}catch{return!1}}async function N(t,s,o){try{const{blob:a}=await r.readBlob({fs:e,dir:t,oid:s,filepath:o}),n=Buffer.from(a);return{content:n.toString("utf8"),buf:n}}catch{return null}}function V(t,s,o,a,n,c,i){const w=U(t,a?s:"",n?o:"",a?`a/${t}`:"/dev/null",n?`b/${t}`:"/dev/null").split(`
2
+ `).slice(4);w.length>0&&w[w.length-1]===""&&w.pop();const h=[];let d=0,g=0;for(const m of w){if(m.startsWith("@@")){const x=m.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);if(x){const k=x[1],C=x[2]!==void 0?parseInt(x[2],10):1,F=x[3],v=x[4]!==void 0?parseInt(x[4],10):1,I=C===1?k:`${k},${C}`,H=v===1?F:`${F},${v}`;h.push(`@@ -${I} +${H} @@`);continue}}m.startsWith("+")&&!m.startsWith("+++")?d++:m.startsWith("-")&&!m.startsWith("---")&&g++,h.push(m)}const p=a&&s!==""&&!s.endsWith(`
3
3
  `),S=n&&o!==""&&!o.endsWith(`
4
- `);if((p||S)&&u.length>0){let m=0;for(let v=0;v<u.length;v++)u[v].startsWith("@@")&&(m=v);let x=-1,H=-1,E=-1;for(let v=u.length-1;v>m;v--){const A=u[v];A.startsWith("-")&&!A.startsWith("---")&&x<0?x=v:A.startsWith("+")&&!A.startsWith("++")&&H<0?H=v:A.startsWith(" ")&&E<0&&(E=v)}const F=Math.max(x,H,E);if(F>=0){const v=u[F];if(v.startsWith(" "))(p||S)&&u.splice(F+1,0,"\");else if(v.startsWith("+")){let A=-1;for(let $=F-1;$>m;$--)if(u[$].startsWith("-")&&!u[$].startsWith("---")){A=$;break}A>=0&&p?(u.splice(A+1,0,"\"),S&&u.splice(F+2,0,"\")):S&&u.splice(F+1,0,"\")}else v.startsWith("-")&&p&&u.splice(F+1,0,"\")}}const b=a&&r?W(r).substring(0,7):"0000000",k=n&&f?W(f).substring(0,7):"0000000",c=[];return c.push(`diff --git a/${t} b/${t}`),a?n?c.push(`index ${b}..${k} 100644`):(c.push("deleted file mode 100644"),c.push(`index ${b}..0000000`)):(c.push("new file mode 100644"),c.push(`index 0000000..${k}`)),c.push(`--- ${a?`a/${t}`:"/dev/null"}`),c.push(`+++ ${n?`b/${t}`:"/dev/null"}`),{diff:[...c,...u].join(`
4
+ `);if((p||S)&&h.length>0){let m=0;for(let v=0;v<h.length;v++)h[v].startsWith("@@")&&(m=v);let x=-1,k=-1,C=-1;for(let v=h.length-1;v>m;v--){const I=h[v];I.startsWith("-")&&!I.startsWith("---")&&x<0?x=v:I.startsWith("+")&&!I.startsWith("++")&&k<0?k=v:I.startsWith(" ")&&C<0&&(C=v)}const F=Math.max(x,k,C);if(F>=0){const v=h[F];if(v.startsWith(" "))(p||S)&&h.splice(F+1,0,"\");else if(v.startsWith("+")){let I=-1;for(let H=F-1;H>m;H--)if(h[H].startsWith("-")&&!h[H].startsWith("---")){I=H;break}I>=0&&p?(h.splice(I+1,0,"\"),S&&h.splice(F+2,0,"\")):S&&h.splice(F+1,0,"\")}else v.startsWith("-")&&p&&h.splice(F+1,0,"\")}}const b=a&&c?B(c).substring(0,7):"0000000",E=n&&i?B(i).substring(0,7):"0000000",l=[];return l.push(`diff --git a/${t} b/${t}`),a?n?l.push(`index ${b}..${E} 100644`):(l.push("deleted file mode 100644"),l.push(`index ${b}..0000000`)):(l.push("new file mode 100644"),l.push(`index 0000000..${E}`)),l.push(`--- ${a?`a/${t}`:"/dev/null"}`),l.push(`+++ ${n?`b/${t}`:"/dev/null"}`),{diff:[...l,...h].join(`
5
5
  `)+`
6
- `,insertions:d,deletions:g}}async function V(t,s){const{authorName:o,authorEmail:a,defaultBranch:n="main"}=s;await i.init({fs:e,dir:t,defaultBranch:n}),await i.setConfig({fs:e,dir:t,path:"user.name",value:o}),await i.setConfig({fs:e,dir:t,path:"user.email",value:a})}async function q(t){const s=await i.currentBranch({fs:e,dir:t,fullname:!1}),o=await i.statusMatrix({fs:e,dir:t}),a=[],n=[],r=[],f=[],l=[];for(const[h,w,u,d]of o)w!==d&&a.push(h),w===0&&d!==0&&r.push(h),(w===1&&d===0||u===0&&d!==0)&&f.push(h),d!==0&&u!==0&&u!==d&&n.push(h),w===0&&d===0&&u!==0&&l.push(h);return{current:s,staged:[...new Set(a)],modified:[...new Set(n)],created:[...new Set(r)],deleted:[...new Set(f)],untracked:[...new Set(l)],conflicted:[],ahead:0,behind:0,tracking:null}}async function _(t,s={}){const{cache:o}=s,a=[];return await i.walk({fs:e,dir:t,cache:o,trees:[i.WORKDIR()],map:async(n,[r])=>{if(!r)return null;if(n===".")return;const f=await r.type();if(f==="tree")return await i.isIgnored({fs:e,dir:t,filepath:n})?null:void 0;if(f!=="blob"||await i.isIgnored({fs:e,dir:t,filepath:n}))return null;a.push(n)}}),a}async function j(t,s={}){const{cache:o}=s,a=await _(t,{cache:o});return a.length>0&&await i.add({fs:e,dir:t,filepath:a,parallel:!0,cache:o,force:!0}),{hasChanges:a.length>0,toAdd:a,toRemove:[]}}async function R(t,s={}){const{cache:o}=s;if(!await I(t))return j(t,{cache:o});const a=await i.statusMatrix({fs:e,dir:t,cache:o}),n=[],r=[];for(const[l,h,w,u]of a)w===2&&u!==2&&n.push(l),h===1&&w===0&&u!==0&&r.push(l);n.length>0&&await i.add({fs:e,dir:t,filepath:n,parallel:!0,cache:o,force:!0});for(const l of r)await i.remove({fs:e,dir:t,filepath:l,cache:o});return{hasChanges:n.length>0||r.length>0||a.some(([,,,l])=>l!==1),toAdd:n,toRemove:r}}async function U(t,s,o={}){const{cache:a,force:n=!1}=o,r=[],f=[];for(const l of s){const h=C.join(t,l);e.existsSync(h)?r.push(l):f.push(l)}r.length>0&&await i.add({fs:e,dir:t,filepath:r,parallel:!0,cache:a,force:n});for(const l of f)await i.remove({fs:e,dir:t,filepath:l,cache:a})}async function K(t,s){const{message:o,authorName:a,authorEmail:n,cache:r}=s,{hasChanges:f}=await R(t,{cache:r});return f?{nothingToCommit:!1,commitHash:await i.commit({fs:e,dir:t,message:o,author:T(a,n),cache:r})}:{nothingToCommit:!0}}async function z(t,s){const{message:o,authorName:a,authorEmail:n,files:r,cache:f={}}=s;return await U(t,r,{cache:f,force:!0}),(await i.statusMatrix({fs:e,dir:t,cache:f,filepaths:r})).some(([,,,u])=>u!==1)?{nothingToCommit:!1,commitHash:await i.commit({fs:e,dir:t,message:o,author:T(a,n),cache:f})}:{nothingToCommit:!0}}async function J(t,s){if(Array.isArray(s)&&s.length>0){for(const n of s)await i.resetIndex({fs:e,dir:t,filepath:n});return{files:s}}const a=(await i.statusMatrix({fs:e,dir:t})).filter(([,,,n])=>n!==1).map(([n])=>n);for(const n of a)await i.resetIndex({fs:e,dir:t,filepath:n});return{files:"all"}}async function Q(t,s){const o=await i.statusMatrix({fs:e,dir:t}),a=Array.isArray(s)&&s.length>0?new Set(s):null,n=[],r=[],f=[];for(const[l,h,w,u]of o)a&&!a.has(l)||(h!==0?(u!==1||w!==1)&&n.push(l):h===0&&u!==0?r.push(l):h===0&&u===0&&w!==0&&f.push(l));if(n.length>0&&await I(t)){const l=await D(t);for(const h of n){const w=await B(t,l,h);if(!w)continue;const u=C.join(t,h);e.mkdirSync(C.dirname(u),{recursive:!0}),e.writeFileSync(u,w.buf),await i.add({fs:e,dir:t,filepath:h})}}for(const l of r){try{await i.remove({fs:e,dir:t,filepath:l})}catch{}const h=C.join(t,l);e.existsSync(h)&&await e.promises.unlink(h)}r.length>0&&await N(t,r);for(const l of f){const h=C.join(t,l);e.existsSync(h)&&await e.promises.unlink(h)}return f.length>0&&await N(t,f),{discardedCount:n.length+r.length+f.length,trackedFiles:n,newFiles:r,untrackedFiles:f}}async function X(t,s={}){const{maxCount:o=50,skip:a=0,branch:n,filePath:r}=s;if(!await I(t))return[];const f={fs:e,dir:t,depth:o+a};n&&(f.ref=n),r&&(f.filepath=r);try{return(await i.log(f)).slice(a,a+o).map(w=>({hash:w.oid,date:new Date(w.commit.author.timestamp*1e3).toISOString(),message:w.commit.message,author_name:w.commit.author.name,author_email:w.commit.author.email}))}catch(l){if(l?.code==="NotFoundError"||/NotFoundError|Could not find|unable to resolve|does not have any commits/i.test(String(l?.message||"")))return[];throw l}}async function Y(t,s={}){const{source:o="worktree",from:a,to:n,paths:r}=s,f=Array.isArray(r)&&r.length>0?new Set(r):null;let l="";const h=[];let w=0,u=0;async function d(g,p,S){const b=!!p,k=!!S;if(b&&k&&p.content===S.content)return;let c=!1;if(b&&M(p.buf)&&(c=!0),k&&!c&&M(S.buf)&&(c=!0),c){const H=b?W(p.buf).substring(0,7):"0000000",E=k?W(S.buf).substring(0,7):"0000000",F=[`diff --git a/${g} b/${g}`];b?k?F.push(`index ${H}..${E} 100644`):(F.push("deleted file mode 100644"),F.push(`index ${H}..0000000`)):(F.push("new file mode 100644"),F.push(`index 0000000..${E}`)),F.push(`Binary files ${b?`a/${g}`:"/dev/null"} and ${k?`b/${g}`:"/dev/null"} differ`),l+=F.join(`
6
+ `,insertions:d,deletions:g}}async function G(t,s){const{authorName:o,authorEmail:a,defaultBranch:n="main"}=s;await r.init({fs:e,dir:t,defaultBranch:n}),await r.setConfig({fs:e,dir:t,path:"user.name",value:o}),await r.setConfig({fs:e,dir:t,path:"user.email",value:a})}async function q(t){const s=await r.currentBranch({fs:e,dir:t,fullname:!1}),o=await r.statusMatrix({fs:e,dir:t}),a=[],n=[],c=[],i=[],f=[];for(const[u,w,h,d]of o)w!==d&&a.push(u),w===0&&d!==0&&c.push(u),(w===1&&d===0||h===0&&d!==0)&&i.push(u),d!==0&&h!==0&&h!==d&&n.push(u),w===0&&d===0&&h!==0&&f.push(u);return{current:s,staged:[...new Set(a)],modified:[...new Set(n)],created:[...new Set(c)],deleted:[...new Set(i)],untracked:[...new Set(f)],conflicted:[],ahead:0,behind:0,tracking:null}}async function R(t,s={}){const{cache:o}=s,a=[];return await r.walk({fs:e,dir:t,cache:o,trees:[r.WORKDIR()],map:async(n,[c])=>{if(!c)return null;if(n===".")return;const i=await c.type();if(i==="tree")return await r.isIgnored({fs:e,dir:t,filepath:n})?null:void 0;if(i!=="blob"||await r.isIgnored({fs:e,dir:t,filepath:n}))return null;a.push(n)}}),a}async function L(t,s={}){const{cache:o}=s,a=await R(t,{cache:o});return a.length>0&&await r.add({fs:e,dir:t,filepath:a,parallel:!0,cache:o,force:!0}),{hasChanges:a.length>0,toAdd:a,toRemove:[]}}async function O(t,s={}){const{cache:o}=s;if(!await T(t))return L(t,{cache:o});const a=await r.statusMatrix({fs:e,dir:t,cache:o}),n=[],c=[];for(const[f,u,w,h]of a)w===2&&h!==2&&n.push(f),u===1&&w===0&&h!==0&&c.push(f);n.length>0&&await r.add({fs:e,dir:t,filepath:n,parallel:!0,cache:o,force:!0});for(const f of c)await r.remove({fs:e,dir:t,filepath:f,cache:o});return{hasChanges:n.length>0||c.length>0||a.some(([,,,f])=>f!==1),toAdd:n,toRemove:c}}async function _(t,s,o={}){const{cache:a,force:n=!1}=o,c=[],i=[];for(const f of s){const u=A.join(t,f);e.existsSync(u)?c.push(f):i.push(f)}c.length>0&&await r.add({fs:e,dir:t,filepath:c,parallel:!0,cache:a,force:n});for(const f of i)await r.remove({fs:e,dir:t,filepath:f,cache:a})}async function K(t,s){const{message:o,authorName:a,authorEmail:n,cache:c}=s,{hasChanges:i}=await O(t,{cache:c});return i?{nothingToCommit:!1,commitHash:await r.commit({fs:e,dir:t,message:o,author:$(a,n),cache:c})}:{nothingToCommit:!0}}async function z(t,s){const{message:o,authorName:a,authorEmail:n,files:c,cache:i={}}=s;return await _(t,c,{cache:i,force:!0}),(await r.statusMatrix({fs:e,dir:t,cache:i,filepaths:c})).some(([,,,h])=>h!==1)?{nothingToCommit:!1,commitHash:await r.commit({fs:e,dir:t,message:o,author:$(a,n),cache:i})}:{nothingToCommit:!0}}async function J(t,s){if(Array.isArray(s)&&s.length>0){for(const n of s)await r.resetIndex({fs:e,dir:t,filepath:n});return{files:s}}const a=(await r.statusMatrix({fs:e,dir:t})).filter(([,,,n])=>n!==1).map(([n])=>n);for(const n of a)await r.resetIndex({fs:e,dir:t,filepath:n});return{files:"all"}}async function Q(t,s){const o=await r.statusMatrix({fs:e,dir:t}),a=Array.isArray(s)&&s.length>0?new Set(s):null,n=[],c=[],i=[];for(const[f,u,w,h]of o)a&&!a.has(f)||(u!==0?(h!==1||w!==1)&&n.push(f):u===0&&h!==0?c.push(f):u===0&&h===0&&w!==0&&i.push(f));if(n.length>0&&await T(t)){const f=await W(t);for(const u of n){const w=await N(t,f,u);if(!w)continue;const h=A.join(t,u);e.mkdirSync(A.dirname(h),{recursive:!0}),e.writeFileSync(h,w.buf),await r.add({fs:e,dir:t,filepath:u})}}for(const f of c){try{await r.remove({fs:e,dir:t,filepath:f})}catch{}const u=A.join(t,f);e.existsSync(u)&&await e.promises.unlink(u)}c.length>0&&await D(t,c);for(const f of i){const u=A.join(t,f);e.existsSync(u)&&await e.promises.unlink(u)}return i.length>0&&await D(t,i),{discardedCount:n.length+c.length+i.length,trackedFiles:n,newFiles:c,untrackedFiles:i}}async function X(t,s={}){const{maxCount:o=50,skip:a=0,branch:n,filePath:c}=s;if(!await T(t))return[];const i={fs:e,dir:t,depth:o+a};n&&(i.ref=n),c&&(i.filepath=c);try{return(await r.log(i)).slice(a,a+o).map(w=>({hash:w.oid,date:new Date(w.commit.author.timestamp*1e3).toISOString(),message:w.commit.message,author_name:w.commit.author.name,author_email:w.commit.author.email}))}catch(f){if(f?.code==="NotFoundError"||/NotFoundError|Could not find|unable to resolve|does not have any commits/i.test(String(f?.message||"")))return[];throw f}}async function Y(t,s={}){const{source:o="worktree",from:a,to:n,paths:c}=s,i=Array.isArray(c)&&c.length>0?new Set(c):null;let f="";const u=[];let w=0,h=0;async function d(g,p,S){const b=!!p,E=!!S;if(b&&E&&p.content===S.content)return;let l=!1;if(b&&M(p.buf)&&(l=!0),E&&!l&&M(S.buf)&&(l=!0),l){const k=b?B(p.buf).substring(0,7):"0000000",C=E?B(S.buf).substring(0,7):"0000000",F=[`diff --git a/${g} b/${g}`];b?E?F.push(`index ${k}..${C} 100644`):(F.push("deleted file mode 100644"),F.push(`index ${k}..0000000`)):(F.push("new file mode 100644"),F.push(`index 0000000..${C}`)),F.push(`Binary files ${b?`a/${g}`:"/dev/null"} and ${E?`b/${g}`:"/dev/null"} differ`),f+=F.join(`
7
7
  `)+`
8
- `,h.push({file:g,changes:0,insertions:0,deletions:0,binary:!0});return}const{diff:y,insertions:m,deletions:x}=G(g,b?p.content:"",k?S.content:"",b,k,b?p.buf:null,k?S.buf:null);l+=y,h.push({file:g,changes:m+x,insertions:m,deletions:x,binary:!1}),w+=m,u+=x}if(o==="commit"){let g,p;if(a&&n)g=a,p=n;else if(a){const c=await i.readCommit({fs:e,dir:t,oid:a});c.commit.parent&&c.commit.parent.length>0?(g=c.commit.parent[0],p=a):(g=null,p=a)}else{const c=new Error("source=commit requires at least 'from'");throw c.code="VALIDATION",c}const S=g?new Set(await i.listFiles({fs:e,dir:t,ref:g})):new Set,b=new Set(await i.listFiles({fs:e,dir:t,ref:p})),k=new Set([...S,...b]);for(const c of k){if(f&&!f.has(c))continue;const y=S.has(c)?await B(t,g,c):null,m=b.has(c)?await B(t,p,c):null;await d(c,y,m)}}else{if(!await I(t))return{diff:"",summary:{files:[],insertions:0,deletions:0}};const g=await D(t),p=await i.statusMatrix({fs:e,dir:t});for(const[S,b,k,c]of p){if(f&&!f.has(S))continue;if(o==="staged"){if(c===1||b===0&&c===0)continue}else if(b===0&&c===0||b===1&&k===1&&c===1)continue;const y=b!==0?await B(t,g,S):null;let m=null;if(k!==0){const x=C.join(t,S);if(e.existsSync(x))try{const H=e.readFileSync(x);m={content:H.toString("utf8"),buf:H}}catch{}}await d(S,y,m)}}return{diff:l,summary:{files:h,insertions:w,deletions:u}}}async function Z(t,s){const{ref:o,filePath:a}=s;if(o==="worktree"||o==="staged"||o===""){const n=C.join(t,a);return e.existsSync(n)?e.readFileSync(n,"utf8"):""}try{const n=await i.resolveRef({fs:e,dir:t,ref:o}),{blob:r}=await i.readBlob({fs:e,dir:t,oid:n,filepath:a});return Buffer.from(r).toString("utf8")}catch{return""}}async function tt(t,s){const{target:o,mode:a}=s;if(!await I(t)){const h=new Error("Cannot reset: repository has no commits yet");throw h.code="BUSINESS",h}const n=await i.log({fs:e,dir:t,depth:1}),r=n.length>0?n[0].oid:null,f=await i.currentBranch({fs:e,dir:t,fullname:!1});if(!f){const h=new Error("Cannot reset: detached HEAD");throw h.code="BUSINESS",h}const l=a==="hard"?new Set(await i.listFiles({fs:e,dir:t,ref:"HEAD"})):null;if(await i.writeRef({fs:e,dir:t,ref:`refs/heads/${f}`,value:o,force:!0}),a==="mixed"||a==="hard"){const h=await i.listFiles({fs:e,dir:t,ref:o}),w=new Set(h);for(const d of h)await i.resetIndex({fs:e,dir:t,filepath:d,ref:o});const u=await i.statusMatrix({fs:e,dir:t});for(const[d,,,g]of u)if(!w.has(d)&&g!==0)try{await i.remove({fs:e,dir:t,filepath:d})}catch{}}if(a==="hard"){const h=await i.listFiles({fs:e,dir:t,ref:o}),w=new Set(h);for(const u of h){const d=await B(t,o,u);if(!d)continue;const g=C.join(t,u);e.mkdirSync(C.dirname(g),{recursive:!0}),e.writeFileSync(g,d.buf)}if(l){for(const u of l)if(!w.has(u)){const d=C.join(t,u);e.existsSync(d)&&e.unlinkSync(d)}}}return{previousHead:r}}async function et(t,s){const{target:o,message:a,authorName:n,authorEmail:r,beforeCommit:f}=s;if(!await I(t)){const c=new Error("Cannot revert: repository has no commits yet");throw c.code="BUSINESS",c}let l;try{l=(await i.readCommit({fs:e,dir:t,oid:o})).oid}catch{const y=new Error("Revert target commit does not exist");throw y.code="VALIDATION",y.field="target",y.target=o,y}const h=await i.statusMatrix({fs:e,dir:t});if(h.some(([,c,y,m])=>c===0&&m===0?!1:y!==1||m!==1)){const c=h.filter(([,m])=>m!==0),y=new Error("Working directory is not clean, please commit or stash your changes before reverting");throw y.code="BUSINESS",y.staged=c.filter(([,,,m])=>m!==1).map(([m])=>m),y.modified=c.filter(([,,m])=>m!==1).map(([m])=>m),y}const u=new Set(await i.listFiles({fs:e,dir:t,ref:l})),d=await D(t),g=new Set(await i.listFiles({fs:e,dir:t,ref:d})),p=[];for(const c of u){const y=await B(t,l,c);if(!y)continue;const m=C.join(t,c);e.mkdirSync(C.dirname(m),{recursive:!0}),e.writeFileSync(m,y.buf),await i.add({fs:e,dir:t,filepath:c})}for(const c of g)if(!u.has(c)){p.push(c);try{await i.remove({fs:e,dir:t,filepath:c})}catch{}const y=C.join(t,c);e.existsSync(y)&&await e.promises.unlink(y)}return p.length>0&&await N(t,p),typeof f=="function"&&await f(),(await i.statusMatrix({fs:e,dir:t})).some(([,,,c])=>c!==1)?{nothingToCommit:!1,commitHash:await i.commit({fs:e,dir:t,message:a,author:T(n,r)}),targetOid:l,previousHead:d}:{nothingToCommit:!0,targetOid:l,previousHead:d}}async function nt(t,s){const o=await i.listFiles({fs:e,dir:t,ref:s});for(const a of o){const n=await B(t,s,a);if(!n)continue;const r=C.join(t,a);e.mkdirSync(C.dirname(r),{recursive:!0}),e.writeFileSync(r,n.buf),await i.add({fs:e,dir:t,filepath:a})}}async function at(t){return i.listTags({fs:e,dir:t})}async function st(t,s){const{tagName:o,message:a,authorName:n,authorEmail:r}=s;a?await i.annotatedTag({fs:e,dir:t,ref:o,message:a,tagger:T(n,r)}):await i.tag({fs:e,dir:t,ref:o})}async function ot(t,s){await i.deleteRef({fs:e,dir:t,ref:`refs/tags/${s}`})}async function it(t){const s=await i.listBranches({fs:e,dir:t}),o=await i.currentBranch({fs:e,dir:t,fullname:!1}),a={};for(const n of s)a[n]={name:n,current:n===o};return{branches:a,current:o}}async function rt(t,s){const{branchName:o,startPoint:a}=s;await i.branch({fs:e,dir:t,ref:o,object:a||"HEAD",checkout:!0})}async function ct(t,s){const o=await i.statusMatrix({fs:e,dir:t});if(o.some(([,n,r,f])=>n===0&&f===0?!1:r!==1||f!==1)){const n=o.filter(([,f])=>f!==0),r=new Error("Working directory is not clean, please commit or stash your changes before switching branches");throw r.code="BUSINESS",r.staged=n.filter(([,,,f])=>f!==1).map(([f])=>f),r.modified=n.filter(([,,f])=>f!==1).map(([f])=>f),r}await i.checkout({fs:e,dir:t,ref:s})}async function ft(t,s){const{branchName:o,force:a=!1}=s;if(await i.currentBranch({fs:e,dir:t,fullname:!1})===o){const r=new Error("Cannot delete the current branch, please switch to another branch first");throw r.code="BUSINESS",r}await i.deleteBranch({fs:e,dir:t,ref:o,force:a})}export{I as isoHasHead,V as isoInit,q as isoStatus,R as isoAddAll,U as isoStageFiles,K as isoCommitAll,z as isoCommitFiles,J as isoUnstage,Q as isoDiscard,X as isoLog,Y as isoDiff,Z as isoFileContent,tt as isoReset,et as isoRevertToTree,nt as isoCheckoutFiles,at as isoListTags,st as isoCreateTag,ot as isoDeleteTag,it as isoListBranches,rt as isoCreateBranch,ct as isoSwitchBranch,ft as isoDeleteBranch,_ as listWorkdirFilesSkippingIgnored,j as addAllFirstCommitWithIsomorphic};
8
+ `,u.push({file:g,changes:0,insertions:0,deletions:0,binary:!0});return}const{diff:y,insertions:m,deletions:x}=V(g,b?p.content:"",E?S.content:"",b,E,b?p.buf:null,E?S.buf:null);f+=y,u.push({file:g,changes:m+x,insertions:m,deletions:x,binary:!1}),w+=m,h+=x}if(o==="commit"){let g,p;if(a&&n)g=a,p=n;else if(a){const l=await r.readCommit({fs:e,dir:t,oid:a});l.commit.parent&&l.commit.parent.length>0?(g=l.commit.parent[0],p=a):(g=null,p=a)}else{const l=new Error("source=commit requires at least 'from'");throw l.code="VALIDATION",l}const S=g?new Set(await r.listFiles({fs:e,dir:t,ref:g})):new Set,b=new Set(await r.listFiles({fs:e,dir:t,ref:p})),E=new Set([...S,...b]);for(const l of E){if(i&&!i.has(l))continue;const y=S.has(l)?await N(t,g,l):null,m=b.has(l)?await N(t,p,l):null;await d(l,y,m)}}else{if(!await T(t))return{diff:"",summary:{files:[],insertions:0,deletions:0}};const g=await W(t),p=await r.statusMatrix({fs:e,dir:t});for(const[S,b,E,l]of p){if(i&&!i.has(S))continue;if(o==="staged"){if(l===1||b===0&&l===0)continue}else if(b===0&&l===0||b===1&&E===1&&l===1)continue;const y=b!==0?await N(t,g,S):null;let m=null;if(E!==0){const x=A.join(t,S);if(e.existsSync(x))try{const k=e.readFileSync(x);m={content:k.toString("utf8"),buf:k}}catch{}}await d(S,y,m)}}return{diff:f,summary:{files:u,insertions:w,deletions:h}}}async function Z(t,s){const{ref:o,filePath:a}=s,n=A.resolve(t),c=A.resolve(t,a||"");if(c!==n&&!c.startsWith(n+A.sep)){const i=new Error("filePath is outside the workspace");throw i.code="VALIDATION",i.field="filePath",i}if(o==="worktree"||o==="staged"||o===""){let i;try{i=e.lstatSync(c)}catch{return""}if(i.isSymbolicLink())try{return e.readlinkSync(c,"utf8")}catch(f){if(f.code==="ENOENT")return"";throw f}if(i.isDirectory()){const f=new Error("filePath is a directory, file-content only supports files");throw f.code="VALIDATION",f.field="filePath",f}try{return e.readFileSync(c,"utf8")}catch(f){if(f.code==="ENOENT")return"";if(f.code==="EISDIR"){const u=new Error("filePath is a directory, file-content only supports files");throw u.code="VALIDATION",u.field="filePath",u}throw f}}try{const i=await r.resolveRef({fs:e,dir:t,ref:o}),{blob:f}=await r.readBlob({fs:e,dir:t,oid:i,filepath:a});return Buffer.from(f).toString("utf8")}catch{return""}}async function tt(t,s){const{target:o,mode:a}=s;if(!await T(t)){const u=new Error("Cannot reset: repository has no commits yet");throw u.code="BUSINESS",u}const n=await r.log({fs:e,dir:t,depth:1}),c=n.length>0?n[0].oid:null,i=await r.currentBranch({fs:e,dir:t,fullname:!1});if(!i){const u=new Error("Cannot reset: detached HEAD");throw u.code="BUSINESS",u}const f=a==="hard"?new Set(await r.listFiles({fs:e,dir:t,ref:"HEAD"})):null;if(await r.writeRef({fs:e,dir:t,ref:`refs/heads/${i}`,value:o,force:!0}),a==="mixed"||a==="hard"){const u=await r.listFiles({fs:e,dir:t,ref:o}),w=new Set(u);for(const d of u)await r.resetIndex({fs:e,dir:t,filepath:d,ref:o});const h=await r.statusMatrix({fs:e,dir:t});for(const[d,,,g]of h)if(!w.has(d)&&g!==0)try{await r.remove({fs:e,dir:t,filepath:d})}catch{}}if(a==="hard"){const u=await r.listFiles({fs:e,dir:t,ref:o}),w=new Set(u);for(const h of u){const d=await N(t,o,h);if(!d)continue;const g=A.join(t,h);e.mkdirSync(A.dirname(g),{recursive:!0}),e.writeFileSync(g,d.buf)}if(f){for(const h of f)if(!w.has(h)){const d=A.join(t,h);e.existsSync(d)&&e.unlinkSync(d)}}}return{previousHead:c}}async function et(t,s){const{target:o,message:a,authorName:n,authorEmail:c,beforeCommit:i}=s;if(!await T(t)){const l=new Error("Cannot revert: repository has no commits yet");throw l.code="BUSINESS",l}let f;try{f=(await r.readCommit({fs:e,dir:t,oid:o})).oid}catch{const y=new Error("Revert target commit does not exist");throw y.code="VALIDATION",y.field="target",y.target=o,y}const u=await r.statusMatrix({fs:e,dir:t});if(u.some(([,l,y,m])=>l===0&&m===0?!1:y!==1||m!==1)){const l=u.filter(([,m])=>m!==0),y=new Error("Working directory is not clean, please commit or stash your changes before reverting");throw y.code="BUSINESS",y.staged=l.filter(([,,,m])=>m!==1).map(([m])=>m),y.modified=l.filter(([,,m])=>m!==1).map(([m])=>m),y}const h=new Set(await r.listFiles({fs:e,dir:t,ref:f})),d=await W(t),g=new Set(await r.listFiles({fs:e,dir:t,ref:d})),p=[];for(const l of h){const y=await N(t,f,l);if(!y)continue;const m=A.join(t,l);e.mkdirSync(A.dirname(m),{recursive:!0}),e.writeFileSync(m,y.buf),await r.add({fs:e,dir:t,filepath:l})}for(const l of g)if(!h.has(l)){p.push(l);try{await r.remove({fs:e,dir:t,filepath:l})}catch{}const y=A.join(t,l);e.existsSync(y)&&await e.promises.unlink(y)}return p.length>0&&await D(t,p),typeof i=="function"&&await i(),(await r.statusMatrix({fs:e,dir:t})).some(([,,,l])=>l!==1)?{nothingToCommit:!1,commitHash:await r.commit({fs:e,dir:t,message:a,author:$(n,c)}),targetOid:f,previousHead:d}:{nothingToCommit:!0,targetOid:f,previousHead:d}}async function nt(t,s){const o=await r.listFiles({fs:e,dir:t,ref:s});for(const a of o){const n=await N(t,s,a);if(!n)continue;const c=A.join(t,a);e.mkdirSync(A.dirname(c),{recursive:!0}),e.writeFileSync(c,n.buf),await r.add({fs:e,dir:t,filepath:a})}}async function at(t){return r.listTags({fs:e,dir:t})}async function st(t,s){const{tagName:o,message:a,authorName:n,authorEmail:c}=s;a?await r.annotatedTag({fs:e,dir:t,ref:o,message:a,tagger:$(n,c)}):await r.tag({fs:e,dir:t,ref:o})}async function ot(t,s){await r.deleteRef({fs:e,dir:t,ref:`refs/tags/${s}`})}async function it(t){const s=await r.listBranches({fs:e,dir:t}),o=await r.currentBranch({fs:e,dir:t,fullname:!1}),a={};for(const n of s)a[n]={name:n,current:n===o};return{branches:a,current:o}}async function rt(t,s){const{branchName:o,startPoint:a}=s;await r.branch({fs:e,dir:t,ref:o,object:a||"HEAD",checkout:!0})}async function ct(t,s){const o=await r.statusMatrix({fs:e,dir:t});if(o.some(([,n,c,i])=>n===0&&i===0?!1:c!==1||i!==1)){const n=o.filter(([,i])=>i!==0),c=new Error("Working directory is not clean, please commit or stash your changes before switching branches");throw c.code="BUSINESS",c.staged=n.filter(([,,,i])=>i!==1).map(([i])=>i),c.modified=n.filter(([,,i])=>i!==1).map(([i])=>i),c}await r.checkout({fs:e,dir:t,ref:s})}async function ft(t,s){const{branchName:o,force:a=!1}=s;if(await r.currentBranch({fs:e,dir:t,fullname:!1})===o){const c=new Error("Cannot delete the current branch, please switch to another branch first");throw c.code="BUSINESS",c}await r.deleteBranch({fs:e,dir:t,ref:o,force:a})}export{T as isoHasHead,G as isoInit,q as isoStatus,O as isoAddAll,_ as isoStageFiles,K as isoCommitAll,z as isoCommitFiles,J as isoUnstage,Q as isoDiscard,X as isoLog,Y as isoDiff,Z as isoFileContent,tt as isoReset,et as isoRevertToTree,nt as isoCheckoutFiles,at as isoListTags,st as isoCreateTag,ot as isoDeleteTag,it as isoListBranches,rt as isoCreateBranch,ct as isoSwitchBranch,ft as isoDeleteBranch,R as listWorkdirFilesSkippingIgnored,L as addAllFirstCommitWithIsomorphic};
@@ -1,7 +1,7 @@
1
- import tt from"cross-spawn";import v from"path";import y from"fs";import O from"../../appConfig/index.js";let U=null,G=0;const et=30*1e3,nt=10*60*1e3;function rt(){U=null,G=0}function j(){return O.GIT_USE_NATIVE!==!1}function ot(t){if(!t||typeof t!="object")return!1;const e=t;if(e.code==="ENOENT"||e.code==="NATIVE_GIT_UNAVAILABLE")return!0;const n=`${e.message||""} ${e.stderr||""}`;return/spawn\s+git(\.exe)?\s+ENOENT|git(\.exe)?:?\s*command not found|git(\.exe)?\s+not found|is not recognized as an internal or external command/i.test(n)}function q(){U=null,G=Date.now()+et}function f(t,e,n={}){const{allowFailure:r=!1,env:a={},timeoutMs:i=nt}=n;return new Promise((o,s)=>{const c=tt("git",["-c","core.quotePath=false",...e],{cwd:t,env:{...process.env,GIT_TERMINAL_PROMPT:"0",...a},windowsHide:!0});let u="",l="",w=!1,p=!1,h=null;const C=i>0?setTimeout(()=>{p=!0;try{c.kill("SIGTERM")}catch{}h=setTimeout(()=>{try{c.kill("SIGKILL")}catch{}},2e3)},i):null,m=d=>{w||(w=!0,C&&clearTimeout(C),h&&clearTimeout(h),d())};c.stdout?.on("data",d=>{u+=d.toString()}),c.stderr?.on("data",d=>{l+=d.toString()}),c.on("error",d=>{m(()=>{if(r){o({stdout:u,stderr:l||d.message,exitCode:1});return}s(d)})}),c.on("close",d=>{m(()=>{if(p){const x=new Error(`git ${e.join(" ")} timed out after ${i}ms`);if(x.code="ETIMEDOUT",x.exitCode=-1,x.stdout=u,x.stderr=l,r){o({stdout:u,stderr:l||x.message,exitCode:-1});return}s(x);return}const g=d??1;if(g!==0&&!r){const x=(l||u||"").trim()||`git ${e.join(" ")} failed`,T=new Error(x);T.exitCode=g,T.stdout=u,T.stderr=l,s(T);return}o({stdout:u,stderr:l,exitCode:g})})})})}function F(t,e){return{GIT_AUTHOR_NAME:t,GIT_AUTHOR_EMAIL:e,GIT_COMMITTER_NAME:t,GIT_COMMITTER_EMAIL:e}}async function V(){if(!j())return!1;if(U===!0)return!0;if(Date.now()<G)return!1;try{if((await f(process.cwd(),["--version"],{allowFailure:!0,timeoutMs:5e3})).exitCode===0)return U=!0,G=0,!0}catch{}return q(),!1}async function it(){return V()}async function A(t){return(await f(t,["rev-parse","--verify","HEAD"],{allowFailure:!0})).exitCode===0}async function I(t,e){const{stdout:n}=await f(t,["rev-parse",e]);return n.trim()}async function N(t,e){const{stdout:n}=await f(t,["ls-tree","-r","--name-only",e]);return n.split(`
2
- `).map(r=>r.trim()).filter(Boolean).map(r=>R(r))}async function at(t,e){const{authorName:n,authorEmail:r,defaultBranch:a="main"}=e;(await f(t,["init","-b",a],{allowFailure:!0})).exitCode!==0&&(await f(t,["init"]),await f(t,["symbolic-ref","HEAD",`refs/heads/${a}`],{allowFailure:!0})),await f(t,["config","user.name",n]),await f(t,["config","user.email",r])}async function D(t){const{stdout:e}=await f(t,["status","--porcelain=v1","-b"]),n=e.split(`
3
- `).filter(C=>C.length>0);let r=null,a=null,i=0,o=0;const s=[],c=[],u=[],l=[],w=[],p=[];for(const C of n){if(C.startsWith("## ")){const P=C.slice(3).trim(),$=P.match(/\s*\[([^\]]+)\]\s*$/),L=$?$[1]:null,E=$?P.slice(0,$.index).trim():P;if(E.startsWith("HEAD (")||E==="HEAD"||/^HEAD\b/i.test(E)&&E.includes("Detached"))r=null;else if(E.startsWith("No commits yet on "))r=E.slice(18).trim()||null;else{const S=E.indexOf("...");S>=0?(r=E.slice(0,S)||null,a=E.slice(S+3)||null):r=E||null}if(L){const S=L.match(/ahead\s+(\d+)/),W=L.match(/behind\s+(\d+)/);S&&(i=parseInt(S[1],10)),W&&(o=parseInt(W[1],10))}continue}const m=C.slice(0,2);let d=C.slice(3);d.includes(" -> ")&&(d=d.split(" -> ").pop()),d=R(d);const g=m[0],x=m[1];if(m==="??"){w.push(d);continue}if(m==="!!")continue;(g==="U"||x==="U"||m==="AA"||m==="DD")&&p.push(d),g!==" "&&g!=="?"&&(s.push(d),(g==="A"||g==="C")&&u.push(d),g==="D"&&l.push(d)),(x==="M"||x==="T")&&c.push(d),x==="D"&&l.push(d)}const h=await f(t,["branch","--show-current"],{allowFailure:!0});return h.exitCode===0&&(r=h.stdout.trim()||null),{current:r,staged:[...new Set(s)],modified:[...new Set(c)],created:[...new Set(u)],deleted:[...new Set(l)],untracked:[...new Set(w)],conflicted:[...new Set(p)],ahead:i,behind:o,tracking:a}}async function z(t){await f(t,["add","-A"]);const e=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(e.exitCode===0)return{hasChanges:!1,toAdd:[],toRemove:[]};if(e.exitCode===1)return{hasChanges:!0,toAdd:[],toRemove:[]};const n=(e.stderr||e.stdout||"").trim()||`git diff --cached --quiet failed (exit ${e.exitCode})`,r=new Error(n);throw r.exitCode=e.exitCode,r.stderr=e.stderr,r.stdout=e.stdout,r}async function K(t,e,n={}){const{force:r=!1}=n;if(!Array.isArray(e)||e.length===0)return;const a=[],i=[];for(const s of e)y.existsSync(v.join(t,s))?a.push(s):i.push(s);await st(t,r?["add","-A","-f"]:["add","-A"],a);for(const s of i){const c=await f(t,["rm","--cached","-f","--ignore-unmatch","--",_(s)],{allowFailure:!0});if(c.exitCode!==0&&!X(c)){const u=(c.stderr||c.stdout||"").trim()||`git rm --cached failed for ${s}`,l=new Error(u);throw l.exitCode=c.exitCode,l}}}function X(t){const e=`${t.stderr||""} ${t.stdout||""}`;return/did not match any file|pathspec.*did not match|No such file|exists on disk, but not in the index/i.test(e)}async function st(t,e,n){if(!n||n.length===0)return;const r=200;for(let a=0;a<n.length;a+=r){const i=n.slice(a,a+r);try{await f(t,[...e,"--",...b(i)])}catch{for(const s of i){const c=await f(t,[...e,"--",_(s)],{allowFailure:!0});if(c.exitCode===0||X(c))continue;const u=(c.stderr||c.stdout||"").trim()||`git ${e.join(" ")} failed for ${s}`,l=new Error(u);throw l.exitCode=c.exitCode,l}}}}async function ct(t,e){const{message:n,authorName:r,authorEmail:a}=e,i=F(r,a),{hasChanges:o}=await z(t);if(!o)return{nothingToCommit:!0};await f(t,["commit","-m",n],{env:i});const{stdout:s}=await f(t,["rev-parse","HEAD"]),c=s.trim();if(!c)throw new Error("Native git commit succeeded but HEAD is empty");return{nothingToCommit:!1,commitHash:c}}async function Y(t,e){const{message:n,authorName:r,authorEmail:a}=e,i=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(i.exitCode===0)return{nothingToCommit:!0};if(i.exitCode!==1){const s=(i.stderr||i.stdout||"").trim()||`git diff --cached --quiet failed (exit ${i.exitCode})`,c=new Error(s);throw c.exitCode=i.exitCode,c}await f(t,["commit","-m",n],{env:F(r,a)});const{stdout:o}=await f(t,["rev-parse","HEAD"]);return{nothingToCommit:!1,commitHash:o.trim()}}async function J(t,e){if(!Array.isArray(e)||e.length===0){const n=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(n.exitCode===0)return!1;if(n.exitCode===1)return!0;const r=(n.stderr||n.stdout||"").trim()||`git diff --cached --quiet failed (exit ${n.exitCode})`,a=new Error(r);throw a.exitCode=n.exitCode,a}for(let n=0;n<e.length;n+=200){const r=b(e.slice(n,n+200)),a=await f(t,["diff","--cached","--quiet","--",...r],{allowFailure:!0});if(a.exitCode===1)return!0;if(a.exitCode!==0){const i=(a.stderr||a.stdout||"").trim()||`git diff --cached --quiet failed (exit ${a.exitCode})`,o=new Error(i);throw o.exitCode=a.exitCode,o}}return!1}async function lt(t,e){const{message:n,files:r,authorName:a,authorEmail:i,force:o=!0}=e;return await K(t,r,{force:o}),await J(t,r)?Y(t,{message:n,authorName:a,authorEmail:i}):{nothingToCommit:!0}}function k(t){const e=`${t.stderr||""} ${t.stdout||""}`;return/did not match any file|pathspec.*did not match|unstaged changes after reset|No changes|ambiguous argument 'HEAD'/i.test(e)}async function M(t,e,n,r={},a=200){if(!(!n||n.length===0))for(let i=0;i<n.length;i+=a){const o=b(n.slice(i,i+a));await f(t,[...e,"--",...o],r)}}function _(t){let e=String(t||"").replace(/\\/g,"/");return e.startsWith(":(")||e.startsWith(":!")||e.startsWith(":^")?e:`:(literal)${e}`}function b(t){return(t||[]).map(_)}function R(t){const e=String(t||"");if(e.length<2||e[0]!=='"'||e[e.length-1]!=='"')return e;const n=e.slice(1,-1);let r="",a=null;const i=()=>{if(a&&a.length){const o=Buffer.from(a),s=o.toString("utf8");r+=s.includes("\uFFFD")?o.toString("latin1"):s}a=null};for(let o=0;o<n.length;o++){const s=n[o];if(s!=="\\"){i(),r+=s;continue}if(o+=1,o>=n.length)break;const c=n[o];switch(c){case"\\":i(),r+="\\";break;case'"':i(),r+='"';break;case"a":i(),r+="\x07";break;case"b":i(),r+="\b";break;case"t":i(),r+=" ";break;case"n":i(),r+=`
4
- `;break;case"v":i(),r+="\v";break;case"f":i(),r+="\f";break;case"r":i(),r+="\r";break;default:if(c>="0"&&c<="7"){let u=c;o+1<n.length&&n[o+1]>="0"&&n[o+1]<="7"&&(u+=n[++o],o+1<n.length&&n[o+1]>="0"&&n[o+1]<="7"&&(u+=n[++o])),(a??=[]).push(parseInt(u,8)&255)}else i(),r+=c;break}}return i(),r}function Q(t){let e=String(t||"").replace(/\\/g,"/");return e.length>1&&e.endsWith("/")&&(e=e.replace(/\/+$/,"")),e}function Z(t,e){const n=[...e].map(Q).filter(Boolean),r=(t||[]).map(Q).filter(Boolean),a=new Set(r),i=new Set;for(const o of n){a.has(o)&&i.add(o);let s=v.posix.dirname(o);for(;s&&s!==".";){a.has(s)&&i.add(s);const c=v.posix.dirname(s);if(c===s)break;s=c}}for(const o of r)for(const s of n)if(s===o||s.startsWith(`${o}/`)){i.add(o);break}return[...i]}async function H(t,e,n){let r=n;if(r||(r=(await D(t)).untracked),!r||r.length===0)return;const a=Z(r,e);for(const i of a){const o=v.join(t,i);y.existsSync(o)&&await y.promises.rm(o,{recursive:!0,force:!0})}a.length>0&&await B(t,a)}async function ut(t,e){const n=await A(t);if(Array.isArray(e)&&e.length>0){if(n){let u=null;try{for(let h=0;h<e.length;h+=200){const C=b(e.slice(h,h+200)),m=await f(t,["restore","--staged","--",...C],{allowFailure:!0});if(m.exitCode!==0&&!k(m)){u=m;break}}}catch(h){u={stderr:h.message,stdout:"",exitCode:1}}if(!u)return;let l=null;for(let h=0;h<e.length;h+=200){const C=b(e.slice(h,h+200)),m=await f(t,["reset","HEAD","--",...C],{allowFailure:!0});if(m.exitCode!==0&&!k(m)){l=m;break}}if(!l)return;const w=(l.stderr||l.stdout||u.stderr||u.stdout||"").trim()||"git unstage failed",p=new Error(w);throw p.exitCode=l.exitCode||u.exitCode,p}let o=null;for(let u=0;u<e.length;u+=200){const l=b(e.slice(u,u+200)),w=await f(t,["rm","--cached","-f","--",...l],{allowFailure:!0});if(w.exitCode!==0&&!k(w)){o=w;break}}if(!o)return;const s=(o.stderr||o.stdout||"").trim()||"git unstage (rm --cached) failed",c=new Error(s);throw c.exitCode=o.exitCode,c}if(n){const o=await f(t,["restore","--staged","."],{allowFailure:!0});if(o.exitCode===0||k(o))return;const s=await f(t,["reset","HEAD"],{allowFailure:!0});if(s.exitCode===0||k(s))return;const c=(s.stderr||s.stdout||o.stderr||o.stdout||"").trim()||"git unstage all failed",u=new Error(c);throw u.exitCode=s.exitCode||o.exitCode,u}const r=await f(t,["reset"],{allowFailure:!0});if(r.exitCode===0||k(r))return;const a=(r.stderr||r.stdout||"").trim()||"git unstage all failed",i=new Error(a);throw i.exitCode=r.exitCode,i}async function B(t,e){const n=new Set;for(const a of e){let i=v.dirname(a);for(;i&&i!==".";)n.add(i),i=v.dirname(i)}const r=[...n].sort((a,i)=>{const o=a.split(/[/\\]/).length;return i.split(/[/\\]/).length-o});for(const a of r){const i=v.join(t,a);try{(await y.promises.readdir(i)).length===0&&await y.promises.rmdir(i)}catch{}}}async function ft(t,e){const n=await D(t),r=Array.isArray(e)&&e.length>0?new Set(e):null,a=[],i=[],o=[],s=new Set([...n.staged,...n.modified,...n.deleted]);for(const l of n.created)s.delete(l);for(const l of s)r&&!r.has(l)||a.push(l);const c=new Set(a);for(const l of n.created)r&&!r.has(l)||c.has(l)||i.push(l);for(const l of n.untracked)r&&!r.has(l)||c.has(l)||o.push(l);const u=await A(t);if(a.length>0&&u&&(await H(t,a,n.untracked),await M(t,["restore","--source=HEAD","--staged","--worktree"],a)),i.length>0){await M(t,["rm","-f","--cached"],i,{allowFailure:!0});for(const l of i){const w=v.join(t,l);y.existsSync(w)&&await y.promises.unlink(w)}await B(t,i)}for(const l of o){const w=v.join(t,l);y.existsSync(w)&&(y.statSync(w).isDirectory()?await y.promises.rm(w,{recursive:!0,force:!0}):await y.promises.unlink(w))}return o.length>0&&await B(t,o),{discardedCount:a.length+i.length+o.length,trackedFiles:a,newFiles:i,untrackedFiles:o}}function dt(t){return/unknown revision|bad revision|invalid object name|ambiguous argument|does not have any commits|Needed a single revision|not a valid object name|unknown revision or path not in the working tree/i.test(t)}async function ht(t,e={}){const{maxCount:n=50,skip:r=0,branch:a,filePath:i}=e;if(!await A(t))return[];const o=["log",`--skip=${r}`,"-n",String(n),"--format=%H%x00%aI%x00%B%x00%an%x00%ae%x1e"];a&&o.push(a),i&&o.push("--",_(i));const s=await f(t,o,{allowFailure:!0});if(s.exitCode!==0){const u=(s.stderr||s.stdout||"").trim();if(dt(u))return[];const l=new Error(u||`git log failed (exit ${s.exitCode})`);throw l.exitCode=s.exitCode,l.stderr=s.stderr,l.stdout=s.stdout,l}return s.stdout.split("").filter(u=>u.trim()).map(u=>{const l=u.replace(/^\n/,"").split("\0"),[w,p,h,C,m]=l;let d="";if(p){const g=new Date(p);d=Number.isNaN(g.getTime())?p:g.toISOString()}return{hash:(w||"").trim(),date:d,message:(h||"").replace(/\n$/,""),author_name:C||"",author_email:m||""}}).filter(u=>u.hash)}function mt(t){const e=[];for(const n of t.split(`
5
- `)){if(!n.trim())continue;const r=n.split(" ");if(r.length<3)continue;const[a,i,o]=r,s=a==="-"||i==="-",c=s?0:parseInt(a,10)||0,u=s?0:parseInt(i,10)||0;e.push({file:R(o),changes:c+u,insertions:c,deletions:u,binary:s})}return e}async function wt(t,e={}){const{source:n="worktree",from:r,to:a,paths:i}=e,o=Array.isArray(i)&&i.length>0?["--",...b(i)]:[];if(n!=="commit"&&!await A(t))return{diff:"",summary:{files:[],insertions:0,deletions:0}};let s,c;if(n==="commit")if(r&&a)s=["diff",r,a,...o],c=["diff","--numstat",r,a,...o];else if(r){const d=((await f(t,["rev-list","--parents","-n","1",r],{allowFailure:!0})).stdout||"").trim().split(/\s+/).filter(Boolean);if(d.length<=1){const g=await f(t,["hash-object","-t","tree","/dev/null"],{allowFailure:!0});s=["show","--format=","--patch",r,...o],c=["show","--format=","--numstat",r,...o]}else{const g=d[1];s=["diff",g,r,...o],c=["diff","--numstat",g,r,...o]}}else{const m=new Error("source=commit requires at least 'from'");throw m.code="VALIDATION",m}else n==="staged"?(s=["diff","--cached",...o],c=["diff","--cached","--numstat",...o]):(s=["diff","HEAD",...o],c=["diff","HEAD","--numstat",...o]);const[u,l]=await Promise.all([f(t,s,{allowFailure:!0}),f(t,c,{allowFailure:!0})]),w=u.exitCode===0||u.exitCode===1?u.stdout:"";if(u.exitCode>1&&!w)throw new Error((u.stderr||u.stdout||"git diff failed").trim());const p=l.exitCode===0||l.exitCode===1?mt(l.stdout):[];let h=0,C=0;for(const m of p)h+=m.insertions,C+=m.deletions;return{diff:w,summary:{files:p,insertions:h,deletions:C}}}async function gt(t,e){const{ref:n,filePath:r}=e;if(n==="worktree"||n==="staged"||n===""){const i=v.join(t,r);return y.existsSync(i)?y.readFileSync(i,"utf8"):""}const a=await f(t,["show",`${n}:${r}`],{allowFailure:!0});return a.exitCode!==0?"":a.stdout}async function pt(t,e){const{target:n,mode:r}=e;if(!await A(t)){const s=new Error("Cannot reset: repository has no commits yet");throw s.code="BUSINESS",s}const a=await f(t,["branch","--show-current"],{allowFailure:!0});if(!(a.exitCode===0?a.stdout.trim():"")){const s=new Error("Cannot reset: detached HEAD");throw s.code="BUSINESS",s}const o=await I(t,"HEAD");if(r==="hard"){let s=[];try{s=await N(t,n)}catch{s=[]}s.length>0&&await H(t,s)}return await f(t,["reset",`--${r}`,n]),{previousHead:o}}async function Ct(t,e){const{target:n,message:r,authorName:a,authorEmail:i,beforeCommit:o}=e;if(!await A(t)){const d=new Error("Cannot revert: repository has no commits yet");throw d.code="BUSINESS",d}let s;try{s=await I(t,n)}catch{const g=new Error("Revert target commit does not exist");throw g.code="VALIDATION",g.field="target",g.target=n,g}const c=await D(t);if(c.staged.length>0||c.modified.length>0||c.deleted.length>0||c.created.length>0||c.conflicted.length>0){const d=new Error("Working directory is not clean, please commit or stash your changes before reverting");throw d.code="BUSINESS",d.staged=c.staged,d.modified=c.modified,d}const l=await I(t,"HEAD"),w=new Set(await N(t,l)),p=new Set(await N(t,s));p.size>0&&(await H(t,p,c.untracked),await f(t,["restore",`--source=${s}`,"--worktree","--staged","."]));const h=[...w].filter(d=>!p.has(d));return h.length>0&&(await M(t,["rm","-f"],h),await B(t,h)),typeof o=="function"&&await o(),(await f(t,["diff","--cached","--quiet"],{allowFailure:!0})).exitCode===0?{nothingToCommit:!0,targetOid:s,previousHead:l}:(await f(t,["commit","-m",r],{env:F(a,i)}),{nothingToCommit:!1,commitHash:await I(t,"HEAD"),targetOid:s,previousHead:l})}async function xt(t,e){const n=await N(t,e);n.length!==0&&(await H(t,n),await M(t,["restore",`--source=${e}`,"--worktree","--staged"],n))}async function yt(t){const{stdout:e}=await f(t,["tag","--list"]);return e.split(`
6
- `).map(n=>n.trim()).filter(Boolean)}async function Et(t,e){const{tagName:n,message:r,authorName:a,authorEmail:i}=e;r?await f(t,["tag","-a",n,"-m",r],{env:F(a||O.GIT_DEFAULT_AUTHOR_NAME,i||O.GIT_DEFAULT_AUTHOR_EMAIL)}):await f(t,["tag",n])}async function vt(t,e){await f(t,["tag","-d",e])}async function bt(t){const{stdout:e}=await f(t,["branch","--format=%(refname:short)"]),n=e.split(`
7
- `).map(o=>o.trim()).filter(Boolean),r=await f(t,["branch","--show-current"],{allowFailure:!0}),a=r.exitCode===0&&r.stdout.trim()?r.stdout.trim():null,i={};for(const o of n)i[o]={name:o,current:o===a};return{branches:i,current:a}}async function At(t,e){const{branchName:n,startPoint:r}=e;r?await f(t,["checkout","-b",n,r]):await f(t,["checkout","-b",n])}async function St(t,e){const n=await D(t);if(n.staged.length>0||n.modified.length>0||n.deleted.length>0||n.created.length>0||n.conflicted.length>0){const a=new Error("Working directory is not clean, please commit or stash your changes before switching branches");throw a.code="BUSINESS",a.staged=n.staged,a.modified=n.modified,a}await f(t,["checkout",e])}async function kt(t,e){const{branchName:n,force:r=!1}=e;if((await f(t,["branch","--show-current"],{allowFailure:!0})).stdout.trim()===n){const i=new Error("Cannot delete the current branch, please switch to another branch first");throw i.code="BUSINESS",i}await f(t,["branch",r?"-D":"-d",n])}export{j as isNativeGitEnabled,V as isNativeGitAvailable,it as shouldUseNativeGit,ot as isNativeGitUnavailableError,q as markNativeGitMissing,f as runGit,F as buildAuthorEnv,A as nativeHasHead,I as nativeResolveOid,N as nativeListFiles,at as nativeInit,D as nativeStatus,z as nativeAddAll,K as nativeStageFiles,ct as nativeAddAllAndCommit,Y as nativeCommitStaged,lt as nativeCommitFiles,J as nativeHasStagedChangesForPaths,_ as toLiteralPathspec,b as toLiteralPathspecs,ut as nativeUnstage,ft as nativeDiscard,ht as nativeLog,wt as nativeDiff,gt as nativeFileContent,pt as nativeReset,Ct as nativeRevertToTree,xt as nativeCheckoutFiles,yt as nativeListTags,Et as nativeCreateTag,vt as nativeDeleteTag,bt as nativeListBranches,At as nativeCreateBranch,St as nativeSwitchBranch,kt as nativeDeleteBranch,rt as resetNativeGitAvailabilityCache,B as cleanEmptyParentDirs,Z as collectUntrackedRestoreBlockers,H as removeUntrackedBlockingRestore,R as decodeGitPorcelainPath};
1
+ import tt from"cross-spawn";import E from"path";import y from"fs";import O from"../../appConfig/index.js";let $=null,R=0;const et=30*1e3,nt=10*60*1e3;function rt(){$=null,R=0}function q(){return O.GIT_USE_NATIVE!==!1}function ot(t){if(!t||typeof t!="object")return!1;const e=t;if(e.code==="ENOENT"||e.code==="NATIVE_GIT_UNAVAILABLE")return!0;const n=`${e.message||""} ${e.stderr||""}`;return/spawn\s+git(\.exe)?\s+ENOENT|git(\.exe)?:?\s*command not found|git(\.exe)?\s+not found|is not recognized as an internal or external command/i.test(n)}function V(){$=null,R=Date.now()+et}function f(t,e,n={}){const{allowFailure:r=!1,env:a={},timeoutMs:i=nt}=n;return new Promise((o,s)=>{const c=tt("git",["-c","core.quotePath=false",...e],{cwd:t,env:{...process.env,GIT_TERMINAL_PROMPT:"0",...a},windowsHide:!0});let l="",u="",w=!1,p=!1,h=null;const C=i>0?setTimeout(()=>{p=!0;try{c.kill("SIGTERM")}catch{}h=setTimeout(()=>{try{c.kill("SIGKILL")}catch{}},2e3)},i):null,m=d=>{w||(w=!0,C&&clearTimeout(C),h&&clearTimeout(h),d())};c.stdout?.on("data",d=>{l+=d.toString()}),c.stderr?.on("data",d=>{u+=d.toString()}),c.on("error",d=>{m(()=>{if(r){o({stdout:l,stderr:u||d.message,exitCode:1});return}s(d)})}),c.on("close",d=>{m(()=>{if(p){const x=new Error(`git ${e.join(" ")} timed out after ${i}ms`);if(x.code="ETIMEDOUT",x.exitCode=-1,x.stdout=l,x.stderr=u,r){o({stdout:l,stderr:u||x.message,exitCode:-1});return}s(x);return}const g=d??1;if(g!==0&&!r){const x=(u||l||"").trim()||`git ${e.join(" ")} failed`,T=new Error(x);T.exitCode=g,T.stdout=l,T.stderr=u,s(T);return}o({stdout:l,stderr:u,exitCode:g})})})})}function I(t,e){return{GIT_AUTHOR_NAME:t,GIT_AUTHOR_EMAIL:e,GIT_COMMITTER_NAME:t,GIT_COMMITTER_EMAIL:e}}async function j(){if(!q())return!1;if($===!0)return!0;if(Date.now()<R)return!1;try{if((await f(process.cwd(),["--version"],{allowFailure:!0,timeoutMs:5e3})).exitCode===0)return $=!0,R=0,!0}catch{}return V(),!1}async function it(){return j()}async function A(t){return(await f(t,["rev-parse","--verify","HEAD"],{allowFailure:!0})).exitCode===0}async function N(t,e){const{stdout:n}=await f(t,["rev-parse",e]);return n.trim()}async function F(t,e){const{stdout:n}=await f(t,["ls-tree","-r","--name-only",e]);return n.split(`
2
+ `).map(r=>r.trim()).filter(Boolean).map(r=>G(r))}async function at(t,e){const{authorName:n,authorEmail:r,defaultBranch:a="main"}=e;(await f(t,["init","-b",a],{allowFailure:!0})).exitCode!==0&&(await f(t,["init"]),await f(t,["symbolic-ref","HEAD",`refs/heads/${a}`],{allowFailure:!0})),await f(t,["config","user.name",n]),await f(t,["config","user.email",r])}async function D(t){const{stdout:e}=await f(t,["status","--porcelain=v1","-b"]),n=e.split(`
3
+ `).filter(C=>C.length>0);let r=null,a=null,i=0,o=0;const s=[],c=[],l=[],u=[],w=[],p=[];for(const C of n){if(C.startsWith("## ")){const M=C.slice(3).trim(),B=M.match(/\s*\[([^\]]+)\]\s*$/),L=B?B[1]:null,v=B?M.slice(0,B.index).trim():M;if(v.startsWith("HEAD (")||v==="HEAD"||/^HEAD\b/i.test(v)&&v.includes("Detached"))r=null;else if(v.startsWith("No commits yet on "))r=v.slice(18).trim()||null;else{const S=v.indexOf("...");S>=0?(r=v.slice(0,S)||null,a=v.slice(S+3)||null):r=v||null}if(L){const S=L.match(/ahead\s+(\d+)/),W=L.match(/behind\s+(\d+)/);S&&(i=parseInt(S[1],10)),W&&(o=parseInt(W[1],10))}continue}const m=C.slice(0,2);let d=C.slice(3);d.includes(" -> ")&&(d=d.split(" -> ").pop()),d=G(d);const g=m[0],x=m[1];if(m==="??"){w.push(d);continue}if(m==="!!")continue;(g==="U"||x==="U"||m==="AA"||m==="DD")&&p.push(d),g!==" "&&g!=="?"&&(s.push(d),(g==="A"||g==="C")&&l.push(d),g==="D"&&u.push(d)),(x==="M"||x==="T")&&c.push(d),x==="D"&&u.push(d)}const h=await f(t,["branch","--show-current"],{allowFailure:!0});return h.exitCode===0&&(r=h.stdout.trim()||null),{current:r,staged:[...new Set(s)],modified:[...new Set(c)],created:[...new Set(l)],deleted:[...new Set(u)],untracked:[...new Set(w)],conflicted:[...new Set(p)],ahead:i,behind:o,tracking:a}}async function z(t){await f(t,["add","-A"]);const e=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(e.exitCode===0)return{hasChanges:!1,toAdd:[],toRemove:[]};if(e.exitCode===1)return{hasChanges:!0,toAdd:[],toRemove:[]};const n=(e.stderr||e.stdout||"").trim()||`git diff --cached --quiet failed (exit ${e.exitCode})`,r=new Error(n);throw r.exitCode=e.exitCode,r.stderr=e.stderr,r.stdout=e.stdout,r}async function K(t,e,n={}){const{force:r=!1}=n;if(!Array.isArray(e)||e.length===0)return;const a=[],i=[];for(const s of e)y.existsSync(E.join(t,s))?a.push(s):i.push(s);await st(t,r?["add","-A","-f"]:["add","-A"],a);for(const s of i){const c=await f(t,["rm","--cached","-f","--ignore-unmatch","--",_(s)],{allowFailure:!0});if(c.exitCode!==0&&!X(c)){const l=(c.stderr||c.stdout||"").trim()||`git rm --cached failed for ${s}`,u=new Error(l);throw u.exitCode=c.exitCode,u}}}function X(t){const e=`${t.stderr||""} ${t.stdout||""}`;return/did not match any file|pathspec.*did not match|No such file|exists on disk, but not in the index/i.test(e)}async function st(t,e,n){if(!n||n.length===0)return;const r=200;for(let a=0;a<n.length;a+=r){const i=n.slice(a,a+r);try{await f(t,[...e,"--",...b(i)])}catch{for(const s of i){const c=await f(t,[...e,"--",_(s)],{allowFailure:!0});if(c.exitCode===0||X(c))continue;const l=(c.stderr||c.stdout||"").trim()||`git ${e.join(" ")} failed for ${s}`,u=new Error(l);throw u.exitCode=c.exitCode,u}}}}async function ct(t,e){const{message:n,authorName:r,authorEmail:a}=e,i=I(r,a),{hasChanges:o}=await z(t);if(!o)return{nothingToCommit:!0};await f(t,["commit","-m",n],{env:i});const{stdout:s}=await f(t,["rev-parse","HEAD"]),c=s.trim();if(!c)throw new Error("Native git commit succeeded but HEAD is empty");return{nothingToCommit:!1,commitHash:c}}async function Y(t,e){const{message:n,authorName:r,authorEmail:a}=e,i=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(i.exitCode===0)return{nothingToCommit:!0};if(i.exitCode!==1){const s=(i.stderr||i.stdout||"").trim()||`git diff --cached --quiet failed (exit ${i.exitCode})`,c=new Error(s);throw c.exitCode=i.exitCode,c}await f(t,["commit","-m",n],{env:I(r,a)});const{stdout:o}=await f(t,["rev-parse","HEAD"]);return{nothingToCommit:!1,commitHash:o.trim()}}async function J(t,e){if(!Array.isArray(e)||e.length===0){const n=await f(t,["diff","--cached","--quiet"],{allowFailure:!0});if(n.exitCode===0)return!1;if(n.exitCode===1)return!0;const r=(n.stderr||n.stdout||"").trim()||`git diff --cached --quiet failed (exit ${n.exitCode})`,a=new Error(r);throw a.exitCode=n.exitCode,a}for(let n=0;n<e.length;n+=200){const r=b(e.slice(n,n+200)),a=await f(t,["diff","--cached","--quiet","--",...r],{allowFailure:!0});if(a.exitCode===1)return!0;if(a.exitCode!==0){const i=(a.stderr||a.stdout||"").trim()||`git diff --cached --quiet failed (exit ${a.exitCode})`,o=new Error(i);throw o.exitCode=a.exitCode,o}}return!1}async function lt(t,e){const{message:n,files:r,authorName:a,authorEmail:i,force:o=!0}=e;return await K(t,r,{force:o}),await J(t,r)?Y(t,{message:n,authorName:a,authorEmail:i}):{nothingToCommit:!0}}function k(t){const e=`${t.stderr||""} ${t.stdout||""}`;return/did not match any file|pathspec.*did not match|unstaged changes after reset|No changes|ambiguous argument 'HEAD'/i.test(e)}async function U(t,e,n,r={},a=200){if(!(!n||n.length===0))for(let i=0;i<n.length;i+=a){const o=b(n.slice(i,i+a));await f(t,[...e,"--",...o],r)}}function _(t){let e=String(t||"").replace(/\\/g,"/");return e.startsWith(":(")||e.startsWith(":!")||e.startsWith(":^")?e:`:(literal)${e}`}function b(t){return(t||[]).map(_)}function G(t){const e=String(t||"");if(e.length<2||e[0]!=='"'||e[e.length-1]!=='"')return e;const n=e.slice(1,-1);let r="",a=null;const i=()=>{if(a&&a.length){const o=Buffer.from(a),s=o.toString("utf8");r+=s.includes("\uFFFD")?o.toString("latin1"):s}a=null};for(let o=0;o<n.length;o++){const s=n[o];if(s!=="\\"){i(),r+=s;continue}if(o+=1,o>=n.length)break;const c=n[o];switch(c){case"\\":i(),r+="\\";break;case'"':i(),r+='"';break;case"a":i(),r+="\x07";break;case"b":i(),r+="\b";break;case"t":i(),r+=" ";break;case"n":i(),r+=`
4
+ `;break;case"v":i(),r+="\v";break;case"f":i(),r+="\f";break;case"r":i(),r+="\r";break;default:if(c>="0"&&c<="7"){let l=c;o+1<n.length&&n[o+1]>="0"&&n[o+1]<="7"&&(l+=n[++o],o+1<n.length&&n[o+1]>="0"&&n[o+1]<="7"&&(l+=n[++o])),(a??=[]).push(parseInt(l,8)&255)}else i(),r+=c;break}}return i(),r}function Q(t){let e=String(t||"").replace(/\\/g,"/");return e.length>1&&e.endsWith("/")&&(e=e.replace(/\/+$/,"")),e}function Z(t,e){const n=[...e].map(Q).filter(Boolean),r=(t||[]).map(Q).filter(Boolean),a=new Set(r),i=new Set;for(const o of n){a.has(o)&&i.add(o);let s=E.posix.dirname(o);for(;s&&s!==".";){a.has(s)&&i.add(s);const c=E.posix.dirname(s);if(c===s)break;s=c}}for(const o of r)for(const s of n)if(s===o||s.startsWith(`${o}/`)){i.add(o);break}return[...i]}async function H(t,e,n){let r=n;if(r||(r=(await D(t)).untracked),!r||r.length===0)return;const a=Z(r,e);for(const i of a){const o=E.join(t,i);y.existsSync(o)&&await y.promises.rm(o,{recursive:!0,force:!0})}a.length>0&&await P(t,a)}async function ut(t,e){const n=await A(t);if(Array.isArray(e)&&e.length>0){if(n){let l=null;try{for(let h=0;h<e.length;h+=200){const C=b(e.slice(h,h+200)),m=await f(t,["restore","--staged","--",...C],{allowFailure:!0});if(m.exitCode!==0&&!k(m)){l=m;break}}}catch(h){l={stderr:h.message,stdout:"",exitCode:1}}if(!l)return;let u=null;for(let h=0;h<e.length;h+=200){const C=b(e.slice(h,h+200)),m=await f(t,["reset","HEAD","--",...C],{allowFailure:!0});if(m.exitCode!==0&&!k(m)){u=m;break}}if(!u)return;const w=(u.stderr||u.stdout||l.stderr||l.stdout||"").trim()||"git unstage failed",p=new Error(w);throw p.exitCode=u.exitCode||l.exitCode,p}let o=null;for(let l=0;l<e.length;l+=200){const u=b(e.slice(l,l+200)),w=await f(t,["rm","--cached","-f","--",...u],{allowFailure:!0});if(w.exitCode!==0&&!k(w)){o=w;break}}if(!o)return;const s=(o.stderr||o.stdout||"").trim()||"git unstage (rm --cached) failed",c=new Error(s);throw c.exitCode=o.exitCode,c}if(n){const o=await f(t,["restore","--staged","."],{allowFailure:!0});if(o.exitCode===0||k(o))return;const s=await f(t,["reset","HEAD"],{allowFailure:!0});if(s.exitCode===0||k(s))return;const c=(s.stderr||s.stdout||o.stderr||o.stdout||"").trim()||"git unstage all failed",l=new Error(c);throw l.exitCode=s.exitCode||o.exitCode,l}const r=await f(t,["reset"],{allowFailure:!0});if(r.exitCode===0||k(r))return;const a=(r.stderr||r.stdout||"").trim()||"git unstage all failed",i=new Error(a);throw i.exitCode=r.exitCode,i}async function P(t,e){const n=new Set;for(const a of e){let i=E.dirname(a);for(;i&&i!==".";)n.add(i),i=E.dirname(i)}const r=[...n].sort((a,i)=>{const o=a.split(/[/\\]/).length;return i.split(/[/\\]/).length-o});for(const a of r){const i=E.join(t,a);try{(await y.promises.readdir(i)).length===0&&await y.promises.rmdir(i)}catch{}}}async function ft(t,e){const n=await D(t),r=Array.isArray(e)&&e.length>0?new Set(e):null,a=[],i=[],o=[],s=new Set([...n.staged,...n.modified,...n.deleted]);for(const u of n.created)s.delete(u);for(const u of s)r&&!r.has(u)||a.push(u);const c=new Set(a);for(const u of n.created)r&&!r.has(u)||c.has(u)||i.push(u);for(const u of n.untracked)r&&!r.has(u)||c.has(u)||o.push(u);const l=await A(t);if(a.length>0&&l&&(await H(t,a,n.untracked),await U(t,["restore","--source=HEAD","--staged","--worktree"],a)),i.length>0){await U(t,["rm","-f","--cached"],i,{allowFailure:!0});for(const u of i){const w=E.join(t,u);y.existsSync(w)&&await y.promises.unlink(w)}await P(t,i)}for(const u of o){const w=E.join(t,u);y.existsSync(w)&&(y.statSync(w).isDirectory()?await y.promises.rm(w,{recursive:!0,force:!0}):await y.promises.unlink(w))}return o.length>0&&await P(t,o),{discardedCount:a.length+i.length+o.length,trackedFiles:a,newFiles:i,untrackedFiles:o}}function dt(t){return/unknown revision|bad revision|invalid object name|ambiguous argument|does not have any commits|Needed a single revision|not a valid object name|unknown revision or path not in the working tree/i.test(t)}async function ht(t,e={}){const{maxCount:n=50,skip:r=0,branch:a,filePath:i}=e;if(!await A(t))return[];const o=["log",`--skip=${r}`,"-n",String(n),"--format=%H%x00%aI%x00%B%x00%an%x00%ae%x1e"];a&&o.push(a),i&&o.push("--",_(i));const s=await f(t,o,{allowFailure:!0});if(s.exitCode!==0){const l=(s.stderr||s.stdout||"").trim();if(dt(l))return[];const u=new Error(l||`git log failed (exit ${s.exitCode})`);throw u.exitCode=s.exitCode,u.stderr=s.stderr,u.stdout=s.stdout,u}return s.stdout.split("").filter(l=>l.trim()).map(l=>{const u=l.replace(/^\n/,"").split("\0"),[w,p,h,C,m]=u;let d="";if(p){const g=new Date(p);d=Number.isNaN(g.getTime())?p:g.toISOString()}return{hash:(w||"").trim(),date:d,message:(h||"").replace(/\n$/,""),author_name:C||"",author_email:m||""}}).filter(l=>l.hash)}function mt(t){const e=[];for(const n of t.split(`
5
+ `)){if(!n.trim())continue;const r=n.split(" ");if(r.length<3)continue;const[a,i,o]=r,s=a==="-"||i==="-",c=s?0:parseInt(a,10)||0,l=s?0:parseInt(i,10)||0;e.push({file:G(o),changes:c+l,insertions:c,deletions:l,binary:s})}return e}async function wt(t,e={}){const{source:n="worktree",from:r,to:a,paths:i}=e,o=Array.isArray(i)&&i.length>0?["--",...b(i)]:[];if(n!=="commit"&&!await A(t))return{diff:"",summary:{files:[],insertions:0,deletions:0}};let s,c;if(n==="commit")if(r&&a)s=["diff",r,a,...o],c=["diff","--numstat",r,a,...o];else if(r){const d=((await f(t,["rev-list","--parents","-n","1",r],{allowFailure:!0})).stdout||"").trim().split(/\s+/).filter(Boolean);if(d.length<=1){const g=await f(t,["hash-object","-t","tree","/dev/null"],{allowFailure:!0});s=["show","--format=","--patch",r,...o],c=["show","--format=","--numstat",r,...o]}else{const g=d[1];s=["diff",g,r,...o],c=["diff","--numstat",g,r,...o]}}else{const m=new Error("source=commit requires at least 'from'");throw m.code="VALIDATION",m}else n==="staged"?(s=["diff","--cached",...o],c=["diff","--cached","--numstat",...o]):(s=["diff","HEAD",...o],c=["diff","HEAD","--numstat",...o]);const[l,u]=await Promise.all([f(t,s,{allowFailure:!0}),f(t,c,{allowFailure:!0})]),w=l.exitCode===0||l.exitCode===1?l.stdout:"";if(l.exitCode>1&&!w)throw new Error((l.stderr||l.stdout||"git diff failed").trim());const p=u.exitCode===0||u.exitCode===1?mt(u.stdout):[];let h=0,C=0;for(const m of p)h+=m.insertions,C+=m.deletions;return{diff:w,summary:{files:p,insertions:h,deletions:C}}}async function gt(t,e){const{ref:n,filePath:r}=e,a=E.resolve(t),i=E.resolve(t,r||"");if(i!==a&&!i.startsWith(a+E.sep)){const c=new Error("filePath is outside the workspace");throw c.code="VALIDATION",c.field="filePath",c}if(n==="worktree"||n==="staged"||n===""){let c;try{c=y.lstatSync(i)}catch{return""}if(c.isSymbolicLink())try{return y.readlinkSync(i,"utf8")}catch(l){if(l.code==="ENOENT")return"";throw l}if(c.isDirectory()){const l=new Error("filePath is a directory, file-content only supports files");throw l.code="VALIDATION",l.field="filePath",l}try{return y.readFileSync(i,"utf8")}catch(l){if(l.code==="ENOENT")return"";if(l.code==="EISDIR"){const u=new Error("filePath is a directory, file-content only supports files");throw u.code="VALIDATION",u.field="filePath",u}throw l}}const o=await f(t,["cat-file","-t",`${n}:${r}`],{allowFailure:!0});if(o.exitCode!==0)return"";if(o.stdout.trim()!=="blob"){const c=new Error("filePath is not a file in this ref (directory)");throw c.code="VALIDATION",c.field="filePath",c}const s=await f(t,["show",`${n}:${r}`],{allowFailure:!0});return s.exitCode!==0?"":s.stdout}async function pt(t,e){const{target:n,mode:r}=e;if(!await A(t)){const s=new Error("Cannot reset: repository has no commits yet");throw s.code="BUSINESS",s}const a=await f(t,["branch","--show-current"],{allowFailure:!0});if(!(a.exitCode===0?a.stdout.trim():"")){const s=new Error("Cannot reset: detached HEAD");throw s.code="BUSINESS",s}const o=await N(t,"HEAD");if(r==="hard"){let s=[];try{s=await F(t,n)}catch{s=[]}s.length>0&&await H(t,s)}return await f(t,["reset",`--${r}`,n]),{previousHead:o}}async function Ct(t,e){const{target:n,message:r,authorName:a,authorEmail:i,beforeCommit:o}=e;if(!await A(t)){const d=new Error("Cannot revert: repository has no commits yet");throw d.code="BUSINESS",d}let s;try{s=await N(t,n)}catch{const g=new Error("Revert target commit does not exist");throw g.code="VALIDATION",g.field="target",g.target=n,g}const c=await D(t);if(c.staged.length>0||c.modified.length>0||c.deleted.length>0||c.created.length>0||c.conflicted.length>0){const d=new Error("Working directory is not clean, please commit or stash your changes before reverting");throw d.code="BUSINESS",d.staged=c.staged,d.modified=c.modified,d}const u=await N(t,"HEAD"),w=new Set(await F(t,u)),p=new Set(await F(t,s));p.size>0&&(await H(t,p,c.untracked),await f(t,["restore",`--source=${s}`,"--worktree","--staged","."]));const h=[...w].filter(d=>!p.has(d));return h.length>0&&(await U(t,["rm","-f","--ignore-unmatch"],h),await P(t,h)),typeof o=="function"&&await o(),(await f(t,["diff","--cached","--quiet"],{allowFailure:!0})).exitCode===0?{nothingToCommit:!0,targetOid:s,previousHead:u}:(await f(t,["commit","-m",r],{env:I(a,i)}),{nothingToCommit:!1,commitHash:await N(t,"HEAD"),targetOid:s,previousHead:u})}async function yt(t,e){const n=await F(t,e);n.length!==0&&(await H(t,n),await U(t,["restore",`--source=${e}`,"--worktree","--staged"],n))}async function xt(t){const{stdout:e}=await f(t,["tag","--list"]);return e.split(`
6
+ `).map(n=>n.trim()).filter(Boolean)}async function Et(t,e){const{tagName:n,message:r,authorName:a,authorEmail:i}=e;r?await f(t,["tag","-a",n,"-m",r],{env:I(a||O.GIT_DEFAULT_AUTHOR_NAME,i||O.GIT_DEFAULT_AUTHOR_EMAIL)}):await f(t,["tag",n])}async function vt(t,e){await f(t,["tag","-d",e])}async function bt(t){const{stdout:e}=await f(t,["branch","--format=%(refname:short)"]),n=e.split(`
7
+ `).map(o=>o.trim()).filter(Boolean),r=await f(t,["branch","--show-current"],{allowFailure:!0}),a=r.exitCode===0&&r.stdout.trim()?r.stdout.trim():null,i={};for(const o of n)i[o]={name:o,current:o===a};return{branches:i,current:a}}async function At(t,e){const{branchName:n,startPoint:r}=e;r?await f(t,["checkout","-b",n,r]):await f(t,["checkout","-b",n])}async function St(t,e){const n=await D(t);if(n.staged.length>0||n.modified.length>0||n.deleted.length>0||n.created.length>0||n.conflicted.length>0){const a=new Error("Working directory is not clean, please commit or stash your changes before switching branches");throw a.code="BUSINESS",a.staged=n.staged,a.modified=n.modified,a}await f(t,["checkout",e])}async function kt(t,e){const{branchName:n,force:r=!1}=e;if((await f(t,["branch","--show-current"],{allowFailure:!0})).stdout.trim()===n){const i=new Error("Cannot delete the current branch, please switch to another branch first");throw i.code="BUSINESS",i}await f(t,["branch",r?"-D":"-d",n])}export{q as isNativeGitEnabled,j as isNativeGitAvailable,it as shouldUseNativeGit,ot as isNativeGitUnavailableError,V as markNativeGitMissing,f as runGit,I as buildAuthorEnv,A as nativeHasHead,N as nativeResolveOid,F as nativeListFiles,at as nativeInit,D as nativeStatus,z as nativeAddAll,K as nativeStageFiles,ct as nativeAddAllAndCommit,Y as nativeCommitStaged,lt as nativeCommitFiles,J as nativeHasStagedChangesForPaths,_ as toLiteralPathspec,b as toLiteralPathspecs,ut as nativeUnstage,ft as nativeDiscard,ht as nativeLog,wt as nativeDiff,gt as nativeFileContent,pt as nativeReset,Ct as nativeRevertToTree,yt as nativeCheckoutFiles,xt as nativeListTags,Et as nativeCreateTag,vt as nativeDeleteTag,bt as nativeListBranches,At as nativeCreateBranch,St as nativeSwitchBranch,kt as nativeDeleteBranch,rt as resetNativeGitAvailabilityCache,P as cleanEmptyParentDirs,Z as collectUntrackedRestoreBlockers,H as removeUntrackedBlockingRestore,G as decodeGitPorcelainPath};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuwax-file-server",
3
3
  "displayName": "nuwax-file-server",
4
- "version": "1.5.4",
4
+ "version": "1.5.5",
5
5
  "description": "Cross-platform file service deployment tool with start/stop/restart CLI commands",
6
6
  "type": "module",
7
7
  "main": "index.js",