filesnap 0.3.0 → 0.3.1-darwin-arm64
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/package.json +10 -32
- package/vendor/aarch64-apple-darwin/bin/filesnap +0 -0
- package/README.md +0 -47
- package/bin/filesnap.js +0 -135
package/package.json
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "filesnap",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Git-free file snapshots and rewind — put a directory back the way it was, without a repository and without touching your version control.",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"bin/",
|
|
11
|
-
"README.md"
|
|
3
|
+
"version": "0.3.1-darwin-arm64",
|
|
4
|
+
"description": "Git-free file snapshots and rewind — put a directory back the way it was, without a repository and without touching your version control. (darwin-arm64 binary)",
|
|
5
|
+
"os": [
|
|
6
|
+
"darwin"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"arm64"
|
|
12
10
|
],
|
|
13
11
|
"license": "Apache-2.0",
|
|
14
12
|
"repository": {
|
|
@@ -16,27 +14,7 @@
|
|
|
16
14
|
"url": "git+https://github.com/extracurricular-ai/filesnap.git"
|
|
17
15
|
},
|
|
18
16
|
"homepage": "https://github.com/extracurricular-ai/filesnap",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
"keywords": [
|
|
23
|
-
"snapshot",
|
|
24
|
-
"rewind",
|
|
25
|
-
"undo",
|
|
26
|
-
"checkpoint",
|
|
27
|
-
"restore",
|
|
28
|
-
"filesystem",
|
|
29
|
-
"cli"
|
|
30
|
-
],
|
|
31
|
-
"engines": {
|
|
32
|
-
"node": ">=18"
|
|
33
|
-
},
|
|
34
|
-
"optionalDependencies": {
|
|
35
|
-
"filesnap-linux-x64": "npm:filesnap@0.3.0-linux-x64",
|
|
36
|
-
"filesnap-linux-arm64": "npm:filesnap@0.3.0-linux-arm64",
|
|
37
|
-
"filesnap-darwin-x64": "npm:filesnap@0.3.0-darwin-x64",
|
|
38
|
-
"filesnap-darwin-arm64": "npm:filesnap@0.3.0-darwin-arm64",
|
|
39
|
-
"filesnap-win32-x64": "npm:filesnap@0.3.0-win32-x64",
|
|
40
|
-
"filesnap-win32-arm64": "npm:filesnap@0.3.0-win32-arm64"
|
|
41
|
-
}
|
|
17
|
+
"files": [
|
|
18
|
+
"vendor/"
|
|
19
|
+
]
|
|
42
20
|
}
|
|
Binary file
|
package/README.md
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# filesnap
|
|
2
|
-
|
|
3
|
-
Git-free file snapshots and rewind: capture what a directory holds at a moment
|
|
4
|
-
you name, and put it back later — without a repository, and without touching
|
|
5
|
-
your version control.
|
|
6
|
-
|
|
7
|
-
```console
|
|
8
|
-
npm install -g filesnap
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
This package is a thin launcher. The binary for your platform arrives as an
|
|
12
|
-
optional dependency, so the install downloads one build rather than six.
|
|
13
|
-
|
|
14
|
-
```console
|
|
15
|
-
$ filesnap capture --session s1 --turn t1
|
|
16
|
-
{"v":1,"type":"capture.done","manifest":"a5a2b149…","reused":0,"hashed":1,"dropped":0}
|
|
17
|
-
|
|
18
|
-
$ echo "something regrettable" > a.txt
|
|
19
|
-
|
|
20
|
-
$ filesnap restore --session s1 --turn t1
|
|
21
|
-
{"v":1,"type":"restore.done","written":1,"deleted":0,"failed":0,"safety":"e41358f0…"}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
That `safety` id is the point the rewind itself can be rewound to. Every
|
|
25
|
-
restore captures one before it writes anything.
|
|
26
|
-
|
|
27
|
-
**Output is JSON Lines on stdout, prose on stderr**, and the exit code is part
|
|
28
|
-
of the contract: `0` everything happened, `1` it ran and reported but not
|
|
29
|
-
everything happened, `2` it did not run, `3` the arguments were wrong.
|
|
30
|
-
|
|
31
|
-
Nine commands — `capture`, `declare`, `log`, `restore`, `undo`, `delete`,
|
|
32
|
-
`gc`, `status`, `doctor`. The full surface, the event contract, and what it
|
|
33
|
-
deliberately refuses to do are in the
|
|
34
|
-
[documentation](https://github.com/extracurricular-ai/filesnap#readme).
|
|
35
|
-
|
|
36
|
-
## Platforms
|
|
37
|
-
|
|
38
|
-
Linux, macOS and Windows, on x64 and arm64. The Linux builds are statically
|
|
39
|
-
linked against musl, so they do not carry a glibc floor from the machine that
|
|
40
|
-
built them.
|
|
41
|
-
|
|
42
|
-
Not on this list? `cargo install filesnap-cli` builds the same command from
|
|
43
|
-
source.
|
|
44
|
-
|
|
45
|
-
## Licence
|
|
46
|
-
|
|
47
|
-
Apache-2.0.
|
package/bin/filesnap.js
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// The `filesnap` command, as npm installs it.
|
|
3
|
-
//
|
|
4
|
-
// This file exists to find one binary and get out of the way. The six
|
|
5
|
-
// platform builds are published as six *versions of this same npm name*
|
|
6
|
-
// (D37), named from here through alias specs in `optionalDependencies`, and
|
|
7
|
-
// `os`/`cpu` on each of them is what makes npm unpack exactly one.
|
|
8
|
-
//
|
|
9
|
-
// Everything below is either locating that binary or forwarding a signal to
|
|
10
|
-
// it. Nothing here parses arguments or interprets output: the contract is the
|
|
11
|
-
// binary's (JSON Lines on stdout, prose on stderr, exit codes 0/1/2/3), and a
|
|
12
|
-
// launcher that inspected either would be a second place for it to drift.
|
|
13
|
-
|
|
14
|
-
import { spawn } from "node:child_process";
|
|
15
|
-
import { existsSync } from "node:fs";
|
|
16
|
-
import { createRequire } from "node:module";
|
|
17
|
-
import path from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
|
|
20
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
-
const require = createRequire(import.meta.url);
|
|
22
|
-
|
|
23
|
-
// Linux is musl deliberately. A glibc build carries a symbol-version floor set
|
|
24
|
-
// by whatever machine produced it, which would break older distributions and
|
|
25
|
-
// containers — the one failure an npm-installed binary cannot help its user
|
|
26
|
-
// debug. filesnap has no C dependency, so the static build costs nothing; it
|
|
27
|
-
// is marginally *smaller* than the glibc one.
|
|
28
|
-
const TRIPLE_BY_PLATFORM = {
|
|
29
|
-
"linux-x64": "x86_64-unknown-linux-musl",
|
|
30
|
-
"linux-arm64": "aarch64-unknown-linux-musl",
|
|
31
|
-
"darwin-x64": "x86_64-apple-darwin",
|
|
32
|
-
"darwin-arm64": "aarch64-apple-darwin",
|
|
33
|
-
"win32-x64": "x86_64-pc-windows-msvc",
|
|
34
|
-
"win32-arm64": "aarch64-pc-windows-msvc",
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Exit the way the binary would have.
|
|
39
|
-
*
|
|
40
|
-
* `2` is the CLI's own "it did not run, or could not report" (D40). A launcher
|
|
41
|
-
* that cannot find its binary is exactly that, seen one level up — so a caller
|
|
42
|
-
* checking exit codes does not need to know whether it was the wrapper or the
|
|
43
|
-
* program that failed. `throw` would print a stack trace, which tells a user
|
|
44
|
-
* nothing they can act on.
|
|
45
|
-
*/
|
|
46
|
-
function fail(message) {
|
|
47
|
-
process.stderr.write(`filesnap: ${message}\n`);
|
|
48
|
-
process.exit(2);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** How this user would reinstall, so the error names their own tool. */
|
|
52
|
-
function installCommand() {
|
|
53
|
-
const agent = process.env.npm_config_user_agent || "";
|
|
54
|
-
if (agent.startsWith("pnpm")) return "pnpm add -g filesnap";
|
|
55
|
-
if (agent.startsWith("yarn")) return "yarn global add filesnap";
|
|
56
|
-
if (/\bbun\//.test(agent)) return "bun install -g filesnap";
|
|
57
|
-
return "npm install -g filesnap";
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Android runs the Linux builds.
|
|
61
|
-
const platform = process.platform === "android" ? "linux" : process.platform;
|
|
62
|
-
const slug = `${platform}-${process.arch}`;
|
|
63
|
-
const triple = TRIPLE_BY_PLATFORM[slug];
|
|
64
|
-
if (!triple) {
|
|
65
|
-
fail(
|
|
66
|
-
`there is no build for ${process.platform} ${process.arch}. ` +
|
|
67
|
-
`Install from source instead: cargo install filesnap-cli`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const platformPackage = `filesnap-${slug}`;
|
|
72
|
-
|
|
73
|
-
function locateBinary() {
|
|
74
|
-
let vendorRoot;
|
|
75
|
-
try {
|
|
76
|
-
// Ask the resolver rather than guessing at a path: pnpm, Yarn PnP and
|
|
77
|
-
// hoisting all put the platform package somewhere different, and every
|
|
78
|
-
// one of them can answer this.
|
|
79
|
-
const manifest = require.resolve(`${platformPackage}/package.json`);
|
|
80
|
-
vendorRoot = path.join(path.dirname(manifest), "vendor");
|
|
81
|
-
} catch {
|
|
82
|
-
// No resolver answer: a tarball someone unpacked by hand, or a bundler
|
|
83
|
-
// that flattened node_modules. Fall back to this package's own tree.
|
|
84
|
-
vendorRoot = path.join(here, "..", "vendor");
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const binary = path.join(
|
|
88
|
-
vendorRoot,
|
|
89
|
-
triple,
|
|
90
|
-
"bin",
|
|
91
|
-
platform === "win32" ? "filesnap.exe" : "filesnap",
|
|
92
|
-
);
|
|
93
|
-
return existsSync(binary) ? binary : null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const binary = locateBinary();
|
|
97
|
-
if (!binary) {
|
|
98
|
-
fail(
|
|
99
|
-
`the ${platformPackage} package is missing or has no binary. ` +
|
|
100
|
-
`Reinstall with \`${installCommand()}\`.`,
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// `spawn`, not `spawnSync`: a synchronous spawn makes Node deaf to signals for
|
|
105
|
-
// the whole run, so a Ctrl-C during a capture over a large project would be
|
|
106
|
-
// swallowed and the user would watch it keep going.
|
|
107
|
-
const child = spawn(binary, process.argv.slice(2), { stdio: "inherit" });
|
|
108
|
-
|
|
109
|
-
const FORWARDED = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
110
|
-
const handlers = new Map();
|
|
111
|
-
for (const signal of FORWARDED) {
|
|
112
|
-
const handler = () => {
|
|
113
|
-
if (child.exitCode === null && !child.killed) child.kill(signal);
|
|
114
|
-
};
|
|
115
|
-
try {
|
|
116
|
-
process.on(signal, handler);
|
|
117
|
-
handlers.set(signal, handler);
|
|
118
|
-
} catch {
|
|
119
|
-
// Windows does not raise every one of these. Not being able to forward a
|
|
120
|
-
// signal that cannot arrive is not a problem worth reporting.
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
child.on("error", (err) => fail(`could not run ${binary}: ${err.message}`));
|
|
125
|
-
|
|
126
|
-
child.on("exit", (code, signal) => {
|
|
127
|
-
for (const [name, handler] of handlers) process.off(name, handler);
|
|
128
|
-
if (signal) {
|
|
129
|
-
// Die of the same signal rather than translating it to a number, so a
|
|
130
|
-
// shell reports "terminated" and a supervising process sees what happened.
|
|
131
|
-
process.kill(process.pid, signal);
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
process.exit(code ?? 2);
|
|
135
|
-
});
|