@pnpm/network.git-utils 1100.0.0 → 1100.0.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.
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # @pnpm/git-utils
1
+ # @pnpm/network.git-utils
2
2
 
3
3
  > Utilities for git
4
4
 
5
5
  <!--@shields('npm')-->
6
- [![npm version](https://img.shields.io/npm/v/@pnpm/git-utils.svg)](https://www.npmjs.com/package/@pnpm/git-utils)
6
+ [![npm version](https://img.shields.io/npm/v/@pnpm/network.git-utils.svg)](https://npmx.dev/package/@pnpm/network.git-utils)
7
7
  <!--/@-->
8
8
 
9
9
  ## Installation
10
10
 
11
11
  ```
12
- pnpm add @pnpm/git-utils
12
+ pnpm add @pnpm/network.git-utils
13
13
  ```
14
14
 
15
15
  ## Usage
package/lib/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- export declare function isGitRepo(): Promise<boolean>;
2
- export declare function getCurrentBranch(): Promise<string | null>;
3
- export declare function isWorkingTreeClean(): Promise<boolean>;
4
- export declare function isRemoteHistoryClean(): Promise<boolean>;
1
+ export interface GitCwdOptions {
2
+ cwd?: string;
3
+ }
4
+ export declare function isGitRepo(opts?: GitCwdOptions): Promise<boolean>;
5
+ export declare function getCurrentBranch(opts?: GitCwdOptions): Promise<string | null>;
6
+ export declare function isWorkingTreeClean(opts?: GitCwdOptions): Promise<boolean>;
7
+ export declare function isRemoteHistoryClean(opts?: GitCwdOptions): Promise<boolean>;
package/lib/index.js CHANGED
@@ -1,17 +1,21 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
1
3
  import { safeExeca as execa } from 'execa';
2
- // git checks logic is from https://github.com/sindresorhus/np/blob/master/source/git-tasks.js
3
- export async function isGitRepo() {
4
+ export async function isGitRepo(opts = {}) {
4
5
  try {
5
- await execa('git', ['rev-parse', '--git-dir']);
6
+ await execa('git', ['rev-parse', '--git-dir'], { cwd: opts.cwd });
6
7
  }
7
8
  catch {
8
9
  return false;
9
10
  }
10
11
  return true;
11
12
  }
12
- export async function getCurrentBranch() {
13
+ export async function getCurrentBranch(opts = {}) {
14
+ const branch = readBranchFromHeadFile(opts.cwd);
15
+ if (branch !== undefined)
16
+ return branch;
13
17
  try {
14
- const { stdout } = await execa('git', ['symbolic-ref', '--short', 'HEAD']);
18
+ const { stdout } = await execa('git', ['symbolic-ref', '--short', 'HEAD'], { cwd: opts.cwd });
15
19
  return stdout;
16
20
  }
17
21
  catch {
@@ -19,9 +23,9 @@ export async function getCurrentBranch() {
19
23
  return null;
20
24
  }
21
25
  }
22
- export async function isWorkingTreeClean() {
26
+ export async function isWorkingTreeClean(opts = {}) {
23
27
  try {
24
- const { stdout: status } = await execa('git', ['status', '--porcelain']);
28
+ const { stdout: status } = await execa('git', ['status', '--porcelain'], { cwd: opts.cwd });
25
29
  if (status !== '') {
26
30
  return false;
27
31
  }
@@ -31,10 +35,10 @@ export async function isWorkingTreeClean() {
31
35
  return false;
32
36
  }
33
37
  }
34
- export async function isRemoteHistoryClean() {
38
+ export async function isRemoteHistoryClean(opts = {}) {
35
39
  let history;
36
40
  try { // Gracefully handle no remote set up.
37
- const { stdout } = await execa('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']);
41
+ const { stdout } = await execa('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD'], { cwd: opts.cwd });
38
42
  history = stdout;
39
43
  }
40
44
  catch {
@@ -45,4 +49,51 @@ export async function isRemoteHistoryClean() {
45
49
  }
46
50
  return true;
47
51
  }
52
+ /**
53
+ * Reads the current branch name from `.git/HEAD` without spawning a git subprocess.
54
+ *
55
+ * Returns:
56
+ * - `string` — the branch name extracted from `ref: refs/heads/<name>`
57
+ * - `null` — HEAD is detached (a raw commit SHA, not a symbolic ref)
58
+ * - `undefined` — `.git/HEAD` could not be read (not a git repo, worktree
59
+ * layout not recognized, permissions error, etc.); caller should fall
60
+ * back to `git symbolic-ref`.
61
+ */
62
+ function readBranchFromHeadFile(cwd) {
63
+ const baseDir = cwd ?? process.cwd();
64
+ const dotGitPath = path.join(baseDir, '.git');
65
+ let gitDir;
66
+ try {
67
+ const stat = fs.statSync(dotGitPath);
68
+ if (stat.isDirectory()) {
69
+ gitDir = dotGitPath;
70
+ }
71
+ else if (stat.isFile()) {
72
+ // `.git` is a file — worktree or submodule. It contains `gitdir: <path>`.
73
+ const content = fs.readFileSync(dotGitPath, 'utf8').trim();
74
+ const match = content.match(/^gitdir:\s*(.+)/);
75
+ if (!match)
76
+ return undefined;
77
+ gitDir = path.isAbsolute(match[1]) ? match[1] : path.resolve(baseDir, match[1]);
78
+ }
79
+ else {
80
+ // `.git` is neither a directory nor a regular file (e.g. a FIFO or
81
+ // device); don't read it. Fall back to `git symbolic-ref`.
82
+ return undefined;
83
+ }
84
+ }
85
+ catch {
86
+ return undefined;
87
+ }
88
+ try {
89
+ const head = fs.readFileSync(path.join(gitDir, 'HEAD'), 'utf8').trim();
90
+ const match = head.match(/^ref:\s*refs\/heads\/(.+)/);
91
+ if (match)
92
+ return match[1];
93
+ return null;
94
+ }
95
+ catch {
96
+ return undefined;
97
+ }
98
+ }
48
99
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/network.git-utils",
3
- "version": "1100.0.0",
3
+ "version": "1100.0.2",
4
4
  "description": "Utilities for git",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -10,7 +10,10 @@
10
10
  ],
11
11
  "license": "MIT",
12
12
  "funding": "https://opencollective.com/pnpm",
13
- "repository": "https://github.com/pnpm/pnpm/tree/main/network/git-utils",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/pnpm/pnpm/tree/main/network/git-utils"
16
+ },
14
17
  "homepage": "https://github.com/pnpm/pnpm/tree/main/network/git-utils#readme",
15
18
  "bugs": {
16
19
  "url": "https://github.com/pnpm/pnpm/issues"
@@ -29,8 +32,9 @@
29
32
  "execa": "npm:safe-execa@0.3.0"
30
33
  },
31
34
  "devDependencies": {
35
+ "@jest/globals": "30.4.1",
32
36
  "tempy": "3.0.0",
33
- "@pnpm/network.git-utils": "1100.0.0"
37
+ "@pnpm/network.git-utils": "1100.0.2"
34
38
  },
35
39
  "engines": {
36
40
  "node": ">=22.13"