summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/useGitBranchName.ts
diff options
context:
space:
mode:
authorBrandon Keiji <[email protected]>2025-05-28 23:30:05 +0000
committerGitHub <[email protected]>2025-05-28 16:30:05 -0700
commitfd6f6b02ead1e7d68618437d483c4936a977d1e6 (patch)
tree268ceca590292aba4d00d37164ad2b379a91b655 /packages/cli/src/ui/hooks/useGitBranchName.ts
parent0d99398689f37c28454475bb3d25b94cdf269280 (diff)
feat: add git branch name to footer (#589)
Diffstat (limited to 'packages/cli/src/ui/hooks/useGitBranchName.ts')
-rw-r--r--packages/cli/src/ui/hooks/useGitBranchName.ts66
1 files changed, 66 insertions, 0 deletions
diff --git a/packages/cli/src/ui/hooks/useGitBranchName.ts b/packages/cli/src/ui/hooks/useGitBranchName.ts
new file mode 100644
index 00000000..6b7b2769
--- /dev/null
+++ b/packages/cli/src/ui/hooks/useGitBranchName.ts
@@ -0,0 +1,66 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { useState, useEffect, useCallback } from 'react';
+import { exec } from 'node:child_process';
+import fs from 'node:fs';
+import fsPromises from 'node:fs/promises';
+import path from 'path';
+
+export function useGitBranchName(cwd: string): string | undefined {
+ const [branchName, setBranchName] = useState<string | undefined>(undefined);
+
+ const fetchBranchName = useCallback(
+ () =>
+ exec(
+ 'git rev-parse --abbrev-ref HEAD',
+ { cwd },
+ (error, stdout, _stderr) => {
+ if (error) {
+ setBranchName(undefined);
+ return;
+ }
+ const branch = stdout.toString().trim();
+ if (branch && branch !== 'HEAD') {
+ setBranchName(branch);
+ } else {
+ setBranchName(undefined);
+ }
+ },
+ ),
+ [cwd, setBranchName],
+ );
+
+ useEffect(() => {
+ fetchBranchName(); // Initial fetch
+
+ const gitHeadPath = path.join(cwd, '.git', 'HEAD');
+ let watcher: fs.FSWatcher | undefined;
+
+ const setupWatcher = async () => {
+ try {
+ await fsPromises.access(gitHeadPath, fs.constants.F_OK);
+ watcher = fs.watch(gitHeadPath, (eventType) => {
+ if (eventType === 'change') {
+ fetchBranchName();
+ }
+ });
+ } catch (_watchError) {
+ // Silently ignore watcher errors (e.g. permissions or file not existing),
+ // similar to how exec errors are handled.
+ // The branch name will simply not update automatically.
+ }
+ };
+
+ setupWatcher();
+
+ return () => {
+ watcher?.close();
+ };
+ }, [cwd, fetchBranchName]);
+
+ return branchName;
+}