@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,24 +1,727 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* backup-source - Backup ~/Source directory using rsync or robocopy.
|
|
5
|
+
*
|
|
6
|
+
* Migrated from legacy dotfiles alias.
|
|
7
|
+
* Original:
|
|
8
|
+
* backup-source(){
|
|
9
|
+
* backupdir="$*$(date +"%Y%m%d%H%M%S")/"
|
|
10
|
+
* backupcmd="rsync -arv --progress --no-links --exclude={.Trash,.android,.atom,...} ~/Source $backupdir"
|
|
11
|
+
* mkdir -p "$backupdir"
|
|
12
|
+
* eval "$backupcmd"
|
|
13
|
+
* cd "$backupdir"
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
5
16
|
* @module scripts/backup-source
|
|
6
17
|
*/
|
|
7
18
|
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const os = require('../utils/common/os');
|
|
22
|
+
const shell = require('../utils/common/shell');
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Directories and files to exclude from backup.
|
|
26
|
+
* These are common development artifacts, caches, and system directories
|
|
27
|
+
* that should not be backed up.
|
|
28
|
+
*/
|
|
29
|
+
const EXCLUDE_PATTERNS = [
|
|
30
|
+
'.Trash',
|
|
31
|
+
'.android',
|
|
32
|
+
'.atom',
|
|
33
|
+
'.bash_sessions',
|
|
34
|
+
'.cache',
|
|
35
|
+
'.cups',
|
|
36
|
+
'.dropbox',
|
|
37
|
+
'.git',
|
|
38
|
+
'.next',
|
|
39
|
+
'.npm',
|
|
40
|
+
'.nvm',
|
|
41
|
+
'.viminfo',
|
|
42
|
+
'bower_components',
|
|
43
|
+
'node_modules',
|
|
44
|
+
'.tmp',
|
|
45
|
+
'.idea',
|
|
46
|
+
'.DS_Store',
|
|
47
|
+
'.terraform'
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Generates a timestamp string in YYYYMMDDHHmmss format.
|
|
52
|
+
* This format is used to create unique backup directory names.
|
|
53
|
+
*
|
|
54
|
+
* @returns {string} Timestamp in YYYYMMDDHHmmss format (e.g., "20240115143022")
|
|
55
|
+
*/
|
|
56
|
+
function generateTimestamp() {
|
|
57
|
+
const now = new Date();
|
|
58
|
+
const year = now.getFullYear();
|
|
59
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
60
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
61
|
+
const hours = String(now.getHours()).padStart(2, '0');
|
|
62
|
+
const minutes = String(now.getMinutes()).padStart(2, '0');
|
|
63
|
+
const seconds = String(now.getSeconds()).padStart(2, '0');
|
|
64
|
+
return `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Gets the path to the user's Source directory.
|
|
69
|
+
* This is typically ~/Source on all platforms.
|
|
70
|
+
*
|
|
71
|
+
* @returns {string} Absolute path to ~/Source
|
|
72
|
+
*/
|
|
73
|
+
function getSourceDirectory() {
|
|
74
|
+
return path.join(os.getHomeDir(), 'Source');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validates that the Source directory exists.
|
|
79
|
+
*
|
|
80
|
+
* @returns {boolean} True if ~/Source exists and is a directory
|
|
81
|
+
*/
|
|
82
|
+
function sourceDirectoryExists() {
|
|
83
|
+
const sourcePath = getSourceDirectory();
|
|
84
|
+
try {
|
|
85
|
+
const stats = fs.statSync(sourcePath);
|
|
86
|
+
return stats.isDirectory();
|
|
87
|
+
} catch {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Checks if rsync is available on the system.
|
|
94
|
+
*
|
|
95
|
+
* @returns {boolean} True if rsync command is available
|
|
96
|
+
*/
|
|
97
|
+
function isRsyncAvailable() {
|
|
98
|
+
return shell.commandExists('rsync');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Node.js implementation note:
|
|
103
|
+
*
|
|
104
|
+
* This script intentionally uses rsync (macOS/Linux) or robocopy (Windows)
|
|
105
|
+
* instead of a pure Node.js implementation because:
|
|
106
|
+
*
|
|
107
|
+
* 1. rsync is battle-tested for decades with excellent file synchronization
|
|
108
|
+
* 2. rsync handles edge cases (symlinks, permissions, sparse files) that
|
|
109
|
+
* would be complex to implement correctly in Node.js
|
|
110
|
+
* 3. rsync has progress reporting and resumable transfers
|
|
111
|
+
* 4. robocopy is the Windows equivalent with similar benefits
|
|
112
|
+
*
|
|
113
|
+
* A pure Node.js implementation would not be appropriate for this use case.
|
|
114
|
+
*
|
|
115
|
+
* @param {string[]} args - Command line arguments (unused - this is a note)
|
|
116
|
+
* @returns {Promise<void>}
|
|
117
|
+
*/
|
|
118
|
+
async function do_backup_source_nodejs(args) {
|
|
119
|
+
// This function documents why we don't use pure Node.js for this task.
|
|
120
|
+
// The platform-specific functions use rsync or robocopy because those tools
|
|
121
|
+
// are superior for file synchronization compared to implementing the same
|
|
122
|
+
// functionality in Node.js.
|
|
123
|
+
throw new Error(
|
|
124
|
+
'do_backup_source_nodejs should not be called directly. ' +
|
|
125
|
+
'This script requires platform-specific tools (rsync or robocopy).'
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Backs up ~/Source directory on macOS using rsync.
|
|
131
|
+
*
|
|
132
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
133
|
+
* uses rsync to copy all files while excluding common development artifacts.
|
|
134
|
+
*
|
|
135
|
+
* @param {string[]} args - Command line arguments
|
|
136
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
137
|
+
* @returns {Promise<void>}
|
|
138
|
+
*/
|
|
139
|
+
async function do_backup_source_macos(args) {
|
|
140
|
+
// Validate destination argument
|
|
141
|
+
if (!args || args.length === 0 || !args[0]) {
|
|
142
|
+
console.error('Error: Destination backup directory is required.');
|
|
143
|
+
console.error('');
|
|
144
|
+
console.error('Usage: backup-source /path/to/backups/');
|
|
145
|
+
console.error('');
|
|
146
|
+
console.error('Example:');
|
|
147
|
+
console.error(' backup-source /Volumes/ExternalDrive/backups/');
|
|
148
|
+
console.error(' backup-source ~/Backups/');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Validate Source directory exists
|
|
153
|
+
if (!sourceDirectoryExists()) {
|
|
154
|
+
console.error('Error: Source directory does not exist.');
|
|
155
|
+
console.error(`Expected path: ${getSourceDirectory()}`);
|
|
156
|
+
console.error('');
|
|
157
|
+
console.error('Create the directory first or check if it exists at a different location.');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Check if rsync is available
|
|
162
|
+
if (!isRsyncAvailable()) {
|
|
163
|
+
console.error('Error: rsync is required but not installed.');
|
|
164
|
+
console.error('Install it with: brew install rsync');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Build the backup directory path with timestamp
|
|
169
|
+
const destBase = args.join(' ').replace(/\/+$/, ''); // Remove trailing slashes
|
|
170
|
+
const timestamp = generateTimestamp();
|
|
171
|
+
const backupDir = `${destBase}${timestamp}/`;
|
|
172
|
+
|
|
173
|
+
// Create the backup directory
|
|
174
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
175
|
+
try {
|
|
176
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
177
|
+
} catch (err) {
|
|
178
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Build rsync command with exclude patterns
|
|
183
|
+
const excludeArgs = EXCLUDE_PATTERNS.map(pattern => `--exclude="${pattern}"`).join(' ');
|
|
184
|
+
const sourcePath = getSourceDirectory();
|
|
185
|
+
const rsyncCmd = `rsync -arv --progress --no-links ${excludeArgs} "${sourcePath}" "${backupDir}"`;
|
|
186
|
+
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log('Starting backup of ~/Source...');
|
|
189
|
+
console.log(`Source: ${sourcePath}`);
|
|
190
|
+
console.log(`Destination: ${backupDir}`);
|
|
191
|
+
console.log('');
|
|
192
|
+
|
|
193
|
+
// Execute rsync with live output
|
|
194
|
+
const result = await shell.spawnAsync('rsync', [
|
|
195
|
+
'-arv',
|
|
196
|
+
'--progress',
|
|
197
|
+
'--no-links',
|
|
198
|
+
...EXCLUDE_PATTERNS.map(p => `--exclude=${p}`),
|
|
199
|
+
sourcePath,
|
|
200
|
+
backupDir
|
|
201
|
+
], {
|
|
202
|
+
onStdout: (data) => process.stdout.write(data),
|
|
203
|
+
onStderr: (data) => process.stderr.write(data)
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
if (result.code !== 0) {
|
|
207
|
+
console.error('');
|
|
208
|
+
console.error('Error: Backup failed.');
|
|
209
|
+
console.error(result.stderr);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log('Backup completed successfully!');
|
|
215
|
+
console.log(`Backup location: ${backupDir}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Backs up ~/Source directory on Ubuntu using rsync.
|
|
220
|
+
*
|
|
221
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
222
|
+
* uses rsync to copy all files while excluding common development artifacts.
|
|
223
|
+
*
|
|
224
|
+
* @param {string[]} args - Command line arguments
|
|
225
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
226
|
+
* @returns {Promise<void>}
|
|
227
|
+
*/
|
|
228
|
+
async function do_backup_source_ubuntu(args) {
|
|
229
|
+
// Validate destination argument
|
|
230
|
+
if (!args || args.length === 0 || !args[0]) {
|
|
231
|
+
console.error('Error: Destination backup directory is required.');
|
|
232
|
+
console.error('');
|
|
233
|
+
console.error('Usage: backup-source /path/to/backups/');
|
|
234
|
+
console.error('');
|
|
235
|
+
console.error('Example:');
|
|
236
|
+
console.error(' backup-source /mnt/backup/');
|
|
237
|
+
console.error(' backup-source ~/Backups/');
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Validate Source directory exists
|
|
242
|
+
if (!sourceDirectoryExists()) {
|
|
243
|
+
console.error('Error: Source directory does not exist.');
|
|
244
|
+
console.error(`Expected path: ${getSourceDirectory()}`);
|
|
245
|
+
console.error('');
|
|
246
|
+
console.error('Create the directory first or check if it exists at a different location.');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Check if rsync is available
|
|
251
|
+
if (!isRsyncAvailable()) {
|
|
252
|
+
console.error('Error: rsync is required but not installed.');
|
|
253
|
+
console.error('Install it with: sudo apt-get install rsync');
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Build the backup directory path with timestamp
|
|
258
|
+
const destBase = args.join(' ').replace(/\/+$/, ''); // Remove trailing slashes
|
|
259
|
+
const timestamp = generateTimestamp();
|
|
260
|
+
const backupDir = `${destBase}${timestamp}/`;
|
|
261
|
+
|
|
262
|
+
// Create the backup directory
|
|
263
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
264
|
+
try {
|
|
265
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Get source path
|
|
272
|
+
const sourcePath = getSourceDirectory();
|
|
273
|
+
|
|
274
|
+
console.log('');
|
|
275
|
+
console.log('Starting backup of ~/Source...');
|
|
276
|
+
console.log(`Source: ${sourcePath}`);
|
|
277
|
+
console.log(`Destination: ${backupDir}`);
|
|
278
|
+
console.log('');
|
|
279
|
+
|
|
280
|
+
// Execute rsync with live output
|
|
281
|
+
const result = await shell.spawnAsync('rsync', [
|
|
282
|
+
'-arv',
|
|
283
|
+
'--progress',
|
|
284
|
+
'--no-links',
|
|
285
|
+
...EXCLUDE_PATTERNS.map(p => `--exclude=${p}`),
|
|
286
|
+
sourcePath,
|
|
287
|
+
backupDir
|
|
288
|
+
], {
|
|
289
|
+
onStdout: (data) => process.stdout.write(data),
|
|
290
|
+
onStderr: (data) => process.stderr.write(data)
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (result.code !== 0) {
|
|
294
|
+
console.error('');
|
|
295
|
+
console.error('Error: Backup failed.');
|
|
296
|
+
console.error(result.stderr);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
console.log('');
|
|
301
|
+
console.log('Backup completed successfully!');
|
|
302
|
+
console.log(`Backup location: ${backupDir}`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Backs up ~/Source directory on Raspberry Pi OS using rsync.
|
|
307
|
+
*
|
|
308
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
309
|
+
* uses rsync to copy all files while excluding common development artifacts.
|
|
310
|
+
*
|
|
311
|
+
* @param {string[]} args - Command line arguments
|
|
312
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
313
|
+
* @returns {Promise<void>}
|
|
314
|
+
*/
|
|
315
|
+
async function do_backup_source_raspbian(args) {
|
|
316
|
+
// Raspbian uses the same rsync approach as Ubuntu
|
|
317
|
+
return do_backup_source_ubuntu(args);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Backs up ~/Source directory on Amazon Linux using rsync.
|
|
322
|
+
*
|
|
323
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
324
|
+
* uses rsync to copy all files while excluding common development artifacts.
|
|
325
|
+
*
|
|
326
|
+
* @param {string[]} args - Command line arguments
|
|
327
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
328
|
+
* @returns {Promise<void>}
|
|
329
|
+
*/
|
|
330
|
+
async function do_backup_source_amazon_linux(args) {
|
|
331
|
+
// Validate destination argument
|
|
332
|
+
if (!args || args.length === 0 || !args[0]) {
|
|
333
|
+
console.error('Error: Destination backup directory is required.');
|
|
334
|
+
console.error('');
|
|
335
|
+
console.error('Usage: backup-source /path/to/backups/');
|
|
336
|
+
console.error('');
|
|
337
|
+
console.error('Example:');
|
|
338
|
+
console.error(' backup-source /mnt/efs/backups/');
|
|
339
|
+
console.error(' backup-source ~/Backups/');
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Validate Source directory exists
|
|
344
|
+
if (!sourceDirectoryExists()) {
|
|
345
|
+
console.error('Error: Source directory does not exist.');
|
|
346
|
+
console.error(`Expected path: ${getSourceDirectory()}`);
|
|
347
|
+
console.error('');
|
|
348
|
+
console.error('Create the directory first or check if it exists at a different location.');
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Check if rsync is available
|
|
353
|
+
if (!isRsyncAvailable()) {
|
|
354
|
+
console.error('Error: rsync is required but not installed.');
|
|
355
|
+
console.error('Install it with: sudo dnf install rsync (or: sudo yum install rsync)');
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Build the backup directory path with timestamp
|
|
360
|
+
const destBase = args.join(' ').replace(/\/+$/, ''); // Remove trailing slashes
|
|
361
|
+
const timestamp = generateTimestamp();
|
|
362
|
+
const backupDir = `${destBase}${timestamp}/`;
|
|
363
|
+
|
|
364
|
+
// Create the backup directory
|
|
365
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
366
|
+
try {
|
|
367
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
368
|
+
} catch (err) {
|
|
369
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Get source path
|
|
374
|
+
const sourcePath = getSourceDirectory();
|
|
375
|
+
|
|
376
|
+
console.log('');
|
|
377
|
+
console.log('Starting backup of ~/Source...');
|
|
378
|
+
console.log(`Source: ${sourcePath}`);
|
|
379
|
+
console.log(`Destination: ${backupDir}`);
|
|
380
|
+
console.log('');
|
|
381
|
+
|
|
382
|
+
// Execute rsync with live output
|
|
383
|
+
const result = await shell.spawnAsync('rsync', [
|
|
384
|
+
'-arv',
|
|
385
|
+
'--progress',
|
|
386
|
+
'--no-links',
|
|
387
|
+
...EXCLUDE_PATTERNS.map(p => `--exclude=${p}`),
|
|
388
|
+
sourcePath,
|
|
389
|
+
backupDir
|
|
390
|
+
], {
|
|
391
|
+
onStdout: (data) => process.stdout.write(data),
|
|
392
|
+
onStderr: (data) => process.stderr.write(data)
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
if (result.code !== 0) {
|
|
396
|
+
console.error('');
|
|
397
|
+
console.error('Error: Backup failed.');
|
|
398
|
+
console.error(result.stderr);
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
console.log('');
|
|
403
|
+
console.log('Backup completed successfully!');
|
|
404
|
+
console.log(`Backup location: ${backupDir}`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Backs up ~/Source directory on Windows Command Prompt using robocopy.
|
|
409
|
+
*
|
|
410
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
411
|
+
* uses robocopy (built into Windows) to copy all files while excluding
|
|
412
|
+
* common development artifacts.
|
|
413
|
+
*
|
|
414
|
+
* @param {string[]} args - Command line arguments
|
|
415
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
416
|
+
* @returns {Promise<void>}
|
|
417
|
+
*/
|
|
418
|
+
async function do_backup_source_cmd(args) {
|
|
419
|
+
// Validate destination argument
|
|
420
|
+
if (!args || args.length === 0 || !args[0]) {
|
|
421
|
+
console.error('Error: Destination backup directory is required.');
|
|
422
|
+
console.error('');
|
|
423
|
+
console.error('Usage: backup-source C:\\path\\to\\backups\\');
|
|
424
|
+
console.error('');
|
|
425
|
+
console.error('Example:');
|
|
426
|
+
console.error(' backup-source D:\\Backups\\');
|
|
427
|
+
console.error(' backup-source %USERPROFILE%\\Backups\\');
|
|
428
|
+
process.exit(1);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Validate Source directory exists
|
|
432
|
+
if (!sourceDirectoryExists()) {
|
|
433
|
+
console.error('Error: Source directory does not exist.');
|
|
434
|
+
console.error(`Expected path: ${getSourceDirectory()}`);
|
|
435
|
+
console.error('');
|
|
436
|
+
console.error('Create the directory first or check if it exists at a different location.');
|
|
437
|
+
process.exit(1);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Build the backup directory path with timestamp
|
|
441
|
+
const destBase = args.join(' ').replace(/\\+$/, '').replace(/\/+$/, ''); // Remove trailing slashes
|
|
442
|
+
const timestamp = generateTimestamp();
|
|
443
|
+
const backupDir = path.join(destBase + timestamp);
|
|
444
|
+
|
|
445
|
+
// Create the backup directory
|
|
446
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
447
|
+
try {
|
|
448
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
449
|
+
} catch (err) {
|
|
450
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
451
|
+
process.exit(1);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Get source path
|
|
455
|
+
const sourcePath = getSourceDirectory();
|
|
456
|
+
const sourceBasename = path.basename(sourcePath);
|
|
457
|
+
const destPath = path.join(backupDir, sourceBasename);
|
|
458
|
+
|
|
459
|
+
console.log('');
|
|
460
|
+
console.log('Starting backup of ~/Source...');
|
|
461
|
+
console.log(`Source: ${sourcePath}`);
|
|
462
|
+
console.log(`Destination: ${destPath}`);
|
|
463
|
+
console.log('');
|
|
464
|
+
|
|
465
|
+
// Build robocopy command with exclude patterns
|
|
466
|
+
// robocopy uses /XD for directories and /XF for files
|
|
467
|
+
const excludeDirs = EXCLUDE_PATTERNS.filter(p => !p.includes('.')).map(p => `/XD "${p}"`).join(' ');
|
|
468
|
+
const excludeFiles = EXCLUDE_PATTERNS.filter(p => p.includes('.')).map(p => `/XF "${p}"`).join(' ');
|
|
469
|
+
|
|
470
|
+
// Execute robocopy
|
|
471
|
+
// /E = copy subdirectories including empty ones
|
|
472
|
+
// /R:3 = retry 3 times on failed copies
|
|
473
|
+
// /W:5 = wait 5 seconds between retries
|
|
474
|
+
// /NP = no progress (we'll use /V for verbose instead)
|
|
475
|
+
// /XJ = exclude junction points (similar to --no-links)
|
|
476
|
+
const robocopyArgs = [
|
|
477
|
+
sourcePath,
|
|
478
|
+
destPath,
|
|
479
|
+
'/E',
|
|
480
|
+
'/R:3',
|
|
481
|
+
'/W:5',
|
|
482
|
+
'/XJ',
|
|
483
|
+
...EXCLUDE_PATTERNS.map(p => `/XD ${p}`),
|
|
484
|
+
...EXCLUDE_PATTERNS.map(p => `/XF ${p}`)
|
|
485
|
+
];
|
|
486
|
+
|
|
487
|
+
const result = await shell.spawnAsync('robocopy', robocopyArgs, {
|
|
488
|
+
onStdout: (data) => process.stdout.write(data),
|
|
489
|
+
onStderr: (data) => process.stderr.write(data)
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// robocopy exit codes: 0-7 are success (0=no files copied, 1=files copied, etc.)
|
|
493
|
+
// Exit code 8+ indicates errors
|
|
494
|
+
if (result.code >= 8) {
|
|
495
|
+
console.error('');
|
|
496
|
+
console.error('Error: Backup failed.');
|
|
497
|
+
console.error(result.stderr);
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
console.log('');
|
|
502
|
+
console.log('Backup completed successfully!');
|
|
503
|
+
console.log(`Backup location: ${backupDir}`);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Backs up ~/Source directory on Windows PowerShell using robocopy.
|
|
508
|
+
*
|
|
509
|
+
* Creates a timestamped backup directory at the specified destination and
|
|
510
|
+
* uses robocopy (built into Windows) to copy all files while excluding
|
|
511
|
+
* common development artifacts.
|
|
512
|
+
*
|
|
513
|
+
* @param {string[]} args - Command line arguments
|
|
514
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
515
|
+
* @returns {Promise<void>}
|
|
516
|
+
*/
|
|
517
|
+
async function do_backup_source_powershell(args) {
|
|
518
|
+
// PowerShell uses the same robocopy approach as CMD
|
|
519
|
+
return do_backup_source_cmd(args);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Backs up ~/Source directory in Git Bash using rsync (if available) or robocopy.
|
|
524
|
+
*
|
|
525
|
+
* Git Bash runs on Windows but can use rsync if it's installed via MSYS2.
|
|
526
|
+
* Falls back to robocopy via PowerShell if rsync is not available.
|
|
527
|
+
*
|
|
528
|
+
* @param {string[]} args - Command line arguments
|
|
529
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
530
|
+
* @returns {Promise<void>}
|
|
531
|
+
*/
|
|
532
|
+
async function do_backup_source_gitbash(args) {
|
|
533
|
+
// Validate destination argument
|
|
534
|
+
if (!args || args.length === 0 || !args[0]) {
|
|
535
|
+
console.error('Error: Destination backup directory is required.');
|
|
536
|
+
console.error('');
|
|
537
|
+
console.error('Usage: backup-source /path/to/backups/');
|
|
538
|
+
console.error('');
|
|
539
|
+
console.error('Example:');
|
|
540
|
+
console.error(' backup-source /d/Backups/');
|
|
541
|
+
console.error(' backup-source ~/Backups/');
|
|
542
|
+
process.exit(1);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Validate Source directory exists
|
|
546
|
+
if (!sourceDirectoryExists()) {
|
|
547
|
+
console.error('Error: Source directory does not exist.');
|
|
548
|
+
console.error(`Expected path: ${getSourceDirectory()}`);
|
|
549
|
+
console.error('');
|
|
550
|
+
console.error('Create the directory first or check if it exists at a different location.');
|
|
551
|
+
process.exit(1);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// Check if rsync is available in Git Bash
|
|
555
|
+
if (isRsyncAvailable()) {
|
|
556
|
+
// Build the backup directory path with timestamp
|
|
557
|
+
const destBase = args.join(' ').replace(/\/+$/, ''); // Remove trailing slashes
|
|
558
|
+
const timestamp = generateTimestamp();
|
|
559
|
+
const backupDir = `${destBase}${timestamp}/`;
|
|
560
|
+
|
|
561
|
+
// Create the backup directory
|
|
562
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
563
|
+
try {
|
|
564
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
565
|
+
} catch (err) {
|
|
566
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
567
|
+
process.exit(1);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Get source path
|
|
571
|
+
const sourcePath = getSourceDirectory();
|
|
572
|
+
|
|
573
|
+
console.log('');
|
|
574
|
+
console.log('Starting backup of ~/Source using rsync...');
|
|
575
|
+
console.log(`Source: ${sourcePath}`);
|
|
576
|
+
console.log(`Destination: ${backupDir}`);
|
|
577
|
+
console.log('');
|
|
578
|
+
|
|
579
|
+
// Execute rsync with live output
|
|
580
|
+
const result = await shell.spawnAsync('rsync', [
|
|
581
|
+
'-arv',
|
|
582
|
+
'--progress',
|
|
583
|
+
'--no-links',
|
|
584
|
+
...EXCLUDE_PATTERNS.map(p => `--exclude=${p}`),
|
|
585
|
+
sourcePath,
|
|
586
|
+
backupDir
|
|
587
|
+
], {
|
|
588
|
+
onStdout: (data) => process.stdout.write(data),
|
|
589
|
+
onStderr: (data) => process.stderr.write(data)
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
if (result.code !== 0) {
|
|
593
|
+
console.error('');
|
|
594
|
+
console.error('Error: Backup failed.');
|
|
595
|
+
console.error(result.stderr);
|
|
596
|
+
process.exit(1);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
console.log('');
|
|
600
|
+
console.log('Backup completed successfully!');
|
|
601
|
+
console.log(`Backup location: ${backupDir}`);
|
|
602
|
+
} else {
|
|
603
|
+
// Fall back to robocopy via PowerShell
|
|
604
|
+
console.log('rsync not found in Git Bash, using robocopy via PowerShell...');
|
|
605
|
+
console.log('');
|
|
606
|
+
|
|
607
|
+
// Convert Git Bash paths to Windows paths for robocopy
|
|
608
|
+
const destBase = args.join(' ').replace(/\/+$/, '');
|
|
609
|
+
const timestamp = generateTimestamp();
|
|
610
|
+
|
|
611
|
+
// Convert /c/Users/... to C:\Users\... for PowerShell
|
|
612
|
+
let windowsDestBase = destBase;
|
|
613
|
+
if (destBase.match(/^\/[a-zA-Z]\//)) {
|
|
614
|
+
// Git Bash style path like /c/Users/...
|
|
615
|
+
windowsDestBase = destBase.replace(/^\/([a-zA-Z])\//, '$1:\\').replace(/\//g, '\\');
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
const backupDir = windowsDestBase + timestamp;
|
|
619
|
+
|
|
620
|
+
// Create the backup directory
|
|
621
|
+
console.log(`Creating backup directory: ${backupDir}`);
|
|
622
|
+
try {
|
|
623
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
624
|
+
} catch (err) {
|
|
625
|
+
console.error(`Error: Failed to create backup directory: ${err.message}`);
|
|
626
|
+
process.exit(1);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// Get source path and convert to Windows format
|
|
630
|
+
const sourcePath = getSourceDirectory();
|
|
631
|
+
let windowsSourcePath = sourcePath;
|
|
632
|
+
if (sourcePath.match(/^\/[a-zA-Z]\//)) {
|
|
633
|
+
windowsSourcePath = sourcePath.replace(/^\/([a-zA-Z])\//, '$1:\\').replace(/\//g, '\\');
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
const sourceBasename = path.basename(sourcePath);
|
|
637
|
+
const destPath = path.join(backupDir, sourceBasename);
|
|
638
|
+
|
|
639
|
+
console.log('');
|
|
640
|
+
console.log('Starting backup of ~/Source using robocopy...');
|
|
641
|
+
console.log(`Source: ${windowsSourcePath}`);
|
|
642
|
+
console.log(`Destination: ${destPath}`);
|
|
643
|
+
console.log('');
|
|
644
|
+
|
|
645
|
+
// Build robocopy command for PowerShell
|
|
646
|
+
const excludeArgs = EXCLUDE_PATTERNS.map(p => `/XD "${p}" /XF "${p}"`).join(' ');
|
|
647
|
+
const robocopyCmd = `robocopy "${windowsSourcePath}" "${destPath}" /E /R:3 /W:5 /XJ ${excludeArgs}`;
|
|
648
|
+
|
|
649
|
+
const result = await shell.exec(`powershell.exe -NoProfile -Command "${robocopyCmd}"`);
|
|
650
|
+
|
|
651
|
+
// robocopy exit codes: 0-7 are success
|
|
652
|
+
// Note: shell.exec returns the exit code differently than spawnAsync
|
|
653
|
+
// We check stderr for errors since robocopy outputs to stdout
|
|
654
|
+
if (result.code >= 8) {
|
|
655
|
+
console.error('');
|
|
656
|
+
console.error('Error: Backup failed.');
|
|
657
|
+
console.error(result.stderr || result.stdout);
|
|
658
|
+
process.exit(1);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
console.log(result.stdout);
|
|
662
|
+
console.log('');
|
|
663
|
+
console.log('Backup completed successfully!');
|
|
664
|
+
console.log(`Backup location: ${backupDir}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
8
668
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
669
|
+
* Main entry point - detects environment and executes appropriate implementation.
|
|
670
|
+
*
|
|
671
|
+
* Creates a timestamped backup of the ~/Source directory to the specified
|
|
672
|
+
* destination. Uses rsync on macOS/Linux (superior for file synchronization)
|
|
673
|
+
* and robocopy on Windows (built-in equivalent).
|
|
674
|
+
*
|
|
675
|
+
* The backup excludes common development artifacts like node_modules, .git,
|
|
676
|
+
* cache directories, and IDE-specific folders to reduce backup size and time.
|
|
11
677
|
*
|
|
12
678
|
* @param {string[]} args - Command line arguments
|
|
13
|
-
* @param {string} args
|
|
679
|
+
* @param {string} args[0] - Destination backup directory path (required)
|
|
14
680
|
* @returns {Promise<void>}
|
|
15
681
|
*/
|
|
16
|
-
async function
|
|
17
|
-
|
|
682
|
+
async function do_backup_source(args) {
|
|
683
|
+
const platform = os.detect();
|
|
684
|
+
|
|
685
|
+
const handlers = {
|
|
686
|
+
'macos': do_backup_source_macos,
|
|
687
|
+
'ubuntu': do_backup_source_ubuntu,
|
|
688
|
+
'debian': do_backup_source_ubuntu,
|
|
689
|
+
'raspbian': do_backup_source_raspbian,
|
|
690
|
+
'amazon_linux': do_backup_source_amazon_linux,
|
|
691
|
+
'rhel': do_backup_source_amazon_linux,
|
|
692
|
+
'fedora': do_backup_source_amazon_linux,
|
|
693
|
+
'cmd': do_backup_source_cmd,
|
|
694
|
+
'windows': do_backup_source_cmd,
|
|
695
|
+
'powershell': do_backup_source_powershell,
|
|
696
|
+
'gitbash': do_backup_source_gitbash,
|
|
697
|
+
'wsl': do_backup_source_ubuntu
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
const handler = handlers[platform.type];
|
|
701
|
+
if (!handler) {
|
|
702
|
+
console.error(`Platform '${platform.type}' is not supported for this command.`);
|
|
703
|
+
console.error('');
|
|
704
|
+
console.error('Supported platforms: macOS, Ubuntu, Debian, Raspberry Pi OS,');
|
|
705
|
+
console.error('Amazon Linux, RHEL, Fedora, Windows, Git Bash, WSL');
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
await handler(args);
|
|
18
710
|
}
|
|
19
711
|
|
|
20
|
-
module.exports = {
|
|
712
|
+
module.exports = {
|
|
713
|
+
main: do_backup_source,
|
|
714
|
+
do_backup_source,
|
|
715
|
+
do_backup_source_nodejs,
|
|
716
|
+
do_backup_source_macos,
|
|
717
|
+
do_backup_source_ubuntu,
|
|
718
|
+
do_backup_source_raspbian,
|
|
719
|
+
do_backup_source_amazon_linux,
|
|
720
|
+
do_backup_source_cmd,
|
|
721
|
+
do_backup_source_powershell,
|
|
722
|
+
do_backup_source_gitbash
|
|
723
|
+
};
|
|
21
724
|
|
|
22
725
|
if (require.main === module) {
|
|
23
|
-
|
|
726
|
+
do_backup_source(process.argv.slice(2));
|
|
24
727
|
}
|