git-ripper 1.4.1 → 1.4.3
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 +19 -23
- package/package.json +64 -58
- package/src/archiver.js +17 -46
- package/src/index.js +6 -36
package/README.md
CHANGED
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/git-ripper)
|
|
6
6
|
[](https://github.com/sairajB/git-ripper/blob/main/LICENSE)
|
|
7
7
|
[](https://www.npmjs.com/package/git-ripper)
|
|
8
|
+
[](https://www.npmjs.com/package/git-ripper)
|
|
9
|
+
[](https://bundlephobia.com/package/git-ripper)
|
|
8
10
|
[](https://github.com/sairajB/git-ripper/issues)
|
|
9
11
|
[](https://github.com/sairajB/git-ripper/stargazers)
|
|
12
|
+
[](https://github.com/sairajB/git-ripper/network)
|
|
13
|
+
[](https://github.com/sairajB/git-ripper/commits/master)
|
|
10
14
|
|
|
11
15
|
**Download specific folders from GitHub repositories without cloning the entire codebase**
|
|
12
16
|
|
|
@@ -31,13 +35,17 @@ Have you ever needed just a single component from a massive repository? Or wante
|
|
|
31
35
|
- **Directory Structure**: Preserves complete folder structure
|
|
32
36
|
- **Custom Output**: Specify your preferred output directory
|
|
33
37
|
- **Branch Support**: Works with any branch, not just the default one
|
|
34
|
-
- **Archive Export**: Create ZIP
|
|
38
|
+
- **Archive Export**: Create ZIP archives of downloaded content
|
|
35
39
|
- **Simple Interface**: Clean, intuitive command-line experience
|
|
36
40
|
- **Lightweight**: Minimal dependencies and fast execution
|
|
37
41
|
- **No Authentication**: Works with public repositories without requiring credentials
|
|
38
42
|
|
|
39
43
|
## Installation
|
|
40
44
|
|
|
45
|
+
### Requirements
|
|
46
|
+
|
|
47
|
+
Git-ripper requires Node.js >=16.0.0 due to its use of modern JavaScript features and built-in Node.js modules.
|
|
48
|
+
|
|
41
49
|
### Global Installation (Recommended)
|
|
42
50
|
|
|
43
51
|
```bash
|
|
@@ -74,22 +82,20 @@ git-ripper https://github.com/username/repository/tree/branch/folder -o ./my-out
|
|
|
74
82
|
git-ripper https://github.com/username/repository/tree/branch/folder --zip
|
|
75
83
|
```
|
|
76
84
|
|
|
77
|
-
### Creating
|
|
85
|
+
### Creating ZIP Archive with Custom Name
|
|
78
86
|
|
|
79
87
|
```bash
|
|
80
|
-
git-ripper https://github.com/username/repository/tree/branch/folder --
|
|
88
|
+
git-ripper https://github.com/username/repository/tree/branch/folder --zip="my-archive.zip"
|
|
81
89
|
```
|
|
82
90
|
|
|
83
91
|
### Command Line Options
|
|
84
92
|
|
|
85
|
-
| Option
|
|
86
|
-
|
|
87
|
-
| `-o, --output <directory>` | Specify output directory
|
|
88
|
-
| `--zip [filename]`
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
| `-V, --version` | Show version number | - |
|
|
92
|
-
| `-h, --help` | Show help | - |
|
|
93
|
+
| Option | Description | Default |
|
|
94
|
+
| -------------------------- | ---------------------------------------- | ----------------- |
|
|
95
|
+
| `-o, --output <directory>` | Specify output directory | Current directory |
|
|
96
|
+
| `--zip [filename]` | Create ZIP archive of downloaded content | - |
|
|
97
|
+
| `-V, --version` | Show version number | - |
|
|
98
|
+
| `-h, --help` | Show help | - |
|
|
93
99
|
|
|
94
100
|
## Examples
|
|
95
101
|
|
|
@@ -127,8 +133,8 @@ git-ripper https://github.com/tailwindlabs/tailwindcss/tree/master/src/component
|
|
|
127
133
|
# Download React DOM package and create a ZIP archive
|
|
128
134
|
git-ripper https://github.com/facebook/react/tree/main/packages/react-dom --zip
|
|
129
135
|
|
|
130
|
-
# Extract VS Code build configuration with
|
|
131
|
-
git-ripper https://github.com/microsoft/vscode/tree/main/build --
|
|
136
|
+
# Extract VS Code build configuration with custom archive name
|
|
137
|
+
git-ripper https://github.com/microsoft/vscode/tree/main/build --zip="vscode-build.zip"
|
|
132
138
|
```
|
|
133
139
|
|
|
134
140
|
## How It Works
|
|
@@ -184,16 +190,6 @@ Contributions make the open-source community an amazing place to learn, inspire,
|
|
|
184
190
|
|
|
185
191
|
See the [open issues](https://github.com/sairajB/git-ripper/issues) for a list of proposed features and known issues.
|
|
186
192
|
|
|
187
|
-
## Roadmap
|
|
188
|
-
|
|
189
|
-
- [x] Add archive export options (ZIP/TAR)
|
|
190
|
-
- [ ] Add GitHub token authentication
|
|
191
|
-
- [ ] Support for GitLab and Bitbucket repositories
|
|
192
|
-
- [ ] Download from specific commits or tags
|
|
193
|
-
- [ ] Dry run mode
|
|
194
|
-
- [ ] File filtering options
|
|
195
|
-
- [ ] CLI interactive mode
|
|
196
|
-
|
|
197
193
|
## License
|
|
198
194
|
|
|
199
195
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
package/package.json
CHANGED
|
@@ -1,60 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
2
|
+
"name": "git-ripper",
|
|
3
|
+
"version": "1.4.3",
|
|
4
|
+
"description": "CLI tool that lets you download specific folders from GitHub repositories without cloning the entire repo.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"git-ripper": "bin/git-ripper.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
+
"dev": "node bin/git-ripper.js",
|
|
13
|
+
"lint": "eslint ."
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"git",
|
|
17
|
+
"clone",
|
|
18
|
+
"github",
|
|
19
|
+
"subfolder",
|
|
20
|
+
"repository",
|
|
21
|
+
"download",
|
|
22
|
+
"partial-clone",
|
|
23
|
+
"directory-download",
|
|
24
|
+
"folder-download",
|
|
25
|
+
"git-utilities",
|
|
26
|
+
"github-api",
|
|
27
|
+
"monorepo-tools",
|
|
28
|
+
"sparse-checkout"
|
|
29
|
+
],
|
|
30
|
+
"author": "sairajb",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"imports": {
|
|
33
|
+
"#ansi-styles": "ansi-styles",
|
|
34
|
+
"#supports-color": "supports-color"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"ansi-styles": "^6.2.1",
|
|
38
|
+
"archiver": "^6.0.1",
|
|
39
|
+
"axios": "^1.6.7",
|
|
40
|
+
"chalk": "^5.3.0",
|
|
41
|
+
"cli-progress": "^3.12.0",
|
|
42
|
+
"commander": "^12.0.0",
|
|
43
|
+
"p-limit": "^6.2.0",
|
|
44
|
+
"pretty-bytes": "^6.1.1",
|
|
45
|
+
"supports-color": "^9.4.0"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/sairajB/git-ripper.git"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/sairajB/git-ripper/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/sairajB/git-ripper",
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=16.0.0"
|
|
57
|
+
},
|
|
58
|
+
"files": [
|
|
59
|
+
"bin/",
|
|
60
|
+
"src/",
|
|
61
|
+
"LICENSE"
|
|
62
|
+
],
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
60
66
|
}
|
package/src/archiver.js
CHANGED
|
@@ -46,19 +46,17 @@ const validateArchivePath = (outputPath) => {
|
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* Creates
|
|
49
|
+
* Creates a ZIP archive from a directory with standard compression
|
|
50
50
|
*
|
|
51
51
|
* @param {string} sourceDir - Source directory to archive
|
|
52
52
|
* @param {string} outputPath - Path where the archive should be saved
|
|
53
|
-
* @param {object} options - Archive options
|
|
54
|
-
* @param {string} options.format - Archive format ('zip' or 'tar')
|
|
55
|
-
* @param {number} options.compressionLevel - Compression level (0-9, default: 6)
|
|
56
53
|
* @returns {Promise<string>} - Path to the created archive
|
|
57
54
|
*/
|
|
58
|
-
export const createArchive = (sourceDir, outputPath
|
|
55
|
+
export const createArchive = (sourceDir, outputPath) => {
|
|
59
56
|
return new Promise((resolve, reject) => {
|
|
60
57
|
try {
|
|
61
|
-
|
|
58
|
+
// Fixed compression level of 5 (balanced between speed and size)
|
|
59
|
+
const compressionLevel = 5;
|
|
62
60
|
|
|
63
61
|
// Validate source directory
|
|
64
62
|
if (!fs.existsSync(sourceDir)) {
|
|
@@ -79,27 +77,11 @@ export const createArchive = (sourceDir, outputPath, options = {}) => {
|
|
|
79
77
|
|
|
80
78
|
// Create output stream
|
|
81
79
|
const output = fs.createWriteStream(outputPath);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
zlib: { level: compressionLevel },
|
|
88
|
-
});
|
|
89
|
-
} else if (format === "tar") {
|
|
90
|
-
// Use gzip compression for tar if compressionLevel > 0
|
|
91
|
-
if (compressionLevel > 0) {
|
|
92
|
-
archive = archiver("tar", {
|
|
93
|
-
gzip: true,
|
|
94
|
-
gzipOptions: { level: compressionLevel },
|
|
95
|
-
});
|
|
96
|
-
} else {
|
|
97
|
-
// Create a tar archive without gzip compression
|
|
98
|
-
archive = archiver("tar");
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
return reject(new Error(`Unsupported archive format: ${format}`));
|
|
102
|
-
}
|
|
80
|
+
|
|
81
|
+
// Create ZIP archive with standard compression
|
|
82
|
+
const archive = archiver("zip", {
|
|
83
|
+
zlib: { level: compressionLevel },
|
|
84
|
+
});
|
|
103
85
|
|
|
104
86
|
// Listen for archive events
|
|
105
87
|
output.on("close", () => {
|
|
@@ -141,28 +123,22 @@ export const createArchive = (sourceDir, outputPath, options = {}) => {
|
|
|
141
123
|
};
|
|
142
124
|
|
|
143
125
|
/**
|
|
144
|
-
* Downloads folder contents and creates
|
|
126
|
+
* Downloads folder contents and creates a ZIP archive
|
|
145
127
|
*
|
|
146
128
|
* @param {object} repoInfo - Repository information object
|
|
147
129
|
* @param {string} outputDir - Directory where files should be downloaded
|
|
148
|
-
* @param {string}
|
|
149
|
-
* @param {string} archiveName - Custom name for the archive file
|
|
150
|
-
* @param {number} compressionLevel - Compression level (0-9)
|
|
130
|
+
* @param {string} archiveName - Custom name for the archive file (optional)
|
|
151
131
|
* @returns {Promise<string>} - Path to the created archive
|
|
152
132
|
*/
|
|
153
133
|
export const downloadAndArchive = async (
|
|
154
134
|
repoInfo,
|
|
155
135
|
outputDir,
|
|
156
|
-
|
|
157
|
-
archiveName = null,
|
|
158
|
-
compressionLevel = 6
|
|
136
|
+
archiveName = null
|
|
159
137
|
) => {
|
|
160
138
|
const { downloadFolder } = await import("./downloader.js");
|
|
161
139
|
|
|
162
140
|
console.log(
|
|
163
|
-
chalk.cyan(
|
|
164
|
-
`Downloading folder and preparing to create ${archiveFormat.toUpperCase()} archive...`
|
|
165
|
-
)
|
|
141
|
+
chalk.cyan(`Downloading folder and preparing to create ZIP archive...`)
|
|
166
142
|
);
|
|
167
143
|
|
|
168
144
|
// Create a temporary directory for the download
|
|
@@ -182,20 +158,15 @@ export const downloadAndArchive = async (
|
|
|
182
158
|
}
|
|
183
159
|
|
|
184
160
|
// Add extension if not present
|
|
185
|
-
if (!archiveFileName.endsWith(
|
|
186
|
-
archiveFileName +=
|
|
161
|
+
if (!archiveFileName.endsWith(`.zip`)) {
|
|
162
|
+
archiveFileName += `.zip`;
|
|
187
163
|
}
|
|
188
164
|
|
|
189
165
|
const archivePath = path.join(outputDir, archiveFileName);
|
|
190
166
|
|
|
191
167
|
// Create the archive
|
|
192
|
-
console.log(
|
|
193
|
-
|
|
194
|
-
);
|
|
195
|
-
await createArchive(tempDir, archivePath, {
|
|
196
|
-
format: archiveFormat,
|
|
197
|
-
compressionLevel,
|
|
198
|
-
});
|
|
168
|
+
console.log(chalk.cyan(`Creating ZIP archive...`));
|
|
169
|
+
await createArchive(tempDir, archivePath);
|
|
199
170
|
|
|
200
171
|
return archivePath;
|
|
201
172
|
} catch (error) {
|
package/src/index.js
CHANGED
|
@@ -59,30 +59,11 @@ const initializeCLI = () => {
|
|
|
59
59
|
.argument("<url>", "GitHub URL of the folder to clone")
|
|
60
60
|
.option("-o, --output <directory>", "Output directory", process.cwd())
|
|
61
61
|
.option("--zip [filename]", "Create ZIP archive of downloaded files")
|
|
62
|
-
.option("--tar [filename]", "Create TAR archive of downloaded files")
|
|
63
|
-
.option("--compression-level <level>", "Compression level (1-9)", "6")
|
|
64
62
|
.action(async (url, options) => {
|
|
65
63
|
try {
|
|
66
64
|
console.log(`Parsing URL: ${url}`);
|
|
67
65
|
const parsedUrl = parseGitHubUrl(url);
|
|
68
66
|
|
|
69
|
-
// Validate options
|
|
70
|
-
if (options.compressionLevel) {
|
|
71
|
-
const level = parseInt(options.compressionLevel, 10);
|
|
72
|
-
if (isNaN(level) || level < 0 || level > 9) {
|
|
73
|
-
// Allow 0 for no compression
|
|
74
|
-
throw new Error(
|
|
75
|
-
"Compression level must be a number between 0 and 9"
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (options.zip && options.tar) {
|
|
81
|
-
throw new Error(
|
|
82
|
-
"Cannot specify both --zip and --tar options at the same time"
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
67
|
// Validate output directory
|
|
87
68
|
try {
|
|
88
69
|
options.output = validateOutputDirectory(options.output);
|
|
@@ -90,25 +71,14 @@ const initializeCLI = () => {
|
|
|
90
71
|
throw new Error(`Output directory error: ${dirError.message}`);
|
|
91
72
|
}
|
|
92
73
|
|
|
93
|
-
// Handle archive
|
|
94
|
-
const
|
|
74
|
+
// Handle archive option
|
|
75
|
+
const createArchive = options.zip !== undefined;
|
|
95
76
|
const archiveName =
|
|
96
|
-
typeof options.zip === "string"
|
|
97
|
-
? options.zip
|
|
98
|
-
: typeof options.tar === "string"
|
|
99
|
-
? options.tar
|
|
100
|
-
: null;
|
|
101
|
-
const compressionLevel = parseInt(options.compressionLevel, 10) || 6;
|
|
77
|
+
typeof options.zip === "string" ? options.zip : null;
|
|
102
78
|
|
|
103
|
-
if (
|
|
104
|
-
console.log(`Creating
|
|
105
|
-
await downloadAndArchive(
|
|
106
|
-
parsedUrl,
|
|
107
|
-
options.output,
|
|
108
|
-
archiveFormat,
|
|
109
|
-
archiveName,
|
|
110
|
-
compressionLevel
|
|
111
|
-
);
|
|
79
|
+
if (createArchive) {
|
|
80
|
+
console.log(`Creating ZIP archive...`);
|
|
81
|
+
await downloadAndArchive(parsedUrl, options.output, archiveName);
|
|
112
82
|
} else {
|
|
113
83
|
console.log(`Downloading folder to: ${options.output}`);
|
|
114
84
|
await downloadFolder(parsedUrl, options.output);
|