Skip to main content

lean_ctx/core/
git_worktree.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Linked git worktrees, read from git's own files without running git.
3
4use std::path::{Path, PathBuf};
5
6/// The main checkout of the linked git worktree at `root`, read from git's
7/// own files without running git: `<root>/.git` is a file naming the
8/// worktree's git dir, whose `gitdir` points back at that file and whose
9/// `commondir` names the repository's `.git` directory of the main checkout.
10/// `None` for a main checkout, a bare repository, or files that do not
11/// agree with each other.
12pub fn main_worktree_root(root: &Path) -> Option<PathBuf> {
13    let dot_git = root.join(".git");
14    if !std::fs::symlink_metadata(&dot_git).ok()?.is_file() {
15        return None;
16    }
17    let text = std::fs::read_to_string(&dot_git).ok()?;
18    let gitdir = text.lines().next()?.strip_prefix("gitdir:")?.trim();
19    let gitdir = root.join(gitdir).canonicalize().ok()?;
20    let back = std::fs::read_to_string(gitdir.join("gitdir")).ok()?;
21    if gitdir.join(back.trim()).canonicalize().ok()? != dot_git.canonicalize().ok()? {
22        return None;
23    }
24    let common = std::fs::read_to_string(gitdir.join("commondir")).ok()?;
25    let common = gitdir.join(common.trim()).canonicalize().ok()?;
26    if common.file_name()? != ".git" {
27        return None;
28    }
29    let main = common.parent()?;
30    let main_dot_git = std::fs::symlink_metadata(main.join(".git")).ok()?;
31    (main_dot_git.is_dir() && main != root.canonicalize().ok()?).then(|| main.to_path_buf())
32}