@fredlackey/devutils 0.0.1 → 0.0.2
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 +5 -5
- package/package.json +1 -1
- package/src/commands/install.js +374 -36
- package/src/installs/adobe-creative-cloud.js +527 -25
- package/src/installs/adobe-creative-cloud.md +605 -0
- package/src/installs/appcleaner.js +303 -26
- package/src/installs/appcleaner.md +699 -0
- package/src/installs/apt-transport-https.js +390 -0
- package/src/installs/apt-transport-https.md +678 -0
- package/src/installs/atomicparsley.js +624 -26
- package/src/installs/atomicparsley.md +795 -0
- package/src/installs/aws-cli.js +779 -26
- package/src/installs/aws-cli.md +727 -0
- package/src/installs/balena-etcher.js +688 -26
- package/src/installs/balena-etcher.md +761 -0
- package/src/installs/bambu-studio.js +912 -26
- package/src/installs/bambu-studio.md +780 -0
- package/src/installs/bash-completion.js +554 -23
- package/src/installs/bash-completion.md +833 -0
- package/src/installs/bash.js +399 -26
- package/src/installs/bash.md +993 -0
- package/src/installs/beyond-compare.js +585 -26
- package/src/installs/beyond-compare.md +813 -0
- package/src/installs/build-essential.js +511 -26
- package/src/installs/build-essential.md +977 -0
- package/src/installs/ca-certificates.js +618 -0
- package/src/installs/ca-certificates.md +937 -0
- package/src/installs/caffeine.js +490 -26
- package/src/installs/caffeine.md +839 -0
- package/src/installs/camtasia.js +577 -25
- package/src/installs/camtasia.md +762 -0
- package/src/installs/chatgpt.js +458 -26
- package/src/installs/chatgpt.md +814 -0
- package/src/installs/chocolatey.js +447 -0
- package/src/installs/chocolatey.md +661 -0
- package/src/installs/chrome-canary.js +472 -26
- package/src/installs/chrome-canary.md +641 -0
- package/src/installs/chromium.js +645 -26
- package/src/installs/chromium.md +838 -0
- package/src/installs/claude-code.js +558 -26
- package/src/installs/claude-code.md +1173 -0
- package/src/installs/curl.js +361 -26
- package/src/installs/curl.md +714 -0
- package/src/installs/cursor.js +561 -26
- package/src/installs/cursor.md +970 -0
- package/src/installs/dbschema.js +674 -26
- package/src/installs/dbschema.md +925 -0
- package/src/installs/dependencies.md +435 -0
- package/src/installs/development-tools.js +600 -0
- package/src/installs/development-tools.md +977 -0
- package/src/installs/docker.js +1010 -25
- package/src/installs/docker.md +1109 -0
- package/src/installs/drawio.js +1001 -26
- package/src/installs/drawio.md +795 -0
- package/src/installs/elmedia-player.js +328 -25
- package/src/installs/elmedia-player.md +556 -0
- package/src/installs/ffmpeg.js +870 -25
- package/src/installs/ffmpeg.md +852 -0
- package/src/installs/file.js +464 -0
- package/src/installs/file.md +987 -0
- package/src/installs/gemini-cli.js +793 -26
- package/src/installs/gemini-cli.md +1153 -0
- package/src/installs/git.js +382 -26
- package/src/installs/git.md +907 -0
- package/src/installs/gitego.js +931 -26
- package/src/installs/gitego.md +1172 -0
- package/src/installs/go.js +913 -26
- package/src/installs/go.md +958 -0
- package/src/installs/google-chrome.js +801 -25
- package/src/installs/google-chrome.md +862 -0
- package/src/installs/gpg.js +412 -73
- package/src/installs/gpg.md +1056 -0
- package/src/installs/homebrew.js +1015 -26
- package/src/installs/homebrew.md +988 -0
- package/src/installs/imageoptim.js +950 -26
- package/src/installs/imageoptim.md +1119 -0
- package/src/installs/installers.json +2297 -0
- package/src/installs/jq.js +382 -26
- package/src/installs/jq.md +809 -0
- package/src/installs/keyboard-maestro.js +701 -26
- package/src/installs/keyboard-maestro.md +825 -0
- package/src/installs/latex.js +771 -26
- package/src/installs/latex.md +1095 -0
- package/src/installs/lftp.js +338 -26
- package/src/installs/lftp.md +907 -0
- package/src/installs/lsb-release.js +346 -0
- package/src/installs/lsb-release.md +814 -0
- package/src/installs/messenger.js +829 -26
- package/src/installs/messenger.md +900 -0
- package/src/installs/microsoft-office.js +550 -26
- package/src/installs/microsoft-office.md +760 -0
- package/src/installs/microsoft-teams.js +782 -25
- package/src/installs/microsoft-teams.md +886 -0
- package/src/installs/node.js +886 -26
- package/src/installs/node.md +1153 -0
- package/src/installs/nordpass.js +698 -26
- package/src/installs/nordpass.md +921 -0
- package/src/installs/nvm.js +977 -26
- package/src/installs/nvm.md +1057 -0
- package/src/installs/openssh.js +734 -64
- package/src/installs/openssh.md +1056 -0
- package/src/installs/pandoc.js +644 -26
- package/src/installs/pandoc.md +1036 -0
- package/src/installs/pinentry.js +492 -26
- package/src/installs/pinentry.md +1142 -0
- package/src/installs/pngyu.js +851 -26
- package/src/installs/pngyu.md +896 -0
- package/src/installs/postman.js +781 -26
- package/src/installs/postman.md +940 -0
- package/src/installs/procps.js +425 -0
- package/src/installs/procps.md +851 -0
- package/src/installs/safari-tech-preview.js +355 -25
- package/src/installs/safari-tech-preview.md +533 -0
- package/src/installs/sfnt2woff.js +640 -26
- package/src/installs/sfnt2woff.md +795 -0
- package/src/installs/shellcheck.js +463 -26
- package/src/installs/shellcheck.md +1005 -0
- package/src/installs/slack.js +722 -25
- package/src/installs/slack.md +865 -0
- package/src/installs/snagit.js +566 -25
- package/src/installs/snagit.md +844 -0
- package/src/installs/software-properties-common.js +372 -0
- package/src/installs/software-properties-common.md +805 -0
- package/src/installs/spotify.js +858 -25
- package/src/installs/spotify.md +901 -0
- package/src/installs/studio-3t.js +803 -26
- package/src/installs/studio-3t.md +918 -0
- package/src/installs/sublime-text.js +780 -25
- package/src/installs/sublime-text.md +914 -0
- package/src/installs/superwhisper.js +687 -25
- package/src/installs/superwhisper.md +630 -0
- package/src/installs/tailscale.js +727 -26
- package/src/installs/tailscale.md +1100 -0
- package/src/installs/tar.js +389 -0
- package/src/installs/tar.md +946 -0
- package/src/installs/termius.js +780 -26
- package/src/installs/termius.md +844 -0
- package/src/installs/terraform.js +761 -26
- package/src/installs/terraform.md +899 -0
- package/src/installs/tidal.js +752 -25
- package/src/installs/tidal.md +864 -0
- package/src/installs/tmux.js +328 -26
- package/src/installs/tmux.md +1030 -0
- package/src/installs/tree.js +393 -26
- package/src/installs/tree.md +833 -0
- package/src/installs/unzip.js +460 -0
- package/src/installs/unzip.md +879 -0
- package/src/installs/vim.js +403 -26
- package/src/installs/vim.md +1040 -0
- package/src/installs/vlc.js +803 -26
- package/src/installs/vlc.md +927 -0
- package/src/installs/vscode.js +825 -26
- package/src/installs/vscode.md +1002 -0
- package/src/installs/wget.js +415 -0
- package/src/installs/wget.md +791 -0
- package/src/installs/whatsapp.js +710 -25
- package/src/installs/whatsapp.md +854 -0
- package/src/installs/winpty.js +352 -0
- package/src/installs/winpty.md +620 -0
- package/src/installs/woff2.js +535 -26
- package/src/installs/woff2.md +977 -0
- package/src/installs/wsl.js +572 -0
- package/src/installs/wsl.md +699 -0
- package/src/installs/xcode-clt.js +520 -0
- package/src/installs/xcode-clt.md +351 -0
- package/src/installs/xcode.js +542 -26
- package/src/installs/xcode.md +573 -0
- package/src/installs/yarn.js +806 -26
- package/src/installs/yarn.md +1074 -0
- package/src/installs/yq.js +636 -26
- package/src/installs/yq.md +944 -0
- package/src/installs/yt-dlp.js +683 -26
- package/src/installs/yt-dlp.md +946 -0
- package/src/installs/yum-utils.js +297 -0
- package/src/installs/yum-utils.md +648 -0
- package/src/installs/zoom.js +740 -25
- package/src/installs/zoom.md +884 -0
- package/src/scripts/README.md +567 -45
- package/src/scripts/STATUS.md +208 -0
- package/src/scripts/afk.js +395 -7
- package/src/scripts/backup-all.js +731 -9
- package/src/scripts/backup-source.js +711 -8
- package/src/scripts/brewd.js +373 -7
- package/src/scripts/brewi.js +505 -9
- package/src/scripts/brewr.js +512 -9
- package/src/scripts/brews.js +462 -9
- package/src/scripts/brewu.js +488 -7
- package/src/scripts/c.js +185 -7
- package/src/scripts/ccurl.js +325 -8
- package/src/scripts/certbot-crontab-init.js +488 -8
- package/src/scripts/certbot-init.js +641 -9
- package/src/scripts/ch.js +339 -7
- package/src/scripts/claude-danger.js +253 -8
- package/src/scripts/clean-dev.js +419 -8
- package/src/scripts/clear-dns-cache.js +525 -7
- package/src/scripts/clone.js +417 -7
- package/src/scripts/code-all.js +420 -7
- package/src/scripts/count-files.js +195 -8
- package/src/scripts/count-folders.js +195 -8
- package/src/scripts/count.js +248 -8
- package/src/scripts/d.js +203 -7
- package/src/scripts/datauri.js +373 -8
- package/src/scripts/delete-files.js +363 -7
- package/src/scripts/docker-clean.js +410 -8
- package/src/scripts/dp.js +426 -7
- package/src/scripts/e.js +375 -9
- package/src/scripts/empty-trash.js +497 -7
- package/src/scripts/evm.js +428 -9
- package/src/scripts/fetch-github-repos.js +441 -10
- package/src/scripts/get-channel.js +329 -8
- package/src/scripts/get-course.js +384 -11
- package/src/scripts/get-dependencies.js +290 -9
- package/src/scripts/get-folder.js +783 -10
- package/src/scripts/get-tunes.js +411 -10
- package/src/scripts/get-video.js +352 -9
- package/src/scripts/git-backup.js +561 -9
- package/src/scripts/git-clone.js +477 -9
- package/src/scripts/git-pup.js +303 -7
- package/src/scripts/git-push.js +380 -8
- package/src/scripts/h.js +607 -9
- package/src/scripts/hide-desktop-icons.js +483 -7
- package/src/scripts/hide-hidden-files.js +522 -7
- package/src/scripts/install-dependencies-from.js +440 -9
- package/src/scripts/ips.js +647 -10
- package/src/scripts/iso.js +354 -8
- package/src/scripts/killni.js +561 -7
- package/src/scripts/ll.js +451 -8
- package/src/scripts/local-ip.js +310 -8
- package/src/scripts/m.js +508 -8
- package/src/scripts/map.js +293 -8
- package/src/scripts/mkd.js +287 -7
- package/src/scripts/ncu-update-all.js +441 -8
- package/src/scripts/nginx-init.js +702 -12
- package/src/scripts/npmi.js +366 -7
- package/src/scripts/o.js +495 -8
- package/src/scripts/org-by-date.js +321 -7
- package/src/scripts/p.js +208 -7
- package/src/scripts/packages.js +313 -8
- package/src/scripts/path.js +209 -7
- package/src/scripts/ports.js +582 -8
- package/src/scripts/q.js +290 -8
- package/src/scripts/refresh-files.js +378 -10
- package/src/scripts/remove-smaller-files.js +500 -8
- package/src/scripts/rename-files-with-date.js +517 -9
- package/src/scripts/resize-image.js +523 -9
- package/src/scripts/rm-safe.js +653 -8
- package/src/scripts/s.js +525 -9
- package/src/scripts/set-git-public.js +349 -7
- package/src/scripts/show-desktop-icons.js +459 -7
- package/src/scripts/show-hidden-files.js +456 -7
- package/src/scripts/tpa.js +265 -8
- package/src/scripts/tpo.js +264 -7
- package/src/scripts/u.js +489 -7
- package/src/scripts/vpush.js +422 -8
- package/src/scripts/y.js +267 -7
- package/src/utils/common/os.js +94 -2
- package/src/utils/ubuntu/apt.js +13 -7
|
@@ -1,25 +1,456 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* fetch-github-repos - Clone all repositories from a GitHub organization
|
|
5
|
+
*
|
|
6
|
+
* Migrated from legacy dotfiles function.
|
|
7
|
+
* Original:
|
|
8
|
+
* fetch-github-repos() {
|
|
9
|
+
* local org="$1"
|
|
10
|
+
* local dest_dir="$2"
|
|
11
|
+
* if [[ -z "$org" || -z "$dest_dir" ]]; then
|
|
12
|
+
* echo "Usage: fetch-github-repos <organization> <destination-folder>"
|
|
13
|
+
* return 1
|
|
14
|
+
* fi
|
|
15
|
+
* if ! command -v jq >/dev/null 2>&1; then
|
|
16
|
+
* echo "Error: 'jq' is required but not installed."
|
|
17
|
+
* return 1
|
|
18
|
+
* fi
|
|
19
|
+
* mkdir -p "$dest_dir"
|
|
20
|
+
* echo "Fetching repositories for organization '$org'..."
|
|
21
|
+
* local repos=$(curl -s "https://api.github.com/orgs/$org/repos?per_page=100" | jq -r '.[].ssh_url')
|
|
22
|
+
* if [[ -z "$repos" ]]; then
|
|
23
|
+
* echo "No repositories found or failed to fetch from GitHub."
|
|
24
|
+
* return 1
|
|
25
|
+
* fi
|
|
26
|
+
* for repo in $repos; do
|
|
27
|
+
* echo "Cloning $repo into $dest_dir..."
|
|
28
|
+
* git clone "$repo" "$dest_dir/$(basename -s .git "$repo")"
|
|
29
|
+
* done
|
|
30
|
+
* echo "All repositories have been cloned."
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* This script fetches the list of repositories from a GitHub organization
|
|
34
|
+
* using the GitHub API and clones each one into a specified destination folder.
|
|
35
|
+
* Unlike the original bash version, this uses Node.js native fetch() instead of
|
|
36
|
+
* curl+jq, making it cross-platform without additional dependencies.
|
|
37
|
+
*
|
|
5
38
|
* @module scripts/fetch-github-repos
|
|
6
39
|
*/
|
|
7
40
|
|
|
41
|
+
const os = require('../utils/common/os');
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const path = require('path');
|
|
44
|
+
const { execSync, spawnSync } = require('child_process');
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Helper function to check if a command exists on the system.
|
|
48
|
+
* Used to verify git is available before attempting to clone.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} cmd - The command name to check
|
|
51
|
+
* @returns {boolean} True if the command exists, false otherwise
|
|
52
|
+
*/
|
|
53
|
+
function isCommandAvailable(cmd) {
|
|
54
|
+
try {
|
|
55
|
+
// Use 'which' on Unix-like systems, 'where' on Windows
|
|
56
|
+
const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `which ${cmd}`;
|
|
57
|
+
execSync(checkCmd, { stdio: 'ignore' });
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Fetches the list of repositories from a GitHub organization.
|
|
66
|
+
*
|
|
67
|
+
* Uses the GitHub API to get all public repositories for an organization.
|
|
68
|
+
* The API returns up to 100 repositories per page. For organizations with
|
|
69
|
+
* more than 100 repos, pagination would be needed (not implemented here
|
|
70
|
+
* to match original behavior).
|
|
71
|
+
*
|
|
72
|
+
* @param {string} org - The GitHub organization name
|
|
73
|
+
* @returns {Promise<Array<{name: string, ssh_url: string, clone_url: string}>>} Array of repo objects
|
|
74
|
+
* @throws {Error} If the API request fails
|
|
75
|
+
*/
|
|
76
|
+
async function fetchRepositories(org) {
|
|
77
|
+
// Use Node.js native fetch() - available in Node.js 18+
|
|
78
|
+
// This replaces the original curl + jq approach
|
|
79
|
+
const apiUrl = `https://api.github.com/orgs/${org}/repos?per_page=100`;
|
|
80
|
+
|
|
81
|
+
const response = await fetch(apiUrl, {
|
|
82
|
+
headers: {
|
|
83
|
+
// GitHub recommends setting a User-Agent header
|
|
84
|
+
'User-Agent': 'devutils-cli',
|
|
85
|
+
'Accept': 'application/vnd.github.v3+json'
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
if (response.status === 404) {
|
|
91
|
+
throw new Error(`Organization '${org}' not found on GitHub.`);
|
|
92
|
+
}
|
|
93
|
+
if (response.status === 403) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
'GitHub API rate limit exceeded. ' +
|
|
96
|
+
'Try again later or use a GitHub token for higher limits.'
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
throw new Error(`GitHub API error: ${response.status} ${response.statusText}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Parse JSON response - this replaces the jq parsing in the original
|
|
103
|
+
const repos = await response.json();
|
|
104
|
+
|
|
105
|
+
if (!Array.isArray(repos)) {
|
|
106
|
+
throw new Error('Unexpected response format from GitHub API.');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return repos;
|
|
110
|
+
}
|
|
111
|
+
|
|
8
112
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
113
|
+
* Clones a single repository into the destination directory.
|
|
114
|
+
*
|
|
115
|
+
* Uses git clone to download the repository. The repository is cloned
|
|
116
|
+
* using the SSH URL by default (matching original behavior), but falls
|
|
117
|
+
* back to HTTPS if SSH fails.
|
|
118
|
+
*
|
|
119
|
+
* @param {string} repoUrl - The SSH or HTTPS URL of the repository
|
|
120
|
+
* @param {string} destPath - The full path where the repo should be cloned
|
|
121
|
+
* @returns {boolean} True if clone succeeded, false otherwise
|
|
122
|
+
*/
|
|
123
|
+
function cloneRepository(repoUrl, destPath) {
|
|
124
|
+
// Check if destination already exists (idempotency)
|
|
125
|
+
if (fs.existsSync(destPath)) {
|
|
126
|
+
console.log(` Skipping: ${path.basename(destPath)} (already exists)`);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
// Use spawnSync for better output control
|
|
132
|
+
const result = spawnSync('git', ['clone', repoUrl, destPath], {
|
|
133
|
+
stdio: 'inherit',
|
|
134
|
+
encoding: 'utf8'
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (result.status !== 0) {
|
|
138
|
+
console.error(` Failed to clone: ${path.basename(destPath)}`);
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return true;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error(` Error cloning ${path.basename(destPath)}: ${error.message}`);
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Pure Node.js implementation for fetching and cloning GitHub organization repos.
|
|
151
|
+
*
|
|
152
|
+
* This function uses pure Node.js for:
|
|
153
|
+
* - HTTP requests (native fetch())
|
|
154
|
+
* - JSON parsing (JSON.parse via response.json())
|
|
155
|
+
* - Directory creation (fs.mkdirSync)
|
|
156
|
+
* - Path manipulation (path.join, path.basename)
|
|
157
|
+
*
|
|
158
|
+
* The only external command required is 'git' for cloning, which is
|
|
159
|
+
* necessary because reimplementing git clone in Node.js would be
|
|
160
|
+
* impractical and inferior to the native tool.
|
|
161
|
+
*
|
|
162
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
163
|
+
* @returns {Promise<void>}
|
|
164
|
+
*/
|
|
165
|
+
async function do_fetch_github_repos_nodejs(args) {
|
|
166
|
+
const org = args[0];
|
|
167
|
+
const destDir = args[1];
|
|
168
|
+
|
|
169
|
+
// Validate arguments
|
|
170
|
+
if (!org || !destDir) {
|
|
171
|
+
console.log('Usage: fetch-github-repos <organization> <destination-folder>');
|
|
172
|
+
console.log('');
|
|
173
|
+
console.log('Arguments:');
|
|
174
|
+
console.log(' organization The GitHub organization name');
|
|
175
|
+
console.log(' destination-folder The folder where repos will be cloned');
|
|
176
|
+
console.log('');
|
|
177
|
+
console.log('Example:');
|
|
178
|
+
console.log(' fetch-github-repos nodejs ./nodejs-repos');
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check if git is available (required for cloning)
|
|
183
|
+
if (!isCommandAvailable('git')) {
|
|
184
|
+
console.error('Error: git is required but not installed.');
|
|
185
|
+
console.error('');
|
|
186
|
+
console.error('Install git:');
|
|
187
|
+
console.error(' macOS: brew install git');
|
|
188
|
+
console.error(' Ubuntu: sudo apt install git');
|
|
189
|
+
console.error(' Windows: https://git-scm.com/download/win');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Resolve the destination directory to an absolute path
|
|
194
|
+
const absoluteDestDir = path.resolve(destDir);
|
|
195
|
+
|
|
196
|
+
// Create destination directory if it doesn't exist (pure Node.js)
|
|
197
|
+
// Using recursive: true makes this idempotent - it won't fail if dir exists
|
|
198
|
+
if (!fs.existsSync(absoluteDestDir)) {
|
|
199
|
+
fs.mkdirSync(absoluteDestDir, { recursive: true });
|
|
200
|
+
console.log(`Created directory: ${absoluteDestDir}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
console.log(`Fetching repositories for organization '${org}'...`);
|
|
204
|
+
console.log('');
|
|
205
|
+
|
|
206
|
+
// Fetch the list of repositories from GitHub API
|
|
207
|
+
let repos;
|
|
208
|
+
try {
|
|
209
|
+
repos = await fetchRepositories(org);
|
|
210
|
+
} catch (error) {
|
|
211
|
+
console.error(`Error: ${error.message}`);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Check if any repositories were found
|
|
216
|
+
if (repos.length === 0) {
|
|
217
|
+
console.log('No repositories found for this organization.');
|
|
218
|
+
console.log('');
|
|
219
|
+
console.log('This could mean:');
|
|
220
|
+
console.log(' - The organization has no public repositories');
|
|
221
|
+
console.log(' - The organization name is incorrect');
|
|
222
|
+
console.log(' - Private repositories require authentication');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
console.log(`Found ${repos.length} repositories.`);
|
|
227
|
+
console.log('');
|
|
228
|
+
|
|
229
|
+
// Clone each repository
|
|
230
|
+
let successCount = 0;
|
|
231
|
+
let skipCount = 0;
|
|
232
|
+
let failCount = 0;
|
|
233
|
+
|
|
234
|
+
for (const repo of repos) {
|
|
235
|
+
// Extract repository name from the SSH URL (e.g., "git@github.com:org/repo.git" -> "repo")
|
|
236
|
+
const repoName = repo.name || path.basename(repo.ssh_url, '.git');
|
|
237
|
+
const destPath = path.join(absoluteDestDir, repoName);
|
|
238
|
+
|
|
239
|
+
// Check if already cloned (idempotency)
|
|
240
|
+
if (fs.existsSync(destPath)) {
|
|
241
|
+
console.log(`Skipping: ${repoName} (already exists)`);
|
|
242
|
+
skipCount++;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
console.log(`Cloning: ${repoName}...`);
|
|
247
|
+
|
|
248
|
+
// Try SSH URL first (original behavior), fall back to HTTPS
|
|
249
|
+
const sshUrl = repo.ssh_url;
|
|
250
|
+
const httpsUrl = repo.clone_url;
|
|
251
|
+
|
|
252
|
+
let cloneSuccess = cloneRepository(sshUrl, destPath);
|
|
253
|
+
|
|
254
|
+
// If SSH fails, try HTTPS
|
|
255
|
+
if (!cloneSuccess && httpsUrl) {
|
|
256
|
+
console.log(` SSH clone failed, trying HTTPS...`);
|
|
257
|
+
cloneSuccess = cloneRepository(httpsUrl, destPath);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (cloneSuccess) {
|
|
261
|
+
successCount++;
|
|
262
|
+
} else {
|
|
263
|
+
failCount++;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Print summary
|
|
268
|
+
console.log('');
|
|
269
|
+
console.log('--- Summary ---');
|
|
270
|
+
console.log(`Successfully cloned: ${successCount}`);
|
|
271
|
+
if (skipCount > 0) {
|
|
272
|
+
console.log(`Already existed (skipped): ${skipCount}`);
|
|
273
|
+
}
|
|
274
|
+
if (failCount > 0) {
|
|
275
|
+
console.log(`Failed to clone: ${failCount}`);
|
|
276
|
+
}
|
|
277
|
+
console.log(`Total repositories: ${repos.length}`);
|
|
278
|
+
console.log(`Destination: ${absoluteDestDir}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Clone all repositories from a GitHub organization on macOS.
|
|
283
|
+
*
|
|
284
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
285
|
+
* (HTTP requests, JSON parsing, file operations) works identically on macOS.
|
|
286
|
+
* The only external dependency is git, which is required on all platforms.
|
|
11
287
|
*
|
|
12
|
-
* @param {string[]} args - Command line arguments
|
|
13
|
-
* @param {string} args.0 - GitHub organization name
|
|
14
|
-
* @param {string} args.1 - Destination folder path
|
|
288
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
15
289
|
* @returns {Promise<void>}
|
|
16
290
|
*/
|
|
17
|
-
async function
|
|
18
|
-
//
|
|
291
|
+
async function do_fetch_github_repos_macos(args) {
|
|
292
|
+
// macOS can use the pure Node.js implementation
|
|
293
|
+
return do_fetch_github_repos_nodejs(args);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Clone all repositories from a GitHub organization on Ubuntu.
|
|
298
|
+
*
|
|
299
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
300
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Ubuntu.
|
|
301
|
+
* The only external dependency is git, which is required on all platforms.
|
|
302
|
+
*
|
|
303
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
304
|
+
* @returns {Promise<void>}
|
|
305
|
+
*/
|
|
306
|
+
async function do_fetch_github_repos_ubuntu(args) {
|
|
307
|
+
// Ubuntu can use the pure Node.js implementation
|
|
308
|
+
return do_fetch_github_repos_nodejs(args);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Clone all repositories from a GitHub organization on Raspberry Pi OS.
|
|
313
|
+
*
|
|
314
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
315
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Raspbian.
|
|
316
|
+
* The only external dependency is git, which is required on all platforms.
|
|
317
|
+
*
|
|
318
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
319
|
+
* @returns {Promise<void>}
|
|
320
|
+
*/
|
|
321
|
+
async function do_fetch_github_repos_raspbian(args) {
|
|
322
|
+
// Raspbian can use the pure Node.js implementation
|
|
323
|
+
return do_fetch_github_repos_nodejs(args);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Clone all repositories from a GitHub organization on Amazon Linux.
|
|
328
|
+
*
|
|
329
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
330
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Amazon Linux.
|
|
331
|
+
* The only external dependency is git, which is required on all platforms.
|
|
332
|
+
*
|
|
333
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
334
|
+
* @returns {Promise<void>}
|
|
335
|
+
*/
|
|
336
|
+
async function do_fetch_github_repos_amazon_linux(args) {
|
|
337
|
+
// Amazon Linux can use the pure Node.js implementation
|
|
338
|
+
return do_fetch_github_repos_nodejs(args);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Clone all repositories from a GitHub organization on Windows Command Prompt.
|
|
343
|
+
*
|
|
344
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
345
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Windows.
|
|
346
|
+
* The only external dependency is git, which must be installed and in PATH.
|
|
347
|
+
*
|
|
348
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
349
|
+
* @returns {Promise<void>}
|
|
350
|
+
*/
|
|
351
|
+
async function do_fetch_github_repos_cmd(args) {
|
|
352
|
+
// Windows CMD can use the pure Node.js implementation
|
|
353
|
+
return do_fetch_github_repos_nodejs(args);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Clone all repositories from a GitHub organization on Windows PowerShell.
|
|
358
|
+
*
|
|
359
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
360
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Windows.
|
|
361
|
+
* The only external dependency is git, which must be installed and in PATH.
|
|
362
|
+
*
|
|
363
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
364
|
+
* @returns {Promise<void>}
|
|
365
|
+
*/
|
|
366
|
+
async function do_fetch_github_repos_powershell(args) {
|
|
367
|
+
// Windows PowerShell can use the pure Node.js implementation
|
|
368
|
+
return do_fetch_github_repos_nodejs(args);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Clone all repositories from a GitHub organization on Git Bash.
|
|
373
|
+
*
|
|
374
|
+
* Uses the pure Node.js implementation since all required functionality
|
|
375
|
+
* (HTTP requests, JSON parsing, file operations) works identically on Git Bash.
|
|
376
|
+
* Git is guaranteed to be available since we're running in Git Bash.
|
|
377
|
+
*
|
|
378
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
379
|
+
* @returns {Promise<void>}
|
|
380
|
+
*/
|
|
381
|
+
async function do_fetch_github_repos_gitbash(args) {
|
|
382
|
+
// Git Bash can use the pure Node.js implementation
|
|
383
|
+
// Bonus: git is guaranteed to be available in Git Bash
|
|
384
|
+
return do_fetch_github_repos_nodejs(args);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Main entry point - detects environment and executes appropriate implementation.
|
|
389
|
+
*
|
|
390
|
+
* This script clones all repositories from a GitHub organization into a
|
|
391
|
+
* destination folder. It's useful for:
|
|
392
|
+
* - Backing up all repos from an organization
|
|
393
|
+
* - Setting up a development environment with multiple related repos
|
|
394
|
+
* - Migrating repositories between systems
|
|
395
|
+
*
|
|
396
|
+
* The script is idempotent: running it multiple times will skip repos that
|
|
397
|
+
* have already been cloned, making it safe to re-run to catch new repos.
|
|
398
|
+
*
|
|
399
|
+
* Unlike the original bash version that required curl and jq, this Node.js
|
|
400
|
+
* implementation uses native fetch() and JSON.parse(), requiring only git
|
|
401
|
+
* as an external dependency.
|
|
402
|
+
*
|
|
403
|
+
* @param {string[]} args - Command line arguments [org, destDir]
|
|
404
|
+
* @returns {Promise<void>}
|
|
405
|
+
*/
|
|
406
|
+
async function do_fetch_github_repos(args) {
|
|
407
|
+
const platform = os.detect();
|
|
408
|
+
|
|
409
|
+
const handlers = {
|
|
410
|
+
'macos': do_fetch_github_repos_macos,
|
|
411
|
+
'ubuntu': do_fetch_github_repos_ubuntu,
|
|
412
|
+
'debian': do_fetch_github_repos_ubuntu,
|
|
413
|
+
'raspbian': do_fetch_github_repos_raspbian,
|
|
414
|
+
'amazon_linux': do_fetch_github_repos_amazon_linux,
|
|
415
|
+
'rhel': do_fetch_github_repos_amazon_linux,
|
|
416
|
+
'fedora': do_fetch_github_repos_ubuntu,
|
|
417
|
+
'linux': do_fetch_github_repos_ubuntu,
|
|
418
|
+
'wsl': do_fetch_github_repos_ubuntu,
|
|
419
|
+
'cmd': do_fetch_github_repos_cmd,
|
|
420
|
+
'windows': do_fetch_github_repos_cmd,
|
|
421
|
+
'powershell': do_fetch_github_repos_powershell,
|
|
422
|
+
'gitbash': do_fetch_github_repos_gitbash
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
const handler = handlers[platform.type];
|
|
426
|
+
if (!handler) {
|
|
427
|
+
console.error(`Platform '${platform.type}' is not supported for this command.`);
|
|
428
|
+
console.error('');
|
|
429
|
+
console.error('Supported platforms:');
|
|
430
|
+
console.error(' - macOS');
|
|
431
|
+
console.error(' - Ubuntu, Debian, and other Linux distributions');
|
|
432
|
+
console.error(' - Raspberry Pi OS');
|
|
433
|
+
console.error(' - Amazon Linux, RHEL, Fedora');
|
|
434
|
+
console.error(' - Windows (CMD, PowerShell, Git Bash)');
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
await handler(args);
|
|
19
439
|
}
|
|
20
440
|
|
|
21
|
-
module.exports = {
|
|
441
|
+
module.exports = {
|
|
442
|
+
main: do_fetch_github_repos,
|
|
443
|
+
do_fetch_github_repos,
|
|
444
|
+
do_fetch_github_repos_nodejs,
|
|
445
|
+
do_fetch_github_repos_macos,
|
|
446
|
+
do_fetch_github_repos_ubuntu,
|
|
447
|
+
do_fetch_github_repos_raspbian,
|
|
448
|
+
do_fetch_github_repos_amazon_linux,
|
|
449
|
+
do_fetch_github_repos_cmd,
|
|
450
|
+
do_fetch_github_repos_powershell,
|
|
451
|
+
do_fetch_github_repos_gitbash
|
|
452
|
+
};
|
|
22
453
|
|
|
23
454
|
if (require.main === module) {
|
|
24
|
-
|
|
455
|
+
do_fetch_github_repos(process.argv.slice(2));
|
|
25
456
|
}
|