gitpick 4.16.0-canary.5 → 4.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![downloads](https://img.shields.io/npm/dt/gitpick?color=red&logo=npm)](https://www.npmjs.com/package/gitpick)
12
12
  [![stars](https://img.shields.io/github/stars/nrjdalal/gitpick?color=blue)](https://github.com/nrjdalal/gitpick)
13
13
 
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.
14
+ > #### Just `copy-and-paste` any GitHub, GitLab or Bitbucket URL - no editing required (shorthands work too) - to clone individual files, folders, branches, commits, raw content or even entire repositories without the `.git` directory.
15
15
 
16
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.
17
17
 
@@ -46,19 +46,28 @@ npx gitpick owner/repo -r
46
46
  npx gitpick https://github.com/owner/repo -r
47
47
  # clone a private repo
48
48
  npx gitpick https://<token>@github.com/owner/repo
49
+ # clone from GitLab
50
+ npx gitpick https://gitlab.com/owner/repo
51
+ npx gitpick https://gitlab.com/owner/repo/-/tree/main/path/to/folder
52
+ # clone from Bitbucket
53
+ npx gitpick https://bitbucket.org/owner/repo
54
+ npx gitpick https://bitbucket.org/owner/repo/src/main/path/to/folder
55
+ # dry run (preview without cloning)
56
+ npx gitpick owner/repo --dry-run
49
57
  ```
50
58
 
51
59
  ---
52
60
 
53
61
  ## ✨ Features
54
62
 
55
- - 🔍 Clone individual files or folders from any GitHub repository
63
+ - 🔍 Clone individual files or folders from GitHub, GitLab and Bitbucket
56
64
  - ⚙️ Auto-detects branches and target directory (if not specified) like `git clone`
57
65
  - 🧠 Use shorthands `TanStack/router` or full URL's `https://github.com/TanStack/router`
58
66
  - 🗑️ Overwrite or replace existing files without a prompt using `-o` | `--overwrite`
59
67
  - 📦 Can easily clone all submodules with `-r` | `--recursive`
60
68
  - 🔁 Sync changes remotely with `--watch` using intervals (e.g., `15s`, `1m`, `1h`)
61
69
  - 🔐 Seamlessly works with both public and private repositories using a PAT
70
+ - 🔎 Preview what would be cloned with `--dry-run` before cloning
62
71
  - 📋 Config file support (`.gitpick.json` / `.gitpick.jsonc`) for multi-path picks
63
72
 
64
73
  ---
@@ -85,6 +94,7 @@ npx gitpick <url/shorthand> -o # overwrite if exists
85
94
  npx gitpick <url/shorthand> -r # clone submodules
86
95
  npx gitpick <url/shorthand> -w 30s # sync every 30 seconds
87
96
  npx gitpick https://<token>@github.com/owner/repo # private repository
97
+ npx gitpick <url/shorthand> --dry-run # preview without cloning
88
98
  ```
89
99
 
90
100
  <img width="720" alt="Image" src="https://github.com/user-attachments/assets/ddbc41b4-bfc6-4287-bb85-eb949d723591" />
@@ -95,6 +105,7 @@ npx gitpick https://<token>@github.com/owner/repo # private repository
95
105
 
96
106
  ```
97
107
  -b, --branch Branch/SHA to clone
108
+ -n, --dry-run Show what would be cloned without cloning
98
109
  -o, --overwrite Skip overwrite prompt
99
110
  -r, --recursive Clone submodules
100
111
  -w, --watch [time] Watch the repository and sync every [time]
@@ -107,12 +118,16 @@ npx gitpick https://<token>@github.com/owner/repo # private repository
107
118
 
108
119
  ## 🔐 Private Repos
109
120
 
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:
121
+ Use a personal access token with read-only contents permission. Works with GitHub, GitLab and Bitbucket:
111
122
 
112
123
  ```sh
113
124
  npx gitpick https://<token>@github.com/owner/repo
125
+ npx gitpick https://<token>@gitlab.com/owner/repo
126
+ npx gitpick https://<token>@bitbucket.org/owner/repo
114
127
  ```
115
128
 
129
+ Create a GitHub token 👉 [here](https://github.com/settings/personal-access-tokens/new) with `repo -> contents: read-only` permission.
130
+
116
131
  ---
117
132
 
118
133
  ## 📋 Config File
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import e from"node:fs";import t from"node:path";import{parseArgs as n,stripVTCon
5
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
6
  `){s++,n=!1,i+=H(e,r,s),r=s;continue}else if(n===B&&c===`
7
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=`4.16.0-canary.5`;const Y=(e,t)=>`\x1b]8;;${t}\x07${e}\x1b]8;;\x07`,X=`
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=`4.16.0`;const Y=(e,t)=>`\x1b]8;;${t}\x07${e}\x1b]8;;\x07`,X=`
9
9
  With ${p(`${Y(`GitPick`,`https://github.com/nrjdalal/gitpick`)}`)} clone specific directories or files from GitHub, GitLab and Bitbucket!
10
10
 
11
11
  $ gitpick ${g(`<url>`)} ${h(`[target]`)} ${_(`[options]`)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitpick",
3
- "version": "4.16.0-canary.5",
3
+ "version": "4.16.0",
4
4
  "description": "Clone exactly what you need aka straightforward project scaffolding!",
5
5
  "keywords": [
6
6
  "clone",