gitpick 0.0.0-8803aa0 ā 0.0.0-c952e88
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 +137 -98
- package/dist/index.mjs +39 -0
- package/package.json +9 -8
- package/dist/index.js +0 -40
package/README.md
CHANGED
|
@@ -1,158 +1,197 @@
|
|
|
1
1
|
# GitPick
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<!-- -->
|
|
4
4
|
|
|
5
|
+
**Clone exactly what you need aka straightforward project scaffolding!**
|
|
6
|
+
|
|
7
|
+
š¦ `Zero dependencies` / `Un/packed (~19/8kb)` / `Faster and more features` yet drop-in replacement for `degit`
|
|
8
|
+
|
|
9
|
+
[](https://twitter.com/nrjdalal_dev)
|
|
5
10
|
[](https://www.npmjs.com/package/gitpick)
|
|
6
|
-
[](https://www.npmjs.com/package/gitpick)
|
|
12
|
+
[](https://github.com/nrjdalal/gitpick)
|
|
8
13
|
|
|
9
|
-
|
|
14
|
+
> #### Just `copy-and-paste` any GitHub URL - no editing required (shorthands work too) - to clone individual files, folders, branches, commits, raw content or even entire repositories without the `.git` directory.
|
|
10
15
|
|
|
11
|
-
|
|
16
|
+
Unlike other tools that force you to tweak URLs or follow strict formats to clone files, folders, branches or commits GitPick works seamlessly with any URL.
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
<img width="400" alt="GitPick Meme" src="https://github.com/user-attachments/assets/180c3e5b-320c-48d7-aaf9-a7402e74c882" />
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
---
|
|
16
21
|
|
|
17
|
-
##
|
|
22
|
+
## š Some Examples
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
### See [Quick Usage](#-quick-usage) for to learn more.
|
|
20
25
|
|
|
21
26
|
```sh
|
|
22
|
-
|
|
27
|
+
# clone a repo without .git
|
|
28
|
+
npx gitpick owner/repo
|
|
29
|
+
npx gitpick https://github.com/owner/repo
|
|
30
|
+
# clone a folder aka tree
|
|
31
|
+
npx gitpick owner/repo/tree/main/path/to/folder
|
|
32
|
+
npx gitpick https://github.com/owner/repo/tree/main/path/to/folder
|
|
33
|
+
# clone a file aka blob
|
|
34
|
+
npx gitpick owner/repo/blob/main/path/to/file
|
|
35
|
+
npx gitpick https://github.com/owner/repo/blob/main/path/to/file
|
|
36
|
+
# clone a branch
|
|
37
|
+
npx gitpick owner/repo -b canary
|
|
38
|
+
npx gitpick https://github.com/owner/repo -b canary
|
|
39
|
+
npx gitpick owner/repo/tree/canary
|
|
40
|
+
npx gitpick https://github.com/owner/repo/tree/canary
|
|
41
|
+
# clone a commit SHA
|
|
42
|
+
npx gitpick owner/repo -b cc8e93
|
|
43
|
+
npx gitpick https://github.com/owner/repo/commit/cc8e93
|
|
44
|
+
# clone submodules
|
|
45
|
+
npx gitpick owner/repo -r
|
|
46
|
+
npx gitpick https://github.com/owner/repo -r
|
|
47
|
+
# clone a private repo
|
|
48
|
+
npx gitpick https://<token>@github.com/owner/repo
|
|
23
49
|
```
|
|
24
50
|
|
|
25
|
-
|
|
51
|
+
---
|
|
26
52
|
|
|
27
|
-
|
|
28
|
-
npx gitpick https://github.com/TanStack/router
|
|
29
|
-
# npx gitpick TanStack/router
|
|
30
|
-
```
|
|
53
|
+
## ⨠Features
|
|
31
54
|
|
|
32
|
-
|
|
55
|
+
- š Clone individual files or folders from any GitHub repository
|
|
56
|
+
- āļø Auto-detects branches and target directory (if not specified) like `git clone`
|
|
57
|
+
- š§ Use shorthands `TanStack/router` or full URL's `https://github.com/TanStack/router`
|
|
58
|
+
- šļø Overwrite or replace existing files without a prompt using `-o` | `--overwrite`
|
|
59
|
+
- š¦ Can easily clone all submodules with `-r` | `--recursive`
|
|
60
|
+
- š Sync changes remotely with `--watch` using intervals (e.g., `15s`, `1m`, `1h`)
|
|
61
|
+
- š Seamlessly works with both public and private repositories using a PAT
|
|
62
|
+
- š Config file support (`.gitpick.json` / `.gitpick.jsonc`) for multi-path picks
|
|
33
63
|
|
|
34
|
-
|
|
35
|
-
npx gitpick https://github.com/TanStack/router/tree/main/examples
|
|
36
|
-
# npx gitpick TanStack/router/tree/main/examples
|
|
37
|
-
```
|
|
64
|
+
---
|
|
38
65
|
|
|
39
|
-
|
|
66
|
+
## š Quick Usage
|
|
40
67
|
|
|
41
68
|
```sh
|
|
42
|
-
npx gitpick
|
|
43
|
-
# npx gitpick TanStack/router/tree/main/package.json
|
|
69
|
+
npx gitpick <url/shorthand> [target] [options]
|
|
44
70
|
```
|
|
45
71
|
|
|
46
|
-
-
|
|
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.
|
|
72
|
+
- [target] and [options] are optional, if not specified, GitPick fallbacks to the default behavior of `git clone`
|
|
52
73
|
|
|
53
|
-
|
|
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
|
|
74
|
+
Examples:
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
```sh
|
|
77
|
+
npx gitpick https://github.com/owner/repo # repo without .git
|
|
78
|
+
npx gitpick owner/repo/tree/main/path/to/folder # a folder aka tree
|
|
79
|
+
npx gitpick owner/repo/blob/main/path/to/file # a file aka blob
|
|
80
|
+
|
|
81
|
+
npx gitpick <url/shorthand> # default git behavior
|
|
82
|
+
npx gitpick <url/shorthand> [target] # with optional target
|
|
83
|
+
npx gitpick <url/shorthand> -b [branch/SHA] # branch or commit SHA
|
|
84
|
+
npx gitpick <url/shorthand> -o # overwrite if exists
|
|
85
|
+
npx gitpick <url/shorthand> -r # clone submodules
|
|
86
|
+
npx gitpick <url/shorthand> -w 30s # sync every 30 seconds
|
|
87
|
+
npx gitpick https://<token>@github.com/owner/repo # private repository
|
|
88
|
+
```
|
|
65
89
|
|
|
66
|
-
|
|
90
|
+
<img width="720" alt="Image" src="https://github.com/user-attachments/assets/ddbc41b4-bfc6-4287-bb85-eb949d723591" />
|
|
67
91
|
|
|
68
|
-
|
|
69
|
-
url GitHub URL with path to file/folder
|
|
70
|
-
target Directory to clone into (optional)
|
|
92
|
+
---
|
|
71
93
|
|
|
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
|
|
94
|
+
## š§ Options
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
```
|
|
97
|
+
-b, --branch Branch/SHA to clone
|
|
98
|
+
-o, --overwrite Skip overwrite prompt
|
|
99
|
+
-r, --recursive Clone submodules
|
|
100
|
+
-w, --watch [time] Watch the repository and sync every [time]
|
|
101
|
+
(e.g. 1h, 30m, 15s)
|
|
102
|
+
-h, --help display help for command
|
|
103
|
+
-v, --version display the version number
|
|
86
104
|
```
|
|
87
105
|
|
|
88
|
-
|
|
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.
|
|
106
|
+
---
|
|
95
107
|
|
|
96
|
-
##
|
|
108
|
+
## š Private Repos
|
|
97
109
|
|
|
98
|
-
|
|
110
|
+
Use a [GitHub personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#about-personal-access-tokens) (create one š [here](https://github.com/settings/personal-access-tokens/new)) with `repo -> contents: read-only` permission:
|
|
99
111
|
|
|
100
112
|
```sh
|
|
101
|
-
|
|
113
|
+
npx gitpick https://<token>@github.com/owner/repo
|
|
102
114
|
```
|
|
103
115
|
|
|
104
|
-
|
|
116
|
+
---
|
|
105
117
|
|
|
106
|
-
|
|
107
|
-
|
|
118
|
+
## š Config File
|
|
119
|
+
|
|
120
|
+
Create a `.gitpick.json` or `.gitpick.jsonc` in your project to pick multiple files/folders in one command:
|
|
121
|
+
|
|
122
|
+
```jsonc
|
|
123
|
+
// .gitpick.jsonc
|
|
124
|
+
[
|
|
125
|
+
// clone a repo without .git
|
|
126
|
+
"owner/repo",
|
|
127
|
+
"https://github.com/owner/repo",
|
|
128
|
+
// clone a folder aka tree
|
|
129
|
+
"owner/repo/tree/main/path/to/folder",
|
|
130
|
+
"https://github.com/owner/repo/tree/main/path/to/folder",
|
|
131
|
+
// clone a file aka blob
|
|
132
|
+
"owner/repo/blob/main/path/to/file",
|
|
133
|
+
"https://github.com/owner/repo/blob/main/path/to/file",
|
|
134
|
+
// clone a branch
|
|
135
|
+
"owner/repo -b canary",
|
|
136
|
+
"https://github.com/owner/repo -b canary",
|
|
137
|
+
"owner/repo/tree/canary",
|
|
138
|
+
"https://github.com/owner/repo/tree/canary",
|
|
139
|
+
// clone a commit SHA
|
|
140
|
+
"owner/repo -b cc8e93",
|
|
141
|
+
"https://github.com/owner/repo/commit/cc8e93",
|
|
142
|
+
// clone submodules
|
|
143
|
+
"owner/repo -r",
|
|
144
|
+
"https://github.com/owner/repo -r",
|
|
145
|
+
// clone a private repo
|
|
146
|
+
"https://<token>@github.com/owner/repo",
|
|
147
|
+
]
|
|
108
148
|
```
|
|
109
149
|
|
|
110
|
-
|
|
150
|
+
Then just run:
|
|
111
151
|
|
|
112
152
|
```sh
|
|
113
|
-
npx gitpick
|
|
153
|
+
npx gitpick
|
|
114
154
|
```
|
|
115
155
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Run `npx gitpick <url> [target] [options]` to clone a file or directory from a GitHub repository.
|
|
156
|
+
Each entry follows the same `<url> [target]` syntax as the CLI. All entries are cloned with `-o` (overwrite) by default.
|
|
119
157
|
|
|
120
158
|
---
|
|
121
159
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
> https://github.com/nrjdalal/nrjdalal/tree/main/.config
|
|
160
|
+
## š¦ Install Globally (Optional)
|
|
125
161
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
npx gitpick https://github.com/nrjdalal/nrjdalal/tree/main/.config config
|
|
162
|
+
```sh
|
|
163
|
+
npm install -g gitpick
|
|
164
|
+
gitpick <url/shorthand> [target] [options]
|
|
130
165
|
```
|
|
131
166
|
|
|
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`.
|
|
133
|
-
|
|
134
167
|
---
|
|
135
168
|
|
|
136
|
-
|
|
169
|
+
## š More Tools
|
|
137
170
|
|
|
138
|
-
|
|
139
|
-
gitpick https://github.com/nrjdalal/nrjdalal/tree/main/.config -w
|
|
140
|
-
```
|
|
171
|
+
Check out more projects at [github.com/nrjdalal](https://github.com/nrjdalal)
|
|
141
172
|
|
|
142
|
-
|
|
173
|
+
## š Related Projects
|
|
143
174
|
|
|
144
|
-
|
|
175
|
+
- [tiged](https://github.com/tiged/tiged) - community driven fork of degit
|
|
176
|
+
- [giget](https://github.com/unjs/giget) - alternative approach
|
|
145
177
|
|
|
146
|
-
|
|
147
|
-
gitpick https://github.com/nrjdalal/awesome-templates/tree/main/next.js-apps/next.js-pro
|
|
148
|
-
```
|
|
178
|
+
[](https://www.star-history.com/#nrjdalal/gitpick&tiged/tiged&unjs/giget&type=timeline&logscale&legend=top-left)
|
|
149
179
|
|
|
150
|
-
|
|
180
|
+
## š¤ Contributing
|
|
151
181
|
|
|
152
|
-
|
|
182
|
+
Contributions welcome ā any help is appreciated!
|
|
183
|
+
|
|
184
|
+
- Fork the repo and create a branch (use descriptive names, e.g. feat/<name> or fix/<name>).
|
|
185
|
+
- Make your changes, add tests if applicable, and run the checks:
|
|
186
|
+
- bun install
|
|
187
|
+
- bun test
|
|
188
|
+
- Follow the existing code style and commit message conventions (use conventional commits: feat, fix, docs, chore).
|
|
189
|
+
- Open a PR describing the change, motivation, and any migration notes; link related issues.
|
|
190
|
+
- For breaking changes or large features, open an issue first to discuss the approach.
|
|
191
|
+
- By contributing you agree to the MIT license and the project's Code of Conduct.
|
|
153
192
|
|
|
154
|
-
|
|
193
|
+
Thank you for helping improve GitPick!
|
|
155
194
|
|
|
156
|
-
## License
|
|
195
|
+
## š License
|
|
157
196
|
|
|
158
|
-
|
|
197
|
+
MIT ā [LICENSE](LICENSE)
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import e from"node:fs";import t from"node:path";import{parseArgs as n,stripVTControlCharacters as r}from"node:util";import i from"node:tty";import a from"node:os";import{spawn as o}from"node:child_process";import{once as s}from"node:events";import c from"node:fs/promises";import l from"node:process";import{fileURLToPath as u}from"node:url";const d=i?.WriteStream?.prototype?.hasColors?.()??!1,f=(e,t)=>{if(!d)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}},p=f(1,22),m=f(31,39),h=f(32,39),g=f(33,39),_=f(36,39);var v=class extends Error{constructor(...e){super(...e),this.name=`SubprocessError`,this.stdout=``,this.stderr=``}};const y=[`.exe`,`.com`],b={},x=e=>(...t)=>b[t.join(`\0`)]??=e(...t),S=x(async(...e)=>{try{return await c.access(e[0]),!0}catch{return!1}}),C=x(async(e,n,r)=>{let i=r.split(t.delimiter).filter(Boolean).map(e=>e.replace(/^"(.*)"$/,`$1`));try{await Promise.any([n,...i].flatMap(n=>y.map(r=>S(`${t.resolve(n,e)}${r}`))))}catch{return!1}return!0}),w=async(e,t)=>l.platform===`win32`&&!t.shell&&!y.some(t=>e.toLowerCase().endsWith(t))&&!await C(e,t.cwd??`.`,(l.env.PATH||l.env.Path)??``),T=e=>e.replaceAll(/([()\][%!^"`<>&|;, *?])/g,`^$1`),E=e=>T(T(`"${e.replaceAll(/(\\*)"/g,`$1$1\\"`).replace(/(\\*)$/,`$1$1`)}"`)),D=e=>/[^\w./-]/.test(e)?`'${e.replaceAll(`'`,`'\\''`)}'`:e;async function O(e,n=[],i={}){let{stdin:a,stdout:c,stderr:d,stdio:f,cwd:p=`.`,env:m,...h}=i,g=p instanceof URL?u(p):t.resolve(p),_=m?{...l.env,...m}:void 0,y=f??[a,c,d],b=[e,...n].map(e=>D(r(e))).join(` `);[`node`,`node.exe`].includes(e.toLowerCase())&&(e=l.execPath,n=[...l.execArgv.filter(e=>!e.startsWith(`--inspect`)),...n]);let x={...h,stdio:y,env:_,cwd:g};await w(e,x)&&(n=n.map(e=>E(e)),e=T(e),x={...x,shell:!0}),x.shell&&n.length>0&&(e=[e,...n].join(` `),n=[]);let S=o(e,n,x),C=``,O=``;S.stdout&&(S.stdout.setEncoding(`utf8`),S.stdout.on(`data`,e=>C+=e)),S.stderr&&(S.stderr.setEncoding(`utf8`),S.stderr.on(`data`,e=>O+=e)),S.once(`error`,()=>{});try{await s(S,`spawn`)}catch(e){throw Object.assign(new v(`Command failed: ${b}`,{cause:e}),{stdout:C,stderr:O})}await s(S,`close`);let k=e=>e.at(-1)===`
|
|
3
|
+
`?e.slice(0,e.at(-2)===`\r`?-2:-1):e;if(S.exitCode&&S.exitCode>0)throw Object.assign(new v(`Command failed with exit code ${S.exitCode}: ${b}`),{stdout:k(C),stderr:k(O),exitCode:S.exitCode});if(S.signalCode)throw Object.assign(new v(`Command was terminated with ${S.signalCode}: ${b}`),{stdout:k(C),stderr:k(O)});return{stdout:k(C),stderr:k(O)}}const k=l.platform!==`win32`||!!l.env.WT_SESSION||l.env.TERM_PROGRAM===`vscode`,A=e=>!!(e.isTTY&&l.env.TERM!==`dumb`&&!(`CI`in l.env)),j=h(k?`ā`:`ā`),M=k?[`ā `,`ā `,`ā ¹`,`ā ø`,`ā ¼`,`ā “`,`ā ¦`,`ā §`,`ā `,`ā `]:[`-`,`\\`,`|`,`/`],N=(e={})=>{let t=-1,n,i=e.text??``,a=e.stream??l.stderr,o=A(a),s=0,c=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=r(e).split(`
|
|
4
|
+
`),i=0;for(let e of n)i+=Math.max(1,Math.ceil(e.length/t));return i},m=()=>{let e=Date.now();(t===-1||e-c>=80)&&(t=++t%M.length,c=e);let n=M[t],r=`${_(n)} ${i}`;o?(f(),d(r),s=p(r)):d(r+`
|
|
5
|
+
`)};return{start(e){return i=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(`${j} ${e??i}\n`),this):this}}},P=async(n,r)=>{let i=await e.promises.readdir(n,{withFileTypes:!0});await e.promises.mkdir(r,{recursive:!0});for(let a of i){if(a.name===`.git`)continue;let i=t.join(n,a.name),o=t.join(r,a.name);if(a.isDirectory())await P(i,o);else if(a.isSymbolicLink()){let t=await e.promises.readlink(i);await e.promises.symlink(t,o)}else await e.promises.copyFile(i,o)}},F=async(n,r,i)=>{process.platform===`win32`&&await O(`git`,[`config`,`--global`,`core.longpaths`,`true`]);let o=`https://${n.token?n.token+`@`:n.token}${n.host}/${n.owner}/${n.repository}.git`,s=t.resolve(a.tmpdir(),`${n.repository}-${Date.now()}${Math.random().toString(16).slice(2,6)}`),c=N(),l=performance.now();r.watch||c.start(`Picking ${n.type}${n.type===`repository`?` without .git`:` from repository`}...`);try{await O(`git`,[`clone`,o,s,`--branch`,n.branch,`--depth`,`1`,`--single-branch`,...r.recursive?[`--recursive`]:[]])}catch{await O(`git`,[`clone`,o,s,...r.recursive?[`--recursive`]:[]]),await O(`git`,[`checkout`,n.branch],{cwd:s})}let u=t.resolve(s,n.path);(await e.promises.stat(u)).isDirectory()?(await e.promises.mkdir(i,{recursive:!0}),await P(u,i)):(await e.promises.mkdir(t.dirname(i),{recursive:!0}),await e.promises.copyFile(u,i)),r.watch?console.log(`- Synced at `+new Date().toLocaleTimeString()):c.success(`Picked ${n.type}${n.type===`repository`?` without .git`:` from repository`} in ${((performance.now()-l)/1e3).toFixed(2)} seconds.`),await e.promises.rm(s,{recursive:!0,force:!0})};function I(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 L=async e=>{let t=(await O(`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},R=[{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 z(e,{branch:t,target:n}){let r=e.match(/^https:\/\/([^@]+)@(github\.com|gitlab\.com|bitbucket\.org)/),i=``;r&&(i=r[1],e=e.replace(`${r[1]}@`,``));let a=`github.com`;for(let{prefix:t,host:n}of R)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 L(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 L(l),f=``):o[2]===`src`?(u=`tree`,d=t||o[3],f=o.slice(4).join(`/`)):(u=`repository`,d=t||await L(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 B=Symbol(`singleComment`),V=Symbol(`multiComment`),H=(e,t,n)=>e.slice(t,n).replace(/[^ \t\r\n]/g,` `),U=(e,t)=>{let n=t-1,r=0;for(;e[n]===`\\`;)--n,r+=1;return!!(r%2)};function W(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===`"`&&(U(e,s)||(t=!t)),!t)if(!n&&c+l===`//`)i+=e.slice(r,s),r=s,n=B,s++;else if(n===B&&c+l===`\r
|
|
6
|
+
`){s++,n=!1,i+=H(e,r,s),r=s;continue}else if(n===B&&c===`
|
|
7
|
+
`)n=!1,i+=H(e,r,s),r=s;else if(!n&&c+l===`/*`){i+=e.slice(r,s),r=s,n=V,s++;continue}else if(n===V&&c+l===`*/`){s++,n=!1,i+=H(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+=H(i,0,1)+i.slice(1),i=``,r=s,o=-1):c!==` `&&c!==` `&&c!==`\r`&&c!==`
|
|
8
|
+
`&&(i+=e.slice(r,s),r=s,o=-1))}let s=n===B?H(e,r):e.slice(r);return a+i+s}const G=[`.gitpick.json`,`.gitpick.jsonc`],K=async()=>{let n;for(let r of G){let i=t.resolve(r);if(e.existsSync(i)){n=i;break}}if(!n)return!1;let r=await e.promises.readFile(n,`utf-8`),i=JSON.parse(W(r));if(!Array.isArray(i)||!i.every(e=>typeof e==`string`))throw Error(`${t.basename(n)} must be an array of strings`);for(let e of i)await O(process.argv[0],[...process.argv.slice(1),...e.split(/\s+/),`-o`],{stdio:`inherit`});return!0};var q=`gitpick`,J=`0.0.0-c952e88`;const Y=(e,t)=>`\x1b]8;;${t}\x07${e}\x1b]8;;\x07`,X=`
|
|
9
|
+
With ${p(`${Y(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific directories or files from GitHub, GitLab and Bitbucket!
|
|
10
|
+
|
|
11
|
+
$ gitpick ${g(`<url>`)} ${h(`[target]`)} ${_(`[options]`)}
|
|
12
|
+
|
|
13
|
+
${p(`Hint:`)}
|
|
14
|
+
[target] and [options] are optional and if not specified,
|
|
15
|
+
GitPick fallbacks to the default behavior of \`git clone\`
|
|
16
|
+
|
|
17
|
+
${p(`Arguments:`)}
|
|
18
|
+
${g(`url`)} GitHub/GitLab/Bitbucket URL with path to file/folder/repository
|
|
19
|
+
${h(`target`)} Directory to clone into (optional)
|
|
20
|
+
|
|
21
|
+
${p(`Options:`)}
|
|
22
|
+
${_(`-b, --branch `)} Branch/SHA to clone
|
|
23
|
+
${_(`-n, --dry-run`)} Show what would be cloned without cloning
|
|
24
|
+
${_(`-o, --overwrite`)} Skip overwrite prompt
|
|
25
|
+
${_(`-r, --recursive`)} Clone submodules
|
|
26
|
+
${_(`-w, --watch [time]`)} Watch the repository and sync every [time]
|
|
27
|
+
(e.g. 1h, 30m, 15s)
|
|
28
|
+
${_(`-h, --help`)} display help for command
|
|
29
|
+
${_(`-v, --version`)} display the version number
|
|
30
|
+
|
|
31
|
+
${p(`Examples:`)}
|
|
32
|
+
$ gitpick <url>
|
|
33
|
+
$ gitpick <url> [target]
|
|
34
|
+
$ gitpick <url> [target] -b [branch/SHA]
|
|
35
|
+
$ gitpick <url> [target] -w [time]
|
|
36
|
+
$ gitpick <url> [target] -b [branch/SHA] -w [time]
|
|
37
|
+
|
|
38
|
+
š More awesome tools at ${_(`https://github.com/nrjdalal`)}`,Z=e=>{try{return n(e)}catch(e){throw Error(`Error parsing arguments: ${e.message}`)}};(async()=>{try{let{positionals:n,values:r}=Z({allowPositionals:!0,options:{branch:{type:`string`,short:`b`},"dry-run":{type:`boolean`,short:`n`},force:{type:`boolean`,short:`f`},help:{type:`boolean`,short:`h`},overwrite:{type:`boolean`,short:`o`},recursive:{type:`boolean`,short:`r`},version:{type:`boolean`,short:`v`},watch:{type:`string`,short:`w`}}});n.length||(r.version&&(console.log(`\n${q}@${J}`),process.exit(0)),await K()&&process.exit(0),console.log(X),process.exit(0)),n[0]===`clone`&&n.shift();let[i,a]=n,o={branch:r.branch,dryRun:r[`dry-run`],force:r.force,overwrite:r.overwrite,recursive:r.recursive,watch:r.watch};console.log(`\nWith ${p(`${Y(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific files, folders, branches, commits and more from GitHub, GitLab and Bitbucket!`);let s=await z(i,{branch:o.branch,target:a});if(s.type===`blob`){let e=s.target.split(/[/\\]/).filter(e=>e!==``),t=e[e.length-1];t!==`.`&&t!==`..`&&t.includes(`.`)?e.pop():t=s.path.split(`/`).pop()||t,s.target=[...e,t].join(`/`)}console.info(`\n${h(`ā`)} ${s.owner}/${s.repository} ${_(s.type+`:`+s.branch)} ${s.type===`repository`?`> ${h(s.target)}`:`${s.path.length?g(s.path)+` >`:`>`} ${h(s.target)}`}`),o.dryRun&&(console.log(),process.exit(0));let c=t.resolve(s.target);if(o.overwrite=o.overwrite||o.force,o.watch&&(o.overwrite=!0),e.existsSync(c)&&!o.overwrite&&(s.type===`blob`&&(console.log(`${g(`\nWarning: The target file exists at ${h(s.target)}. Use ${_(`-f`)} or ${_(`-o`)} to overwrite.`)}`),process.exit(1)),(await e.promises.readdir(c)).length&&(console.log(`${g(`\nWarning: The target directory exists at ${h(s.target)} and is not empty. Use ${_(`-f`)} or ${_(`-o`)} to overwrite.`)}`),process.exit(1))),o.watch){console.log(`\nš Watching every ${I(o.watch)/1e3+`s`}\n`),await F(s,o,c);let e=I(o.watch);setInterval(async()=>await F(s,o,c),e)}else await F(s,o,c),process.exit(0)}catch(e){e instanceof Error?console.log(p(`\n${m(`Error: `)}`)+e.message):console.log(p(`${m(`
|
|
39
|
+
Unexpected Error: `)}`)+JSON.stringify(e,null,2)),process.exit(1)}})();export{};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gitpick",
|
|
3
|
-
"version": "0.0.0-
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.0-c952e88",
|
|
4
|
+
"description": "Clone exactly what you need aka straightforward project scaffolding!",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"clone",
|
|
7
7
|
"degit",
|
|
@@ -10,26 +10,27 @@
|
|
|
10
10
|
"folder",
|
|
11
11
|
"git",
|
|
12
12
|
"github",
|
|
13
|
+
"repository",
|
|
13
14
|
"scaffolding",
|
|
14
15
|
"template",
|
|
15
16
|
"url"
|
|
16
17
|
],
|
|
17
18
|
"homepage": "https://github.com/nrjdalal/gitpick#readme",
|
|
18
19
|
"bugs": "https://github.com/nrjdalal/gitpick/issues",
|
|
19
|
-
"repository": "nrjdalal/gitpick",
|
|
20
|
-
"funding": "https://github.com/sponsors/nrjdalal",
|
|
21
20
|
"license": "MIT",
|
|
22
21
|
"author": {
|
|
23
22
|
"name": "Neeraj Dalal",
|
|
24
23
|
"email": "admin@nrjdalal.com",
|
|
25
24
|
"url": "https://nrjdalal.com"
|
|
26
25
|
},
|
|
27
|
-
"
|
|
26
|
+
"repository": "nrjdalal/gitpick",
|
|
27
|
+
"funding": "https://github.com/sponsors/nrjdalal",
|
|
28
28
|
"bin": {
|
|
29
|
-
"degit": "./dist/index.
|
|
30
|
-
"gitpick": "./dist/index.
|
|
29
|
+
"degit": "./dist/index.mjs",
|
|
30
|
+
"gitpick": "./dist/index.mjs"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist"
|
|
34
|
-
]
|
|
34
|
+
],
|
|
35
|
+
"type": "module"
|
|
35
36
|
}
|
package/dist/index.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
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="0.0.0-8803aa0";var Xt=`
|
|
7
|
-
${d("With GitPick, you can clone precisely what you need.")}
|
|
8
|
-
|
|
9
|
-
${d("gitpick")} ${j("<url>")} ${A("[target]")} ${g("[options]")}
|
|
10
|
-
|
|
11
|
-
${d("Hint:")} Target is optional, and follows default git clone behavior.
|
|
12
|
-
|
|
13
|
-
${d("Arguments:")}
|
|
14
|
-
${j("url")} GitHub URL with path to file/folder/repository
|
|
15
|
-
${A("target")} Directory to clone into (optional)
|
|
16
|
-
|
|
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]
|
|
21
|
-
(e.g. 1h, 30m, 15s) default: 1m
|
|
22
|
-
${g("-h, --help")} display help for command
|
|
23
|
-
${g("-v, --version")} display the version number
|
|
24
|
-
|
|
25
|
-
${d("Examples:")}
|
|
26
|
-
$ gitpick <url>
|
|
27
|
-
$ gitpick <url> [target]
|
|
28
|
-
$ gitpick <url> [target] -b [branch]
|
|
29
|
-
$ gitpick <url> [target] -w [time]
|
|
30
|
-
$ gitpick <url> [target] -b [branch] -w [time]
|
|
31
|
-
|
|
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();
|