diff options
| author | Brandon Keiji <[email protected]> | 2025-05-28 23:30:05 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-05-28 16:30:05 -0700 |
| commit | fd6f6b02ead1e7d68618437d483c4936a977d1e6 (patch) | |
| tree | 268ceca590292aba4d00d37164ad2b379a91b655 /packages/cli/src/ui/hooks/useGitBranchName.ts | |
| parent | 0d99398689f37c28454475bb3d25b94cdf269280 (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.ts | 66 |
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; +} |
