@solaqua/gji 0.12.3 → 0.12.4

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.
@@ -18883,11 +18883,12 @@ import { execFile as execFile5 } from "node:child_process";
18883
18883
  import { constants as constants5 } from "node:fs";
18884
18884
  import { lstat as lstat3, open as open3, readdir, realpath as realpath2 } from "node:fs/promises";
18885
18885
  import { basename as basename6, dirname as dirname8, isAbsolute as isAbsolute3, join as join11, resolve as resolve8, sep as sep2 } from "node:path";
18886
- import { promisify as promisify6 } from "node:util";
18886
+ import { promisify as promisify6, TextDecoder } from "node:util";
18887
18887
  var execFileAsync5 = promisify6(execFile5);
18888
18888
  var UV_VALIDATION_MAX_ENTRIES = 1e4;
18889
18889
  var UV_VALIDATION_MAX_FILE_BYTES = 1024 * 1024;
18890
18890
  var UV_VALIDATION_MAX_TOTAL_BYTES = 16 * 1024 * 1024;
18891
+ var UV_VALIDATION_TEXT_PROBE_BYTES = 4 * 1024;
18891
18892
  function virtualEnvironmentPrefixes(text) {
18892
18893
  const prefixes = [];
18893
18894
  for (const line of text.split(/\r?\n/u)) {
@@ -19052,6 +19053,14 @@ async function readBoundedUvTextFile(path9, remainingBytes) {
19052
19053
  try {
19053
19054
  const stats = await handle.stat();
19054
19055
  if (!stats.isFile()) return void 0;
19056
+ const probeBytes = Math.min(UV_VALIDATION_TEXT_PROBE_BYTES, stats.size);
19057
+ if (probeBytes > remainingBytes) {
19058
+ throw new Error("uv launchers exceed the total validation size limit");
19059
+ }
19060
+ const probe = await readFilePrefix(handle, probeBytes);
19061
+ if (!looksLikeUtf8Text(probe, probe.byteLength === stats.size)) {
19062
+ return { bytes: probe.byteLength };
19063
+ }
19055
19064
  if (stats.size > UV_VALIDATION_MAX_FILE_BYTES) {
19056
19065
  throw new Error(`uv launcher exceeds the validation size limit: ${path9}`);
19057
19066
  }
@@ -19067,11 +19076,22 @@ async function readBoundedUvTextFile(path9, remainingBytes) {
19067
19076
  throw new Error("uv launchers exceed the total validation size limit");
19068
19077
  }
19069
19078
  const text = contents.toString("utf8");
19070
- return Buffer.from(text, "utf8").equals(contents) ? { bytes: contents.byteLength, text } : { bytes: contents.byteLength };
19079
+ return looksLikeUtf8Text(contents, true) ? { bytes: contents.byteLength, text } : { bytes: contents.byteLength };
19071
19080
  } finally {
19072
19081
  await handle.close();
19073
19082
  }
19074
19083
  }
19084
+ function looksLikeUtf8Text(contents, complete) {
19085
+ if (contents.includes(0)) return false;
19086
+ try {
19087
+ new TextDecoder("utf-8", { fatal: true }).decode(contents, {
19088
+ stream: !complete
19089
+ });
19090
+ return true;
19091
+ } catch {
19092
+ return false;
19093
+ }
19094
+ }
19075
19095
  async function readFilePrefix(handle, maxBytes) {
19076
19096
  const contents = Buffer.allocUnsafe(maxBytes);
19077
19097
  let offset = 0;
@@ -2,12 +2,13 @@ import { execFile } from "node:child_process";
2
2
  import { constants } from "node:fs";
3
3
  import { lstat, open, readdir, realpath } from "node:fs/promises";
4
4
  import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
5
- import { promisify } from "node:util";
5
+ import { promisify, TextDecoder } from "node:util";
6
6
  import { isNotFoundError } from "./fs-utils.js";
7
7
  const execFileAsync = promisify(execFile);
8
8
  const UV_VALIDATION_MAX_ENTRIES = 10_000;
9
9
  const UV_VALIDATION_MAX_FILE_BYTES = 1024 * 1024;
10
10
  const UV_VALIDATION_MAX_TOTAL_BYTES = 16 * 1024 * 1024;
11
+ const UV_VALIDATION_TEXT_PROBE_BYTES = 4 * 1024;
11
12
  function virtualEnvironmentPrefixes(text) {
12
13
  const prefixes = [];
13
14
  for (const line of text.split(/\r?\n/u)) {
@@ -168,6 +169,14 @@ async function readBoundedUvTextFile(path, remainingBytes) {
168
169
  const stats = await handle.stat();
169
170
  if (!stats.isFile())
170
171
  return undefined;
172
+ const probeBytes = Math.min(UV_VALIDATION_TEXT_PROBE_BYTES, stats.size);
173
+ if (probeBytes > remainingBytes) {
174
+ throw new Error("uv launchers exceed the total validation size limit");
175
+ }
176
+ const probe = await readFilePrefix(handle, probeBytes);
177
+ if (!looksLikeUtf8Text(probe, probe.byteLength === stats.size)) {
178
+ return { bytes: probe.byteLength };
179
+ }
171
180
  if (stats.size > UV_VALIDATION_MAX_FILE_BYTES) {
172
181
  throw new Error(`uv launcher exceeds the validation size limit: ${path}`);
173
182
  }
@@ -183,7 +192,7 @@ async function readBoundedUvTextFile(path, remainingBytes) {
183
192
  throw new Error("uv launchers exceed the total validation size limit");
184
193
  }
185
194
  const text = contents.toString("utf8");
186
- return Buffer.from(text, "utf8").equals(contents)
195
+ return looksLikeUtf8Text(contents, true)
187
196
  ? { bytes: contents.byteLength, text }
188
197
  : { bytes: contents.byteLength };
189
198
  }
@@ -191,6 +200,19 @@ async function readBoundedUvTextFile(path, remainingBytes) {
191
200
  await handle.close();
192
201
  }
193
202
  }
203
+ function looksLikeUtf8Text(contents, complete) {
204
+ if (contents.includes(0))
205
+ return false;
206
+ try {
207
+ new TextDecoder("utf-8", { fatal: true }).decode(contents, {
208
+ stream: !complete,
209
+ });
210
+ return true;
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ }
194
216
  async function readFilePrefix(handle, maxBytes) {
195
217
  const contents = Buffer.allocUnsafe(maxBytes);
196
218
  let offset = 0;
@@ -1,4 +1,4 @@
1
- .TH GJI\-BACK 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-BACK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-back \- navigate to the previously visited worktree, optionally N steps back
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CLEAN 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-CLEAN 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-clean \- interactively prune linked worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-COMPLETION 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-COMPLETION 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-completion \- print shell completion definitions
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-CONFIG 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-CONFIG 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-config \- manage global config defaults
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DOCTOR 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-DOCTOR 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-doctor \- check gji installation and configuration health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-DONE 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-DONE 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-done \- finish the current linked worktree and return safely
4
4
  .SH SYNOPSIS
package/man/man1/gji-go.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-GO 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-GO 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-go \- resolve and jump to a worktree path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-HISTORY 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-HISTORY 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-history \- show navigation history
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-INIT 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-INIT 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-init \- set up shell integration interactively or print a shell wrapper
4
4
  .SH SYNOPSIS
package/man/man1/gji-ls.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-LS 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-LS 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-ls \- list active worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-NEW 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-NEW 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-new \- create a new branch or detached linked worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-OPEN 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-OPEN 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-open \- open the worktree in an editor
4
4
  .SH SYNOPSIS
package/man/man1/gji-pr.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI\-PR 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-PR 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-pr \- fetch a pull request by number, #number, or URL into a linked worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-REMOVE 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-REMOVE 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-remove \- deprecated: use gji done for one worktree or gji clean for bulk cleanup
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-ROOT 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-ROOT 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-root \- print the main repository root path
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-RUN\-HOOK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-run\-hook \- run a named hook (after\-create, after\-enter, before\-remove) in the current worktree
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-STATUS 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-STATUS 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-status \- summarize repository and worktree health
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-SYNC\-FILES 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync\-files \- manage local files copied into new worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-SYNC 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-SYNC 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-sync \- fetch and update one or all worktrees
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-TASK 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-TASK 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-task \- show or update the current worktree task
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-UNDO 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-UNDO 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-undo \- restore the most recent destructive worktree operation
4
4
  .SH SYNOPSIS
@@ -1,4 +1,4 @@
1
- .TH GJI\-WARP 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI\-WARP 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji\-warp \- deprecated: use gji go (press Tab for all known repos)
4
4
  .SH SYNOPSIS
package/man/man1/gji.1 CHANGED
@@ -1,4 +1,4 @@
1
- .TH GJI 1 "August 2026" "gji 0.12.3" "User Commands"
1
+ .TH GJI 1 "August 2026" "gji 0.12.4" "User Commands"
2
2
  .SH NAME
3
3
  gji \- Context switching without the mess.
4
4
  .SH SYNOPSIS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solaqua/gji",
3
- "version": "0.12.3",
3
+ "version": "0.12.4",
4
4
  "description": "Git worktree CLI for fast context switching.",
5
5
  "license": "MIT",
6
6
  "author": "sjquant",