amont 1.5.0 → 1.6.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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/bin/amont.js +47 -39
  3. package/package.json +7 -7
package/README.md CHANGED
@@ -18,7 +18,7 @@ write, no runtime to install, nothing to configure before it is useful.
18
18
  — a gate pre-commit, lefthook and husky do not have.
19
19
  - **Nothing on the commit path but `std`.** The hook binary links no external
20
20
  crates, and CI fails any build that changes that.
21
- - **Leaving is one command.** `amont uninstall` removes exactly the four
21
+ - **Leaving is one command.** `amont uninstall` removes exactly the five
22
22
  shims install wrote; a hook you or another tool put there is named and left
23
23
  alone.
24
24
 
@@ -99,7 +99,7 @@ amont uninstall --binary # …and remove ~/.local/bin/amont too
99
99
 
100
100
  Uninstall is listed second on purpose. These hooks can block a commit, so the
101
101
  honest question to answer first is how you get out — and the answer is that
102
- `uninstall` removes our four shims and **nothing else**. A hook you wrote
102
+ `uninstall` removes our five shims and **nothing else**. A hook you wrote
103
103
  yourself is left where it is and named in the output, whatever it is; a hook it
104
104
  cannot even read is named too rather than passed over in silence. Your
105
105
  `hook.skip` and `amont.severity` settings are never touched, because those
@@ -108,7 +108,7 @@ are your statements about your repository.
108
108
  This is also why the README does not tell you to run
109
109
  `rm $(git rev-parse --git-dir)/hooks/*`. That glob deletes every hook in the
110
110
  directory — including ones other tools installed and ones you wrote — to remove
111
- four files that belong to us.
111
+ five files that belong to us.
112
112
 
113
113
  To bypass a single run rather than uninstall: `git commit --no-verify`.
