{"version":3,"file":"git-branch.d.ts","sourceRoot":"","sources":["../../src/core/git-branch.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAgCzD;AAED,8FAA8F;AAC9F,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAWjE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK7D","sourcesContent":["import { spawnSync } from \"child_process\";\nimport { existsSync, readFileSync, statSync } from \"fs\";\nimport { dirname, join, resolve } from \"path\";\n\n/**\n * Locating a repo's git metadata, and reading the branch out of it.\n *\n * Shared because two callers want it for different reasons: the footer shows the\n * live branch and watches it for changes, while a session records the branch it\n * started on into its header. Keeping one implementation means the branch a\n * session remembers is the same string the footer was showing at the time.\n */\n\nexport type GitPaths = {\n\trepoDir: string;\n\tcommonGitDir: string;\n\theadPath: string;\n};\n\n/**\n * Find git metadata paths by walking up from cwd.\n * Handles both regular git repos (.git is a directory) and worktrees (.git is a file).\n */\nexport function findGitPaths(cwd: string): GitPaths | null {\n\tlet dir = cwd;\n\twhile (true) {\n\t\tconst gitPath = join(dir, \".git\");\n\t\tif (existsSync(gitPath)) {\n\t\t\ttry {\n\t\t\t\tconst stat = statSync(gitPath);\n\t\t\t\tif (stat.isFile()) {\n\t\t\t\t\tconst content = readFileSync(gitPath, \"utf8\").trim();\n\t\t\t\t\tif (content.startsWith(\"gitdir: \")) {\n\t\t\t\t\t\tconst gitDir = resolve(dir, content.slice(8).trim());\n\t\t\t\t\t\tconst headPath = join(gitDir, \"HEAD\");\n\t\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\t\tconst commonDirPath = join(gitDir, \"commondir\");\n\t\t\t\t\t\tconst commonGitDir = existsSync(commonDirPath)\n\t\t\t\t\t\t\t? resolve(gitDir, readFileSync(commonDirPath, \"utf8\").trim())\n\t\t\t\t\t\t\t: gitDir;\n\t\t\t\t\t\treturn { repoDir: dir, commonGitDir, headPath };\n\t\t\t\t\t}\n\t\t\t\t} else if (stat.isDirectory()) {\n\t\t\t\t\tconst headPath = join(gitPath, \"HEAD\");\n\t\t\t\t\tif (!existsSync(headPath)) return null;\n\t\t\t\t\treturn { repoDir: dir, commonGitDir: gitPath, headPath };\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tconst parent = dirname(dir);\n\t\tif (parent === dir) return null;\n\t\tdir = parent;\n\t}\n}\n\n/** Ask git for the current branch. Returns null on detached HEAD or if git is unavailable. */\nexport function resolveBranchWithGitSync(repoDir: string): string | null {\n\tconst result = spawnSync(\"git\", [\"--no-optional-locks\", \"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n\t\tcwd: repoDir,\n\t\tencoding: \"utf8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t});\n\tconst branch = result.status === 0 ? result.stdout.trim() : \"\";\n\treturn branch || null;\n}\n\n/**\n * Read the branch from an already-located HEAD. Returns \"detached\" when HEAD is\n * not on a branch, null when it cannot be read at all. Reftable repos write a\n * `.invalid` placeholder into HEAD, which is the one case that has to shell out.\n */\nexport function readBranchFromHead(paths: GitPaths): string | null {\n\ttry {\n\t\tconst content = readFileSync(paths.headPath, \"utf8\").trim();\n\t\tif (content.startsWith(\"ref: refs/heads/\")) {\n\t\t\tconst branch = content.slice(16);\n\t\t\treturn branch === \".invalid\" ? (resolveBranchWithGitSync(paths.repoDir) ?? \"detached\") : branch;\n\t\t}\n\t\treturn \"detached\";\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * The branch `cwd` is on, or undefined when there is no branch worth recording —\n * outside a repo, or on a detached HEAD, where the answer names no work.\n *\n * Cheap enough to call on the session-creation path: a walk up to `.git` and one\n * file read, with no subprocess outside the reftable case.\n */\nexport function readGitBranch(cwd: string): string | undefined {\n\tconst paths = findGitPaths(cwd);\n\tif (!paths) return undefined;\n\tconst branch = readBranchFromHead(paths);\n\treturn branch && branch !== \"detached\" ? branch : undefined;\n}\n"]}