git-ripper 1.4.6 → 1.4.7
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/package.json +1 -1
- package/src/archiver.js +1 -1
- package/src/downloader.js +50 -30
- package/src/index.js +4 -4
- package/src/parser.js +4 -4
package/package.json
CHANGED
package/src/archiver.js
CHANGED
|
@@ -88,7 +88,7 @@ export const createArchive = (sourceDir, outputPath) => {
|
|
|
88
88
|
const size = archive.pointer();
|
|
89
89
|
console.log(
|
|
90
90
|
chalk.green(
|
|
91
|
-
|
|
91
|
+
`Archive created: ${outputPath} (${(size / 1024 / 1024).toFixed(
|
|
92
92
|
2
|
|
93
93
|
)} MB)`
|
|
94
94
|
)
|
package/src/downloader.js
CHANGED
|
@@ -52,7 +52,9 @@ const fetchFolderContents = async (owner, repo, branch, folderPath) => {
|
|
|
52
52
|
if (!effectiveBranch) {
|
|
53
53
|
// If no branch is specified, fetch the default branch for the repository
|
|
54
54
|
try {
|
|
55
|
-
const repoInfoUrl = `https://api.github.com/repos/${
|
|
55
|
+
const repoInfoUrl = `https://api.github.com/repos/${encodeURIComponent(
|
|
56
|
+
owner
|
|
57
|
+
)}/${encodeURIComponent(repo)}`;
|
|
56
58
|
const repoInfoResponse = await axios.get(repoInfoUrl);
|
|
57
59
|
effectiveBranch = repoInfoResponse.data.default_branch;
|
|
58
60
|
if (!effectiveBranch) {
|
|
@@ -75,7 +77,11 @@ const fetchFolderContents = async (owner, repo, branch, folderPath) => {
|
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
const apiUrl = `https://api.github.com/repos/${
|
|
80
|
+
const apiUrl = `https://api.github.com/repos/${encodeURIComponent(
|
|
81
|
+
owner
|
|
82
|
+
)}/${encodeURIComponent(repo)}/git/trees/${encodeURIComponent(
|
|
83
|
+
effectiveBranch
|
|
84
|
+
)}?recursive=1`;
|
|
79
85
|
|
|
80
86
|
try {
|
|
81
87
|
const response = await axios.get(apiUrl);
|
|
@@ -164,7 +170,9 @@ const downloadFile = async (owner, repo, branch, filePath, outputPath) => {
|
|
|
164
170
|
// This check might be redundant if fetchFolderContents already resolved it,
|
|
165
171
|
// but it's a good fallback for direct downloadFile calls if any.
|
|
166
172
|
try {
|
|
167
|
-
const repoInfoUrl = `https://api.github.com/repos/${
|
|
173
|
+
const repoInfoUrl = `https://api.github.com/repos/${encodeURIComponent(
|
|
174
|
+
owner
|
|
175
|
+
)}/${encodeURIComponent(repo)}`;
|
|
168
176
|
const repoInfoResponse = await axios.get(repoInfoUrl);
|
|
169
177
|
effectiveBranch = repoInfoResponse.data.default_branch;
|
|
170
178
|
if (!effectiveBranch) {
|
|
@@ -191,10 +199,16 @@ const downloadFile = async (owner, repo, branch, filePath, outputPath) => {
|
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
201
|
|
|
194
|
-
const baseUrl = `https://raw.githubusercontent.com/${
|
|
202
|
+
const baseUrl = `https://raw.githubusercontent.com/${encodeURIComponent(
|
|
203
|
+
owner
|
|
204
|
+
)}/${encodeURIComponent(repo)}`;
|
|
205
|
+
const encodedFilePath = filePath
|
|
206
|
+
.split("/")
|
|
207
|
+
.map((part) => encodeURIComponent(part))
|
|
208
|
+
.join("/");
|
|
195
209
|
const fileUrlPath = effectiveBranch
|
|
196
|
-
? `/${effectiveBranch}/${
|
|
197
|
-
: `/${
|
|
210
|
+
? `/${encodeURIComponent(effectiveBranch)}/${encodedFilePath}`
|
|
211
|
+
: `/${encodedFilePath}`; // filePath might be at root
|
|
198
212
|
const url = `${baseUrl}${fileUrlPath}`;
|
|
199
213
|
|
|
200
214
|
try {
|
|
@@ -483,7 +497,7 @@ const downloadFolder = async (
|
|
|
483
497
|
// Don't claim success if files failed to download
|
|
484
498
|
if (succeeded === 0) {
|
|
485
499
|
console.log(
|
|
486
|
-
chalk.red(
|
|
500
|
+
chalk.red(`Download failed: No files were downloaded successfully`)
|
|
487
501
|
);
|
|
488
502
|
return {
|
|
489
503
|
success: false,
|
|
@@ -492,7 +506,7 @@ const downloadFolder = async (
|
|
|
492
506
|
isEmpty: false,
|
|
493
507
|
};
|
|
494
508
|
} else {
|
|
495
|
-
console.log(chalk.yellow(
|
|
509
|
+
console.log(chalk.yellow(`Download completed with errors`));
|
|
496
510
|
return {
|
|
497
511
|
success: false,
|
|
498
512
|
filesDownloaded: succeeded,
|
|
@@ -502,7 +516,7 @@ const downloadFolder = async (
|
|
|
502
516
|
}
|
|
503
517
|
} else {
|
|
504
518
|
console.log(
|
|
505
|
-
chalk.green(
|
|
519
|
+
chalk.green(`All ${succeeded} files downloaded successfully!`)
|
|
506
520
|
);
|
|
507
521
|
console.log(chalk.green(`Folder cloned successfully!`));
|
|
508
522
|
return {
|
|
@@ -514,7 +528,7 @@ const downloadFolder = async (
|
|
|
514
528
|
}
|
|
515
529
|
} catch (error) {
|
|
516
530
|
// Log the specific error details
|
|
517
|
-
console.error(chalk.red(
|
|
531
|
+
console.error(chalk.red(`Error downloading folder: ${error.message}`));
|
|
518
532
|
|
|
519
533
|
// Re-throw the error so the main CLI can exit with proper error code
|
|
520
534
|
throw error;
|
|
@@ -539,9 +553,17 @@ const downloadFolderWithResume = async (
|
|
|
539
553
|
}
|
|
540
554
|
|
|
541
555
|
const resumeManager = new ResumeManager();
|
|
542
|
-
const
|
|
543
|
-
folderPath
|
|
544
|
-
|
|
556
|
+
const encodedFolderPath = folderPath
|
|
557
|
+
? folderPath
|
|
558
|
+
.split("/")
|
|
559
|
+
.map((part) => encodeURIComponent(part))
|
|
560
|
+
.join("/")
|
|
561
|
+
: "";
|
|
562
|
+
const url = `https://github.com/${encodeURIComponent(
|
|
563
|
+
owner
|
|
564
|
+
)}/${encodeURIComponent(repo)}/tree/${encodeURIComponent(
|
|
565
|
+
branch || "main"
|
|
566
|
+
)}/${encodedFolderPath}`;
|
|
545
567
|
|
|
546
568
|
// Clear checkpoint if force restart is requested
|
|
547
569
|
if (forceRestart) {
|
|
@@ -554,14 +576,14 @@ const downloadFolderWithResume = async (
|
|
|
554
576
|
if (checkpoint) {
|
|
555
577
|
console.log(
|
|
556
578
|
chalk.blue(
|
|
557
|
-
|
|
579
|
+
`Found previous download from ${new Date(
|
|
558
580
|
checkpoint.timestamp
|
|
559
581
|
).toLocaleString()}`
|
|
560
582
|
)
|
|
561
583
|
);
|
|
562
584
|
console.log(
|
|
563
585
|
chalk.blue(
|
|
564
|
-
|
|
586
|
+
`Progress: ${checkpoint.downloadedFiles.length}/${checkpoint.totalFiles} files completed`
|
|
565
587
|
)
|
|
566
588
|
);
|
|
567
589
|
|
|
@@ -587,11 +609,11 @@ const downloadFolderWithResume = async (
|
|
|
587
609
|
if (corruptedCount > 0) {
|
|
588
610
|
console.log(
|
|
589
611
|
chalk.yellow(
|
|
590
|
-
|
|
612
|
+
`Detected ${corruptedCount} corrupted files, will re-download`
|
|
591
613
|
)
|
|
592
614
|
);
|
|
593
615
|
}
|
|
594
|
-
console.log(chalk.green(
|
|
616
|
+
console.log(chalk.green(`Verified ${validFiles.length} existing files`));
|
|
595
617
|
}
|
|
596
618
|
|
|
597
619
|
console.log(
|
|
@@ -640,7 +662,7 @@ const downloadFolderWithResume = async (
|
|
|
640
662
|
);
|
|
641
663
|
console.log(
|
|
642
664
|
chalk.cyan(
|
|
643
|
-
|
|
665
|
+
`Starting download of ${totalFiles} files from ${chalk.white(
|
|
644
666
|
owner + "/" + repo
|
|
645
667
|
)}...`
|
|
646
668
|
)
|
|
@@ -648,7 +670,7 @@ const downloadFolderWithResume = async (
|
|
|
648
670
|
} else {
|
|
649
671
|
// Update total files in case repository changed
|
|
650
672
|
checkpoint.totalFiles = totalFiles;
|
|
651
|
-
console.log(chalk.cyan(
|
|
673
|
+
console.log(chalk.cyan(`Resuming download...`));
|
|
652
674
|
}
|
|
653
675
|
|
|
654
676
|
// Get remaining files to download
|
|
@@ -663,13 +685,13 @@ const downloadFolderWithResume = async (
|
|
|
663
685
|
});
|
|
664
686
|
|
|
665
687
|
if (remainingFiles.length === 0) {
|
|
666
|
-
console.log(chalk.green(
|
|
688
|
+
console.log(chalk.green(`All files already downloaded!`));
|
|
667
689
|
resumeManager.cleanupCheckpoint(url, outputDir);
|
|
668
690
|
return;
|
|
669
691
|
}
|
|
670
692
|
|
|
671
693
|
console.log(
|
|
672
|
-
chalk.cyan(
|
|
694
|
+
chalk.cyan(`Downloading ${remainingFiles.length} remaining files...`)
|
|
673
695
|
);
|
|
674
696
|
|
|
675
697
|
// Setup progress bar
|
|
@@ -753,10 +775,8 @@ const downloadFolderWithResume = async (
|
|
|
753
775
|
if (error.name === "SIGINT") {
|
|
754
776
|
resumeManager.saveCheckpoint(checkpoint);
|
|
755
777
|
progressBar.stop();
|
|
756
|
-
console.log(
|
|
757
|
-
|
|
758
|
-
);
|
|
759
|
-
console.log(chalk.blue(`💡 Run the same command again to resume.`));
|
|
778
|
+
console.log(chalk.blue(`\nDownload interrupted. Progress saved.`));
|
|
779
|
+
console.log(chalk.blue(`Run the same command again to resume.`));
|
|
760
780
|
return;
|
|
761
781
|
}
|
|
762
782
|
|
|
@@ -793,13 +813,13 @@ const downloadFolderWithResume = async (
|
|
|
793
813
|
}
|
|
794
814
|
|
|
795
815
|
console.log(
|
|
796
|
-
chalk.blue(
|
|
816
|
+
chalk.blue(`Run the same command again to retry failed downloads`)
|
|
797
817
|
);
|
|
798
818
|
|
|
799
819
|
// Don't claim success if files failed to download
|
|
800
820
|
if (succeeded === 0) {
|
|
801
821
|
console.log(
|
|
802
|
-
chalk.red(
|
|
822
|
+
chalk.red(`Download failed: No files were downloaded successfully`)
|
|
803
823
|
);
|
|
804
824
|
return {
|
|
805
825
|
success: false,
|
|
@@ -808,7 +828,7 @@ const downloadFolderWithResume = async (
|
|
|
808
828
|
isEmpty: false,
|
|
809
829
|
};
|
|
810
830
|
} else {
|
|
811
|
-
console.log(chalk.yellow(
|
|
831
|
+
console.log(chalk.yellow(`Download completed with errors`));
|
|
812
832
|
return {
|
|
813
833
|
success: false,
|
|
814
834
|
filesDownloaded: succeeded,
|
|
@@ -818,7 +838,7 @@ const downloadFolderWithResume = async (
|
|
|
818
838
|
}
|
|
819
839
|
} else {
|
|
820
840
|
console.log(
|
|
821
|
-
chalk.green(
|
|
841
|
+
chalk.green(`All ${succeeded} files downloaded successfully!`)
|
|
822
842
|
);
|
|
823
843
|
resumeManager.cleanupCheckpoint(url, outputDir);
|
|
824
844
|
console.log(chalk.green(`Folder cloned successfully!`));
|
|
@@ -835,7 +855,7 @@ const downloadFolderWithResume = async (
|
|
|
835
855
|
resumeManager.saveCheckpoint(checkpoint);
|
|
836
856
|
}
|
|
837
857
|
|
|
838
|
-
console.error(chalk.red(
|
|
858
|
+
console.error(chalk.red(`Error downloading folder: ${error.message}`));
|
|
839
859
|
throw error;
|
|
840
860
|
}
|
|
841
861
|
};
|
package/src/index.js
CHANGED
|
@@ -76,7 +76,7 @@ const initializeCLI = () => {
|
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
console.log(chalk.cyan("\
|
|
79
|
+
console.log(chalk.cyan("\nDownload Checkpoints:"));
|
|
80
80
|
checkpoints.forEach((cp, index) => {
|
|
81
81
|
console.log(chalk.blue(`\n${index + 1}. ID: ${cp.id}`));
|
|
82
82
|
console.log(` URL: ${cp.url}`);
|
|
@@ -151,12 +151,12 @@ const initializeCLI = () => {
|
|
|
151
151
|
if (error) {
|
|
152
152
|
const failMsg =
|
|
153
153
|
operationType === "archive"
|
|
154
|
-
?
|
|
155
|
-
:
|
|
154
|
+
? `Archive creation failed: ${error.message}`
|
|
155
|
+
: `Download failed: ${error.message}`;
|
|
156
156
|
console.error(chalk.red(failMsg));
|
|
157
157
|
process.exit(1);
|
|
158
158
|
} else if (!createArchive && result && !result.success) {
|
|
159
|
-
console.error(chalk.red(
|
|
159
|
+
console.error(chalk.red(`Download failed`));
|
|
160
160
|
process.exit(1);
|
|
161
161
|
} else if (!createArchive && result && result.isEmpty) {
|
|
162
162
|
console.log("Operation completed - no files to download!");
|
package/src/parser.js
CHANGED
|
@@ -16,10 +16,10 @@ export function parseGitHubUrl(url) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
// Extract components from the matched pattern
|
|
19
|
-
const owner = match[1];
|
|
20
|
-
const repo = match[2];
|
|
21
|
-
const branch = match[3]; // Branch
|
|
22
|
-
const folderPath = match[4]
|
|
19
|
+
const owner = decodeURIComponent(match[1]);
|
|
20
|
+
const repo = decodeURIComponent(match[2]);
|
|
21
|
+
const branch = match[3] ? decodeURIComponent(match[3]) : ""; // Branch is an empty string if not present
|
|
22
|
+
const folderPath = match[4] ? decodeURIComponent(match[4]) : ""; // Empty string if no folder path
|
|
23
23
|
|
|
24
24
|
// Additional validation
|
|
25
25
|
if (!owner || !repo) {
|