| 250 | } |
| 251 | |
| 252 | int cbm_git_context_resolve(const char *path, cbm_git_context_t *out) { |
| 253 | if (!out) { |
| 254 | return CBM_NOT_FOUND; |
| 255 | } |
| 256 | |
| 257 | memset(out, 0, sizeof(*out)); |
| 258 | if (!path || !path[0]) { |
| 259 | return CBM_NOT_FOUND; |
| 260 | } |
| 261 | |
| 262 | out->input_path = git_strdup(path); |
| 263 | if (!out->input_path) { |
| 264 | return CBM_NOT_FOUND; |
| 265 | } |
| 266 | |
| 267 | struct stat st; |
| 268 | out->root_exists = (stat(path, &st) == 0); |
| 269 | if (!out->root_exists) { |
| 270 | return 0; |
| 271 | } |
| 272 | |
| 273 | if (git_capture(path, "rev-parse --show-toplevel", &out->worktree_root) != 0) { |
| 274 | out->is_git = false; |
| 275 | return 0; |
| 276 | } |
| 277 | out->is_git = true; |
| 278 | |
| 279 | if (git_capture(path, "rev-parse --git-dir", &out->git_dir) != 0) { |
| 280 | out->git_dir = git_strdup(""); |
| 281 | } |
| 282 | if (git_capture(path, "rev-parse --git-common-dir", &out->git_common_dir) != 0) { |
| 283 | out->git_common_dir = git_strdup(""); |
| 284 | } |
| 285 | if (git_capture(path, "rev-parse --verify HEAD", &out->head_sha) != 0) { |
| 286 | out->head_sha = git_strdup(""); |
| 287 | } |
| 288 | |
| 289 | if (git_capture(path, "symbolic-ref --quiet --short HEAD", &out->branch) != 0) { |
| 290 | out->branch = git_strdup("DETACHED"); |
| 291 | out->is_detached = true; |
| 292 | } |
| 293 | |
| 294 | out->is_worktree = |
| 295 | out->git_dir && out->git_common_dir && strcmp(out->git_dir, out->git_common_dir) != 0; |
| 296 | /* git 2.31+ canonical absolute common-dir (best-effort; NULL on older git, |
| 297 | * where derive_canonical_root falls back to the relative common-dir). */ |
| 298 | char *abs_common_dir = NULL; |
| 299 | (void)git_capture(path, "rev-parse --path-format=absolute --git-common-dir", &abs_common_dir); |
| 300 | out->canonical_root = |
| 301 | derive_canonical_root(path, out->worktree_root, out->git_common_dir, abs_common_dir); |
| 302 | free(abs_common_dir); |
| 303 | out->branch_slug = slug_from_branch(out->branch, out->is_detached); |
| 304 | if (git_capture(path, "merge-base HEAD @{upstream}", &out->base_sha) != 0) { |
| 305 | out->base_sha = git_strdup(""); |
| 306 | } |
| 307 | |
| 308 | if (!out->git_dir || !out->git_common_dir || !out->head_sha || !out->branch || |
| 309 | !out->canonical_root || !out->branch_slug || !out->base_sha) { |