gitpick 3.27.0-canary.3 → 3.27.0-canary.30

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.
Files changed (3) hide show
  1. package/README.md +43 -116
  2. package/dist/index.js +27 -19
  3. package/package.json +2 -31
package/README.md CHANGED
@@ -1,158 +1,85 @@
1
1
  # GitPick
2
2
 
3
- With [gitpick](https://www.npmjs.com/package/gitpick), you can clone precisely what you need.
3
+ **Clone exactly what you need.**
4
+ No more full-repo clones when all you want is a file or folder.
4
5
 
5
6
  [![npm](https://img.shields.io/npm/v/gitpick?color=red&logo=npm)](https://www.npmjs.com/package/gitpick)
6
- [![npm](https://img.shields.io/npm/dt/gitpick?color=red&logo=npm)](https://www.npmjs.com/package/gitpick)
7
- [![GitHub](https://img.shields.io/github/stars/nrjdalal/gitpick?color=blue)](https://github.com/nrjdalal/gitpick)
8
-
9
- Tired of cloning an entire repository when you only need a specific file or folder? Need to watch remote changes and sync them locally? GitPick is here to help!
10
-
11
- Simply copy the Github URL and run with `npx gitpick <url>`, be that a public or a private repository.
12
-
13
- - Target is optional, and `gitpick` follows default git clone behavior. Read [usage](#usage) for more details.
7
+ [![downloads](https://img.shields.io/npm/dt/gitpick?color=red&logo=npm)](https://www.npmjs.com/package/gitpick)
8
+ [![stars](https://img.shields.io/github/stars/nrjdalal/gitpick?color=blue)](https://github.com/nrjdalal/gitpick)
14
9
 
15
10
  <img width="400" alt="GitPick Meme" src="https://github.com/user-attachments/assets/dde09ae9-1ee4-4cd8-a181-91f8e6ed6ba6" />
16
11
 
17
- ## Features
18
-
19
- Shorthand (or use full URL):
20
-
21
- ```sh
22
- npx gitpick TanStack/router
23
- ```
24
-
25
- Or clone a repository:
12
+ ---
26
13
 
27
- ```sh
28
- npx gitpick https://github.com/TanStack/router
29
- # npx gitpick TanStack/router
30
- ```
14
+ ## ✨ Features
31
15
 
32
- Or clone a specific directory:
16
+ - 🔍 Clone individual files or folders from any GitHub repository
17
+ - ⚙️ Auto-detects branches and target directory (if not specified) like `git clone`
18
+ - 🔁 Sync changes remotely with `--watch` using intervals (e.g., `15s`, `1m`, `1h`)
19
+ - 🗑️ Overwrite existing files without prompt using `--overwrite`
20
+ - 🔐 Works with public & private repositories (via PAT)
21
+ - 🧠 Shorthand URLs supported (e.g. `TanStack/router`)
33
22
 
34
- ```sh
35
- npx gitpick https://github.com/TanStack/router/tree/main/examples
36
- # npx gitpick TanStack/router/tree/main/examples
37
- ```
23
+ ---
38
24
 
39
- Or clone a specific file:
25
+ ## 🚀 Quick Usage
40
26
 
41
27
  ```sh
42
- npx gitpick https://github.com/TanStack/router/tree/main/package.json
43
- # npx gitpick TanStack/router/tree/main/package.json
28
+ npx gitpick <url> [target] [options]
44
29
  ```
45
30
 
46
- - Clone a file or directory from a GitHub repository.
47
- - Autodetect branch and target directory if not provided explicitly.
48
- - Clone from public or private repositories using personal access tokens.
49
- - Overwrite existing files without prompt using `-o` or `--overwrite` flag.
50
- - Sync changes with remote repository at a specified interval using `-w` or `--watch` flag.
51
- - Use shorthands like `npx gitpick TanStack/router` or `npx gitpick TanStack/router/tree/main/examples`, no need to provide full URL.
52
-
53
- <img width="600" alt="Demo Image" src="https://github.com/user-attachments/assets/954f670a-f30d-43cf-b674-f65a170c989d" />
54
-
55
- ## Usage
56
-
57
- ```text
58
- With gitpick, you can clone precisely what you need.
59
-
60
- 🚀 More awesome tools at https://github.com/nrjdalal
61
-
62
- -------------------------------------
63
- gitpick <url> [target] [options]
64
- -------------------------------------
65
-
66
- Hint: Target is optional, and follows default git clone behavior.
67
-
68
- Arguments:
69
- url GitHub URL with path to file/folder
70
- target Directory to clone into (optional)
71
-
72
- Options:
73
- -b, --branch Branch to clone
74
- -o, --overwrite Skip overwrite prompt
75
- -w, --watch [time] Watch the repository and sync every [time]
76
- (e.g. 1h, 30m, 15s) default: 1m
77
- -h, --help display help for command
78
- -v, --version display the version number
31
+ - [target] and [options] are optional
79
32
 
80
33
  Examples:
81
- $ gitpick <url>
82
- $ gitpick <url> [target]
83
- $ gitpick <url> [target] -b [branch]
84
- $ gitpick <url> [target] -w [time]
85
- $ gitpick <url> [target] -b [branch] -w [time]
86
- ```
87
-
88
- If you wish to clone a private repository, generate a [personal access token](https://github.com/settings/personal-access-tokens/new).
89
-
90
- - For fine-grained access, select Repository permissions to be `Contents: Read-Only`.
91
-
92
- - Use `https://<token>@github.com` as URL prefix when cloning.
93
-
94
- Checkout https://github.com/nrjdalal for more awesome repositories.
95
-
96
- ## Installation
97
-
98
- You can install GitPick globally using npm:
99
34
 
100
35
  ```sh
101
- npm install -g gitpick
36
+ npx gitpick https://github.com/TanStack/router # full repo without .git
37
+ npx gitpick TanStack/router/tree/main/examples # a folder
38
+ npx gitpick TanStack/router/tree/main/package.json # a file
39
+ npx gitpick <url/shorthand> -w 30s # sync every 30 seconds
40
+ npx gitpick <url/shorthand> -o # overwrite if exists
41
+ npx gitpick https://<token>@github.com/owner/repo # private repo
102
42
  ```
103
43
 
104
- After installing, you can run the command:
105
-
106
- ```sh
107
- gitpick <url> [target] [options]
108
- ```
44
+ ---
109
45
 
110
- Or use `npx` to run the command without installing:
46
+ ## 🔧 Options
111
47
 
112
- ```sh
113
- npx gitpick <url> [target] [options]
48
+ ```txt
49
+ -b, --branch Branch to clone from
50
+ -o, --overwrite Skip overwrite prompt
51
+ -w, --watch [time] Auto-sync at intervals (default: 1m)
52
+ -h, --help Show help
53
+ -v, --version Show version
114
54
  ```
115
55
 
116
- ## Usage
117
-
118
- Run `npx gitpick <url> [target] [options]` to clone a file or directory from a GitHub repository.
119
-
120
56
  ---
121
57
 
122
- Say your files are located at following GitHub URL with a directory:
123
-
124
- > https://github.com/nrjdalal/nrjdalal/tree/main/.config
58
+ ## 🔐 Private Repos
125
59
 
126
- You can sync them to a target directory in your project using:
60
+ Use a [GitHub personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with `repo -> contents: read-only` permission:
127
61
 
128
- ```bash
129
- npx gitpick https://github.com/nrjdalal/nrjdalal/tree/main/.config config
62
+ ```
63
+ npx gitpick https://<token>@github.com/owner/repo
130
64
  ```
131
65
 
132
- > This will clone the `.config` directory from the `nrjdalal/nrjdalal` repository to the `config` directory in your project. If no target directory is given, it will use the last segment of the URL, e.g., in this case, `.config`.
66
+ Create PAT: https://github.com/settings/personal-access-tokens/new
133
67
 
134
68
  ---
135
69
 
136
- If you need to watch for changes, just add `-w` or `-w [time]` (e.g., `1s`, `1m`, `1h` which is time in a human-readable format, default is `1m`):
70
+ ## 📦 Install Globally (Optional)
137
71
 
138
- ```bash
139
- gitpick https://github.com/nrjdalal/nrjdalal/tree/main/.config -w
72
+ ```sh
73
+ npm install -g gitpick
74
+ gitpick <url> [target] [options]
140
75
  ```
141
76
 
142
77
  ---
143
78
 
144
- Additionally, you can use this tool to clone any file or directory from any repository. For example:
145
-
146
- ```bash
147
- gitpick https://github.com/nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-pro
148
- ```
149
-
150
- The above command will clone the `next.js-pro` template from that particular repository.
151
-
152
- ---
79
+ ## 🛠 More Tools
153
80
 
154
- I would love feedback from you all. Let's go!
81
+ Check out more projects at [github.com/nrjdalal](https://github.com/nrjdalal)
155
82
 
156
- ## License
83
+ ## 📄 License
157
84
 
158
- This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
85
+ MIT [LICENSE](LICENSE)
package/dist/index.js CHANGED
@@ -1,32 +1,40 @@
1
1
  #!/usr/bin/env node
2
- import T from"fs";import{parseArgs as H}from"node:util";import I from"path";import{cancel as M,confirm as S,intro as U,isCancel as L,log as A}from"@clack/prompts";import R from"terminal-link";import o from"yoctocolors";var v="gitpick",k="3.26.0";import m from"node:fs";import G from"node:os";import j from"node:path";import{log as f,spinner as P}from"@clack/prompts";import W from"simple-git";import g from"node:fs";import x from"node:path";var u=async(t,i)=>{let a=await g.promises.readdir(t,{withFileTypes:!0});await g.promises.mkdir(i,{recursive:!0});for(let s of a){if(s.name===".git")continue;let e=x.join(t,s.name),r=x.join(i,s.name);s.isDirectory()?await u(e,r):await g.promises.copyFile(e,r)}};var w=async(t,i,a)=>{let s=P();try{let e=W();process.platform==="win32"&&await e.raw(["config","--global","core.longpaths","true"]);let r=`https://${t.token?t.token+"@":t.token}github.com/${t.owner}/${t.repository}.git`,c=j.join(G.tmpdir(),`${t.repository}-${Date.now()}${Math.random().toString(16).slice(2,6)}`);i.watch||s.start(`Picking ${t.type}${t.type==="repository"?" without .git":" from repository"}`);let n=performance.now();await e.clone(r,c,["--depth","1","--single-branch","--branch",t.branch]);let p=j.join(c,t.path);(await m.promises.stat(p)).isDirectory()?(await m.promises.mkdir(a,{recursive:!0}),await u(p,a)):(await m.promises.mkdir(a,{recursive:!0}),await m.promises.copyFile(p,a+"/"+t.path.split("/").pop())),i.watch?f.success("Synced at "+new Date().toLocaleTimeString()):s.stop(`Picked ${t.type}${t.type==="repository"?" without .git":" from repository"} in ${((performance.now()-n)/1e3).toFixed(2)} seconds!`),await m.promises.rm(c,{recursive:!0,force:!0})}catch(e){s.stop("Level 2: An error occurred while cloning!"),e instanceof Error?f.error("Error: "+e.message):f.error("Unexpected Error: "+JSON.stringify(e,null,2)),process.exit(1)}};function y(t){if(typeof t=="number"||/^\d+$/.test(t))return typeof t=="number"?t:parseInt(t,10);let i=/(\d+)([hms])/g,a=0,s;for(;(s=i.exec(t))!==null;){let e=parseInt(s[1],10);switch(s[2]){case"h":a+=e*36e5;break;case"m":a+=e*6e4;break;case"s":a+=e*1e3;break}}return a}import B from"simple-git";var D=async t=>{var e,r;let i=await B().listRemote([t]),a=(e=i.match(/(.+)\s+HEAD/))==null?void 0:e[1],s=(r=i.match(new RegExp(`${a}\\s+refs/heads/(.+)`)))==null?void 0:r[1];if(!s)throw new Error("Could not determine default branch!");return s};async function E(t,{branch:i,target:a}){let s=/^https:\/\/([^@]+)@github\.com/,e=t.match(s),r="";e&&(r=e[1],t=t.replace(s,"https://github.com"));let c=["git@github.com:","https://github.com/","https://raw.githubusercontent.com/"];for(let b of c)if(t.startsWith(b)){t=t.replace(b,"");break}let n=t.split("/"),p=n[0],h=n[1].endsWith(".git")?n[1].slice(0,-4):n[1],l=n[2]==="blob"?"blob":n[2]==="tree"?"tree":n[2]+n[3]==="refsheads"?"raw":"repository",C=i||(l==="repository"?await D(`https://${r&&r+"@"}github.com/${p}/${h}`):l==="raw"?n[4]:n[3]),d=l?l==="raw"?n.slice(5).join("/"):n.slice(4).join("/"):n.slice(2).join("/")||"/",F=a||(l==="blob"?".":d.split("/").pop()||h);return{token:r,owner:p,repository:h,type:l,branch:C,path:d,target:F}}var O=`
3
- ${o.whiteBright("With GitPick, you can clone precisely what you need.")}
2
+ var vt=Object.defineProperty,kt=Object.defineProperties;var Et=Object.getOwnPropertyDescriptors;var S=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,J=Object.prototype.propertyIsEnumerable;var v=(t,e)=>(e=Symbol[t])?e:Symbol.for("Symbol."+t),jt=t=>{throw TypeError(t)};var T=(t,e,o)=>e in t?vt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o,f=(t,e)=>{for(var o in e||(e={}))_.call(e,o)&&T(t,o,e[o]);if(S)for(var o of S(e))J.call(e,o)&&T(t,o,e[o]);return t},b=(t,e)=>kt(t,Et(e));var D=(t,e)=>{var o={};for(var r in t)_.call(t,r)&&e.indexOf(r)<0&&(o[r]=t[r]);if(t!=null&&S)for(var r of S(t))e.indexOf(r)<0&&J.call(t,r)&&(o[r]=t[r]);return o};var V=(t,e,o)=>T(t,typeof e!="symbol"?e+"":e,o);var y=function(t,e){this[0]=t,this[1]=e},F=(t,e,o)=>{var r=(i,a,c,p)=>{try{var l=o[i](a),u=(a=l.value)instanceof y,w=l.done;Promise.resolve(u?a[0]:a).then(m=>u?r(i==="return"?i:"next",a[1]?{done:m.done,value:m.value}:m,c,p):c({value:m,done:w})).catch(m=>r("throw",m,c,p))}catch(m){p(m)}},n=i=>s[i]=a=>new Promise((c,p)=>r(i,a,c,p)),s={};return o=o.apply(t,e),s[v("asyncIterator")]=()=>s,n("next"),n("throw"),n("return"),s},q=t=>{var e=t[v("asyncIterator")],o=!1,r,n={};return e==null?(e=t[v("iterator")](),r=s=>n[s]=i=>e[s](i)):(e=e.call(t),r=s=>n[s]=i=>{if(o){if(o=!1,s==="throw")throw i;return i}return o=!0,{done:!1,value:new y(new Promise(a=>{var c=e[s](i);c instanceof Object||jt("Object expected"),a(c)}),1)}}),n[v("iterator")]=()=>n,r("next"),"throw"in e?r("throw"):n.throw=s=>{throw s},"return"in e&&r("return"),n},C=(t,e,o)=>(e=t[v("asyncIterator")])?e.call(t):(t=t[v("iterator")](),e={},o=(r,n)=>(n=t[r])&&(e[r]=s=>new Promise((i,a,c)=>(s=n.call(t,s),c=s.done,Promise.resolve(s.value).then(p=>i({value:p,done:c}),a)))),o("next"),o("return"),e);import xt from"fs";import{parseArgs as Yt}from"node:util";import Zt from"path";import E from"node:fs";import zt from"node:os";import mt from"node:path";import O from"node:fs";import z from"node:path";var W=async(t,e)=>{let o=await O.promises.readdir(t,{withFileTypes:!0});await O.promises.mkdir(e,{recursive:!0});for(let r of o){if(r.name===".git")continue;let n=z.join(t,r.name),s=z.join(e,r.name);r.isDirectory()?await W(n,s):await O.promises.copyFile(n,s)}};import Pt from"node:process";import{stripVTControlCharacters as St}from"node:util";var K=t=>({start:Pt.hrtime.bigint(),command:t.map(e=>Ct(St(e))).join(" "),state:{stdout:"",stderr:"",output:""}}),Ct=t=>/[^\w./-]/.test(t)?`'${t.replaceAll("'","'\\''")}'`:t;var B=function(r,n,s){return F(this,arguments,function*(t,{state:e},o){if(e.isIterating===!1)throw new Error(`The subprocess must be iterated right away, for example:
3
+ for await (const line of spawn(...)) { ... }`);e.isIterating=!0;try{let{[o]:l}=yield new y(t.nodeChildProcess);if(!l)return;let u="";try{for(var i=C(l.iterator({destroyOnReturn:!1})),a,c,p;a=!(c=yield new y(i.next())).done;a=!1){let w=c.value;let m=`${u}${w}`.split(/\r?\n/);u=m.pop(),yield*q(m)}}catch(c){p=[c]}finally{try{a&&(c=i.return)&&(yield new y(c.call(i)))}finally{if(p)throw p[0]}}u&&(yield u)}finally{yield new y(t)}})},Q=function(...t){return F(this,null,function*(){try{let e=[];for(;t.length>0;){e=t.map((i,a)=>{var c;return(c=e[a])!=null?c:It(i)});let[{value:o,done:r},n]=yield new y(Promise.race(e.map((i,a)=>Promise.all([i,a])))),[s]=t.splice(n,1);e.splice(n,1),r||(t.push(s),yield o)}}finally{yield new y(Promise.all(t.map(e=>e.return())))}})},It=async t=>{try{return await t.next()}catch(e){await t.throw(e)}};import k from"node:path";import Y from"node:process";import{fileURLToPath as Rt}from"node:url";var Z=c=>{var p=c,{stdin:t,stdout:e,stderr:o,stdio:r=[t,e,o],env:n,preferLocal:s,cwd:i="."}=p,a=D(p,["stdin","stdout","stderr","stdio","env","preferLocal","cwd"]);var m;let l=i instanceof URL?Rt(i):k.resolve(i),u=n?f(f({},Y.env),n):void 0,w=(m=r[0])==null?void 0:m.string;return b(f({},a),{input:w,stdio:w===void 0?r:["pipe",...r.slice(1)],env:s?At(u!=null?u:Y.env,l):u,cwd:l})},At=(n,r)=>{var s=n,{Path:t="",PATH:e=t}=s,o=D(s,["Path","PATH"]);let i=e.split(k.delimiter),a=X([],k.resolve(r)).map(c=>k.join(c,"node_modules/.bin")).filter(c=>!i.includes(c));return b(f({},o),{PATH:[...a,e].filter(Boolean).join(k.delimiter)})},X=(t,e)=>t.at(-1)===e?t:X([...t,e],k.resolve(e,".."));import{pipeline as Tt}from"node:stream/promises";var tt=async t=>{var r;let[[e,o]]=await Promise.all([Promise.allSettled(t),Dt(t)]);if(o.reason)throw o.reason.pipedFrom=(r=e.reason)!=null?r:e.value,o.reason;if(e.reason)throw e.reason;return b(f({},o.value),{pipedFrom:e.value})},Dt=async t=>{try{let[{stdout:e},{stdin:o}]=await Promise.all(t.map(({nodeChildProcess:r})=>r));if(o===null)throw new Error('The "stdin" option must be set on the first "spawn()" call in the pipeline.');if(e===null)throw new Error('The "stdout" option must be set on the last "spawn()" call in the pipeline.');Tt(e,o).catch(()=>{})}catch(e){throw await Promise.allSettled(t.map(({nodeChildProcess:o})=>Ft(o))),e}},Ft=async t=>{let{stdin:e}=await t;e.end()};import{on as Ot,once as Wt}from"node:events";import Bt from"node:process";var et=async(t,{input:e},o)=>{let r=await t;e!==void 0&&r.stdin.end(e);let n=Wt(r,"close");try{return await Promise.race([n,...r.stdio.filter(Boolean).map(s=>Lt(s))]),Ut(o,ot(r)),rt(o)}catch(s){throw await Promise.allSettled([n]),U(s,r,o)}},Lt=async t=>{try{for(var e=C(Ot(t,"error")),o,r,n;o=!(r=await e.next()).done;o=!1){let[s]=r.value;if(!["ERR_STREAM_PREMATURE_CLOSE","EPIPE"].includes(s==null?void 0:s.code))throw s}}catch(r){n=[r]}finally{try{o&&(r=e.return)&&await r.call(e)}finally{if(n)throw n[0]}}},Ut=({command:t},{exitCode:e,signalName:o})=>{if(o!==void 0)throw new $(`Command was terminated with ${o}: ${t}`);if(e!==void 0)throw new $(`Command failed with exit code ${e}: ${t}`)},U=(t,e,o)=>Object.assign(Mt(t,o),ot(e),rt(o)),Mt=(t,{command:e})=>t instanceof $?t:new $(`Command failed: ${e}`,{cause:t}),$=class extends Error{constructor(){super(...arguments);V(this,"name","SubprocessError")}},ot=({exitCode:t,signalCode:e})=>f(f({},t<1?{}:{exitCode:t}),e===null?{}:{signalName:e}),rt=({state:{stdout:t,stderr:e,output:o},command:r,start:n})=>({stdout:L(t),stderr:L(e),output:L(o),command:r,durationMs:Number(Bt.hrtime.bigint()-n)/1e6}),L=t=>t.at(-1)===`
4
+ `?t.slice(0,t.at(-2)==="\r"?-2:-1):t;import{spawn as Vt}from"node:child_process";import{once as qt}from"node:events";import ct from"node:process";import{stat as Gt}from"node:fs/promises";import st from"node:path";import nt from"node:process";var it=async(t,e,o)=>await Ht(t,o)?[G(t),e.map(r=>Jt(r)),b(f({},o),{shell:!0})]:[t,e,o],Ht=async(t,{shell:e,cwd:o,env:r=nt.env})=>nt.platform==="win32"&&!e&&!await Nt(t,o,r),Nt=async(t,e,{Path:o="",PATH:r=o})=>{var n,s;return at.some(i=>t.toLowerCase().endsWith(i))||((s=M[n=`${t}\0${e}\0${r}`])!=null?s:M[n]=await _t(t,e,r))},M={},_t=async(t,e,o)=>{let r=o.split(st.delimiter).filter(Boolean).map(n=>n.replace(/^"(.*)"$/,"$1"));try{await Promise.all(at.flatMap(n=>[e,...r].map(s=>`${st.resolve(s,t)}${n}`)).map(async n=>{try{await Gt(n)}catch(s){return}throw 0}))}catch(n){return!0}return!1},at=[".exe",".com"],Jt=t=>G(G(`"${t.replaceAll(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1")}"`)),G=t=>t.replaceAll(/([()\][%!^"`<>&|;, *?])/g,"^$1");var lt=async(t,e,o,r)=>{try{[t,e]=["node","node.exe"].includes(t.toLowerCase())?[ct.execPath,[...ct.execArgv.filter(s=>!s.startsWith("--inspect")),...e]]:[t,e];let n=Vt(...await it(t,e,o));return pt(n.stdout,r,"stdout"),pt(n.stderr,r,"stderr"),n.once("error",()=>{}),await qt(n,"spawn"),n}catch(n){throw U(n,{},r)}},pt=(t,{state:e},o)=>{t&&(t.setEncoding("utf8"),e.isIterating||(e.isIterating=!1,t.on("data",r=>{e[o]+=r,e.output+=r})))};function x(t,e,o,r){let[n=[],s={}]=Array.isArray(e)?[e,o]:[[],e],i=K([t,...n]),a=Z(s),c=lt(t,n,a,i),p=et(c,a,i);Object.assign(p,{nodeChildProcess:c}),p=r?tt([r,p]):p;let l=B(p,i,"stdout"),u=B(p,i,"stderr");return Object.assign(p,{nodeChildProcess:c,stdout:l,stderr:u,[Symbol.asyncIterator]:()=>Q(l,u),pipe:(w,m,P)=>x(w,m,P,p)})}var I=async(t,e,o)=>{process.platform==="win32"&&await x("git",["config","--global","core.longpaths","true"]);let r=`https://${t.token?t.token+"@":t.token}github.com/${t.owner}/${t.repository}.git`,n=mt.join(zt.tmpdir(),`${t.repository}-${Date.now()}${Math.random().toString(16).slice(2,6)}`);e.watch||console.log(`
5
+ \u{1F50D} Picking ${t.type}${t.type==="repository"?" without .git":" from repository"} ...`);let s=performance.now();await x("git",["clone",r,n,"--branch",t.branch,"--depth","1","--single-branch"]);let i=mt.join(n,t.path);(await E.promises.stat(i)).isDirectory()?(await E.promises.mkdir(o,{recursive:!0}),await W(i,o)):(await E.promises.mkdir(o,{recursive:!0}),await E.promises.copyFile(i,o+"/"+t.path.split("/").pop())),e.watch?console.log("- Synced at "+new Date().toLocaleTimeString()):console.log(`
6
+ \u{1F389} Picked ${t.type}${t.type==="repository"?" without .git":" from repository"} in ${((performance.now()-s)/1e3).toFixed(2)} seconds!`),await E.promises.rm(n,{recursive:!0,force:!0})};import Kt from"node:tty";var ht,ut,R,dt,ft,Qt=(ft=(dt=(R=(ut=(ht=Kt)==null?void 0:ht.WriteStream)==null?void 0:ut.prototype)==null?void 0:R.hasColors)==null?void 0:dt.call(R))!=null?ft:!1,h=(t,e)=>{if(!Qt)return n=>n;let o=`\x1B[${t}m`,r=`\x1B[${e}m`;return n=>{let s=n+"",i=s.indexOf(r);if(i===-1)return o+s+r;let a=o,c=0;for(;i!==-1;)a+=s.slice(c,i)+o,c=i+r.length,i=s.indexOf(r,c);return a+=s.slice(c)+r,a}},Ke=h(0,0),d=h(1,22),Qe=h(2,22),Ye=h(3,23),Ze=h(4,24),Xe=h(53,55),to=h(7,27),eo=h(8,28),oo=h(9,29),ro=h(30,39),H=h(31,39),A=h(32,39),j=h(33,39),so=h(34,39),no=h(35,39),g=h(36,39),io=h(37,39),ao=h(90,39);function N(t){if(typeof t=="number"||/^\d+$/.test(t))return typeof t=="number"?t:parseInt(t,10);let e=/(\d+)([hms])/g,o=0,r;for(;(r=e.exec(t))!==null;){let n=parseInt(r[1],10);switch(r[2]){case"h":o+=n*36e5;break;case"m":o+=n*6e4;break;case"s":o+=n*1e3;break}}return o}var gt=async t=>{var n,s;let e=(await x("git",["ls-remote",t])).stdout,o=(n=e.match(/(.+)\s+HEAD/))==null?void 0:n[1],r=(s=e.match(new RegExp(`${o}\\s+refs/heads/(.+)`)))==null?void 0:s[1];if(!r)throw new Error("Could not determine default branch!");return r};async function wt(t,{branch:e,target:o}){let r=/^https:\/\/([^@]+)@github\.com/,n=t.match(r),s="";n&&(s=n[1],t=t.replace(r,"https://github.com"));let i=["git@github.com:","https://github.com/","https://raw.githubusercontent.com/"];for(let P of i)if(t.startsWith(P)){t=t.replace(P,"");break}let a=t.split("/"),c=a[0],p=a[1].endsWith(".git")?a[1].slice(0,-4):a[1],l=a[2]==="blob"?"blob":a[2]==="tree"?"tree":a[2]+a[3]==="refsheads"?"raw":"repository",u=e||(l==="repository"?await gt(`https://${s&&s+"@"}github.com/${c}/${p}`):l==="raw"?a[4]:a[3]),w=l?l==="raw"?a.slice(5).join("/"):a.slice(4).join("/"):a.slice(2).join("/")||"/",m=o||(l==="blob"?".":w.split("/").pop()||p);return{token:s,owner:c,repository:p,type:l,branch:u,path:w,target:m}}var bt="gitpick",$t="3.27.0-canary.30";var Xt=`
7
+ ${d("With GitPick, you can clone precisely what you need.")}
4
8
 
5
- ${o.cyan("gitpick <url>")} ${o.green("[target]")} ${o.blue("[options]")}
9
+ ${d("gitpick")} ${j("<url>")} ${A("[target]")} ${g("[options]")}
6
10
 
7
- ${o.bold("Hint:")} Target is optional, and follows default git clone behavior.
11
+ ${d("Hint:")} Target is optional, and follows default git clone behavior.
8
12
 
9
- ${o.bold("Arguments:")}
10
- ${o.cyan("url")} GitHub URL with path to file/folder/repository
11
- ${o.green("target")} Directory to clone into (optional)
13
+ ${d("Arguments:")}
14
+ ${j("url")} GitHub URL with path to file/folder/repository
15
+ ${A("target")} Directory to clone into (optional)
12
16
 
13
- ${o.bold("Options:")}
14
- ${o.blue("-b, --branch ")} Branch to clone
15
- ${o.blue("-o, --overwrite")} Skip overwrite prompt
16
- ${o.blue("-w, --watch [time]")} Watch the repository and sync every [time]
17
+ ${d("Options:")}
18
+ ${g("-b, --branch ")} Branch to clone
19
+ ${g("-o, --overwrite")} Skip overwrite prompt
20
+ ${g("-w, --watch [time]")} Watch the repository and sync every [time]
17
21
  (e.g. 1h, 30m, 15s) default: 1m
18
- ${o.blue("-h, --help")} display help for command
19
- ${o.blue("-v, --version")} display the version number
22
+ ${g("-h, --help")} display help for command
23
+ ${g("-v, --version")} display the version number
20
24
 
21
- ${o.bold("Examples:")}
25
+ ${d("Examples:")}
22
26
  $ gitpick <url>
23
27
  $ gitpick <url> [target]
24
28
  $ gitpick <url> [target] -b [branch]
25
29
  $ gitpick <url> [target] -w [time]
26
30
  $ gitpick <url> [target] -b [branch] -w [time]
27
31
 
28
- \u{1F680} More awesome tools at ${o.cyan("https://github.com/nrjdalal")}`,N=t=>{try{return H(t)}catch(i){throw new Error(`Error parsing arguments: ${i.message}`)}},J=async()=>{try{let{positionals:t,values:i}=N({allowPositionals:!0,options:{branch:{type:"string",short:"b"},overwrite:{type:"boolean",short:"o"},force:{type:"boolean",short:"f"},watch:{type:"string",short:"w"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}}});t.length||(i.version&&(console.log(`${v}@${k}`),process.exit(0)),console.log(O),process.exit(0)),t[0]==="clone"&&t.shift();let[a,s]=t,e={branch:i.branch,overwrite:i.overwrite,force:i.force,watch:i.watch};e.overwrite=e.overwrite||e.force,e.watch&&(typeof e.watch=="boolean"&&(e.watch="1m"),console.log(`\u{1F440} Watching every ${y(e.watch)/1e3+"s"}
29
- `));let r=await E(a,{branch:e.branch,target:s});console.log(o.white(`
30
- ${R("GitPick \u2197\uFE0F ","https://github.com/nrjdalal/gitpick")} - Clone specific directories or files from GitHub!
31
- `)),U(`${o.bold(r.owner)}/${o.bold(r.repository)} ${o.green(`<${r.type}:${r.branch}>`)} ${r.type==="repository"?`> ${o.cyan(r.target)}`:`${o.yellow(r.path)} > ${o.cyan(`${r.target}${r.type==="blob"?`/${r.path.split("/").pop()}`:""}`)}`}`);let c=I.resolve(r.target);if(e.watch&&(e.overwrite=!0),T.existsSync(c+(r.type==="blob"?"/"+r.path.split("/").pop():""))&&(await T.promises.readdir(c)).length&&!e.overwrite){let n=r.type==="tree"?"The target directory is not empty. Do you want to overwrite the files?":"The target file already exists. Do you want to overwrite the file?",p=await S({message:n});L(p)&&(M("Operation cancelled."),process.exit(0)),p||(A.info("Chose not to overwrite files."),process.exit(0)),A.info("You can use -o | --overwrite or -f | --force flag to skip this prompt next time.")}if(await w(r,e,c),e.watch){let n=y(e.watch);setInterval(async()=>await w(r,e,c),n)}process.exit(0)}catch(t){console.error(`
32
- Error: ${t.message}`),process.exit(1)}};J();
32
+ \u{1F680} More awesome tools at ${g("https://github.com/nrjdalal")}`,te=t=>{try{return Yt(t)}catch(e){throw new Error(`Error parsing arguments: ${e.message}`)}},ee=async()=>{try{let{positionals:t,values:e}=te({allowPositionals:!0,options:{branch:{type:"string",short:"b"},overwrite:{type:"boolean",short:"o"},force:{type:"boolean",short:"f"},watch:{type:"string",short:"w"},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"}}});t.length||(e.version&&(console.log(`
33
+ ${bt}@${$t}`),process.exit(0)),console.log(Xt),process.exit(0)),t[0]==="clone"&&t.shift();let[o,r]=t,n={branch:e.branch,overwrite:e.overwrite,force:e.force,watch:e.watch};console.log(`
34
+ ${d("GitPick")} - Clone specific directories or files from GitHub!`),n.overwrite=n.overwrite||n.force;let s=await wt(o,{branch:n.branch,target:r});console.info(`
35
+ ${d(s.owner)}/${d(s.repository)} ${A(`<${s.type}:${s.branch}>`)} ${s.type==="repository"?`> ${g(s.target)}`:`${j(s.path)} > ${g(`${s.target}${s.type==="blob"?`/${s.path.split("/").pop()}`:""}`)}`}`);let i=Zt.resolve(s.target);if(n.watch&&(n.overwrite=!0),xt.existsSync(i+(s.type==="blob"?"/"+s.path.split("/").pop():""))&&(await xt.promises.readdir(i)).length&&!n.overwrite&&(console.log(d(`${j(`
36
+ Warning: The target directory is not empty. Use ${g("-f")} | ${g("-o")} to overwrite.`)}`)),process.exit(0)),n.watch){console.log(`
37
+ \u{1F440} Watching every ${N(n.watch)/1e3+"s"}
38
+ `),await I(s,n,i);let a=N(n.watch);setInterval(async()=>await I(s,n,i),a)}else await I(s,n,i),process.exit(0)}catch(t){t instanceof Error?console.log(d(`
39
+ ${H("Error: ")}`)+t.message):console.log(d(`${H(`
40
+ Unexpected Error: `)}`)+JSON.stringify(t,null,2)),process.exit(1)}};ee();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitpick",
3
- "version": "3.27.0-canary.3",
3
+ "version": "3.27.0-canary.30",
4
4
  "description": "With gitpick, you can clone precisely what you need.",
5
5
  "keywords": [
6
6
  "clone",
@@ -31,34 +31,5 @@
31
31
  },
32
32
  "files": [
33
33
  "dist"
34
- ],
35
- "scripts": {
36
- "build": "tsup",
37
- "dev": "tsup --watch",
38
- "prepare": "npx simple-git-hooks",
39
- "test": "bun run build && node dist/index.js",
40
- "tests": "bash tests.sh"
41
- },
42
- "simple-git-hooks": {
43
- "pre-commit": "npx lint-staged",
44
- "commit-msg": "npx commitlint --edit $1"
45
- },
46
- "dependencies": {
47
- "@clack/prompts": "^0.10.0",
48
- "simple-git": "^3.27.0",
49
- "terminal-link": "^4.0.0",
50
- "yoctocolors": "^2.1.1"
51
- },
52
- "devDependencies": {
53
- "@commitlint/cli": "^19.8.0",
54
- "@commitlint/config-conventional": "^19.8.0",
55
- "@ianvs/prettier-plugin-sort-imports": "^4.4.1",
56
- "@types/node": "^22.13.13",
57
- "lint-staged": "^15.5.0",
58
- "prettier": "^3.5.3",
59
- "simple-git-hooks": "^2.12.1",
60
- "sort-package-json": "^2.15.1",
61
- "tsup": "^8.4.0",
62
- "typescript": "^5.8.2"
63
- }
34
+ ]
64
35
  }