gitpick 6.1.0-canary.20 → 6.1.0-canary.22
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/README.md +5 -4
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -164,17 +164,18 @@ npx gitpick https://codeberg.org/owner/repo # Codeberg
|
|
|
164
164
|
|
|
165
165
|
## ⚡ Fast Mode (`--fast`)
|
|
166
166
|
|
|
167
|
-
By default GitPick uses `git clone`, so a pick is byte-for-byte what a checkout gives you. Pass `--fast` (or set `GITPICK_FAST=1` for a whole CI fleet) to fetch through the host's **archive / raw HTTP endpoints** instead
|
|
167
|
+
By default GitPick uses `git clone`, so a pick is byte-for-byte what a checkout gives you. Pass `--fast` (or set `GITPICK_FAST=1` for a whole CI fleet) to fetch through the host's **archive / raw HTTP endpoints** instead: no `git` process, typically **2-4x faster**, and (in a 100-repo differential test) byte-identical to a clone.
|
|
168
168
|
|
|
169
169
|
```sh
|
|
170
170
|
npx gitpick owner/repo --fast # download + extract the tarball
|
|
171
171
|
GITPICK_FAST=1 npx gitpick owner/repo # opt in fleet-wide
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
Three cases where a `--fast` pick can differ from a clone (all are how every archive-based tool, e.g. `degit`, behaves, which is why it's opt-in):
|
|
175
175
|
|
|
176
|
-
- **`.gitattributes` `export-ignore` / `export-subst
|
|
177
|
-
- **`core.autocrlf` on Windows
|
|
176
|
+
- **`.gitattributes` `export-ignore` / `export-subst`**: host archives honor these (they omit paths / expand keywords); a clone does not. Common in PHP/Composer repos.
|
|
177
|
+
- **`core.autocrlf` on Windows**: archives store blobs verbatim (LF); a clone would CRLF-normalize.
|
|
178
|
+
- **Symlink-hostile Windows**: `--fast` warns and skips a symlink it can't create; a clone may fail or write git's text stub instead.
|
|
178
179
|
|
|
179
180
|
`--recursive` (submodules) always uses a clone.
|
|
180
181
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
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{Readable as d}from"node:stream";import{createGunzip as f}from"node:zlib";import{pipeline as p}from"node:stream/promises";import m from"node:https";var h=class extends Error{constructor(...e){super(...e),this.name=`SubprocessError`,this.stdout=``,this.stderr=``}};const g=[`.exe`,`.com`],_={},v=e=>(...t)=>_[t.join(`\0`)]??=e(...t),y=v(async(...e)=>{try{return await s.access(e[0]),!0}catch{return!1}}),b=v(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=>g.map(r=>y(`${n.resolve(t,e)}${r}`))))}catch{return!1}return!0}),x=async(e,t)=>c.platform===`win32`&&!t.shell&&!g.some(t=>e.toLowerCase().endsWith(t))&&!await b(e,t.cwd??`.`,(c.env.PATH||c.env.Path)??``),S=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,`^$1`),ee=e=>S(S(`"${e.replaceAll(/(\\*)"/g,`$1$1\\"`).replace(/(\\*)$/,`$1$1`)}"`)),te=e=>/[^\w./-]/.test(e)?`'${e.replaceAll(`'`,`'\\''`)}'`:e,ne=new Set;async function C(e,t=[],r={}){let{stdin:s,stdout:u,stderr:d,stdio:f,cwd:p=`.`,env:m,...g}=r,_=p instanceof URL?l(p):n.resolve(p),v=m?{...c.env,...m}:void 0,y=f??[s,u,d],b=[e,...t].map(e=>te(i(e))).join(` `);[`node`,`node.exe`].includes(e.toLowerCase())&&(e=c.execPath,t=[...c.execArgv.filter(e=>!e.startsWith(`--inspect`)),...t]);let C={...g,stdio:y,env:v,cwd:_};await x(e,C)&&(t=t.map(e=>ee(e)),e=S(e),C={...C,shell:!0}),C.shell&&t.length>0&&(e=[e,...t].join(` `),t=[]);let w=a(e,t,C);ne.add(w);let T=()=>ne.delete(w);w.once(`close`,T),w.once(`exit`,T);let E=``,D=``;w.stdout&&(w.stdout.setEncoding(`utf8`),w.stdout.on(`data`,e=>E+=e)),w.stderr&&(w.stderr.setEncoding(`utf8`),w.stderr.on(`data`,e=>D+=e)),w.once(`error`,()=>{});try{await o(w,`spawn`)}catch(e){throw Object.assign(new h(`Command failed: ${b}`,{cause:e}),{stdout:E,stderr:D})}await o(w,`close`);let O=e=>e.at(-1)===`
|
|
3
3
|
`?e.slice(0,e.at(-2)===`\r`?-2:-1):e;if(w.exitCode&&w.exitCode>0)throw Object.assign(new h(`Command failed with exit code ${w.exitCode}: ${b}`),{stdout:O(E),stderr:O(D),exitCode:w.exitCode});if(w.signalCode)throw Object.assign(new h(`Command was terminated with ${w.signalCode}: ${b}`),{stdout:O(E),stderr:O(D)});return{stdout:O(E),stderr:O(D)}}const w=u?.WriteStream?.prototype?.hasColors?.()??!1,T=(e,t)=>{if(!w)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}},E=T(1,22),D=T(2,22),O=T(31,39),k=T(32,39),A=T(33,39),j=T(36,39),re=c.platform!==`win32`||!!c.env.WT_SESSION||c.env.TERM_PROGRAM===`vscode`,ie=e=>!!(e.isTTY&&c.env.TERM!==`dumb`&&!(`CI`in c.env)),ae=k(re?`✔`:`√`),oe=re?[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`]:[`-`,`\\`,`|`,`/`],se=(e={})=>{let t=-1,n,r=e.text??``,a=e.stream??c.stderr,o=ie(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%oe.length,l=e);let n=oe[t],i=`${j(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(`${ae} ${e??r}\n`),this):this}}},M=new Set;function ce(){for(let e of ne)try{e.kill(`SIGKILL`)}catch{}for(let t of M)try{e.rmSync(t,{recursive:!0,force:!0})}catch{}process.exit(1)}process.on(`SIGINT`,ce),process.on(`SIGTERM`,ce);const le=e=>/[.+^${}()|[\]\\]/.test(e)?`\\${e}`:e,ue=e=>{let t=``,n=0;for(;n<e.length;){let r=e[n];if(r===`*`)if(e[n+1]===`*`){let r=n===0||e[n-1]===`/`;n+=2;let i=e[n]===`/`;r&&i?(t+=`(?:.*/)?`,n+=1):t+=`.*`}else t+=`[^/]*`,n+=1;else r===`?`?(t+=`[^/]`,n+=1):r===`/`?(t+=`/`,n+=1):(t+=le(r),n+=1)}return t},de=e=>{let t=e.trim();if(!t||t.startsWith(`#`))return null;let n=!1;t.startsWith(`!`)&&(n=!0,t=t.slice(1));let r=!1;t.endsWith(`/`)&&(r=!0,t=t.replace(/\/+$/,``));let i=!1;if(t.startsWith(`/`)?(i=!0,t=t.replace(/^\/+/,``)):t.includes(`/`)&&(i=!0),!t)return null;let a=ue(t),o=i?`^${a}$`:`^(?:.*/)?${a}$`;return{negated:n,dirOnly:r,regex:new RegExp(o)}},fe=e=>{let t=[];for(let n of e.split(/\r?\n/)){let e=de(n);e&&t.push(e)}return{ignores(e,r){let i=e.split(n.sep).join(`/`);if(!i||i===`.`)return!1;let a=!1;for(let e of t)e.dirOnly&&!r||e.regex.test(i)&&(a=!e.negated);return a}}},pe=t=>{let r;try{r=e.readFileSync(n.join(t,`.gitpickignore`),`utf8`)}catch{return null}return fe(r)},me=e=>({matcher:pe(e),srcRoot:e}),he=async(t,r,i,a)=>{let o=i??r,s=a??me(t),c=await e.promises.readdir(t,{withFileTypes:!0});await e.promises.mkdir(r,{recursive:!0});let l=[];for(let i of c){if(i.name===`.git`)continue;let a=n.join(t,i.name),c=n.join(r,i.name),u=n.relative(s.srcRoot,a);if(u!==`.gitpickignore`&&!s.matcher?.ignores(u,i.isDirectory()))if(i.isDirectory())l.push(...await he(a,c,o,s));else if(i.isSymbolicLink()){let t=await e.promises.readlink(a);await e.promises.rm(c,{force:!0,recursive:!0}),await e.promises.symlink(t,c),l.push(n.relative(o,c))}else await e.promises.copyFile(a,c),l.push(n.relative(o,c))}return l},N=e=>Number(((performance.now()-e)/1e3).toFixed(2)),P=(e,t,n)=>{let r=t,i=t+n;for(;r<i&&e[r]!==0;)r++;return e.toString(`utf8`,t,r)},ge=(e,t,n)=>{let r=P(e,t,n).trim();return r?parseInt(r,8):0},_e=e=>{let t=!0;for(let n=0;n<512;n++)if(e[n]!==0){t=!1;break}if(t)return null;let n=P(e,0,100),r=P(e,345,155);return{name:r?`${r}/${n}`:n,size:ge(e,124,12),type:String.fromCharCode(e[156]),linkname:P(e,157,100),mode:ge(e,100,8)}},ve=e=>{let t={},n=0;for(;n<e.length;){let r=n;for(;r<e.length&&e[r]!==32;)r++;if(r>=e.length)break;let i=Number.parseInt(e.toString(`ascii`,n,r),10);if(!Number.isFinite(i)||i<=0||n+i>e.length)break;let a=e.toString(`utf8`,r+1,n+i-1),o=a.indexOf(`=`);o>0&&(t[a.slice(0,o)]=a.slice(o+1)),n+=i}return t},ye=async(t,r,i=1)=>{let a=0,o=0,s={},c=async(t,c)=>{let l=s.path??t.name,u=s.linkpath??t.linkname;s={};let d=l.split(`/`).slice(i).join(`/`);if(!d)return;let f=n.join(r,d);if(t.type===`5`)await e.promises.mkdir(f,{recursive:!0});else if(t.type===`2`){await e.promises.mkdir(n.dirname(f),{recursive:!0});try{await e.promises.symlink(u,f),o++}catch{console.warn(`Warning: could not create symlink ${d} -> ${u}`)}}else if(t.type===`0`||t.type===`\0`||t.type===``)await e.promises.mkdir(n.dirname(f),{recursive:!0}),await e.promises.writeFile(f,c,{mode:t.mode&511||420}),a++;else throw Error(`untar: unsupported entry type '${t.type}' for ${d}`)},l=async(e,t)=>{e.type===`x`||e.type===`g`?s={...s,...ve(t)}:await c(e,t)},u=[],d=0,p=e=>{let t=Buffer.allocUnsafe(e),n=0;for(;n<e;){let r=u[0],i=Math.min(r.length,e-n);r.copy(t,n,0,i),n+=i,i===r.length?u.shift():u[0]=r.subarray(i)}return d-=e,t},m=null,h=512,g=f();t.on(`error`,e=>
|
|
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%oe.length,l=e);let n=oe[t],i=`${j(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(`${ae} ${e??r}\n`),this):this}}},M=new Set;function ce(){for(let e of ne)try{e.kill(`SIGKILL`)}catch{}for(let t of M)try{e.rmSync(t,{recursive:!0,force:!0})}catch{}process.exit(1)}process.on(`SIGINT`,ce),process.on(`SIGTERM`,ce);const le=e=>/[.+^${}()|[\]\\]/.test(e)?`\\${e}`:e,ue=e=>{let t=``,n=0;for(;n<e.length;){let r=e[n];if(r===`*`)if(e[n+1]===`*`){let r=n===0||e[n-1]===`/`;n+=2;let i=e[n]===`/`;r&&i?(t+=`(?:.*/)?`,n+=1):t+=`.*`}else t+=`[^/]*`,n+=1;else r===`?`?(t+=`[^/]`,n+=1):r===`/`?(t+=`/`,n+=1):(t+=le(r),n+=1)}return t},de=e=>{let t=e.trim();if(!t||t.startsWith(`#`))return null;let n=!1;t.startsWith(`!`)&&(n=!0,t=t.slice(1));let r=!1;t.endsWith(`/`)&&(r=!0,t=t.replace(/\/+$/,``));let i=!1;if(t.startsWith(`/`)?(i=!0,t=t.replace(/^\/+/,``)):t.includes(`/`)&&(i=!0),!t)return null;let a=ue(t),o=i?`^${a}$`:`^(?:.*/)?${a}$`;return{negated:n,dirOnly:r,regex:new RegExp(o)}},fe=e=>{let t=[];for(let n of e.split(/\r?\n/)){let e=de(n);e&&t.push(e)}return{ignores(e,r){let i=e.split(n.sep).join(`/`);if(!i||i===`.`)return!1;let a=!1;for(let e of t)e.dirOnly&&!r||e.regex.test(i)&&(a=!e.negated);return a}}},pe=t=>{let r;try{r=e.readFileSync(n.join(t,`.gitpickignore`),`utf8`)}catch{return null}return fe(r)},me=e=>({matcher:pe(e),srcRoot:e}),he=async(t,r,i,a)=>{let o=i??r,s=a??me(t),c=await e.promises.readdir(t,{withFileTypes:!0});await e.promises.mkdir(r,{recursive:!0});let l=[];for(let i of c){if(i.name===`.git`)continue;let a=n.join(t,i.name),c=n.join(r,i.name),u=n.relative(s.srcRoot,a);if(u!==`.gitpickignore`&&!s.matcher?.ignores(u,i.isDirectory()))if(i.isDirectory())l.push(...await he(a,c,o,s));else if(i.isSymbolicLink()){let t=await e.promises.readlink(a);await e.promises.rm(c,{force:!0,recursive:!0}),await e.promises.symlink(t,c),l.push(n.relative(o,c))}else await e.promises.copyFile(a,c),l.push(n.relative(o,c))}return l},N=e=>Number(((performance.now()-e)/1e3).toFixed(2)),P=(e,t,n)=>{let r=t,i=t+n;for(;r<i&&e[r]!==0;)r++;return e.toString(`utf8`,t,r)},ge=(e,t,n)=>{let r=P(e,t,n).trim();return r?parseInt(r,8):0},_e=e=>{let t=!0;for(let n=0;n<512;n++)if(e[n]!==0){t=!1;break}if(t)return null;let n=P(e,0,100),r=P(e,345,155);return{name:r?`${r}/${n}`:n,size:ge(e,124,12),type:String.fromCharCode(e[156]),linkname:P(e,157,100),mode:ge(e,100,8)}},ve=e=>{let t={},n=0;for(;n<e.length;){let r=n;for(;r<e.length&&e[r]!==32;)r++;if(r>=e.length)break;let i=Number.parseInt(e.toString(`ascii`,n,r),10);if(!Number.isFinite(i)||i<=0||n+i>e.length)break;let a=e.toString(`utf8`,r+1,n+i-1),o=a.indexOf(`=`);o>0&&(t[a.slice(0,o)]=a.slice(o+1)),n+=i}return t},ye=async(t,r,i=1)=>{let a=0,o=0,s={},c=async(t,c)=>{let l=s.path??t.name,u=s.linkpath??t.linkname;s={};let d=l.split(`/`).slice(i).join(`/`);if(!d)return;if(n.isAbsolute(d)||d.split(`/`).some(e=>e===`..`))throw Error(`untar: refusing unsafe path '${d}'`);let f=n.join(r,d);if(t.type===`5`)await e.promises.mkdir(f,{recursive:!0});else if(t.type===`2`){await e.promises.mkdir(n.dirname(f),{recursive:!0});try{await e.promises.symlink(u,f),o++}catch{console.warn(`Warning: could not create symlink ${d} -> ${u}`)}}else if(t.type===`0`||t.type===`\0`||t.type===``)await e.promises.mkdir(n.dirname(f),{recursive:!0}),await e.promises.writeFile(f,c,{mode:t.mode&511||420}),a++;else throw Error(`untar: unsupported entry type '${t.type}' for ${d}`)},l=async(e,t)=>{e.type===`x`||e.type===`g`?s={...s,...ve(t)}:await c(e,t)},u=[],d=0,p=e=>{let t=Buffer.allocUnsafe(e),n=0;for(;n<e;){let r=u[0],i=Math.min(r.length,e-n);r.copy(t,n,0,i),n+=i,i===r.length?u.shift():u[0]=r.subarray(i)}return d-=e,t},m=null,h=512,g=!1,_=f();t.on(`error`,e=>_.destroy(e));for await(let e of t.pipe(_))for(u.push(e),d+=e.length;d>=h;)if(m===null){let e=_e(p(512));if(!e){g=!0;continue}let t=Math.ceil(e.size/512)*512;t===0?await l(e,Buffer.alloc(0)):(m=e,h=t)}else{let e=p(h);await l(m,e.subarray(0,m.size)),m=null,h=512}if(m!==null||!g)throw Error(`untar: truncated archive (incomplete or missing end marker)`);return{files:a,symlinks:o}},be=e=>e.split(`/`).map(encodeURIComponent).join(`/`),xe=e=>{let{host:t,owner:n,repository:r,branch:i}=e,a=`${encodeURIComponent(n)}/${encodeURIComponent(r)}`,o=be(i);switch(t){case`github.com`:return`https://codeload.github.com/${a}/tar.gz/${o}`;case`gitlab.com`:return`https://gitlab.com/${a}/-/archive/${o}.tar.gz`;case`bitbucket.org`:return`https://bitbucket.org/${a}/get/${o}.tar.gz`;case`codeberg.org`:return`https://codeberg.org/${a}/archive/${o}.tar.gz`;default:return null}},Se=async(t,n)=>{let r=xe(t);if(!r)return!1;let i;try{i=await fetch(r)}catch{return!1}if(!i.ok||!i.body)return!1;try{await e.promises.mkdir(n,{recursive:!0}),await ye(d.fromWeb(i.body),n)}catch{return!1}return!0},F=e=>`${e}${Date.now()}${Math.random().toString(16).slice(2,6)}`,Ce=e=>e.split(`/`).map(encodeURIComponent).join(`/`),we=e=>{let{host:t,owner:n,repository:r,branch:i,path:a}=e;if(!a)return null;let o=`${encodeURIComponent(n)}/${encodeURIComponent(r)}`,s=Ce(i),c=Ce(a);switch(t){case`github.com`:return`https://raw.githubusercontent.com/${o}/${s}/${c}`;case`gitlab.com`:return`https://gitlab.com/${o}/-/raw/${s}/${c}`;case`codeberg.org`:return`https://codeberg.org/${o}/raw/${s}/${c}`;default:return null}},Te=async(t,r)=>{let i=we(t);if(!i)return null;let a=performance.now(),o;try{o=await fetch(i)}catch{return null}if(!o.ok||!o.body)return null;let s=N(a),c=performance.now(),l=`${r}.${F(`gitpick-`)}.part`;M.add(l);try{await e.promises.mkdir(n.dirname(r),{recursive:!0}),await p(d.fromWeb(o.body),e.createWriteStream(l)),await e.promises.rename(l,r)}catch{return await e.promises.rm(l,{force:!0}),null}finally{M.delete(l)}let u=N(c),{size:f}=await e.promises.stat(r);return{size:f,networkTime:s,copyTime:u}},Ee=(e,t)=>{for(let n=t.length;n>=1;n--){let r=t.slice(0,n).join(`/`);if(e.has(r))return{branch:r,path:t.slice(n).join(`/`)}}return null},De=async e=>{let{stdout:t}=await C(`git`,[`for-each-ref`,`--format=%(refname)`,`refs/heads`,`refs/remotes/origin`,`refs/tags`],{cwd:e}),n=new Set;for(let e of t.split(`
|
|
5
5
|
`)){let t=e.trim();if(t.startsWith(`refs/heads/`))n.add(t.slice(11));else if(t.startsWith(`refs/remotes/origin/`)){let e=t.slice(20);e!==`HEAD`&&n.add(e)}else t.startsWith(`refs/tags/`)&&n.add(t.slice(10))}return n},Oe=async e=>{let{stdout:t}=await C(`git`,[`ls-remote`,`--heads`,`--tags`,e]),n=new Set;for(let e of t.split(`
|
|
6
6
|
`)){let t=e.split(` `)[1]?.trim();t&&(t.startsWith(`refs/heads/`)?n.add(t.slice(11)):t.startsWith(`refs/tags/`)&&n.add(t.slice(10).replace(/\^\{\}$/,``)))}return n},ke=async(e,t)=>t.length?Ee(await De(e),t):null,Ae=async(e,t)=>t.length?Ee(await Oe(e),t):null,je=async e=>{try{return await C(`git`,[`symbolic-ref`,`-q`,`HEAD`],{cwd:e}),!1}catch{return!0}},Me=async(e,t)=>{if(t.refSegments?.length){let n=await ke(e,t.refSegments);n&&(t.branch=n.branch,t.path=n.path)}await C(`git`,[`checkout`,t.branch],{cwd:e})},Ne=async(e,t,n,r)=>{let i=r?[`--recursive`]:[];try{return await C(`git`,[`clone`,e,t,`--branch`,n.branch,`--depth`,`1`,`--single-branch`,...i]),`shallow`}catch{return await C(`git`,[`clone`,e,t,...i]),await Me(t,n),`full`}},Pe=async(t,r,i,a,o)=>{if(o===`full`||!i.refSegments||i.refSegments.length<=1||e.existsSync(n.join(r,i.path))||!await je(r))return null;let s=await Ae(t,i.refSegments);return!s||s.branch===i.branch?null:(i.branch=s.branch,i.path=s.path,await e.promises.rm(r,{recursive:!0,force:!0}),Ne(t,r,i,a))},Fe=e=>e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`,Ie={raw:`raw (single GET)`,tarball:`tarball (stream)`,shallow:`shallow (depth=1)`,full:`full (depth=full)`},I=async(r,i,a)=>{let o=i.tree||i.quiet,s=i.verbose&&!o;process.platform===`win32`&&await C(`git`,[`config`,`--global`,`core.longpaths`,`true`]);let c=`https://${r.host}/${r.owner}/${r.repository}.git`,l=se(),u=performance.now();!i.watch&&!o&&l.start(`Picking ${r.type}${r.type===`repository`?` without .git`:` from repository`}...`);let d=(e,t,n,d,f)=>{let p=N(u);return o||(i.watch?console.log(`- Synced at `+new Date().toLocaleTimeString()):l.success(`Picked ${r.type}${r.type===`repository`?` without .git`:` from repository`} in ${p} seconds.`)),s&&(console.log(D(` clone: ${Ie[f]??f}`)),console.log(D(` from: ${c} @ ${j(r.branch)}`)),console.log(D(` to: ${a}`)),console.log(D(` files: ${e.length} (${Fe(t)})`)),console.log(D(` network: ${n}s`)),console.log(D(` copy: ${d}s`)),console.log(D(` total: ${p}s`))),{files:e,duration:p,networkTime:n,copyTime:d,totalSize:t,cloneStrategy:f}};if(i.fast&&(r.type===`blob`||r.type===`raw`)){let e=await Te(r,a);if(e)return d([n.basename(a)],e.size,e.networkTime,e.copyTime,`raw`)}let f=`https://${r.token?r.token+`@`:r.token}${r.host}/${r.owner}/${r.repository}.git`,p=n.resolve(t.tmpdir(),F(`${r.repository}-`));M.add(p);let m=performance.now(),h;if(i.fast&&!i.recursive&&(r.type===`tree`||r.type===`repository`)&&await Se(r,p)&&e.existsSync(n.join(p,r.path)))h=`tarball`;else{await e.promises.rm(p,{recursive:!0,force:!0}),h=await Ne(f,p,r,i.recursive);let t=await Pe(f,p,r,i.recursive,h);t&&(h=t)}let g=N(m),_=n.resolve(p,r.path),v=await e.promises.stat(_),y=[],b=performance.now();v.isDirectory()?(await e.promises.mkdir(a,{recursive:!0}),y=await he(_,a)):(await e.promises.mkdir(n.dirname(a),{recursive:!0}),await e.promises.copyFile(_,a),y=[n.basename(a)]);let x=N(b),S=0;for(let t of y)try{let r=await e.promises.stat(n.join(a,t));S+=r.size}catch{let t=await e.promises.stat(a);S+=t.size;break}return await e.promises.rm(p,{recursive:!0,force:!0}),M.delete(p),d(y,S,g,x,h)},Le=e=>e?.stderr?.trim()||e?.stdout?.trim()||e?.message||`git failed`,L=async(r,i,a)=>{let o=!!i.autoCommit||i.commit!==void 0;if(!i.init&&!o)return;let s=i.quiet,c=e.existsSync(r)&&e.statSync(r).isFile(),l=c?n.dirname(r):r;if(n.resolve(l)===process.cwd()){s||console.log(A(`
|
|
7
7
|
Skipping git init: won't initialize a repository in the current directory (clone into a sub-directory to init there).`));return}if(!e.existsSync(n.join(l,`.git`)))try{await C(`git`,[`init`],{cwd:l})}catch(e){s||console.log(A(`\nSkipping git init — git reported:\n${Le(e)}`));return}if(!o)return;if(!c&&!a?.length){s||console.log(A(`
|
|
@@ -19,7 +19,7 @@ Skipping commit: nothing was cloned to commit.`));return}let u=i.commit||`chore:
|
|
|
19
19
|
`;let s=f.length>r?D(`${l+1}-${Math.min(l+r,f.length)}/${f.length}`)+D(` • `):``,d=D(`↑↓:navigate esc/q:back`);i+=` ${s}${d}\n`,u.write(i)}function S(e){let t=e.toString();if(t===``){g=!1,_=null,d.removeListener(`data`,S),p(),process.removeListener(`exit`,m),process.removeListener(`SIGINT`,h),a([]);return}if(t===`\x1B`||t===`q`||t===`Q`||t===`\r`){g=!1,_=null,d.removeListener(`data`,S),d.on(`data`,x),y();return}(t===`\x1B[A`||t===`k`)&&c>0&&c--,(t===`\x1B[B`||t===`j`)&&c<f.length-1&&c++,b()}g=!0,_=b,d.on(`data`,S),b()}function x(e){let t=cr(o),n=t.length+1,r=e.toString();if(r===``||r===`q`||r===`Q`){p(),process.removeListener(`exit`,m),process.removeListener(`SIGINT`,h),a([]);return}if(r===`c`||r===`C`){p(),process.removeListener(`exit`,m),process.removeListener(`SIGINT`,h),a(dr(o));return}if((r===`\x1B[A`||r===`k`)&&c>0&&c--,(r===`\x1B[B`||r===`j`)&&c<n-1&&c++,c===0&&(r===` `||r===`\r`)||r===`.`){let e=o.every(e=>e.selected);for(let t of o)K(t,!e)}if(r===` `&&c>0){let e=t[c-1];if(e){let t=!e.node.selected;if(K(e.node,t),t&&e.node.type===`symlink`&&e.node.linkTarget){let t=q(o,lr(e.node.path,e.node.linkTarget));t&&K(t,!0)}ur(o)}}if(r===`\r`&&c>0){let e=t[c-1];if(e&&e.node.type===`tree`)e.node.expanded=!e.node.expanded;else if(e&&e.node.type===`symlink`&&e.node.linkTarget.endsWith(`/`)){let t=lr(e.node.path,e.node.linkTarget),n=t.split(`/`);for(let e=1;e<=n.length;e++){let t=q(o,n.slice(0,e).join(`/`));t&&t.type===`tree`&&(t.expanded=!0)}let r=q(o,t);if(r){r.type===`tree`&&(r.expanded=!0);let e=cr(o).findIndex(e=>e.node===r);e>=0&&(c=e+1)}}else if(e&&i&&(e.node.type===`blob`||e.node.type===`symlink`)){b(e.node);return}}if((r===`\x1B[C`||r===`l`)&&c>0){let e=t[c-1];e&&e.node.type===`tree`&&(e.node.expanded=!0)}if((r===`\x1B[D`||r===`h`)&&c>0){let e=t[c-1];e&&e.node.type===`tree`&&(e.node.expanded=!1)}y()}d.on(`data`,x),y()})}function mr(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 Y=async e=>{let t=(await C(`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},hr=[{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`},{prefix:`git@codeberg.org:`,host:`codeberg.org`},{prefix:`https://codeberg.org/`,host:`codeberg.org`}];async function gr(e,{branch:t,target:n}){let r=e.match(/^https:\/\/([^@]+)@(github\.com|gitlab\.com|bitbucket\.org|codeberg\.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||``,"codeberg.org":process.env.CODEBERG_TOKEN||``};for(let{prefix:n,host:r}of hr)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 hr)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;if(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 Y(l),f=``);else if(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 Y(l),f=``);else if(a===`bitbucket.org`)o[2]===`src`?(u=`tree`,d=t||o[3],f=o.slice(4).join(`/`)):(u=`repository`,d=t||await Y(l),f=``);else if(a===`codeberg.org`)[`src`,`raw`,`media`].includes(o[2])&&[`branch`,`tag`,`commit`].includes(o[3])?(u=o[2]===`src`?`tree`:`blob`,d=t||o[4],f=o.slice(5).join(`/`)):(u=`repository`,d=t||await Y(l),f=``);else{let e=a;throw Error(`Unsupported host: ${e}`)}let p=n||(u===`blob`?`.`:f.split(`/`).pop()||c),m=!t&&(u===`tree`||u===`blob`)?[d,...f?f.split(`/`):[]]:void 0;return{token:i,host:a,owner:s,repository:c,type:u,branch:d,path:f,target:p,refSegments:m}}const _r=n.join(t.homedir(),`.cache`,`gitpick`),vr=n.join(_r,`update-check.json`);function yr(){try{return JSON.parse(e.readFileSync(vr,`utf-8`))}catch{return null}}function br(t){try{e.mkdirSync(_r,{recursive:!0}),e.writeFileSync(vr,JSON.stringify(t))}catch{}}function xr(){return new Promise(e=>{let t=m.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 Sr(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 X(e,t){if(t)return;let n=yr();n&&Sr(n.latestVersion,e)&&console.log(D(`\n Update available: ${A(e)} → ${j(E(n.latestVersion))}\n Run ${j(`npm i -g gitpick`)} to update\n`))}function Cr(){let e=yr();e&&Date.now()-e.lastCheck<864e5||setTimeout(async()=>{let e=await xr();e&&br({lastCheck:Date.now(),latestVersion:e})},0)}const wr=Symbol(`singleComment`),Tr=Symbol(`multiComment`),Z=(e,t,n)=>e.slice(t,n).replace(/[^ \t\r\n]/g,` `),Er=(e,t)=>{let n=t-1,r=0;for(;e[n]===`\\`;)--n,r+=1;return!!(r%2)};function Dr(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===`"`&&(Er(e,s)||(t=!t)),!t)if(!n&&c+l===`//`)i+=e.slice(r,s),r=s,n=wr,s++;else if(n===wr&&c+l===`\r
|
|
20
20
|
`){s++,n=!1,i+=Z(e,r,s),r=s;continue}else if(n===wr&&c===`
|
|
21
21
|
`)n=!1,i+=Z(e,r,s),r=s;else if(!n&&c+l===`/*`){i+=e.slice(r,s),r=s,n=Tr,s++;continue}else if(n===Tr&&c+l===`*/`){s++,n=!1,i+=Z(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+=Z(i,0,1)+i.slice(1),i=``,r=s,o=-1):c!==` `&&c!==` `&&c!==`\r`&&c!==`
|
|
22
|
-
`&&(i+=e.slice(r,s),r=s,o=-1))}let s=n===wr?Z(e,r):e.slice(r);return a+i+s}const Or=[`.gitpick.json`,`.gitpick.jsonc`],kr=async()=>{let t;for(let r of Or){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(Dr(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 C(process.argv[0],[...process.argv.slice(1),...e.split(/\s+/),`-o`],{stdio:`inherit`});return!0};var Ar=`gitpick`,Q=`6.1.0-canary.
|
|
22
|
+
`&&(i+=e.slice(r,s),r=s,o=-1))}let s=n===wr?Z(e,r):e.slice(r);return a+i+s}const Or=[`.gitpick.json`,`.gitpick.jsonc`],kr=async()=>{let t;for(let r of Or){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(Dr(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 C(process.argv[0],[...process.argv.slice(1),...e.split(/\s+/),`-o`],{stdio:`inherit`});return!0};var Ar=`gitpick`,Q=`6.1.0-canary.22`;const jr=(e,t)=>`\x1b]8;;${t}\x07${e}\x1b]8;;\x07`,Mr=`
|
|
23
23
|
With ${E(`${jr(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific directories or files from GitHub, GitLab, Bitbucket and Codeberg!
|
|
24
24
|
|
|
25
25
|
$ gitpick ${A(`<url>`)} ${k(`[target]`)} ${j(`[options]`)}
|