backdot 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -14
- package/dist/cli.js +33 -79
- package/dist/commands/history.js +2 -2
- package/dist/commands/init.js +3 -3
- package/dist/commands/restore.d.ts +4 -4
- package/dist/commands/restore.js +2 -2
- package/dist/commands/status.js +2 -2
- package/dist/config.js +1 -1
- package/dist/launchd.js +1 -1
- package/dist/staging.js +2 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install -g backdot
|
|
13
|
-
backdot
|
|
13
|
+
backdot init
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
This creates `~/.backdot.json` with sensible defaults and walks you through setup. Open the config file and set your repository URL and the files you want backed up:
|
|
@@ -26,13 +26,13 @@ This creates `~/.backdot.json` with sensible defaults and walks you through setu
|
|
|
26
26
|
Run your first backup:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
backdot
|
|
29
|
+
backdot backup
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
or configure the backport process to run automatically (daily at 2am)
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
backdot
|
|
35
|
+
backdot schedule
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Configuration
|
|
@@ -51,17 +51,17 @@ Prefix a pattern with `!` to exclude matching files:
|
|
|
51
51
|
|
|
52
52
|
## Commands
|
|
53
53
|
|
|
54
|
-
| Command
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
54
|
+
| Command | Description |
|
|
55
|
+
| ------------------------------ | ---------------------------------------------- |
|
|
56
|
+
| `init` | Set up backdot for the first time |
|
|
57
|
+
| `backup` | Run a backup now |
|
|
58
|
+
| `restore` | Restore latest backup from the configured repo |
|
|
59
|
+
| `restore <url>` | Restore from a specific repo URL |
|
|
60
|
+
| `restore [url] --commit <sha>` | Restore from a specific backup commit |
|
|
61
|
+
| `history [url]` | Browse and restore a previous backup |
|
|
62
|
+
| `schedule` | Schedule automatic daily backup (Mac-only) |
|
|
63
|
+
| `unschedule` | Unschedule the daily backup |
|
|
64
|
+
| `status` | Show schedule and resolved file list |
|
|
65
65
|
|
|
66
66
|
## Development
|
|
67
67
|
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import
|
|
4
|
+
import cac from "cac";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { CONFIG_PATH } from "./config.js";
|
|
7
7
|
import { backup } from "./commands/backup.js";
|
|
@@ -23,86 +23,40 @@ function getVersion() {
|
|
|
23
23
|
return "unknown";
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
backup: { type: "boolean" },
|
|
53
|
-
restore: { type: "boolean" },
|
|
54
|
-
history: { type: "boolean" },
|
|
55
|
-
schedule: { type: "boolean" },
|
|
56
|
-
unschedule: { type: "boolean" },
|
|
57
|
-
status: { type: "boolean" },
|
|
58
|
-
version: { type: "boolean" },
|
|
59
|
-
help: { type: "boolean" },
|
|
60
|
-
commit: { type: "string" },
|
|
61
|
-
yes: { type: "boolean", short: "y" },
|
|
62
|
-
},
|
|
63
|
-
allowPositionals: true,
|
|
64
|
-
strict: true,
|
|
65
|
-
}));
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
console.error(`\n Error: ${errorMessage(err)}\n`);
|
|
69
|
-
printHelp();
|
|
70
|
-
process.exit(1);
|
|
26
|
+
const cli = cac("backdot");
|
|
27
|
+
cli.command("init", "Set up backdot for the first time").action(() => init());
|
|
28
|
+
cli.command("backup", "Run a backup now").action(async () => {
|
|
29
|
+
await backup();
|
|
30
|
+
});
|
|
31
|
+
cli
|
|
32
|
+
.command("restore [url]", "Restore files")
|
|
33
|
+
.option("--commit <sha>", "Restore from a specific backup commit")
|
|
34
|
+
.option("-y, --yes", "Accept defaults without prompting")
|
|
35
|
+
.action(async (url, options) => {
|
|
36
|
+
await restore({ repoUrl: url, commit: options.commit, yes: !!options.yes });
|
|
37
|
+
});
|
|
38
|
+
cli
|
|
39
|
+
.command("history [url]", "List and restore a previous backup")
|
|
40
|
+
.action(async (url) => {
|
|
41
|
+
await history(url);
|
|
42
|
+
});
|
|
43
|
+
cli.command("schedule", "Schedule daily backup").action(() => schedule());
|
|
44
|
+
cli.command("unschedule", "Unschedule the daily backup").action(() => unschedule());
|
|
45
|
+
cli.command("status", "Show the status of the backup").action(async () => {
|
|
46
|
+
await status();
|
|
47
|
+
});
|
|
48
|
+
cli.command("", "").action(() => {
|
|
49
|
+
cli.outputHelp();
|
|
50
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
51
|
+
console.log(` No config found. Run ${chalk.bold("backdot init")} to get started.\n`);
|
|
71
52
|
}
|
|
53
|
+
});
|
|
54
|
+
cli.help();
|
|
55
|
+
cli.version(getVersion());
|
|
56
|
+
async function main() {
|
|
72
57
|
try {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
else if (values.backup) {
|
|
77
|
-
await backup();
|
|
78
|
-
}
|
|
79
|
-
else if (values.schedule) {
|
|
80
|
-
schedule();
|
|
81
|
-
}
|
|
82
|
-
else if (values.unschedule) {
|
|
83
|
-
unschedule();
|
|
84
|
-
}
|
|
85
|
-
else if (values.status) {
|
|
86
|
-
await status();
|
|
87
|
-
}
|
|
88
|
-
else if (values.restore) {
|
|
89
|
-
await restore(positionals[0], values.commit, {
|
|
90
|
-
yes: !!values.yes,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
else if (values.history) {
|
|
94
|
-
await history(positionals[0]);
|
|
95
|
-
}
|
|
96
|
-
else if (values.version) {
|
|
97
|
-
console.log(getVersion());
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
printHelp();
|
|
101
|
-
if (!fs.existsSync(CONFIG_PATH)) {
|
|
102
|
-
console.log(` No config found. Run ${chalk.bold("backdot --init")} to get started.`);
|
|
103
|
-
console.log();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
58
|
+
cli.parse(process.argv, { run: false });
|
|
59
|
+
await cli.runMatchedCommand();
|
|
106
60
|
}
|
|
107
61
|
catch (err) {
|
|
108
62
|
const msg = errorMessage(err);
|
package/dist/commands/history.js
CHANGED
|
@@ -22,7 +22,7 @@ export async function history(repoUrl) {
|
|
|
22
22
|
console.log("\n No backup history found.\n");
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
const
|
|
25
|
+
const selectedCommit = await select({
|
|
26
26
|
message: "Select a backup to restore from:",
|
|
27
27
|
loop: false,
|
|
28
28
|
choices: commits.map((c) => ({
|
|
@@ -31,5 +31,5 @@ export async function history(repoUrl) {
|
|
|
31
31
|
})),
|
|
32
32
|
});
|
|
33
33
|
console.log();
|
|
34
|
-
await restore(repoUrl,
|
|
34
|
+
await restore({ repoUrl, commit: selectedCommit });
|
|
35
35
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -50,8 +50,8 @@ export function init() {
|
|
|
50
50
|
// Step 3
|
|
51
51
|
console.log(chalk.bold(" Step 3 — Run your first backup"));
|
|
52
52
|
console.log();
|
|
53
|
-
console.log(` ${chalk.bold("backdot
|
|
54
|
-
console.log(` ${chalk.bold("backdot
|
|
55
|
-
console.log(` ${chalk.bold("backdot
|
|
53
|
+
console.log(` ${chalk.bold("backdot backup")} Run a one-time backup`);
|
|
54
|
+
console.log(` ${chalk.bold("backdot schedule")} Schedule daily backups (macOS)`);
|
|
55
|
+
console.log(` ${chalk.bold("backdot status")} Check which files will be backed up`);
|
|
56
56
|
console.log();
|
|
57
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
export declare function restore({ repoUrl, commit, yes, }?: {
|
|
2
|
+
repoUrl?: string;
|
|
3
|
+
commit?: string;
|
|
2
4
|
yes?: boolean;
|
|
3
|
-
}
|
|
4
|
-
export declare function restore(repoUrl?: string, commit?: string, options?: RestoreOptions): Promise<void>;
|
|
5
|
-
export {};
|
|
5
|
+
}): Promise<void>;
|
package/dist/commands/restore.js
CHANGED
|
@@ -58,7 +58,7 @@ async function resolveRepoAndMachine(repoUrl, commit) {
|
|
|
58
58
|
}
|
|
59
59
|
return { repository: repoUrl, machine };
|
|
60
60
|
}
|
|
61
|
-
export async function restore(repoUrl, commit,
|
|
61
|
+
export async function restore({ repoUrl, commit, yes, } = {}) {
|
|
62
62
|
logger.info("Starting restore");
|
|
63
63
|
const { repository, machine } = await resolveRepoAndMachine(repoUrl, commit);
|
|
64
64
|
const spinner = ora("Fetching latest backup").start();
|
|
@@ -102,7 +102,7 @@ export async function restore(repoUrl, commit, options = {}) {
|
|
|
102
102
|
spinner.stop();
|
|
103
103
|
console.log();
|
|
104
104
|
let toRestore;
|
|
105
|
-
if (
|
|
105
|
+
if (yes) {
|
|
106
106
|
toRestore = fresh;
|
|
107
107
|
if (existing.length > 0) {
|
|
108
108
|
console.log(` Skipped ${pluralize(existing.length, "existing file")}. Run without --yes to select them.`);
|
package/dist/commands/status.js
CHANGED
|
@@ -13,7 +13,7 @@ function tildePath(filePath) {
|
|
|
13
13
|
export async function status() {
|
|
14
14
|
const scheduled = isScheduled();
|
|
15
15
|
console.log();
|
|
16
|
-
console.log(` Schedule: ${scheduled ? "active (daily at 02:00)" : `not active (run ${chalk.bold("backdot
|
|
16
|
+
console.log(` Schedule: ${scheduled ? "active (daily at 02:00)" : `not active (run ${chalk.bold("backdot schedule")} to enable)`}`);
|
|
17
17
|
const config = loadConfig();
|
|
18
18
|
console.log(` Repo: ${config.repository}`);
|
|
19
19
|
console.log(` Machine: ${config.machine}`);
|
|
@@ -59,7 +59,7 @@ export async function status() {
|
|
|
59
59
|
}
|
|
60
60
|
console.log();
|
|
61
61
|
}
|
|
62
|
-
console.log(` Run ${chalk.bold("backdot
|
|
62
|
+
console.log(` Run ${chalk.bold("backdot backup")} to back up all changes.`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
catch (err) {
|
package/dist/config.js
CHANGED
|
@@ -21,7 +21,7 @@ const ConfigSchema = z.object({
|
|
|
21
21
|
});
|
|
22
22
|
export function loadConfig() {
|
|
23
23
|
if (!fs.existsSync(CONFIG_PATH)) {
|
|
24
|
-
throw new Error(`Config file not found: ${CONFIG_PATH}\n Run "backdot
|
|
24
|
+
throw new Error(`Config file not found: ${CONFIG_PATH}\n Run "backdot init" to create it.`);
|
|
25
25
|
}
|
|
26
26
|
let raw;
|
|
27
27
|
try {
|
package/dist/launchd.js
CHANGED
|
@@ -33,7 +33,7 @@ function buildPlist() {
|
|
|
33
33
|
<array>
|
|
34
34
|
<string>${escapeXml(nodePath)}</string>
|
|
35
35
|
<string>${escapeXml(scriptPath)}</string>
|
|
36
|
-
<string
|
|
36
|
+
<string>backup</string>
|
|
37
37
|
</array>
|
|
38
38
|
<key>WorkingDirectory</key>
|
|
39
39
|
<string>${escapeXml(workingDir)}</string>
|
package/dist/staging.js
CHANGED
|
@@ -47,7 +47,7 @@ export async function compareFiles(files, machine, repository) {
|
|
|
47
47
|
return { backedUp: [], modified: [], notBackedUp: [] };
|
|
48
48
|
}
|
|
49
49
|
if (!fs.existsSync(STAGING_GIT_DIR)) {
|
|
50
|
-
return failedComparisonResult(new Error(
|
|
50
|
+
return failedComparisonResult(new Error('Backup repository not found. Run "backdot backup" first.'));
|
|
51
51
|
}
|
|
52
52
|
const git = simpleGit(STAGING_DIR);
|
|
53
53
|
try {
|
|
@@ -113,7 +113,7 @@ This repository contains files backed up automatically using [backdot](https://g
|
|
|
113
113
|
## Restore
|
|
114
114
|
|
|
115
115
|
\`\`\`bash
|
|
116
|
-
npx backdot
|
|
116
|
+
npx backdot restore ${repository}
|
|
117
117
|
\`\`\`
|
|
118
118
|
|
|
119
119
|
For full documentation, configuration options, and scheduling, see the [official README](https://github.com/sorenlouv/backdot).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "backdot",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Lightweight CLI to backup dotfiles and gitignored files to a Git repo on a daily schedule",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@inquirer/prompts": "^8.3.0",
|
|
44
|
+
"cac": "^7.0.0",
|
|
44
45
|
"chalk": "^5.6.2",
|
|
45
46
|
"fast-glob": "^3.3.3",
|
|
46
47
|
"ora": "^9.3.0",
|