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 CHANGED
@@ -5,8 +5,12 @@
5
5
  [![NPM version](https://img.shields.io/npm/v/git-ripper.svg)](https://www.npmjs.com/package/git-ripper)
6
6
  [![License](https://img.shields.io/npm/l/git-ripper.svg)](https://github.com/sairajB/git-ripper/blob/main/LICENSE)
7
7
  [![Downloads](https://img.shields.io/npm/dt/git-ripper.svg?style=flat&label=total%20downloads)](https://www.npmjs.com/package/git-ripper)
8
+ [![Weekly Downloads](https://img.shields.io/npm/dw/git-ripper.svg)](https://www.npmjs.com/package/git-ripper)
9
+ [![Bundle Size](https://img.shields.io/bundlephobia/min/git-ripper.svg)](https://bundlephobia.com/package/git-ripper)
8
10
  [![GitHub issues](https://img.shields.io/github/issues/sairajB/git-ripper.svg)](https://github.com/sairajB/git-ripper/issues)
9
11
  [![GitHub stars](https://img.shields.io/github/stars/sairajB/git-ripper.svg)](https://github.com/sairajB/git-ripper/stargazers)
12
+ [![GitHub forks](https://img.shields.io/github/forks/sairajB/git-ripper.svg)](https://github.com/sairajB/git-ripper/network)
13
+ [![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)](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 or TAR archives of downloaded content
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 TAR Archive with Custom Name
85
+ ### Creating ZIP Archive with Custom Name
78
86
 
79
87
  ```bash
80
- git-ripper https://github.com/username/repository/tree/branch/folder --tar="my-archive.tar"
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 | Description | Default |
86
- |--------|-------------|---------|
87
- | `-o, --output <directory>` | Specify output directory | Current directory |
88
- | `--zip [filename]` | Create ZIP archive of downloaded content | - |
89
- | `--tar [filename]` | Create TAR archive of downloaded content | - |
90
- | `--compression-level <level>` | Set compression level (1-9) | 6 |
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 maximum compression
131
- git-ripper https://github.com/microsoft/vscode/tree/main/build --tar --compression-level=9
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
- "name": "git-ripper",
3
- "version": "1.4.1",
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
- "dependencies": {
33
- "archiver": "^6.0.1",
34
- "axios": "^1.6.7",
35
- "chalk": "^5.3.0",
36
- "cli-progress": "^3.12.0",
37
- "commander": "^12.0.0",
38
- "p-limit": "^6.2.0",
39
- "pretty-bytes": "^6.1.1"
40
- },
41
- "repository": {
42
- "type": "git",
43
- "url": "git+https://github.com/sairajB/git-ripper.git"
44
- },
45
- "bugs": {
46
- "url": "https://github.com/sairajB/git-ripper/issues"
47
- },
48
- "homepage": "https://github.com/sairajB/git-ripper",
49
- "engines": {
50
- "node": ">=14.0.0"
51
- },
52
- "files": [
53
- "bin/",
54
- "src/",
55
- "LICENSE"
56
- ],
57
- "publishConfig": {
58
- "access": "public"
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 an archive (zip or tar) from a directory
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, options = {}) => {
55
+ export const createArchive = (sourceDir, outputPath) => {
59
56
  return new Promise((resolve, reject) => {
60
57
  try {
61
- const { format = "zip", compressionLevel = 6 } = options;
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
- let archive;
83
-
84
- // Create the appropriate archive type
85
- if (format === "zip") {
86
- archive = archiver("zip", {
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 an archive
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} archiveFormat - Archive format ('zip' or 'tar')
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
- archiveFormat = "zip",
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(`.${archiveFormat}`)) {
186
- archiveFileName += `.${archiveFormat}`;
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
- chalk.cyan(`Creating ${archiveFormat.toUpperCase()} archive...`)
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 options
94
- const archiveFormat = options.zip ? "zip" : options.tar ? "tar" : null;
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 (archiveFormat) {
104
- console.log(`Creating ${archiveFormat.toUpperCase()} archive...`);
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);