git-ripper 1.5.0 → 1.5.1
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 +15 -5
- package/package.json +1 -1
- package/src/downloader.js +32 -6
package/README.md
CHANGED
|
@@ -120,9 +120,9 @@ You can use either a **Fine-grained token** (Recommended) or a **Classic token**
|
|
|
120
120
|
4. **Resource owner**: Select your user.
|
|
121
121
|
5. **Repository access**: Select **Only select repositories** and choose the private repository you want to download from.
|
|
122
122
|
6. **Permissions**:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
- Click on **Repository permissions**.
|
|
124
|
+
- Find **Contents** and change Access to **Read-only**.
|
|
125
|
+
- _Note: Metadata permission is selected automatically._
|
|
126
126
|
7. Click **Generate token**.
|
|
127
127
|
|
|
128
128
|
#### Option B: Classic Token
|
|
@@ -131,7 +131,7 @@ You can use either a **Fine-grained token** (Recommended) or a **Classic token**
|
|
|
131
131
|
2. Click **Generate new token** > **Generate new token (classic)**.
|
|
132
132
|
3. Give your token a descriptive name.
|
|
133
133
|
4. **Select Scopes:**
|
|
134
|
-
|
|
134
|
+
- **For Private Repositories:** Select the **`repo`** scope (Full control of private repositories).
|
|
135
135
|
5. Click **Generate token**.
|
|
136
136
|
|
|
137
137
|
### Using the Token
|
|
@@ -174,6 +174,13 @@ git-ripper https://github.com/nodejs/node/tree/main/doc -o ./node-docs
|
|
|
174
174
|
git-ripper https://github.com/tailwindlabs/tailwindcss/tree/master/src/components -o ./tailwind-components
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
+
### Download from Private Repository
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Download from a private repository using a token
|
|
181
|
+
git-ripper https://github.com/my-org/private-project/tree/main/src --gh-token ghp_abc123...
|
|
182
|
+
```
|
|
183
|
+
|
|
177
184
|
### Download and Create Archive
|
|
178
185
|
|
|
179
186
|
```bash
|
|
@@ -260,7 +267,10 @@ Git-ripper works out of the box without configuration. For rate-limited GitHub A
|
|
|
260
267
|
Error: Request failed with status code 403
|
|
261
268
|
```
|
|
262
269
|
|
|
263
|
-
**Solution**: GitHub limits unauthenticated API requests.
|
|
270
|
+
**Solution**: GitHub limits unauthenticated API requests. You can either:
|
|
271
|
+
|
|
272
|
+
1. Wait a few minutes and try again
|
|
273
|
+
2. Use the `--gh-token` option with a Personal Access Token to significantly increase your rate limit
|
|
264
274
|
|
|
265
275
|
#### Invalid URL Format
|
|
266
276
|
|
package/package.json
CHANGED
package/src/downloader.js
CHANGED
|
@@ -131,7 +131,7 @@ const fetchFolderContents = async (owner, repo, branch, folderPath, token) => {
|
|
|
131
131
|
isRateLimit = true;
|
|
132
132
|
errorMessage = `GitHub API rate limit exceeded. Please wait until ${new Date(
|
|
133
133
|
parseInt(error.response.headers["x-ratelimit-reset"]) * 1000
|
|
134
|
-
).toLocaleTimeString()} or
|
|
134
|
+
).toLocaleTimeString()} or use the --gh-token option to increase your rate limit.`;
|
|
135
135
|
} else {
|
|
136
136
|
errorMessage = `Access forbidden: ${
|
|
137
137
|
error.response.data.message ||
|
|
@@ -171,7 +171,14 @@ const fetchFolderContents = async (owner, repo, branch, folderPath, token) => {
|
|
|
171
171
|
* @param {string} [token] - GitHub Personal Access Token
|
|
172
172
|
* @returns {Promise<Object>} - Object containing download status
|
|
173
173
|
*/
|
|
174
|
-
const downloadFile = async (
|
|
174
|
+
const downloadFile = async (
|
|
175
|
+
owner,
|
|
176
|
+
repo,
|
|
177
|
+
branch,
|
|
178
|
+
filePath,
|
|
179
|
+
outputPath,
|
|
180
|
+
token
|
|
181
|
+
) => {
|
|
175
182
|
const headers = {
|
|
176
183
|
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
177
184
|
};
|
|
@@ -223,7 +230,10 @@ const downloadFile = async (owner, repo, branch, filePath, outputPath, token) =>
|
|
|
223
230
|
const url = `${baseUrl}${fileUrlPath}`;
|
|
224
231
|
|
|
225
232
|
try {
|
|
226
|
-
const response = await axios.get(url, {
|
|
233
|
+
const response = await axios.get(url, {
|
|
234
|
+
responseType: "arraybuffer",
|
|
235
|
+
headers,
|
|
236
|
+
});
|
|
227
237
|
|
|
228
238
|
// Ensure the directory exists
|
|
229
239
|
try {
|
|
@@ -363,7 +373,13 @@ const downloadFolder = async (
|
|
|
363
373
|
);
|
|
364
374
|
|
|
365
375
|
try {
|
|
366
|
-
const contents = await fetchFolderContents(
|
|
376
|
+
const contents = await fetchFolderContents(
|
|
377
|
+
owner,
|
|
378
|
+
repo,
|
|
379
|
+
branch,
|
|
380
|
+
folderPath,
|
|
381
|
+
token
|
|
382
|
+
);
|
|
367
383
|
|
|
368
384
|
if (!contents || contents.length === 0) {
|
|
369
385
|
const message = `No files found in ${folderPath || "repository root"}`;
|
|
@@ -565,7 +581,11 @@ const downloadFolderWithResume = async (
|
|
|
565
581
|
const { resume = true, forceRestart = false, token } = options;
|
|
566
582
|
|
|
567
583
|
if (!resume) {
|
|
568
|
-
return downloadFolder(
|
|
584
|
+
return downloadFolder(
|
|
585
|
+
{ owner, repo, branch, folderPath },
|
|
586
|
+
outputDir,
|
|
587
|
+
options
|
|
588
|
+
);
|
|
569
589
|
}
|
|
570
590
|
|
|
571
591
|
const resumeManager = new ResumeManager();
|
|
@@ -637,7 +657,13 @@ const downloadFolderWithResume = async (
|
|
|
637
657
|
);
|
|
638
658
|
|
|
639
659
|
try {
|
|
640
|
-
const contents = await fetchFolderContents(
|
|
660
|
+
const contents = await fetchFolderContents(
|
|
661
|
+
owner,
|
|
662
|
+
repo,
|
|
663
|
+
branch,
|
|
664
|
+
folderPath,
|
|
665
|
+
token
|
|
666
|
+
);
|
|
641
667
|
if (!contents || contents.length === 0) {
|
|
642
668
|
const message = `No files found in ${folderPath || "repository root"}`;
|
|
643
669
|
console.log(chalk.yellow(message));
|