114
114
  To turn off one check permanently, see [Turning a check off, or down](#turning-a-check-off-or-down).
@@ -136,7 +136,7 @@ pre-push
136
136
  ● runs here ○ inert ⊘ skipped via hook.skip ✗ declaration unusable
137
137
  ```
138
138
 
139
- Twenty-one built-in checks across four git hooks, plus any your repository declares
139
+ Twenty-one built-in checks across five git hooks, plus any your repository declares
140
140
  itself. The full list, with what each one needs before it fires, is in
141
141
  [the checks reference](docs/checks.md).
142
142
 
@@ -240,7 +240,7 @@ writing cannot go on silently disabling things. More in
240
240
 
241
241
  ## Making the commit convention yours
242
242
 
243
- `commit-msg` is the one hook `hook.skip` and `--no-verify` cannot reach, so its
243
+ `commit-msg` is the one hook `hook.skip` and `amont.severity` cannot reach, so its
244
244
  opinions are adjustable in themselves:
245
245
 
246
246
  ```sh
package/bin/amont.js CHANGED
@@ -34,49 +34,57 @@ function candidates() {
34
34
  // pnpm does not hoist — the real package sits under `node_modules/.pnpm/` — so a
35
35
  // path assembled from `__dirname` is correct under npm and wrong under pnpm and
36
36
  // yarn. Node's own resolver knows where the dependency actually is.
37
- function resolveBinary() {
37
+ function binaryOf(pkg) {
38
38
  const exe = process.platform === "win32" ? "amont.exe" : "amont";
39
- for (const pkg of candidates()) {
40
- try {
41
- const p = require.resolve(`${pkg}/bin/${exe}`);
42
- if (existsSync(p)) return p;
43
- } catch {
44
- // Not installed: either the wrong libc for this host, or an
45
- // `--ignore-scripts`-style install that skipped optional deps. Try the
46
- // next candidate before giving up.
47
- }
39
+ try {
40
+ const p = require.resolve(`${pkg}/bin/${exe}`);
41
+ if (existsSync(p)) return p;
42
+ } catch {
43
+ // Not installed: either the wrong libc for this host, or an
44
+ // `--ignore-scripts`-style install that skipped optional deps.
48
45
  }
49
46
  return null;
50
47
  }
51
48
 
52
- const binary = resolveBinary();
53
- if (!binary) {
54
- // Name the platform. "amont binary not found" sends people to reinstall;
55
- // "no build for linux/ppc64" tells them the actual answer, which is that they
56
- // want `cargo install amont` or the shell installer.
57
- const target = `${process.platform}/${process.arch}`;
58
- process.stderr.write(
59
- `amont: no native binary for ${target}.\n` +
60
- ` npm installs one of: ${Object.values(PACKAGES).flat().join(", ")}\n` +
61
- ` If your platform is not among them, build from source:\n` +
62
- ` cargo install amont\n` +
63
- ` If it is, the optional dependency did not install — try:\n` +
64
- ` npm install --force amont\n`,
65
- );
66
- process.exit(1);
49
+ // Existence is not runnability, so the loop is over SPAWNS, not paths. With a
50
+ // package manager that ignores the `libc` field — yarn classic does, and
51
+ // `npm install --force` is this file's own suggested remedy BOTH linux-x64
52
+ // builds get installed, gnu listed first, and on a musl host the gnu binary
53
+ // fails at exec on the missing glibc loader while the right one sits a
54
+ // candidate later. Only a spawn-level failure (`result.error`) falls through:
55
+ // a binary that ran and exited non-zero has ANSWERED, and its exit code is the
56
+ // whole product of a hook runner.
57
+ const failures = [];
58
+ for (const pkg of candidates()) {
59
+ const binary = binaryOf(pkg);
60
+ if (!binary) continue;
61
+ // `spawnSync` with inherited stdio rather than `execFileSync`: this forwards
62
+ // the child's exit CODE. It also keeps the child's stdin, which `amont run`
63
+ // reads.
64
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
65
+ if (result.error) {
66
+ failures.push(` ${binary}: ${result.error.message}`);
67
+ continue;
68
+ }
69
+ // A signalled child has a null status. Report it the way a shell does, so
70
+ // "killed by SIGINT" does not read as a clean exit 0.
71
+ if (result.status === null && result.signal) {
72
+ process.exit(128 + (require("node:os").constants.signals[result.signal] ?? 0));
73
+ }
74
+ process.exit(result.status ?? 1);
67
75
  }
68
76
 
69
- // `spawnSync` with inherited stdio rather than `execFileSync`: this forwards the
70
- // child's exit CODE, and a hook runner's exit code is the whole product. It also
71
- // keeps the child's stdin, which `amont run` reads.
72
- const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
73
- if (result.error) {
74
- process.stderr.write(`amont: could not run ${binary}: ${result.error.message}\n`);
75
- process.exit(1);
76
- }
77
- // A signalled child has a null status. Report it the way a shell does, so
78
- // "killed by SIGINT" does not read as a clean exit 0.
79
- if (result.status === null && result.signal) {
80
- process.exit(128 + (require("node:os").constants.signals[result.signal] ?? 0));
81
- }
82
- process.exit(result.status ?? 1);
77
+ // Name the platform. "amont binary not found" sends people to reinstall;
78
+ // "no build for linux/ppc64" tells them the actual answer, which is that they
79
+ // want `cargo install amont` or the shell installer.
80
+ const target = `${process.platform}/${process.arch}`;
81
+ process.stderr.write(
82
+ `amont: no runnable native binary for ${target}.\n` +
83
+ (failures.length ? ` Installed but could not run:\n${failures.join("\n")}\n` : "") +
84
+ ` npm installs one of: ${Object.values(PACKAGES).flat().join(", ")}\n` +
85
+ ` If your platform is not among them, build from source:\n` +
86
+ ` cargo install amont\n` +
87
+ ` If it is, the optional dependency did not install — try:\n` +
88
+ ` npm install --force amont\n`,
89
+ );
90
+ process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amont",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Opinionated git hooks that judge what you are committing, not what is on disk",
5
5
  "keywords": [
6
6
  "git",
@@ -31,11 +31,11 @@
31
31
  "node": ">=18"
32
32
  },
33
33
  "optionalDependencies": {
34
- "amont-darwin-arm64": "1.5.0",
35
- "amont-darwin-x64": "1.5.0",
36
- "amont-linux-arm64-gnu": "1.5.0",
37
- "amont-linux-x64-gnu": "1.5.0",
38
- "amont-linux-x64-musl": "1.5.0",
39
- "amont-win32-x64": "1.5.0"
34
+ "amont-darwin-arm64": "1.6.0",
35
+ "amont-darwin-x64": "1.6.0",
36
+ "amont-linux-arm64-gnu": "1.6.0",
37
+ "amont-linux-x64-gnu": "1.6.0",
38
+ "amont-linux-x64-musl": "1.6.0",
39
+ "amont-win32-x64": "1.6.0"
40
40
  }
41
41
  }