git-ripper
Advanced tools
Comparing version
118
package.json
{ | ||
"name": "git-ripper", | ||
"version": "1.4.1", | ||
"description": "CLI tool that lets you download specific folders from GitHub repositories without cloning the entire repo.", | ||
"main": "src/index.js", | ||
"type": "module", | ||
"bin": { | ||
"git-ripper": "bin/git-ripper.js" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"dev": "node bin/git-ripper.js", | ||
"lint": "eslint ." | ||
}, | ||
"keywords": [ | ||
"git", | ||
"clone", | ||
"github", | ||
"subfolder", | ||
"repository", | ||
"download", | ||
"partial-clone", | ||
"directory-download", | ||
"folder-download", | ||
"git-utilities", | ||
"github-api", | ||
"monorepo-tools", | ||
"sparse-checkout" | ||
], | ||
"author": "sairajb", | ||
"license": "MIT", | ||
"dependencies": { | ||
"archiver": "^6.0.1", | ||
"axios": "^1.6.7", | ||
"chalk": "^5.3.0", | ||
"cli-progress": "^3.12.0", | ||
"commander": "^12.0.0", | ||
"p-limit": "^6.2.0", | ||
"pretty-bytes": "^6.1.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/sairajB/git-ripper.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/sairajB/git-ripper/issues" | ||
}, | ||
"homepage": "https://github.com/sairajB/git-ripper", | ||
"engines": { | ||
"node": ">=14.0.0" | ||
}, | ||
"files": [ | ||
"bin/", | ||
"src/", | ||
"LICENSE" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
"name": "git-ripper", | ||
"version": "1.4.2", | ||
"description": "CLI tool that lets you download specific folders from GitHub repositories without cloning the entire repo.", | ||
"main": "src/index.js", | ||
"type": "module", | ||
"bin": { | ||
"git-ripper": "bin/git-ripper.js" | ||
}, | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"dev": "node bin/git-ripper.js", | ||
"lint": "eslint ." | ||
}, | ||
"keywords": [ | ||
"git", | ||
"clone", | ||
"github", | ||
"subfolder", | ||
"repository", | ||
"download", | ||
"partial-clone", | ||
"directory-download", | ||
"folder-download", | ||
"git-utilities", | ||
"github-api", | ||
"monorepo-tools", | ||
"sparse-checkout" | ||
], | ||
"author": "sairajb", | ||
"license": "MIT", | ||
"dependencies": { | ||
"ansi-styles": "^6.2.1", | ||
"archiver": "^6.0.1", | ||
"axios": "^1.6.7", | ||
"chalk": "^5.3.0", | ||
"cli-progress": "^3.12.0", | ||
"commander": "^12.0.0", | ||
"p-limit": "^6.2.0", | ||
"pretty-bytes": "^6.1.1", | ||
"supports-color": "^9.3.1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/sairajB/git-ripper.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/sairajB/git-ripper/issues" | ||
}, | ||
"homepage": "https://github.com/sairajB/git-ripper", | ||
"engines": { | ||
"node": ">=16.0.0" | ||
}, | ||
"files": [ | ||
"bin/", | ||
"src/", | ||
"LICENSE" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
@@ -8,4 +8,8 @@ # Git-ripper | ||
[](https://www.npmjs.com/package/git-ripper) | ||
[](https://www.npmjs.com/package/git-ripper) | ||
[](https://bundlephobia.com/package/git-ripper) | ||
[](https://github.com/sairajB/git-ripper/issues) | ||
[](https://github.com/sairajB/git-ripper/stargazers) | ||
[](https://github.com/sairajB/git-ripper/network) | ||
[](https://github.com/sairajB/git-ripper/commits/master) | ||
@@ -29,2 +33,13 @@ **Download specific folders from GitHub repositories without cloning the entire codebase** | ||
## Project Stats | ||
Git-ripper has grown to become a trusted tool in the developer ecosystem: | ||
- **Total Downloads**: Thousands of developers worldwide have downloaded Git-ripper to optimize their workflow and save time when working with large repositories. | ||
- **Weekly Active Users**: Our weekly download statistics show consistent adoption and usage among developers, indicating the tool's reliability and usefulness. | ||
- **Minimal Bundle Size**: Git-ripper is designed to be lightweight and efficient, with a minimal bundle size that ensures quick installation and minimal impact on your system resources. | ||
- **Active Maintenance**: The project is actively maintained with regular updates and improvements, ensuring compatibility with the latest GitHub API changes and addressing user feedback. | ||
- **Community Support**: With growing stars and forks on GitHub, Git-ripper has built a supportive community of users who contribute to its ongoing development and share their success stories. | ||
- **Enterprise Adoption**: Used by teams in various organizations, from startups to large enterprises, Git-ripper helps development teams streamline their workflows when working with modular components from large codebases. | ||
## Features | ||
@@ -36,3 +51,3 @@ | ||
- **Branch Support**: Works with any branch, not just the default one | ||
- **Archive Export**: Create ZIP or TAR archives of downloaded content | ||
- **Archive Export**: Create ZIP archives of downloaded content | ||
- **Simple Interface**: Clean, intuitive command-line experience | ||
@@ -44,2 +59,6 @@ - **Lightweight**: Minimal dependencies and fast execution | ||
### Requirements | ||
Git-ripper requires Node.js >=16.0.0 due to its use of modern JavaScript features and built-in Node.js modules. | ||
### Global Installation (Recommended) | ||
@@ -81,6 +100,6 @@ | ||
### Creating TAR Archive with Custom Name | ||
### Creating ZIP Archive with Custom Name | ||
```bash | ||
git-ripper https://github.com/username/repository/tree/branch/folder --tar="my-archive.tar" | ||
git-ripper https://github.com/username/repository/tree/branch/folder --zip="my-archive.zip" | ||
``` | ||
@@ -90,10 +109,8 @@ | ||
| Option | Description | Default | | ||
|--------|-------------|---------| | ||
| `-o, --output <directory>` | Specify output directory | Current directory | | ||
| `--zip [filename]` | Create ZIP archive of downloaded content | - | | ||
| `--tar [filename]` | Create TAR archive of downloaded content | - | | ||
| `--compression-level <level>` | Set compression level (1-9) | 6 | | ||
| `-V, --version` | Show version number | - | | ||
| `-h, --help` | Show help | - | | ||
| Option | Description | Default | | ||
| -------------------------- | ---------------------------------------- | ----------------- | | ||
| `-o, --output <directory>` | Specify output directory | Current directory | | ||
| `--zip [filename]` | Create ZIP archive of downloaded content | - | | ||
| `-V, --version` | Show version number | - | | ||
| `-h, --help` | Show help | - | | ||
@@ -136,4 +153,4 @@ ## Examples | ||
# Extract VS Code build configuration with maximum compression | ||
git-ripper https://github.com/microsoft/vscode/tree/main/build --tar --compression-level=9 | ||
# Extract VS Code build configuration with custom archive name | ||
git-ripper https://github.com/microsoft/vscode/tree/main/build --zip="vscode-build.zip" | ||
``` | ||
@@ -194,12 +211,2 @@ | ||
## Roadmap | ||
- [x] Add archive export options (ZIP/TAR) | ||
- [ ] Add GitHub token authentication | ||
- [ ] Support for GitLab and Bitbucket repositories | ||
- [ ] Download from specific commits or tags | ||
- [ ] Dry run mode | ||
- [ ] File filtering options | ||
- [ ] CLI interactive mode | ||
## License | ||
@@ -206,0 +213,0 @@ |
@@ -49,15 +49,13 @@ import fs from "fs"; | ||
/** | ||
* Creates an archive (zip or tar) from a directory | ||
* Creates a ZIP archive from a directory with standard compression | ||
* | ||
* @param {string} sourceDir - Source directory to archive | ||
* @param {string} outputPath - Path where the archive should be saved | ||
* @param {object} options - Archive options | ||
* @param {string} options.format - Archive format ('zip' or 'tar') | ||
* @param {number} options.compressionLevel - Compression level (0-9, default: 6) | ||
* @returns {Promise<string>} - Path to the created archive | ||
*/ | ||
export const createArchive = (sourceDir, outputPath, options = {}) => { | ||
export const createArchive = (sourceDir, outputPath) => { | ||
return new Promise((resolve, reject) => { | ||
try { | ||
const { format = "zip", compressionLevel = 6 } = options; | ||
// Fixed compression level of 5 (balanced between speed and size) | ||
const compressionLevel = 5; | ||
@@ -83,23 +81,7 @@ // Validate source directory | ||
const output = fs.createWriteStream(outputPath); | ||
let archive; | ||
// Create the appropriate archive type | ||
if (format === "zip") { | ||
archive = archiver("zip", { | ||
zlib: { level: compressionLevel }, | ||
}); | ||
} else if (format === "tar") { | ||
// Use gzip compression for tar if compressionLevel > 0 | ||
if (compressionLevel > 0) { | ||
archive = archiver("tar", { | ||
gzip: true, | ||
gzipOptions: { level: compressionLevel }, | ||
}); | ||
} else { | ||
// Create a tar archive without gzip compression | ||
archive = archiver("tar"); | ||
} | ||
} else { | ||
return reject(new Error(`Unsupported archive format: ${format}`)); | ||
} | ||
// Create ZIP archive with standard compression | ||
const archive = archiver("zip", { | ||
zlib: { level: compressionLevel }, | ||
}); | ||
@@ -146,9 +128,7 @@ // Listen for archive events | ||
/** | ||
* Downloads folder contents and creates an archive | ||
* Downloads folder contents and creates a ZIP archive | ||
* | ||
* @param {object} repoInfo - Repository information object | ||
* @param {string} outputDir - Directory where files should be downloaded | ||
* @param {string} archiveFormat - Archive format ('zip' or 'tar') | ||
* @param {string} archiveName - Custom name for the archive file | ||
* @param {number} compressionLevel - Compression level (0-9) | ||
* @param {string} archiveName - Custom name for the archive file (optional) | ||
* @returns {Promise<string>} - Path to the created archive | ||
@@ -159,5 +139,3 @@ */ | ||
outputDir, | ||
archiveFormat = "zip", | ||
archiveName = null, | ||
compressionLevel = 6 | ||
archiveName = null | ||
) => { | ||
@@ -167,5 +145,3 @@ const { downloadFolder } = await import("./downloader.js"); | ||
console.log( | ||
chalk.cyan( | ||
`Downloading folder and preparing to create ${archiveFormat.toUpperCase()} archive...` | ||
) | ||
chalk.cyan(`Downloading folder and preparing to create ZIP archive...`) | ||
); | ||
@@ -190,4 +166,4 @@ | ||
// Add extension if not present | ||
if (!archiveFileName.endsWith(`.${archiveFormat}`)) { | ||
archiveFileName += `.${archiveFormat}`; | ||
if (!archiveFileName.endsWith(`.zip`)) { | ||
archiveFileName += `.zip`; | ||
} | ||
@@ -198,9 +174,4 @@ | ||
// Create the archive | ||
console.log( | ||
chalk.cyan(`Creating ${archiveFormat.toUpperCase()} archive...`) | ||
); | ||
await createArchive(tempDir, archivePath, { | ||
format: archiveFormat, | ||
compressionLevel, | ||
}); | ||
console.log(chalk.cyan(`Creating ZIP archive...`)); | ||
await createArchive(tempDir, archivePath); | ||
@@ -207,0 +178,0 @@ return archivePath; |
@@ -62,4 +62,2 @@ import { program } from "commander"; | ||
.option("--zip [filename]", "Create ZIP archive of downloaded files") | ||
.option("--tar [filename]", "Create TAR archive of downloaded files") | ||
.option("--compression-level <level>", "Compression level (1-9)", "6") | ||
.action(async (url, options) => { | ||
@@ -70,19 +68,2 @@ try { | ||
// Validate options | ||
if (options.compressionLevel) { | ||
const level = parseInt(options.compressionLevel, 10); | ||
if (isNaN(level) || level < 0 || level > 9) { | ||
// Allow 0 for no compression | ||
throw new Error( | ||
"Compression level must be a number between 0 and 9" | ||
); | ||
} | ||
} | ||
if (options.zip && options.tar) { | ||
throw new Error( | ||
"Cannot specify both --zip and --tar options at the same time" | ||
); | ||
} | ||
// Validate output directory | ||
@@ -95,21 +76,10 @@ try { | ||
// Handle archive options | ||
const archiveFormat = options.zip ? "zip" : options.tar ? "tar" : null; | ||
// Handle archive option | ||
const createArchive = options.zip !== undefined; | ||
const archiveName = | ||
typeof options.zip === "string" | ||
? options.zip | ||
: typeof options.tar === "string" | ||
? options.tar | ||
: null; | ||
const compressionLevel = parseInt(options.compressionLevel, 10) || 6; | ||
typeof options.zip === "string" ? options.zip : null; | ||
if (archiveFormat) { | ||
console.log(`Creating ${archiveFormat.toUpperCase()} archive...`); | ||
await downloadAndArchive( | ||
parsedUrl, | ||
options.output, | ||
archiveFormat, | ||
archiveName, | ||
compressionLevel | ||
); | ||
if (createArchive) { | ||
console.log(`Creating ZIP archive...`); | ||
await downloadAndArchive(parsedUrl, options.output, archiveName); | ||
} else { | ||
@@ -116,0 +86,0 @@ console.log(`Downloading folder to: ${options.output}`); |
219
3.3%37856
-1.36%9
28.57%726
-7.28%+ Added
+ Added
+ Added
+ Added