genesis-compiler 1.5.0 → 1.5.2

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/package.json +1 -1
  2. package/src/index/git.js +32 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genesis-compiler",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "type": "module",
5
5
  "description": "An agent-independent prompt, multi-language code-index, cleanup, and verification companion with project agent guidance.",
6
6
  "repository": {
package/src/index/git.js CHANGED
@@ -2,30 +2,52 @@ import { realpath } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { fail } from './errors.js';
5
- import { runGitText } from './process.js';
5
+ import { runGit } from './process.js';
6
6
 
7
7
  /** Resolve the caller's working directory and the one Git repository that contains it. */
8
8
  export async function gitContext(projectRoot = process.cwd()) {
9
9
  let root;
10
10
  try { root = await realpath(path.resolve(projectRoot)); } catch (error) {
11
- fail('GIT_REPOSITORY_REQUIRED', `Project root does not exist: ${projectRoot}.`, {
12
- cause: error.code || error.message,
11
+ fail('GIT_PROJECT_ROOT_UNAVAILABLE', `Cannot resolve project root: ${projectRoot}. ${error.message}`, {
12
+ stage: 'resolve-project-root',
13
+ projectRoot,
14
+ cause: error.code,
13
15
  });
14
16
  }
15
- let repositoryRoot;
17
+ let discovery;
16
18
  try {
17
- repositoryRoot = await realpath(path.resolve(await runGitText(root, ['rev-parse', '--show-toplevel'])));
19
+ discovery = await runGit(root, ['rev-parse', '--show-toplevel'], { env: { LC_ALL: 'C' } });
18
20
  } catch (error) {
21
+ const details = { ...error.details, stage: 'discover-worktree', projectRoot: root };
19
22
  if (/detected dubious ownership/iu.test(error?.details?.stderr || '')) {
20
- fail('GIT_REPOSITORY_UNTRUSTED', `Git rejected ownership of the project worktree: ${projectRoot}. The caller must explicitly trust this shared repository.`, {
21
- cause: error.code,
22
- });
23
+ fail('GIT_REPOSITORY_UNTRUSTED', `Git rejected ownership of the project worktree: ${projectRoot}. The caller must explicitly trust this shared repository.`, details);
24
+ }
25
+ if (error?.details?.status === 128 && /^fatal: (?:not a git repository|this operation must be run in a work tree)/mu.test(error.details.stderr || '')) {
26
+ fail('GIT_REPOSITORY_REQUIRED', `Project root is not inside a Git worktree: ${projectRoot}.`, details);
23
27
  }
24
- fail('GIT_REPOSITORY_REQUIRED', `Project root is not inside a Git worktree: ${projectRoot}.`);
28
+ error.details = details;
29
+ throw error;
30
+ }
31
+ // Git terminates this path with one newline; whitespace can belong to the path.
32
+ const reportedRoot = discovery.stdout.toString('utf8').replace(/\n$/u, '');
33
+ if (!path.isAbsolute(reportedRoot)) {
34
+ fail('GIT_WORKTREE_PATH_INVALID', 'Git returned an empty or non-absolute worktree path.', {
35
+ stage: 'resolve-worktree', projectRoot: root, reportedRoot,
36
+ });
37
+ }
38
+ let repositoryRoot;
39
+ try {
40
+ repositoryRoot = await realpath(reportedRoot);
41
+ } catch (error) {
42
+ fail('GIT_WORKTREE_PATH_UNAVAILABLE', `Cannot resolve the worktree reported by Git: ${reportedRoot}. ${error.message}`, {
43
+ stage: 'resolve-worktree', projectRoot: root, reportedRoot, cause: error.code,
44
+ });
25
45
  }
26
46
  const relative = path.relative(repositoryRoot, root);
27
47
  if (relative === '..' || relative.startsWith(`..${path.sep}`)) {
28
- fail('GIT_REPOSITORY_REQUIRED', `Project root is outside its reported Git worktree: ${projectRoot}.`);
48
+ fail('GIT_WORKTREE_PATH_INVALID', `Project root is outside its reported Git worktree: ${projectRoot}.`, {
49
+ stage: 'resolve-worktree', projectRoot: root, reportedRoot,
50
+ });
29
51
  }
30
52
  return { workingDirectory: root, repositoryRoot };
31
53
  }