git-ripper 1.0.0
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 +135 -0
- package/bin/git-ripper.js +3 -0
- package/package.json +34 -0
- package/src/downloader.js +39 -0
- package/src/index.js +27 -0
- package/src/parser.js +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# 📁 Git-ripper
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/git-ripperper)
|
|
6
|
+
[](https://github.com/yourusername/git-ripper/blob/main/LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/git-ripper)
|
|
8
|
+
|
|
9
|
+
Download specific folders from GitHub repositories without cloning the entire repo. Fast, simple, and efficient.
|
|
10
|
+
|
|
11
|
+
[Installation](#installation) •
|
|
12
|
+
[Usage](#usage) •
|
|
13
|
+
[Features](#features) •
|
|
14
|
+
[Examples](#examples) •
|
|
15
|
+
[Contributing](#contributing)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
## 🚀 Features
|
|
20
|
+
|
|
21
|
+
- 📥 Download specific folders instead of entire repositories
|
|
22
|
+
- 🌳 Preserve complete folder structure
|
|
23
|
+
- 📂 Specify custom output directory
|
|
24
|
+
- 🔄 Works with any branch
|
|
25
|
+
- 💻 Simple command-line interface
|
|
26
|
+
- ⚡ Fast and lightweight
|
|
27
|
+
- 🔒 No authentication required for public repositories
|
|
28
|
+
|
|
29
|
+
## 📦 Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Install globally
|
|
33
|
+
npm install -g git-ripper
|
|
34
|
+
|
|
35
|
+
# Or run with npx
|
|
36
|
+
npx git-ripper
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 🎯 Usage
|
|
40
|
+
|
|
41
|
+
### Basic Usage
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git-ripper https://github.com/sairajB/git-ripper/tree/main/src
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### With Output Directory
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git-ripper https://github.com/sairajB/git-ripper/tree/main/src -o ripped-folder
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Command Line Options
|
|
54
|
+
|
|
55
|
+
| Option | Description | Default |
|
|
56
|
+
|--------|-------------|---------|
|
|
57
|
+
| `-o, --output <directory>` | Specify output directory | Current directory |
|
|
58
|
+
| `-V, --version` | Show version number | - |
|
|
59
|
+
| `-h, --help` | Show help | - |
|
|
60
|
+
|
|
61
|
+
## 📝 Examples
|
|
62
|
+
|
|
63
|
+
### Download a React Component Library
|
|
64
|
+
```bash
|
|
65
|
+
git-ripper https://github.com/facebook/react/tree/main/packages/react-dom
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Download Configuration Files
|
|
69
|
+
```bash
|
|
70
|
+
git-ripper https://github.com/microsoft/vscode/tree/main/build -o ./build-config
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Download Documentation
|
|
74
|
+
```bash
|
|
75
|
+
git-ripper https://github.com/nodejs/node/tree/main/doc -o ./node-docs
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 🔍 How It Works
|
|
79
|
+
|
|
80
|
+
1. Parses the provided GitHub URL to extract:
|
|
81
|
+
- Repository owner
|
|
82
|
+
- Repository name
|
|
83
|
+
- Branch name (defaults to 'main')
|
|
84
|
+
- Target folder path
|
|
85
|
+
|
|
86
|
+
2. Uses GitHub's API to fetch the folder structure
|
|
87
|
+
3. Downloads each file while maintaining the directory structure
|
|
88
|
+
4. Saves files to the specified output directory
|
|
89
|
+
|
|
90
|
+
## 🤝 Contributing
|
|
91
|
+
|
|
92
|
+
Contributions are always welcome! Here's how you can help:
|
|
93
|
+
|
|
94
|
+
1. Fork the repository
|
|
95
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
96
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
97
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
98
|
+
5. Open a Pull Request
|
|
99
|
+
|
|
100
|
+
## 📄 License
|
|
101
|
+
|
|
102
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
103
|
+
|
|
104
|
+
## 🐛 Troubleshooting
|
|
105
|
+
|
|
106
|
+
### Rate Limiting
|
|
107
|
+
If you encounter rate limiting issues with the GitHub API, you can:
|
|
108
|
+
- Wait and try again later
|
|
109
|
+
- Use a GitHub token (coming soon)
|
|
110
|
+
|
|
111
|
+
### Common Issues
|
|
112
|
+
|
|
113
|
+
1. **"Invalid URL" Error**
|
|
114
|
+
- Make sure the URL follows the format: `https://github.com/owner/repo/tree/branch/folder`
|
|
115
|
+
- Check if the repository and folder exist
|
|
116
|
+
|
|
117
|
+
2. **"Path not found" Error**
|
|
118
|
+
- Verify the folder path is correct
|
|
119
|
+
- Check if the branch name is correct
|
|
120
|
+
|
|
121
|
+
## 🙏 Acknowledgments
|
|
122
|
+
|
|
123
|
+
- Thanks to GitHub for providing the API
|
|
124
|
+
- Inspired by the need to download specific folders without cloning entire repositories
|
|
125
|
+
|
|
126
|
+
## 📬 Contact
|
|
127
|
+
|
|
128
|
+
- Create an issue in this repository
|
|
129
|
+
- Follow me on [GitHub](https://github.com/sairajB)
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
<div align="center">
|
|
134
|
+
Made with ❤️ by sairajB
|
|
135
|
+
</div>
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-ripper",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Download specific folders from GitHub repositories without cloning the entire repo.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"git-ripper": "./bin/git-ripper.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"dev": "node bin/git-ripper.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"github",
|
|
15
|
+
"download",
|
|
16
|
+
"folder",
|
|
17
|
+
"clone",
|
|
18
|
+
"repository"
|
|
19
|
+
],
|
|
20
|
+
"author": "sairajb",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"axios": "^1.6.7",
|
|
24
|
+
"commander": "^12.0.0"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/sairajB/git-ripper.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/sairajB/git-ripper/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/sairajB/git-ripper#readme"
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fetchFolderContents = async (owner, repo, branch, folderPath) => {
|
|
5
|
+
const apiUrl =
|
|
6
|
+
`https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}?recurs
|
|
7
|
+
ive=1`;
|
|
8
|
+
const response = await axios.get(apiUrl);
|
|
9
|
+
return response.data.tree.filter((item) =>
|
|
10
|
+
item.path.startsWith(folderPath));
|
|
11
|
+
};
|
|
12
|
+
const downloadFile = async (owner, repo, branch, filePath, outputPath) =>
|
|
13
|
+
{
|
|
14
|
+
const url =
|
|
15
|
+
`https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filePath}
|
|
16
|
+
`;
|
|
17
|
+
const response = await axios.get(url, { responseType: 'arraybuffer' });
|
|
18
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
19
|
+
fs.writeFileSync(outputPath, Buffer.from(response.data));
|
|
20
|
+
};
|
|
21
|
+
const downloadFolder = async ({ owner, repo, branch, folderPath },
|
|
22
|
+
outputDir) => {
|
|
23
|
+
console.log(`Cloning ${folderPath} from ${owner}/${repo}
|
|
24
|
+
(${branch})...`);
|
|
25
|
+
|
|
26
|
+
const contents = await fetchFolderContents(owner, repo, branch,
|
|
27
|
+
folderPath);
|
|
28
|
+
|
|
29
|
+
for (const item of contents) {
|
|
30
|
+
if (item.type === 'blob') {
|
|
31
|
+
const relativeFilePath = item.path.substring(folderPath.length);
|
|
32
|
+
const outputFilePath = path.join(outputDir, relativeFilePath);
|
|
33
|
+
await downloadFile(owner, repo, branch, item.path, outputFilePath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
module.exports = {
|
|
38
|
+
downloadFolder
|
|
39
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { program } = require('commander');
|
|
2
|
+
const { parseGitHubUrl } = require('./parser');
|
|
3
|
+
const { downloadFolder } = require('./downloader');
|
|
4
|
+
|
|
5
|
+
const initializeCLI = () => {
|
|
6
|
+
program
|
|
7
|
+
.version('0.0.1')
|
|
8
|
+
.description('Clone specific folders from GitHub repositories')
|
|
9
|
+
.argument('<url>', 'GitHub URL of the folder to clone')
|
|
10
|
+
.option('-o, --output <directory>', 'Output directory', process.cwd())
|
|
11
|
+
.action(async (url, options) => {
|
|
12
|
+
try {
|
|
13
|
+
const parsedUrl = parseGitHubUrl(url);
|
|
14
|
+
await downloadFolder(parsedUrl, options.output);
|
|
15
|
+
console.log('Folder cloned successfully!');
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Error:', error.message);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
program.parse(process.argv);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
downloadFolder: initializeCLI
|
|
27
|
+
};
|
package/src/parser.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const parseGitHubUrl = (url) => {
|
|
2
|
+
const urlParts = url.split('/');
|
|
3
|
+
const owner = urlParts[3];
|
|
4
|
+
const repo = urlParts[4];
|
|
5
|
+
const branch = urlParts[6] || 'main';
|
|
6
|
+
const folderPath = urlParts.slice(7).join('/');
|
|
7
|
+
return { owner, repo, branch, folderPath };
|
|
8
|
+
};
|
|
9
|
+
module.exports = {
|
|
10
|
+
parseGitHubUrl
|
|
11
|
+
};
|
|
12
|
+
|