@fredlackey/devutils 0.0.1 → 0.0.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 +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
- package/src/utils/windows/choco.js +82 -26
- package/src/utils/windows/winget.js +89 -27
package/src/scripts/git-clone.js
CHANGED
|
@@ -1,25 +1,493 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* git-clone - Copy repository structure without .git folder and common excludes
|
|
5
|
+
*
|
|
6
|
+
* Migrated from legacy dotfiles function.
|
|
7
|
+
* Original:
|
|
8
|
+
* git-clone(){
|
|
9
|
+
* eval "rsync -av --progress $* ./ --exclude .git --exclude README.md --exclude LICENSE --exclude node_modules --exclude bower_components"
|
|
10
|
+
* }
|
|
11
|
+
*
|
|
12
|
+
* This script copies files from a source directory (typically a git repository)
|
|
13
|
+
* to the current directory, excluding common files and folders that should not
|
|
14
|
+
* be copied when using a repo as a template:
|
|
15
|
+
* - .git (version control history)
|
|
16
|
+
* - README.md (documentation specific to the source)
|
|
17
|
+
* - LICENSE (license specific to the source)
|
|
18
|
+
* - node_modules (dependencies that should be reinstalled)
|
|
19
|
+
* - bower_components (legacy dependencies that should be reinstalled)
|
|
20
|
+
*
|
|
21
|
+
* Use case: You want to use an existing repository as a starting template for
|
|
22
|
+
* a new project without carrying over the git history or generated files.
|
|
23
|
+
*
|
|
5
24
|
* @module scripts/git-clone
|
|
6
25
|
*/
|
|
7
26
|
|
|
27
|
+
const os = require('../utils/common/os');
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
const { execSync } = require('child_process');
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Default list of files and directories to exclude when copying.
|
|
34
|
+
* These are common items that should not be copied when using a repo as a template.
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_EXCLUDES = [
|
|
37
|
+
'.git',
|
|
38
|
+
'README.md',
|
|
39
|
+
'LICENSE',
|
|
40
|
+
'node_modules',
|
|
41
|
+
'bower_components'
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Helper function to check if a command exists on the system.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} cmd - The command name to check
|
|
48
|
+
* @returns {boolean} True if the command exists, false otherwise
|
|
49
|
+
*/
|
|
50
|
+
function isCommandAvailable(cmd) {
|
|
51
|
+
try {
|
|
52
|
+
const checkCmd = process.platform === 'win32' ? `where ${cmd}` : `which ${cmd}`;
|
|
53
|
+
execSync(checkCmd, { stdio: 'ignore' });
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Check if a path should be excluded from copying.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} relativePath - The path relative to the source directory
|
|
64
|
+
* @param {string[]} excludes - Array of patterns to exclude
|
|
65
|
+
* @returns {boolean} True if the path should be excluded
|
|
66
|
+
*/
|
|
67
|
+
function shouldExclude(relativePath, excludes) {
|
|
68
|
+
// Normalize path separators for cross-platform compatibility
|
|
69
|
+
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
70
|
+
const pathParts = normalizedPath.split('/');
|
|
71
|
+
|
|
72
|
+
for (const exclude of excludes) {
|
|
73
|
+
// Check if any part of the path matches the exclude pattern
|
|
74
|
+
// This handles both files and directories at any depth
|
|
75
|
+
if (pathParts.includes(exclude)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
// Also check if the relative path starts with the exclude (for top-level matches)
|
|
79
|
+
if (normalizedPath === exclude || normalizedPath.startsWith(exclude + '/')) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Recursively copy a directory, excluding specified patterns.
|
|
88
|
+
* This is a pure Node.js implementation that works on all platforms.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} srcDir - Source directory path
|
|
91
|
+
* @param {string} destDir - Destination directory path
|
|
92
|
+
* @param {string[]} excludes - Array of patterns to exclude
|
|
93
|
+
* @param {string} [relativePath=''] - Current relative path (used for recursion)
|
|
94
|
+
* @param {boolean} [verbose=true] - Whether to show progress
|
|
95
|
+
* @returns {number} Number of files copied
|
|
96
|
+
*/
|
|
97
|
+
function copyDirectoryRecursive(srcDir, destDir, excludes, relativePath = '', verbose = true) {
|
|
98
|
+
let filesCopied = 0;
|
|
99
|
+
|
|
100
|
+
// Read all entries in the source directory
|
|
101
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
102
|
+
|
|
103
|
+
for (const entry of entries) {
|
|
104
|
+
const entryRelativePath = relativePath ? path.join(relativePath, entry.name) : entry.name;
|
|
105
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
106
|
+
const destPath = path.join(destDir, entry.name);
|
|
107
|
+
|
|
108
|
+
// Check if this entry should be excluded
|
|
109
|
+
if (shouldExclude(entryRelativePath, excludes)) {
|
|
110
|
+
if (verbose) {
|
|
111
|
+
console.log(`Skipping: ${entryRelativePath}`);
|
|
112
|
+
}
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (entry.isDirectory()) {
|
|
117
|
+
// Create the directory if it doesn't exist
|
|
118
|
+
if (!fs.existsSync(destPath)) {
|
|
119
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
// Recursively copy contents
|
|
122
|
+
filesCopied += copyDirectoryRecursive(srcPath, destPath, excludes, entryRelativePath, verbose);
|
|
123
|
+
} else if (entry.isFile()) {
|
|
124
|
+
// Copy the file
|
|
125
|
+
fs.copyFileSync(srcPath, destPath);
|
|
126
|
+
if (verbose) {
|
|
127
|
+
console.log(`Copying: ${entryRelativePath}`);
|
|
128
|
+
}
|
|
129
|
+
filesCopied++;
|
|
130
|
+
} else if (entry.isSymbolicLink()) {
|
|
131
|
+
// Handle symbolic links - read the link target and recreate it
|
|
132
|
+
try {
|
|
133
|
+
const linkTarget = fs.readlinkSync(srcPath);
|
|
134
|
+
// Remove existing symlink if it exists
|
|
135
|
+
if (fs.existsSync(destPath)) {
|
|
136
|
+
fs.unlinkSync(destPath);
|
|
137
|
+
}
|
|
138
|
+
fs.symlinkSync(linkTarget, destPath);
|
|
139
|
+
if (verbose) {
|
|
140
|
+
console.log(`Linking: ${entryRelativePath} -> ${linkTarget}`);
|
|
141
|
+
}
|
|
142
|
+
filesCopied++;
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.warn(`Warning: Could not copy symbolic link ${entryRelativePath}: ${err.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return filesCopied;
|
|
150
|
+
}
|
|
151
|
+
|
|
8
152
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
153
|
+
* Pure Node.js implementation for copying repository structure.
|
|
154
|
+
* Uses Node.js fs module to recursively copy files while excluding
|
|
155
|
+
* specified patterns. This works identically on all platforms.
|
|
12
156
|
*
|
|
13
157
|
* @param {string[]} args - Command line arguments
|
|
14
|
-
* @param {string} args
|
|
158
|
+
* @param {string} args[0] - Source directory path
|
|
15
159
|
* @returns {Promise<void>}
|
|
16
160
|
*/
|
|
17
|
-
async function
|
|
18
|
-
//
|
|
161
|
+
async function do_git_clone_nodejs(args) {
|
|
162
|
+
// Validate arguments
|
|
163
|
+
if (args.length === 0) {
|
|
164
|
+
console.error('Usage: git-clone <source-directory> [destination-directory]');
|
|
165
|
+
console.error('');
|
|
166
|
+
console.error('Copies files from source to destination (default: current directory),');
|
|
167
|
+
console.error('excluding: .git, README.md, LICENSE, node_modules, bower_components');
|
|
168
|
+
console.error('');
|
|
169
|
+
console.error('Examples:');
|
|
170
|
+
console.error(' git-clone /path/to/template-repo');
|
|
171
|
+
console.error(' git-clone ../my-template ./new-project');
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Parse source path - remove trailing slash for consistency
|
|
176
|
+
const sourcePath = path.resolve(args[0].replace(/\/+$/, ''));
|
|
177
|
+
|
|
178
|
+
// Parse destination path - default to current directory
|
|
179
|
+
const destPath = args[1] ? path.resolve(args[1]) : process.cwd();
|
|
180
|
+
|
|
181
|
+
// Validate source directory exists
|
|
182
|
+
if (!fs.existsSync(sourcePath)) {
|
|
183
|
+
console.error(`Error: Source directory does not exist: ${sourcePath}`);
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Validate source is a directory
|
|
188
|
+
const sourceStats = fs.statSync(sourcePath);
|
|
189
|
+
if (!sourceStats.isDirectory()) {
|
|
190
|
+
console.error(`Error: Source path is not a directory: ${sourcePath}`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Create destination directory if it doesn't exist
|
|
195
|
+
if (!fs.existsSync(destPath)) {
|
|
196
|
+
console.log(`Creating destination directory: ${destPath}`);
|
|
197
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Validate destination is a directory
|
|
201
|
+
const destStats = fs.statSync(destPath);
|
|
202
|
+
if (!destStats.isDirectory()) {
|
|
203
|
+
console.error(`Error: Destination path is not a directory: ${destPath}`);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Prevent copying a directory into itself
|
|
208
|
+
const resolvedSource = fs.realpathSync(sourcePath);
|
|
209
|
+
const resolvedDest = fs.realpathSync(destPath);
|
|
210
|
+
if (resolvedDest.startsWith(resolvedSource + path.sep) || resolvedSource === resolvedDest) {
|
|
211
|
+
console.error('Error: Cannot copy a directory into itself or a subdirectory of itself.');
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
console.log(`Copying from: ${sourcePath}`);
|
|
216
|
+
console.log(`Copying to: ${destPath}`);
|
|
217
|
+
console.log(`Excluding: ${DEFAULT_EXCLUDES.join(', ')}`);
|
|
218
|
+
console.log('');
|
|
219
|
+
|
|
220
|
+
// Perform the copy
|
|
221
|
+
const filesCopied = copyDirectoryRecursive(sourcePath, destPath, DEFAULT_EXCLUDES, '', true);
|
|
222
|
+
|
|
223
|
+
console.log('');
|
|
224
|
+
console.log(`Done! Copied ${filesCopied} file(s).`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Copy repository structure on macOS.
|
|
229
|
+
*
|
|
230
|
+
* Uses rsync if available (the original implementation approach) for better
|
|
231
|
+
* performance with large directories. Falls back to pure Node.js if rsync
|
|
232
|
+
* is not installed.
|
|
233
|
+
*
|
|
234
|
+
* rsync advantages:
|
|
235
|
+
* - Shows progress for large files
|
|
236
|
+
* - Preserves permissions and timestamps more reliably
|
|
237
|
+
* - Handles edge cases with special files
|
|
238
|
+
*
|
|
239
|
+
* @param {string[]} args - Command line arguments
|
|
240
|
+
* @returns {Promise<void>}
|
|
241
|
+
*/
|
|
242
|
+
async function do_git_clone_macos(args) {
|
|
243
|
+
// rsync is installed by default on macOS, so use it for better performance
|
|
244
|
+
if (isCommandAvailable('rsync')) {
|
|
245
|
+
return do_git_clone_rsync(args);
|
|
246
|
+
}
|
|
247
|
+
// Fallback to pure Node.js implementation
|
|
248
|
+
return do_git_clone_nodejs(args);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Copy repository structure on Ubuntu.
|
|
253
|
+
*
|
|
254
|
+
* Uses rsync if available for better performance. rsync is commonly
|
|
255
|
+
* installed on Ubuntu systems. Falls back to pure Node.js if not available.
|
|
256
|
+
*
|
|
257
|
+
* @param {string[]} args - Command line arguments
|
|
258
|
+
* @returns {Promise<void>}
|
|
259
|
+
*/
|
|
260
|
+
async function do_git_clone_ubuntu(args) {
|
|
261
|
+
if (isCommandAvailable('rsync')) {
|
|
262
|
+
return do_git_clone_rsync(args);
|
|
263
|
+
}
|
|
264
|
+
// Fallback to pure Node.js implementation
|
|
265
|
+
return do_git_clone_nodejs(args);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Copy repository structure on Raspberry Pi OS.
|
|
270
|
+
*
|
|
271
|
+
* Uses rsync if available for better performance. Falls back to
|
|
272
|
+
* pure Node.js implementation if rsync is not installed.
|
|
273
|
+
*
|
|
274
|
+
* @param {string[]} args - Command line arguments
|
|
275
|
+
* @returns {Promise<void>}
|
|
276
|
+
*/
|
|
277
|
+
async function do_git_clone_raspbian(args) {
|
|
278
|
+
if (isCommandAvailable('rsync')) {
|
|
279
|
+
return do_git_clone_rsync(args);
|
|
280
|
+
}
|
|
281
|
+
return do_git_clone_nodejs(args);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Copy repository structure on Amazon Linux.
|
|
286
|
+
*
|
|
287
|
+
* Uses rsync if available for better performance. Falls back to
|
|
288
|
+
* pure Node.js implementation if rsync is not installed.
|
|
289
|
+
*
|
|
290
|
+
* @param {string[]} args - Command line arguments
|
|
291
|
+
* @returns {Promise<void>}
|
|
292
|
+
*/
|
|
293
|
+
async function do_git_clone_amazon_linux(args) {
|
|
294
|
+
if (isCommandAvailable('rsync')) {
|
|
295
|
+
return do_git_clone_rsync(args);
|
|
296
|
+
}
|
|
297
|
+
return do_git_clone_nodejs(args);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Copy repository structure on Windows Command Prompt.
|
|
302
|
+
*
|
|
303
|
+
* Windows does not have rsync by default, so this uses the pure Node.js
|
|
304
|
+
* implementation which works reliably on Windows.
|
|
305
|
+
*
|
|
306
|
+
* @param {string[]} args - Command line arguments
|
|
307
|
+
* @returns {Promise<void>}
|
|
308
|
+
*/
|
|
309
|
+
async function do_git_clone_cmd(args) {
|
|
310
|
+
// Windows doesn't have rsync by default, use pure Node.js
|
|
311
|
+
return do_git_clone_nodejs(args);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Copy repository structure on Windows PowerShell.
|
|
316
|
+
*
|
|
317
|
+
* Uses the pure Node.js implementation for reliable cross-platform behavior.
|
|
318
|
+
* PowerShell's Copy-Item doesn't have the same exclude capabilities as rsync.
|
|
319
|
+
*
|
|
320
|
+
* @param {string[]} args - Command line arguments
|
|
321
|
+
* @returns {Promise<void>}
|
|
322
|
+
*/
|
|
323
|
+
async function do_git_clone_powershell(args) {
|
|
324
|
+
// Use pure Node.js for consistent behavior
|
|
325
|
+
return do_git_clone_nodejs(args);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Copy repository structure from Git Bash on Windows.
|
|
330
|
+
*
|
|
331
|
+
* Git Bash may have rsync available if installed separately (e.g., via MSYS2).
|
|
332
|
+
* Falls back to pure Node.js if rsync is not available.
|
|
333
|
+
*
|
|
334
|
+
* @param {string[]} args - Command line arguments
|
|
335
|
+
* @returns {Promise<void>}
|
|
336
|
+
*/
|
|
337
|
+
async function do_git_clone_gitbash(args) {
|
|
338
|
+
// Git Bash might have rsync if user installed it
|
|
339
|
+
if (isCommandAvailable('rsync')) {
|
|
340
|
+
return do_git_clone_rsync(args);
|
|
341
|
+
}
|
|
342
|
+
return do_git_clone_nodejs(args);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Implementation using rsync for Unix-like systems.
|
|
347
|
+
*
|
|
348
|
+
* This matches the original bash function behavior exactly:
|
|
349
|
+
* rsync -av --progress $* ./ --exclude .git --exclude README.md ...
|
|
350
|
+
*
|
|
351
|
+
* rsync provides:
|
|
352
|
+
* - Progress indication for large transfers
|
|
353
|
+
* - Efficient incremental updates
|
|
354
|
+
* - Proper handling of permissions and special files
|
|
355
|
+
*
|
|
356
|
+
* @param {string[]} args - Command line arguments
|
|
357
|
+
* @returns {Promise<void>}
|
|
358
|
+
*/
|
|
359
|
+
async function do_git_clone_rsync(args) {
|
|
360
|
+
// Validate arguments
|
|
361
|
+
if (args.length === 0) {
|
|
362
|
+
console.error('Usage: git-clone <source-directory> [destination-directory]');
|
|
363
|
+
console.error('');
|
|
364
|
+
console.error('Copies files from source to destination (default: current directory),');
|
|
365
|
+
console.error('excluding: .git, README.md, LICENSE, node_modules, bower_components');
|
|
366
|
+
console.error('');
|
|
367
|
+
console.error('Examples:');
|
|
368
|
+
console.error(' git-clone /path/to/template-repo');
|
|
369
|
+
console.error(' git-clone ../my-template ./new-project');
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Parse source path - ensure it ends with / for rsync directory behavior
|
|
374
|
+
let sourcePath = path.resolve(args[0]);
|
|
375
|
+
if (!sourcePath.endsWith('/')) {
|
|
376
|
+
sourcePath += '/';
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Parse destination path - default to current directory
|
|
380
|
+
let destPath = args[1] ? path.resolve(args[1]) : process.cwd();
|
|
381
|
+
if (!destPath.endsWith('/')) {
|
|
382
|
+
destPath += '/';
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Validate source directory exists
|
|
386
|
+
const sourceDir = sourcePath.replace(/\/+$/, '');
|
|
387
|
+
if (!fs.existsSync(sourceDir)) {
|
|
388
|
+
console.error(`Error: Source directory does not exist: ${sourceDir}`);
|
|
389
|
+
process.exit(1);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Validate source is a directory
|
|
393
|
+
const sourceStats = fs.statSync(sourceDir);
|
|
394
|
+
if (!sourceStats.isDirectory()) {
|
|
395
|
+
console.error(`Error: Source path is not a directory: ${sourceDir}`);
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Create destination directory if it doesn't exist
|
|
400
|
+
const destDir = destPath.replace(/\/+$/, '');
|
|
401
|
+
if (!fs.existsSync(destDir)) {
|
|
402
|
+
console.log(`Creating destination directory: ${destDir}`);
|
|
403
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Build the rsync command matching the original behavior
|
|
407
|
+
// Original: rsync -av --progress $* ./ --exclude .git --exclude README.md ...
|
|
408
|
+
const excludeArgs = DEFAULT_EXCLUDES.map(exc => `--exclude "${exc}"`).join(' ');
|
|
409
|
+
const rsyncCmd = `rsync -av --progress "${sourcePath}" "${destPath}" ${excludeArgs}`;
|
|
410
|
+
|
|
411
|
+
console.log(`Executing: ${rsyncCmd}`);
|
|
412
|
+
console.log('');
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
execSync(rsyncCmd, { stdio: 'inherit' });
|
|
416
|
+
console.log('');
|
|
417
|
+
console.log('Done!');
|
|
418
|
+
} catch (error) {
|
|
419
|
+
console.error('Error: rsync command failed.');
|
|
420
|
+
console.error('Falling back to Node.js implementation...');
|
|
421
|
+
console.log('');
|
|
422
|
+
// Fall back to Node.js implementation
|
|
423
|
+
return do_git_clone_nodejs(args);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Main entry point - detects environment and executes appropriate implementation.
|
|
429
|
+
*
|
|
430
|
+
* The "git-clone" command copies files from a source directory (typically a
|
|
431
|
+
* git repository) to the current directory or a specified destination,
|
|
432
|
+
* excluding common files that should not be copied when using a repo as
|
|
433
|
+
* a template.
|
|
434
|
+
*
|
|
435
|
+
* This is useful when you want to:
|
|
436
|
+
* - Use an existing repository as a starting point for a new project
|
|
437
|
+
* - Copy project structure without git history
|
|
438
|
+
* - Skip dependency folders that should be reinstalled fresh
|
|
439
|
+
*
|
|
440
|
+
* @param {string[]} args - Command line arguments
|
|
441
|
+
* @returns {Promise<void>}
|
|
442
|
+
*/
|
|
443
|
+
async function do_git_clone(args) {
|
|
444
|
+
const platform = os.detect();
|
|
445
|
+
|
|
446
|
+
const handlers = {
|
|
447
|
+
'macos': do_git_clone_macos,
|
|
448
|
+
'ubuntu': do_git_clone_ubuntu,
|
|
449
|
+
'debian': do_git_clone_ubuntu,
|
|
450
|
+
'raspbian': do_git_clone_raspbian,
|
|
451
|
+
'amazon_linux': do_git_clone_amazon_linux,
|
|
452
|
+
'rhel': do_git_clone_amazon_linux,
|
|
453
|
+
'fedora': do_git_clone_ubuntu,
|
|
454
|
+
'linux': do_git_clone_ubuntu,
|
|
455
|
+
'wsl': do_git_clone_ubuntu,
|
|
456
|
+
'cmd': do_git_clone_cmd,
|
|
457
|
+
'windows': do_git_clone_cmd,
|
|
458
|
+
'powershell': do_git_clone_powershell,
|
|
459
|
+
'gitbash': do_git_clone_gitbash
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
const handler = handlers[platform.type];
|
|
463
|
+
if (!handler) {
|
|
464
|
+
console.error(`Platform '${platform.type}' is not supported for this command.`);
|
|
465
|
+
console.error('');
|
|
466
|
+
console.error('Supported platforms:');
|
|
467
|
+
console.error(' - macOS');
|
|
468
|
+
console.error(' - Ubuntu, Debian, and other Linux distributions');
|
|
469
|
+
console.error(' - Raspberry Pi OS');
|
|
470
|
+
console.error(' - Amazon Linux, RHEL, Fedora');
|
|
471
|
+
console.error(' - Windows (CMD, PowerShell, Git Bash)');
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
await handler(args);
|
|
19
476
|
}
|
|
20
477
|
|
|
21
|
-
module.exports = {
|
|
478
|
+
module.exports = {
|
|
479
|
+
main: do_git_clone,
|
|
480
|
+
do_git_clone,
|
|
481
|
+
do_git_clone_nodejs,
|
|
482
|
+
do_git_clone_macos,
|
|
483
|
+
do_git_clone_ubuntu,
|
|
484
|
+
do_git_clone_raspbian,
|
|
485
|
+
do_git_clone_amazon_linux,
|
|
486
|
+
do_git_clone_cmd,
|
|
487
|
+
do_git_clone_powershell,
|
|
488
|
+
do_git_clone_gitbash
|
|
489
|
+
};
|
|
22
490
|
|
|
23
491
|
if (require.main === module) {
|
|
24
|
-
|
|
492
|
+
do_git_clone(process.argv.slice(2));
|
|
25
493
|
}
|