gitpick 4.19.0 → 4.20.0-canary.0
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/index.mjs +36 -26
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,36 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import e from"node:fs";import t from"node:os";import n from"node:path";import{parseArgs as r,stripVTControlCharacters as i}from"node:util";import
|
|
3
|
-
`?e.slice(0,e.at(-2)===`\r`?-2:-1):e;if(
|
|
4
|
-
`),r=0;for(let e of n)r+=Math.max(1,Math.ceil(e.length/t));return r},m=()=>{if(!o)return;let e=Date.now();(t===-1||e-
|
|
5
|
-
|
|
6
|
-
`
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import e from"node:fs";import t from"node:os";import n from"node:path";import{parseArgs as r,stripVTControlCharacters as i}from"node:util";import{spawn as a}from"node:child_process";import{once as o}from"node:events";import s from"node:fs/promises";import c from"node:process";import{fileURLToPath as l}from"node:url";import u from"node:tty";import d from"node:https";var f=class extends Error{constructor(...e){super(...e),this.name=`SubprocessError`,this.stdout=``,this.stderr=``}};const p=[`.exe`,`.com`],m={},h=e=>(...t)=>m[t.join(`\0`)]??=e(...t),g=h(async(...e)=>{try{return await s.access(e[0]),!0}catch{return!1}}),_=h(async(e,t,r)=>{let i=r.split(n.delimiter).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,`$1`));try{await Promise.any([t,...i].flatMap(t=>p.map(r=>g(`${n.resolve(t,e)}${r}`))))}catch{return!1}return!0}),v=async(e,t)=>c.platform===`win32`&&!t.shell&&!p.some(t=>e.toLowerCase().endsWith(t))&&!await _(e,t.cwd??`.`,(c.env.PATH||c.env.Path)??``),y=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,`^$1`),b=e=>y(y(`"${e.replaceAll(/(\\*)"/g,`$1$1\\"`).replace(/(\\*)$/,`$1$1`)}"`)),x=e=>/[^\w./-]/.test(e)?`'${e.replaceAll(`'`,`'\\''`)}'`:e;async function S(e,t=[],r={}){let{stdin:s,stdout:u,stderr:d,stdio:p,cwd:m=`.`,env:h,...g}=r,_=m instanceof URL?l(m):n.resolve(m),S=h?{...c.env,...h}:void 0,C=p??[s,u,d],w=[e,...t].map(e=>x(i(e))).join(` `);[`node`,`node.exe`].includes(e.toLowerCase())&&(e=c.execPath,t=[...c.execArgv.filter(e=>!e.startsWith(`--inspect`)),...t]);let T={...g,stdio:C,env:S,cwd:_};await v(e,T)&&(t=t.map(e=>b(e)),e=y(e),T={...T,shell:!0}),T.shell&&t.length>0&&(e=[e,...t].join(` `),t=[]);let E=a(e,t,T),D=``,O=``;E.stdout&&(E.stdout.setEncoding(`utf8`),E.stdout.on(`data`,e=>D+=e)),E.stderr&&(E.stderr.setEncoding(`utf8`),E.stderr.on(`data`,e=>O+=e)),E.once(`error`,()=>{});try{await o(E,`spawn`)}catch(e){throw Object.assign(new f(`Command failed: ${w}`,{cause:e}),{stdout:D,stderr:O})}await o(E,`close`);let k=e=>e.at(-1)===`
|
|
3
|
+
`?e.slice(0,e.at(-2)===`\r`?-2:-1):e;if(E.exitCode&&E.exitCode>0)throw Object.assign(new f(`Command failed with exit code ${E.exitCode}: ${w}`),{stdout:k(D),stderr:k(O),exitCode:E.exitCode});if(E.signalCode)throw Object.assign(new f(`Command was terminated with ${E.signalCode}: ${w}`),{stdout:k(D),stderr:k(O)});return{stdout:k(D),stderr:k(O)}}const C=u?.WriteStream?.prototype?.hasColors?.()??!1,w=(e,t)=>{if(!C)return e=>e;let n=`\u001B[${e}m`,r=`\u001B[${t}m`;return e=>{let i=e+``,a=i.indexOf(r);if(a===-1)return n+i+r;let o=n,s=0,c=(t===22?r:``)+n;for(;a!==-1;)o+=i.slice(s,a)+c,s=a+r.length,a=i.indexOf(r,s);return o+=i.slice(s)+r,o}},T=w(1,22),E=w(2,22),D=w(31,39),O=w(32,39),k=w(33,39),A=w(36,39),ee=c.platform!==`win32`||!!c.env.WT_SESSION||c.env.TERM_PROGRAM===`vscode`,te=e=>!!(e.isTTY&&c.env.TERM!==`dumb`&&!(`CI`in c.env)),ne=O(ee?`✔`:`√`),j=ee?[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`]:[`-`,`\\`,`|`,`/`],M=(e={})=>{let t=-1,n,r=e.text??``,a=e.stream??c.stderr,o=te(a),s=0,l=0,u=!1,d=e=>a.write(e),f=()=>{if(!(!o||s===0)){a.cursorTo(0);for(let e=0;e<s;e++)e>0&&a.moveCursor(0,-1),a.clearLine(1);s=0}},p=e=>{let t=a.columns??80,n=i(e).split(`
|
|
4
|
+
`),r=0;for(let e of n)r+=Math.max(1,Math.ceil(e.length/t));return r},m=()=>{if(!o)return;let e=Date.now();(t===-1||e-l>=80)&&(t=++t%j.length,l=e);let n=j[t],i=`${A(n)} ${r}`;f(),d(i),s=p(i)};return{start(e){return r=e,u=!0,o&&d(`\x1B[?25l`),m(),o&&(n=setInterval(m,80)),this},success(e){return u?(u=!1,n&&=(clearInterval(n),void 0),f(),o&&d(`\x1B[?25h`),d(`${ne} ${e??r}\n`),this):this}}},N=async(t,r,i)=>{let a=i??r,o=await e.promises.readdir(t,{withFileTypes:!0});await e.promises.mkdir(r,{recursive:!0});let s=[];for(let i of o){if(i.name===`.git`)continue;let o=n.join(t,i.name),c=n.join(r,i.name);if(i.isDirectory())s.push(...await N(o,c,a));else if(i.isSymbolicLink()){let t=await e.promises.readlink(o);await e.promises.symlink(t,c),s.push(n.relative(a,c))}else await e.promises.copyFile(o,c),s.push(n.relative(a,c))}return s},P=new Set;function F(){for(let t of P)try{e.rmSync(t,{recursive:!0,force:!0})}catch{}process.exit(1)}process.on(`SIGINT`,F),process.on(`SIGTERM`,F);const re=e=>e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`,I=async(r,i,a)=>{let o=i.tree||i.quiet,s=i.verbose&&!o;process.platform===`win32`&&await S(`git`,[`config`,`--global`,`core.longpaths`,`true`]);let c=`https://${r.token?r.token+`@`:r.token}${r.host}/${r.owner}/${r.repository}.git`,l=`https://${r.host}/${r.owner}/${r.repository}.git`,u=n.resolve(t.tmpdir(),`${r.repository}-${Date.now()}${Math.random().toString(16).slice(2,6)}`);P.add(u);let d=M(),f=performance.now();!i.watch&&!o&&d.start(`Picking ${r.type}${r.type===`repository`?` without .git`:` from repository`}...`);let p=`shallow`,m=performance.now();try{await S(`git`,[`clone`,c,u,`--branch`,r.branch,`--depth`,`1`,`--single-branch`,...i.recursive?[`--recursive`]:[]])}catch{p=`full`,await S(`git`,[`clone`,c,u,...i.recursive?[`--recursive`]:[]]),await S(`git`,[`checkout`,r.branch],{cwd:u})}let h=Number(((performance.now()-m)/1e3).toFixed(2)),g=n.resolve(u,r.path),_=await e.promises.stat(g),v=[],y=performance.now();_.isDirectory()?(await e.promises.mkdir(a,{recursive:!0}),v=await N(g,a)):(await e.promises.mkdir(n.dirname(a),{recursive:!0}),await e.promises.copyFile(g,a),v=[n.basename(a)]);let b=Number(((performance.now()-y)/1e3).toFixed(2)),x=Number(((performance.now()-f)/1e3).toFixed(2)),C=0;for(let t of v)try{let r=await e.promises.stat(n.join(a,t));C+=r.size}catch{let t=await e.promises.stat(a);C+=t.size;break}return o||(i.watch?console.log(`- Synced at `+new Date().toLocaleTimeString()):d.success(`Picked ${r.type}${r.type===`repository`?` without .git`:` from repository`} in ${x} seconds.`)),s&&(console.log(E(` clone: ${p} (depth=${p===`shallow`?`1`:`full`})`)),console.log(E(` from: ${l} @ ${A(r.branch)}`)),console.log(E(` to: ${a}`)),console.log(E(` files: ${v.length} (${re(C)})`)),console.log(E(` network: ${h}s`)),console.log(E(` copy: ${b}s`)),console.log(E(` total: ${x}s`))),await e.promises.rm(u,{recursive:!0,force:!0}),P.delete(u),{files:v,duration:x,networkTime:h,copyTime:b,totalSize:C,cloneStrategy:p}};function L(e,t){return new Promise((n,r)=>{let i=d.get(e,{headers:t,timeout:15e3},e=>{if(e.statusCode===301||e.statusCode===302){let i=e.headers.location;if(i)return e.resume(),L(i,t).then(n,r)}let i=``;e.on(`data`,e=>i+=e),e.on(`end`,()=>n({statusCode:e.statusCode||0,headers:e.headers,body:i}))});i.on(`error`,r),i.on(`timeout`,()=>{i.destroy(),r(Error(`Request timed out`))})})}async function ie(e,t,n,r){let i=`https://api.github.com/repos/${e}/${t}/git/trees/${n}?recursive=1`,a={Accept:`application/vnd.github.v3+json`,"User-Agent":`gitpick`};r&&(a.Authorization=`token ${r}`);let o=await L(i,a);if(o.statusCode===401||o.statusCode===403)throw Error(`GitHub API returned ${o.statusCode}. For private repos or rate limits, set GITHUB_TOKEN or pass a token in the URL.`);if(o.statusCode!==200)throw Error(`GitHub API returned ${o.statusCode}: ${o.body.slice(0,200)}`);return(JSON.parse(o.body).tree||[]).map(e=>({path:e.path,type:e.type===`blob`?`blob`:`tree`,size:e.size}))}async function ae(e,t,n,r){let i=encodeURIComponent(`${e}/${t}`),a=[],o=1;for(;;){let e=`https://gitlab.com/api/v4/projects/${i}/repository/tree?ref=${encodeURIComponent(n)}&recursive=true&per_page=100&page=${o}`,t={"User-Agent":`gitpick`};r&&(t[`PRIVATE-TOKEN`]=r);let s=await L(e,t);if(s.statusCode===401||s.statusCode===403)throw Error(`GitLab API returned ${s.statusCode}. For private repos, set GITLAB_TOKEN or pass a token in the URL.`);if(s.statusCode!==200)throw Error(`GitLab API returned ${s.statusCode}: ${s.body.slice(0,200)}`);let c=JSON.parse(s.body);for(let e of c)a.push({path:e.path,type:e.type===`blob`?`blob`:`tree`});let l=s.headers[`x-next-page`];if(!l||l===``||c.length===0)break;o=Number(l)}return a}async function oe(e,t,n,r){let i=[],a=`https://api.bitbucket.org/2.0/repositories/${e}/${t}/src/${encodeURIComponent(n)}/?pagelen=100&max_depth=100`;for(;a;){let e={"User-Agent":`gitpick`};r&&(e.Authorization=`Bearer ${r}`);let t=await L(a,e);if(t.statusCode===401||t.statusCode===403)throw Error(`Bitbucket API returned ${t.statusCode}. For private repos, set BITBUCKET_TOKEN or pass a token in the URL.`);if(t.statusCode!==200)throw Error(`Bitbucket API returned ${t.statusCode}: ${t.body.slice(0,200)}`);let n=JSON.parse(t.body);for(let e of n.values||[])i.push({path:e.path,type:e.type===`commit_directory`?`tree`:`blob`});a=n.next||null}return i}async function se(e){if(e.host===`github.com`)return ie(e.owner,e.repository,e.branch,e.token);if(e.host===`gitlab.com`)return ae(e.owner,e.repository,e.branch,e.token);if(e.host===`bitbucket.org`)return oe(e.owner,e.repository,e.branch,e.token);throw Error(`Interactive mode is not supported for host: ${e.host}`)}const R=e=>e.replace(/\x1B\[\d+(?:;\d+)*m/g,``);function ce(e){let t=[],n=new Map,r=[...e].sort((e,t)=>e.type===t.type?e.path.localeCompare(t.path,void 0,{sensitivity:`base`}):e.type===`tree`?-1:1);for(let e of r){let r=e.path.split(`/`),i={name:r[r.length-1],path:e.path,type:e.type,size:e.size||0,children:[],expanded:!1,selected:!1,depth:r.length-1};if(e.type===`tree`&&n.set(e.path,i),r.length===1)t.push(i);else{let e=r.slice(0,-1).join(`/`),a=n.get(e);if(a)a.children.push(i);else{let e=``,a=t;for(let t=0;t<r.length-1;t++){e=e?e+`/`+r[t]:r[t];let i=n.get(e);i||(i={name:r[t],path:e,type:`tree`,size:0,children:[],expanded:!1,selected:!1,depth:t},n.set(e,i),a.push(i)),a=i.children}a.push(i)}}}function i(e){e.sort((e,t)=>e.type===t.type?e.name.localeCompare(t.name,void 0,{sensitivity:`base`}):e.type===`tree`?-1:1);for(let t of e)t.children.length&&i(t.children)}return i(t),t}function z(e){let t=[];function n(e,r){for(let i=0;i<e.length;i++){let a=e[i],o=i===e.length-1,s=o?`└── `:`├── `;t.push({node:a,prefix:r,connector:s}),a.type===`tree`&&a.expanded&&n(a.children,r+(o?` `:`│ `))}}return n(e,``),t}function B(e,t){e.selected=t;for(let n of e.children)B(n,t)}function le(e){let t=[];function n(e){for(let r of e)r.selected?r.type===`tree`?r.children.length>0&&r.children.every(e=>e.selected)||r.children.length===0?t.push(r.path):n(r.children):t.push(r.path):r.type===`tree`&&n(r.children)}return n(e),t}function ue(e){let t=0,n=0,r=0;function i(e){for(let a of e)a.selected&&(a.type===`tree`?n++:(t++,r+=a.size)),a.children.length&&i(a.children)}return i(e),{files:t,folders:n,size:r}}const de=e=>e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`;function fe(e,t){return new Promise(n=>{let r=ce(e);if(!r.length){n([]);return}function i(e,t,n=0){for(let r of e)r.type===`tree`&&n<=t&&(r.expanded=!0,i(r.children,t,n+1))}e.length<=30?i(r,1/0):i(r,1);let a=0,o=0,s=process.stdout,c=process.stdin,l=c.isRaw;c.setRawMode(!0),c.resume(),s.write(`\x1B[?1049h\x1B[?25l`);function u(){c.setRawMode(l??!1),c.pause(),c.removeListener(`data`,p),s.write(`\x1B[?25h\x1B[?1049l`)}let d=()=>{s.write(`\x1B[?25h\x1B[?1049l`)};process.on(`exit`,d);function f(){let e=s.rows||24,n=s.columns||80,i=e-3-1-5,c=z(r);c.length+1;let l=a-1;l>=0?(l<o&&(o=l),l>=o+i&&(o=l-i+1)):o=0,o<0&&(o=0);let u=c.slice(o,o+i),{files:d,folders:f,size:p}=ue(r),m=`\x1B[H\x1B[2J`;m+=`\n ${t}\n\n`;let h=r.every(e=>e.selected),g=a===0,_=h?O(`[✔]`):E(`[ ]`),v=`${g?k(`>`):` `} ${_} ${E(`.`)}`;if(g){let e=Math.max(0,n-R(v).length);v=`\x1B[48;5;236m${v}${` `.repeat(e)}\x1B[49m`}m+=v+`
|
|
5
|
+
`;for(let e=0;e<u.length;e++){let t=u[e],r=o+e+1===a,i=t.node.selected?O(`[✔]`):E(`[ ]`),s=t.node.type===`tree`?A(t.node.name+`/`):t.node.name,c=t.node.type===`tree`?t.node.expanded?E(`▾ `):E(`▸ `):` `,l=`${r?k(`>`):` `} ${i} ${E(t.prefix)}${E(t.connector)}${c}${s}`;if(r){let e=Math.max(0,n-R(l).length);l=`\x1B[48;5;236m${l}${` `.repeat(e)}\x1B[49m`}m+=l+`
|
|
6
|
+
`}for(let e=u.length;e<i;e++)m+=`
|
|
7
|
+
`;m+=`
|
|
8
|
+
`;let y=[];f>0&&y.push(A(`${f} folder${f===1?``:`s`}`)),d>0&&y.push(`${d} file${d===1?``:`s`}`);let b=[];y.length>0&&b.push(y.join(` `)),b.length>0&&b.push(E(de(p)));let x=c.length>i?E(` • ${o+1}-${Math.min(o+i,c.length)}/${c.length}`):``,S=b.length>0?` ${b.join(E(` • `))}${x}`:E(` nothing selected`)+x;m+=S+`
|
|
9
|
+
`,m+=`
|
|
10
|
+
`;let C=E(`↑↓:navigate enter:expand space:select c:confirm q:quit`);m+=` ${C}\n`,s.write(m)}function p(e){let t=z(r),i=t.length+1,o=e.toString();if(o===``||o===`q`||o===`Q`){u(),process.removeListener(`exit`,d),n([]);return}if(o===`c`||o===`C`){u(),process.removeListener(`exit`,d),n(le(r));return}if((o===`\x1B[A`||o===`k`)&&a>0&&a--,(o===`\x1B[B`||o===`j`)&&a<i-1&&a++,a===0&&(o===` `||o===`\r`)){let e=r.every(e=>e.selected);for(let t of r)B(t,!e)}if(o===` `&&a>0){let e=t[a-1];e&&B(e.node,!e.node.selected)}if(o===`\r`&&a>0){let e=t[a-1];e&&e.node.type===`tree`&&(e.node.expanded=!e.node.expanded)}if((o===`\x1B[C`||o===`l`)&&a>0){let e=t[a-1];e&&e.node.type===`tree`&&(e.node.expanded=!0)}if((o===`\x1B[D`||o===`h`)&&a>0){let e=t[a-1];e&&e.node.type===`tree`&&(e.node.expanded=!1)}f()}c.on(`data`,p),f()})}function V(e){if(typeof e==`number`||/^\d+$/.test(e))return typeof e==`number`?e:parseInt(e,10);let t=/(\d+)([hms])/g,n=0,r;for(;(r=t.exec(e))!==null;){let e=parseInt(r[1],10);switch(r[2]){case`h`:n+=e*36e5;break;case`m`:n+=e*6e4;break;case`s`:n+=e*1e3;break}}return n}const H=async e=>{let t=(await S(`git`,[`ls-remote`,e])).stdout,n=t.match(/(.+)\s+HEAD/)?.[1],r=t.match(RegExp(`${n}\\s+refs/heads/(.+)`))?.[1];if(!r)throw Error(`Could not determine default branch!`);return r},U=[{prefix:`git@github.com:`,host:`github.com`},{prefix:`https://github.com/`,host:`github.com`},{prefix:`https://raw.githubusercontent.com/`,host:`github.com`},{prefix:`git@gitlab.com:`,host:`gitlab.com`},{prefix:`https://gitlab.com/`,host:`gitlab.com`},{prefix:`git@bitbucket.org:`,host:`bitbucket.org`},{prefix:`https://bitbucket.org/`,host:`bitbucket.org`}];async function pe(e,{branch:t,target:n}){let r=e.match(/^https:\/\/([^@]+)@(github\.com|gitlab\.com|bitbucket\.org)/),i=``;if(r)i=r[1],e=e.replace(`${r[1]}@`,``);else{let t={"github.com":process.env.GITHUB_TOKEN||process.env.GH_TOKEN||``,"gitlab.com":process.env.GITLAB_TOKEN||``,"bitbucket.org":process.env.BITBUCKET_TOKEN||``};for(let{prefix:n,host:r}of U)if(e.startsWith(n)){i=t[r];break}!i&&!e.startsWith(`https://`)&&!e.startsWith(`git@`)&&(i=t[`github.com`])}let a=`github.com`;for(let{prefix:t,host:n}of U)if(e.startsWith(t)){a=n,e=e.replace(t,``);break}let o=e.split(`/`),s=o[0],c=o[1]?.endsWith(`.git`)?o[1].slice(0,-4):o[1],l=`https://${i&&i+`@`}${a}/${s}/${c}`,u,d,f;a===`github.com`?o[2]===`refs`&&[`heads`,`tags`].includes(o[3])?(u=`raw`,d=t||o[4],f=o.slice(5).join(`/`)):o[2]===`refs`&&o[3]===`remotes`?(u=`raw`,d=t||`${o[4]}/${o[5]}`,f=o.slice(6).join(`/`)):o[2]===`blob`?(u=`blob`,d=t||o[3],f=o.slice(4).join(`/`)):o[2]===`tree`?(u=`tree`,d=t||o[3],f=o.slice(4).join(`/`)):o[2]===`commit`?(u=`repository`,d=t||o[3],f=``):(u=`repository`,d=t||await H(l),f=``):a===`gitlab.com`?o[2]===`-`&&o[3]===`blob`?(u=`blob`,d=t||o[4],f=o.slice(5).join(`/`)):o[2]===`-`&&o[3]===`tree`?(u=`tree`,d=t||o[4],f=o.slice(5).join(`/`)):(u=`repository`,d=t||await H(l),f=``):o[2]===`src`?(u=`tree`,d=t||o[3],f=o.slice(4).join(`/`)):(u=`repository`,d=t||await H(l),f=``);let p=n||(u===`blob`?`.`:f.split(`/`).pop()||c);return{token:i,host:a,owner:s,repository:c,type:u,branch:d,path:f,target:p}}const W=n.join(t.homedir(),`.cache`,`gitpick`),G=n.join(W,`update-check.json`);function K(){try{return JSON.parse(e.readFileSync(G,`utf-8`))}catch{return null}}function me(t){try{e.mkdirSync(W,{recursive:!0}),e.writeFileSync(G,JSON.stringify(t))}catch{}}function he(){return new Promise(e=>{let t=d.get(`https://registry.npmjs.org/gitpick/latest`,{headers:{Accept:`application/json`},timeout:3e3},t=>{if(t.statusCode!==200)return t.resume(),e(null);let n=``;t.on(`data`,e=>n+=e),t.on(`end`,()=>{try{e(JSON.parse(n).version||null)}catch{e(null)}})});t.on(`error`,()=>e(null)),t.on(`timeout`,()=>{t.destroy(),e(null)})})}function ge(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]||0)>(r[e]||0))return!0;if((n[e]||0)<(r[e]||0))return!1}return!1}function q(e,t){if(t)return;let n=K();n&&ge(n.latestVersion,e)&&console.log(E(`\n Update available: ${k(e)} → ${A(T(n.latestVersion))}\n Run ${A(`npm i -g gitpick`)} to update\n`))}function _e(){let e=K();e&&Date.now()-e.lastCheck<864e5||setTimeout(async()=>{let e=await he();e&&me({lastCheck:Date.now(),latestVersion:e})},0)}const J=Symbol(`singleComment`),ve=Symbol(`multiComment`),Y=(e,t,n)=>e.slice(t,n).replace(/[^ \t\r\n]/g,` `),ye=(e,t)=>{let n=t-1,r=0;for(;e[n]===`\\`;)--n,r+=1;return!!(r%2)};function be(e){if(typeof e!=`string`)throw TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof e}\``);let t=!1,n=!1,r=0,i=``,a=``,o=-1;for(let s=0;s<e.length;s++){let c=e[s],l=e[s+1];if(!n&&c===`"`&&(ye(e,s)||(t=!t)),!t)if(!n&&c+l===`//`)i+=e.slice(r,s),r=s,n=J,s++;else if(n===J&&c+l===`\r
|
|
11
|
+
`){s++,n=!1,i+=Y(e,r,s),r=s;continue}else if(n===J&&c===`
|
|
12
|
+
`)n=!1,i+=Y(e,r,s),r=s;else if(!n&&c+l===`/*`){i+=e.slice(r,s),r=s,n=ve,s++;continue}else if(n===ve&&c+l===`*/`){s++,n=!1,i+=Y(e,r,s+1),r=s+1;continue}else n||(o===-1?c===`,`&&(a+=i+e.slice(r,s),i=``,r=s,o=s):c===`}`||c===`]`?(i+=e.slice(r,s),a+=Y(i,0,1)+i.slice(1),i=``,r=s,o=-1):c!==` `&&c!==` `&&c!==`\r`&&c!==`
|
|
13
|
+
`&&(i+=e.slice(r,s),r=s,o=-1))}let s=n===J?Y(e,r):e.slice(r);return a+i+s}const xe=[`.gitpick.json`,`.gitpick.jsonc`],Se=async()=>{let t;for(let r of xe){let i=n.resolve(r);if(e.existsSync(i)){t=i;break}}if(!t)return!1;let r=await e.promises.readFile(t,`utf-8`),i=JSON.parse(be(r));if(!Array.isArray(i)||!i.every(e=>typeof e==`string`))throw Error(`${n.basename(t)} must be an array of strings`);for(let e of i)await S(process.argv[0],[...process.argv.slice(1),...e.split(/\s+/),`-o`],{stdio:`inherit`});return!0};var Ce=`gitpick`,X=`4.20.0-canary.0`;const Z=(e,t)=>`\x1b]8;;${t}\x07${e}\x1b]8;;\x07`,we=`
|
|
14
|
+
With ${T(`${Z(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific directories or files from GitHub, GitLab and Bitbucket!
|
|
9
15
|
|
|
10
|
-
$ gitpick ${
|
|
16
|
+
$ gitpick ${k(`<url>`)} ${O(`[target]`)} ${A(`[options]`)}
|
|
11
17
|
|
|
12
|
-
${
|
|
18
|
+
${T(`Hint:`)}
|
|
13
19
|
[target] and [options] are optional and if not specified,
|
|
14
20
|
GitPick fallbacks to the default behavior of \`git clone\`
|
|
15
21
|
|
|
16
|
-
${
|
|
17
|
-
${
|
|
18
|
-
${
|
|
22
|
+
${T(`Arguments:`)}
|
|
23
|
+
${k(`url`)} GitHub/GitLab/Bitbucket URL with path to file/folder/repository
|
|
24
|
+
${O(`target`)} Directory to clone into (optional)
|
|
19
25
|
|
|
20
|
-
${
|
|
21
|
-
${
|
|
22
|
-
${
|
|
23
|
-
${
|
|
24
|
-
${
|
|
25
|
-
${
|
|
26
|
+
${T(`Options:`)}
|
|
27
|
+
${A(`-b, --branch `)} Branch/SHA to clone
|
|
28
|
+
${A(`-i, --interactive`)} Browse and pick files/folders interactively
|
|
29
|
+
${A(`-n, --dry-run`)} Show what would be cloned without cloning
|
|
30
|
+
${A(`-o, --overwrite`)} Skip overwrite prompt
|
|
31
|
+
${A(`-r, --recursive`)} Clone submodules
|
|
32
|
+
${A(`-w, --watch [time]`)} Watch the repository and sync every [time]
|
|
26
33
|
(e.g. 1h, 30m, 15s)
|
|
27
|
-
${
|
|
28
|
-
${
|
|
29
|
-
${
|
|
30
|
-
${
|
|
31
|
-
${
|
|
34
|
+
${A(` --tree`)} List copied files as a tree
|
|
35
|
+
${A(`-q, --quiet`)} Suppress all output except errors
|
|
36
|
+
${A(` --verbose`)} Show detailed clone information
|
|
37
|
+
${A(`-h, --help`)} display help for command
|
|
38
|
+
${A(`-v, --version`)} display the version number
|
|
32
39
|
|
|
33
|
-
${
|
|
40
|
+
${T(`Examples:`)}
|
|
34
41
|
$ gitpick <url>
|
|
35
42
|
$ gitpick <url> [target]
|
|
36
43
|
$ gitpick <url> [target] -b [branch/SHA]
|
|
@@ -40,6 +47,9 @@ ${m(`Examples:`)}
|
|
|
40
47
|
$ gitpick https://gitlab.com/owner/repo
|
|
41
48
|
$ gitpick https://bitbucket.org/owner/repo
|
|
42
49
|
|
|
43
|
-
🚀 More awesome tools at ${
|
|
44
|
-
|
|
50
|
+
🚀 More awesome tools at ${A(`https://github.com/nrjdalal`)}`,Q=e=>{let r=process.cwd(),i=t.homedir(),a=n.sep;return e===r?`.`:e.startsWith(r+a)?`./`+n.relative(r,e).replaceAll(a,`/`):e.startsWith(i+a)?`~/`+n.relative(i,e).replaceAll(a,`/`):e},$=async(t,r=``)=>{let i=(await e.promises.readdir(t,{withFileTypes:!0})).filter(e=>e.name!==`.git`).sort((e,t)=>e.name.localeCompare(t.name,void 0,{sensitivity:`base`}));for(let a=0;a<i.length;a++){let o=i[a],s=a===i.length-1,c=s?`└── `:`├── `,l=n.join(t,o.name);if(o.isSymbolicLink()){let t=await e.promises.readlink(l),n=!1;try{n=e.statSync(l).isDirectory()}catch{}process.stdout.write(`${r}${c}${k(o.name)} -> ${n?A(t):t}\n`)}else o.isDirectory()?(process.stdout.write(`${r}${c}${A(o.name)}\n`),await $(l,`${r}${s?` `:`│ `}`)):process.stdout.write(`${r}${c}${o.name}\n`)}},Te=e=>{try{return r(e)}catch(e){throw Error(`Error parsing arguments: ${e.message}`)}};(async()=>{_e();try{let{positionals:r,values:i}=Te({allowPositionals:!0,options:{branch:{type:`string`,short:`b`},"dry-run":{type:`boolean`,short:`n`},force:{type:`boolean`,short:`f`},help:{type:`boolean`,short:`h`},interactive:{type:`boolean`,short:`i`},quiet:{type:`boolean`,short:`q`},tree:{type:`boolean`},verbose:{type:`boolean`},overwrite:{type:`boolean`,short:`o`},recursive:{type:`boolean`,short:`r`},version:{type:`boolean`,short:`v`},watch:{type:`string`,short:`w`}}});r.length||(i.version&&(console.log(`\n${Ce}@${X}`),process.exit(0)),await Se()&&process.exit(0),console.log(we),process.exit(0)),r[0]===`clone`&&r.shift();let[a,o]=r,s={branch:i.branch,dryRun:i[`dry-run`],force:i.force,interactive:i.interactive,quiet:i.quiet,tree:i.tree,verbose:i.verbose,overwrite:i.overwrite,recursive:i.recursive,watch:i.watch},c=s.tree||s.quiet;c||console.log(`\nWith ${T(`${Z(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific files, folders, branches,\ncommits and much more from GitHub, GitLab and Bitbucket!`);let l=await pe(a,{branch:s.branch,target:o});if(l.type===`blob`){let e=l.target.split(/[/\\]/).filter(e=>e!==``),t=e[e.length-1];t!==`.`&&t!==`..`&&t.includes(`.`)?e.pop():t=l.path.split(`/`).pop()||t,l.target=[...e,t].join(`/`)}c||console.info(`\n${O(`✔`)} ${l.owner}/${l.repository} ${A(l.type+`:`+l.branch)} ${l.type===`repository`?`> ${O(l.target)}`:`${l.path.length?k(l.path)+` >`:`>`} ${O(l.target)}`}`);let u=n.resolve(l.target);if(s.interactive){if(!process.stdout.isTTY)throw Error(`Interactive mode requires a TTY`);let r=M();r.start(`Fetching file tree from ${l.owner}/${l.repository}...`);let i=await se(l);r.success(`Fetched ${i.length} entries from ${l.owner}/${l.repository}`),i.length||(console.log(k(`
|
|
51
|
+
Repository has no files.`)),process.exit(0));let a=await fe(i,`${l.owner}/${l.repository} ${A(`repository:`+l.branch)} > ${O(l.target)}`);a.length||(console.log(`
|
|
52
|
+
No files selected.`),process.exit(0)),console.log(`\n${O(`✔`)} Picking ${a.length} selected path${a.length===1?``:`s`}...`);let o=n.resolve(t.tmpdir(),`gitpick-interactive-${Date.now()}${Math.random().toString(16).slice(2,6)}`),c=`https://${l.token?l.token+`@`:``}${l.host}/${l.owner}/${l.repository}.git`;try{await S(`git`,[`clone`,c,o,`--branch`,l.branch,`--depth`,`1`,`--single-branch`,...s.recursive?[`--recursive`]:[]])}catch{await S(`git`,[`clone`,c,o,...s.recursive?[`--recursive`]:[]]),await S(`git`,[`checkout`,l.branch],{cwd:o})}await e.promises.mkdir(u,{recursive:!0});let d=0;for(let t of a){let r=n.join(o,t),i=n.join(u,t),a=await e.promises.stat(r).catch(()=>null);if(a)if(a.isDirectory()){await e.promises.mkdir(i,{recursive:!0});let t=await N(r,i);d+=t.length}else await e.promises.mkdir(n.dirname(i),{recursive:!0}),await e.promises.copyFile(r,i),d++}await e.promises.rm(o,{recursive:!0,force:!0}),console.log(O(`✔ Copied ${d} file${d===1?``:`s`} to ${Q(u)}`)),s.tree&&(process.stdout.write(`\n${T(A(Q(u)))}\n`),await $(u),process.stdout.write(`
|
|
53
|
+
`)),q(X,!1),process.exit(0)}let d=async t=>{e.statSync(t).isDirectory()?(process.stdout.write(`${T(A(Q(u)))}\n`),await $(t)):(process.stdout.write(`${T(A(Q(n.dirname(u))))}\n`),process.stdout.write(`└── ${n.basename(u)}\n`)),process.stdout.write(`
|
|
54
|
+
`)};if(s.dryRun){if(s.tree){let r=n.resolve(t.tmpdir(),`gitpick-dry-${Date.now()}${Math.random().toString(16).slice(2,6)}`);try{await I(l,s,r),await d(r)}finally{await e.promises.rm(r,{recursive:!0,force:!0})}}c||console.log(),q(X,c),process.exit(0)}if(s.overwrite=s.overwrite||s.force,s.watch&&(s.overwrite=!0),e.existsSync(u)&&!s.overwrite&&(l.type===`blob`&&(console.log(`${k(`\nWarning: The target file exists at ${O(l.target)}. Use ${A(`-f`)} or ${A(`-o`)} to overwrite.`)}`),process.exit(1)),(await e.promises.readdir(u)).length&&(console.log(`${k(`\nWarning: The target directory exists at ${O(l.target)} and is not empty. Use ${A(`-f`)} or ${A(`-o`)} to overwrite.`)}`),process.exit(1))),s.watch){c||console.log(`\n👀 Watching every ${V(s.watch)/1e3+`s`}\n`),await I(l,s,u),s.tree&&await d(u);let e=V(s.watch);setInterval(async()=>{await I(l,s,u),s.tree&&await d(u)},e)}else await I(l,s,u),s.tree&&await d(u),q(X,c),process.exit(0)}catch(e){e instanceof Error?console.log(T(`\n${D(`Error: `)}`)+e.message):console.log(T(`${D(`
|
|
45
55
|
Unexpected Error: `)}`)+JSON.stringify(e,null,2)),process.exit(1)}})();export{};
|