gnhf 0.1.19 → 0.1.20

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 (2) hide show
  1. package/dist/cli.mjs +66 -32
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -6,7 +6,7 @@ import process$1 from "node:process";
6
6
  import { createInterface } from "node:readline";
7
7
  import { Command, InvalidArgumentError } from "commander";
8
8
  import yaml from "js-yaml";
9
- import { execFileSync, execSync, spawn } from "node:child_process";
9
+ import { execFileSync, spawn } from "node:child_process";
10
10
  import { createServer } from "node:net";
11
11
  import { EventEmitter } from "node:events";
12
12
  import { createHash } from "node:crypto";
@@ -302,32 +302,24 @@ const NOT_GIT_REPOSITORY_MESSAGE = "This command must be run inside a Git reposi
302
302
  function translateGitError(error) {
303
303
  return error instanceof Error ? error : new Error(String(error));
304
304
  }
305
- function git(args, cwd) {
305
+ function git(args, cwd, options = {}) {
306
306
  try {
307
- return execSync(`git ${args}`, {
307
+ return execFileSync("git", args, {
308
308
  cwd,
309
309
  encoding: "utf-8",
310
- stdio: "pipe"
310
+ stdio: "pipe",
311
+ ...options.env ? { env: options.env } : {}
311
312
  }).trim();
312
313
  } catch (error) {
313
314
  throw translateGitError(error);
314
315
  }
315
316
  }
316
- /** Wrap a value in single quotes, escaping embedded single quotes for POSIX shells. */
317
- function shellEscape(value) {
318
- return `'${value.replace(/'/g, "'\\''")}'`;
319
- }
320
317
  function isGitRepository(cwd) {
321
318
  try {
322
- execSync("git rev-parse --git-dir", {
323
- cwd,
324
- encoding: "utf-8",
325
- stdio: "pipe",
326
- env: {
327
- ...process.env,
328
- LC_ALL: "C"
329
- }
330
- });
319
+ git(["rev-parse", "--git-dir"], cwd, { env: {
320
+ ...process.env,
321
+ LC_ALL: "C"
322
+ } });
331
323
  return true;
332
324
  } catch {
333
325
  return false;
@@ -339,23 +331,41 @@ function ensureGitRepository(cwd) {
339
331
  function getCurrentBranch(cwd) {
340
332
  ensureGitRepository(cwd);
341
333
  try {
342
- return git("symbolic-ref --short HEAD", cwd);
334
+ return git([
335
+ "symbolic-ref",
336
+ "--short",
337
+ "HEAD"
338
+ ], cwd);
343
339
  } catch {
344
- return git("rev-parse --abbrev-ref HEAD", cwd);
340
+ return git([
341
+ "rev-parse",
342
+ "--abbrev-ref",
343
+ "HEAD"
344
+ ], cwd);
345
345
  }
346
346
  }
347
347
  function ensureCleanWorkingTree(cwd) {
348
- if (git("status --porcelain", cwd)) throw new Error("Working tree is not clean. Commit or stash changes first.");
348
+ if (git(["status", "--porcelain"], cwd)) throw new Error("Working tree is not clean. Commit or stash changes first.");
349
349
  }
350
350
  function createBranch(branchName, cwd) {
351
- git(`checkout -b ${branchName}`, cwd);
351
+ git([
352
+ "checkout",
353
+ "-b",
354
+ branchName
355
+ ], cwd);
352
356
  }
353
357
  function getHeadCommit(cwd) {
354
- return git("rev-parse HEAD", cwd);
358
+ return git(["rev-parse", "HEAD"], cwd);
355
359
  }
356
360
  function findLegacyRunBaseCommit(runId, cwd) {
357
361
  try {
358
- const marker = git("log --first-parent --reverse --format=%H%x09%s HEAD", cwd).split("\n").map((line) => {
362
+ const marker = git([
363
+ "log",
364
+ "--first-parent",
365
+ "--reverse",
366
+ "--format=%H%x09%s",
367
+ "HEAD"
368
+ ], cwd).split("\n").map((line) => {
359
369
  const [sha, ...subjectParts] = line.split(" ");
360
370
  return {
361
371
  sha,
@@ -363,33 +373,57 @@ function findLegacyRunBaseCommit(runId, cwd) {
363
373
  };
364
374
  }).find(({ subject }) => subject === `gnhf: initialize run ${runId}` || subject === `gnhf: overwrite run ${runId}`);
365
375
  if (!marker?.sha) return null;
366
- return git(`rev-parse ${marker.sha}^`, cwd);
376
+ return git(["rev-parse", `${marker.sha}^`], cwd);
367
377
  } catch {
368
378
  return null;
369
379
  }
370
380
  }
371
381
  function getBranchCommitCount(baseCommit, cwd) {
372
382
  if (!baseCommit) return 0;
373
- return Number.parseInt(git(`rev-list --count --first-parent ${baseCommit}..HEAD`, cwd), 10);
383
+ return Number.parseInt(git([
384
+ "rev-list",
385
+ "--count",
386
+ "--first-parent",
387
+ `${baseCommit}..HEAD`
388
+ ], cwd), 10);
374
389
  }
375
390
  function commitAll(message, cwd) {
376
- git("add -A", cwd);
391
+ git(["add", "-A"], cwd);
377
392
  try {
378
- git(`commit -m "${message.replace(/"/g, "\\\"")}"`, cwd);
393
+ git([
394
+ "commit",
395
+ "-m",
396
+ message
397
+ ], cwd);
379
398
  } catch {}
380
399
  }
381
400
  function resetHard(cwd) {
382
- git("reset --hard HEAD", cwd);
383
- git("clean -fd", cwd);
401
+ git([
402
+ "reset",
403
+ "--hard",
404
+ "HEAD"
405
+ ], cwd);
406
+ git(["clean", "-fd"], cwd);
384
407
  }
385
408
  function getRepoRootDir(cwd) {
386
- return git("rev-parse --show-toplevel", cwd);
409
+ return git(["rev-parse", "--show-toplevel"], cwd);
387
410
  }
388
411
  function createWorktree(baseCwd, worktreePath, branchName) {
389
- git(`worktree add -b ${shellEscape(branchName)} ${shellEscape(worktreePath)}`, baseCwd);
412
+ git([
413
+ "worktree",
414
+ "add",
415
+ "-b",
416
+ branchName,
417
+ worktreePath
418
+ ], baseCwd);
390
419
  }
391
420
  function removeWorktree(baseCwd, worktreePath) {
392
- git(`worktree remove --force ${shellEscape(worktreePath)}`, baseCwd);
421
+ git([
422
+ "worktree",
423
+ "remove",
424
+ "--force",
425
+ worktreePath
426
+ ], baseCwd);
393
427
  }
394
428
  //#endregion
395
429
  //#region src/core/agents/types.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnhf",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Before I go to bed, I tell my agents: good night, have fun",
5
5
  "type": "module",
6
6
  "bin": {