* Initialize a git repository in the project directory. * Runs `git init` and creates an initial commit so branches exist. * Also handles "unborn" repos (git init already run but no commits yet).
(projectPath: string)
| 1165 | * Also handles "unborn" repos (git init already run but no commits yet). |
| 1166 | */ |
| 1167 | async gitInit(projectPath: string): Promise<Result<void>> { |
| 1168 | if (typeof projectPath !== "string" || projectPath.trim().length === 0) { |
| 1169 | return Err("Project path is required"); |
| 1170 | } |
| 1171 | try { |
| 1172 | const validation = await validateProjectPath(projectPath); |
| 1173 | if (!validation.valid) { |
| 1174 | return Err(validation.error ?? "Invalid project path"); |
| 1175 | } |
| 1176 | const normalizedPath = validation.expandedPath!; |
| 1177 | |
| 1178 | const isGitRepo = await isGitRepository(normalizedPath); |
| 1179 | |
| 1180 | if (isGitRepo) { |
| 1181 | // Check if repo is "unborn" (git init but no commits yet) |
| 1182 | const branches = await listLocalBranches(normalizedPath); |
| 1183 | if (branches.length > 0) { |
| 1184 | return Err("Directory is already a git repository with commits"); |
| 1185 | } |
| 1186 | // Repo exists but is unborn - just create the initial commit |
| 1187 | } else { |
| 1188 | // Initialize git repository with main as default branch |
| 1189 | using initProc = execFileAsync("git", ["-C", normalizedPath, "init", "-b", "main"]); |
| 1190 | await initProc.result; |
| 1191 | } |
| 1192 | |
| 1193 | // Create an initial empty commit so the branch exists and worktree/SSH can work |
| 1194 | // Without a commit, the repo is "unborn" and has no branches |
| 1195 | // Use -c flags to set identity only for this commit (don't persist to repo config) |
| 1196 | using commitProc = execFileAsync("git", [ |
| 1197 | "-C", |
| 1198 | normalizedPath, |
| 1199 | "-c", |
| 1200 | "user.name=mux", |
| 1201 | "-c", |
| 1202 | "user.email=mux@localhost", |
| 1203 | "commit", |
| 1204 | "--allow-empty", |
| 1205 | "-m", |
| 1206 | "Initial commit", |
| 1207 | ]); |
| 1208 | await commitProc.result; |
| 1209 | |
| 1210 | // Invalidate file completions cache since the repo state changed |
| 1211 | this.fileCompletionsCache.delete(normalizedPath); |
| 1212 | |
| 1213 | return Ok(undefined); |
| 1214 | } catch (error) { |
| 1215 | const message = getErrorMessage(error); |
| 1216 | log.error("Failed to initialize git repository:", error); |
| 1217 | return Err(`Failed to initialize git repository: ${message}`); |
| 1218 | } |
| 1219 | } |
| 1220 | |
| 1221 | async getFileCompletions( |
| 1222 | projectPath: string, |
no test coverage detected