Skip to main content

Repository

Struct Repository 

Source
pub struct Repository {
    pub git_dir: PathBuf,
    pub work_tree: Option<PathBuf>,
    pub odb: Odb,
    pub explicit_git_dir: bool,
    pub discovery_root: Option<PathBuf>,
    pub work_tree_from_env: bool,
    pub discovery_via_gitfile: bool,
    /* private fields */
}
Expand description

A handle to an open Git repository.

Fields§

§git_dir: PathBuf

Absolute path to the git directory (.git/ or bare repo root).

§work_tree: Option<PathBuf>

Absolute path to the working tree, or None for bare repos.

§odb: Odb

Loose object database.

§explicit_git_dir: bool

Discovery provenance: true when opened via GIT_DIR env or explicit API.

This suppresses safe.bareRepository implicit checks.

§discovery_root: Option<PathBuf>

When the repo was found by walking from a directory containing .git / a gitfile, that directory (matches Git’s setup trace using .git for the default git-dir).

§work_tree_from_env: bool

GIT_WORK_TREE was set without GIT_DIR and applied after discovery (t1510 #1, #5, …).

§discovery_via_gitfile: bool

.git was a gitfile (not a directory) when the repo was discovered.

Implementations§

Source§

impl Repository

Source

pub fn open(git_dir: &Path, work_tree: Option<&Path>) -> Result<Self>

Open a repository from an explicit git-dir and optional work-tree.

§Errors

Returns Error::NotARepository if git_dir does not look like a valid git directory (missing objects/, HEAD, etc.).

Examples found in repository?
examples/repo_init_and_open.rs (line 16)
8fn main() -> grit_lib::error::Result<()> {
9    let root = tempfile::tempdir()?;
10    let path = root.path();
11
12    let repo = init_repository(path, false, "main", None, "files")?;
13    println!("opened after init: git_dir = {}", repo.git_dir.display());
14    println!("work tree: {}", repo.work_tree.as_ref().unwrap().display());
15
16    let again = Repository::open(&repo.git_dir, repo.work_tree.as_deref())?;
17    println!("re-open by path: bare = {}", again.is_bare());
18
19    let marker = path.join("marker.txt");
20    fs::write(&marker, b"inside work tree\n")?;
21    let sub = path.join("subdir");
22    fs::create_dir_all(&sub)?;
23    assert!(std::env::set_current_dir(&sub).is_ok());
24    let discovered = Repository::discover(None)?;
25    println!(
26        "discover from subdir: same git_dir = {}",
27        discovered.git_dir == repo.git_dir
28    );
29
30    Ok(())
31}
Source

pub fn open_skipping_format_validation( git_dir: &Path, work_tree: Option<&Path>, ) -> Result<Self>

Like Self::open but skips [validate_repository_format].

Used after repository discovery when the format is unsupported so callers still learn the git directory (Git GIT_DIR_INVALID_FORMAT still records gitdir for read_early_config).

Source

pub fn discover(start: Option<&Path>) -> Result<Self>

Discover the repository starting from start (defaults to cwd if None).

Checks GIT_DIR first; if set, uses it directly. Otherwise walks up the directory tree looking for .git (regular directory or gitfile).

§Errors

Returns Error::NotARepository if no repository can be found.

Examples found in repository?
examples/repo_init_and_open.rs (line 24)
8fn main() -> grit_lib::error::Result<()> {
9    let root = tempfile::tempdir()?;
10    let path = root.path();
11
12    let repo = init_repository(path, false, "main", None, "files")?;
13    println!("opened after init: git_dir = {}", repo.git_dir.display());
14    println!("work tree: {}", repo.work_tree.as_ref().unwrap().display());
15
16    let again = Repository::open(&repo.git_dir, repo.work_tree.as_deref())?;
17    println!("re-open by path: bare = {}", again.is_bare());
18
19    let marker = path.join("marker.txt");
20    fs::write(&marker, b"inside work tree\n")?;
21    let sub = path.join("subdir");
22    fs::create_dir_all(&sub)?;
23    assert!(std::env::set_current_dir(&sub).is_ok());
24    let discovered = Repository::discover(None)?;
25    println!(
26        "discover from subdir: same git_dir = {}",
27        discovered.git_dir == repo.git_dir
28    );
29
30    Ok(())
31}
Source

pub fn effective_pathspec_cwd(&self) -> PathBuf

Current directory to use for pathspec / cwd-prefix logic.

When GIT_WORK_TREE points at a directory that does not contain the process cwd (alternate work tree + index from the main repo directory), Git treats pathspecs as relative to the work tree root — use that root as the effective cwd.

Source

pub fn index_path(&self) -> PathBuf

Path to the index file.

Source

pub fn index_path_for_env(&self) -> Result<PathBuf>

Resolve which index file to use, honouring GIT_INDEX_FILE like Git plumbing.

Relative paths are resolved from the process current directory.

Source

pub fn load_index(&self) -> Result<Index>

Load the index, expanding sparse-directory placeholders from the object database.

Commands that operate on individual paths should use this instead of Index::load.

Examples found in repository?
examples/index_add.rs (line 38)
9fn main() -> grit_lib::error::Result<()> {
10    let root = tempfile::tempdir()?;
11    let repo = init_repository(root.path(), false, "main", None, "files")?;
12
13    let blob_oid = repo.odb.write(ObjectKind::Blob, b"staged content\n")?;
14
15    let path = b"notes.txt".to_vec();
16    let entry = IndexEntry {
17        ctime_sec: 0,
18        ctime_nsec: 0,
19        mtime_sec: 0,
20        mtime_nsec: 0,
21        dev: 0,
22        ino: 0,
23        mode: MODE_REGULAR,
24        uid: 0,
25        gid: 0,
26        size: 0,
27        oid: blob_oid,
28        flags: (path.len().min(0xfff)) as u16,
29        flags_extended: None,
30        path,
31        base_index_pos: 0,
32    };
33
34    let mut index = Index::new();
35    index.add_or_replace(entry);
36    repo.write_index(&mut index)?;
37
38    let round_trip = repo.load_index()?;
39    println!("index entries: {}", round_trip.entries.len());
40    let first = &round_trip.entries[0];
41    println!(
42        "first path: {}, oid: {}",
43        String::from_utf8_lossy(&first.path),
44        first.oid
45    );
46
47    Ok(())
48}
More examples
Hide additional examples
examples/rev_list.rs (line 37)
12fn make_initial_commit(repo: &Repository) -> grit_lib::error::Result<grit_lib::objects::ObjectId> {
13    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
14
15    let blob_oid = repo.odb.write(ObjectKind::Blob, b"log line\n")?;
16    let path = b"file.txt".to_vec();
17    let entry = IndexEntry {
18        ctime_sec: 0,
19        ctime_nsec: 0,
20        mtime_sec: 0,
21        mtime_nsec: 0,
22        dev: 0,
23        ino: 0,
24        mode: MODE_REGULAR,
25        uid: 0,
26        gid: 0,
27        size: 0,
28        oid: blob_oid,
29        flags: (path.len().min(0xfff)) as u16,
30        flags_extended: None,
31        path,
32        base_index_pos: 0,
33    };
34    let mut index = Index::new();
35    index.add_or_replace(entry);
36    repo.write_index(&mut index)?;
37    let index = repo.load_index()?;
38    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
39
40    let commit = CommitData {
41        tree: tree_oid,
42        parents: Vec::new(),
43        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
44        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
45        author_raw: Vec::new(),
46        committer_raw: Vec::new(),
47        encoding: None,
48        message: "root\n".to_owned(),
49        raw_message: None,
50    };
51    let oid = repo
52        .odb
53        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
54    refs::write_ref(&repo.git_dir, "refs/heads/main", &oid)?;
55    Ok(oid)
56}
examples/merge_base.rs (line 40)
11fn commit_tree(
12    repo: &grit_lib::repo::Repository,
13    parent: Option<grit_lib::objects::ObjectId>,
14    message: &str,
15) -> grit_lib::error::Result<grit_lib::objects::ObjectId> {
16    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
17
18    let blob_oid = repo.odb.write(ObjectKind::Blob, b"content\n")?;
19    let path = b"file.txt".to_vec();
20    let entry = IndexEntry {
21        ctime_sec: 0,
22        ctime_nsec: 0,
23        mtime_sec: 0,
24        mtime_nsec: 0,
25        dev: 0,
26        ino: 0,
27        mode: MODE_REGULAR,
28        uid: 0,
29        gid: 0,
30        size: 0,
31        oid: blob_oid,
32        flags: (path.len().min(0xfff)) as u16,
33        flags_extended: None,
34        path,
35        base_index_pos: 0,
36    };
37    let mut index = Index::new();
38    index.add_or_replace(entry);
39    repo.write_index(&mut index)?;
40    let index = repo.load_index()?;
41    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
42
43    let mut parents = Vec::new();
44    if let Some(p) = parent {
45        parents.push(p);
46    }
47    let commit = CommitData {
48        tree: tree_oid,
49        parents,
50        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
51        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
52        author_raw: Vec::new(),
53        committer_raw: Vec::new(),
54        encoding: None,
55        message: format!("{message}\n"),
56        raw_message: None,
57    };
58    repo.odb
59        .write(ObjectKind::Commit, &serialize_commit(&commit))
60}
examples/commit_tree.rs (line 42)
12fn main() -> grit_lib::error::Result<()> {
13    let root = tempfile::tempdir()?;
14    let repo = init_repository(root.path(), false, "main", None, "files")?;
15
16    let blob_oid = repo
17        .odb
18        .write(ObjectKind::Blob, b"hello from grit-lib examples\n")?;
19    let path = b"README".to_vec();
20    let entry = IndexEntry {
21        ctime_sec: 0,
22        ctime_nsec: 0,
23        mtime_sec: 0,
24        mtime_nsec: 0,
25        dev: 0,
26        ino: 0,
27        mode: MODE_REGULAR,
28        uid: 0,
29        gid: 0,
30        size: 0,
31        oid: blob_oid,
32        flags: (path.len().min(0xfff)) as u16,
33        flags_extended: None,
34        path,
35        base_index_pos: 0,
36    };
37
38    let mut index = Index::new();
39    index.add_or_replace(entry);
40    repo.write_index(&mut index)?;
41
42    let index = repo.load_index()?;
43    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
44    println!("tree: {tree_oid}");
45
46    let commit = CommitData {
47        tree: tree_oid,
48        parents: Vec::new(),
49        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
50        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
51        author_raw: Vec::new(),
52        committer_raw: Vec::new(),
53        encoding: None,
54        message: "initial example commit\n".to_owned(),
55        raw_message: None,
56    };
57    let raw = serialize_commit(&commit);
58    let commit_oid = repo.odb.write(ObjectKind::Commit, &raw)?;
59    println!("commit: {commit_oid}");
60
61    refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_oid)?;
62    println!("updated refs/heads/main -> {commit_oid}");
63
64    Ok(())
65}
examples/rev_parse.rs (line 38)
11fn main() -> grit_lib::error::Result<()> {
12    let root = tempfile::tempdir()?;
13    let repo = init_repository(root.path(), false, "main", None, "files")?;
14
15    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
16    let blob_oid = repo.odb.write(ObjectKind::Blob, b"x\n")?;
17    let path = b"a".to_vec();
18    let entry = IndexEntry {
19        ctime_sec: 0,
20        ctime_nsec: 0,
21        mtime_sec: 0,
22        mtime_nsec: 0,
23        dev: 0,
24        ino: 0,
25        mode: MODE_REGULAR,
26        uid: 0,
27        gid: 0,
28        size: 0,
29        oid: blob_oid,
30        flags: 1,
31        flags_extended: None,
32        path,
33        base_index_pos: 0,
34    };
35    let mut index = Index::new();
36    index.add_or_replace(entry);
37    repo.write_index(&mut index)?;
38    let index = repo.load_index()?;
39    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
40    let commit = CommitData {
41        tree: tree_oid,
42        parents: Vec::new(),
43        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
44        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
45        author_raw: Vec::new(),
46        committer_raw: Vec::new(),
47        encoding: None,
48        message: "r\n".to_owned(),
49        raw_message: None,
50    };
51    let oid = repo
52        .odb
53        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
54    refs::write_ref(&repo.git_dir, "refs/heads/main", &oid)?;
55
56    let head = resolve_revision(&repo, "HEAD")?;
57    let full = resolve_revision(&repo, &oid.to_hex())?;
58    println!("HEAD resolves to {head}");
59    println!("full hex resolves to {full}");
60    assert_eq!(head, full);
61
62    Ok(())
63}
examples/walk_tree.rs (line 70)
36fn main() -> grit_lib::error::Result<()> {
37    let root = tempfile::tempdir()?;
38    let repo = init_repository(root.path(), false, "main", None, "files")?;
39
40    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
41
42    let blob_a = repo.odb.write(ObjectKind::Blob, b"a\n")?;
43    let blob_b = repo.odb.write(ObjectKind::Blob, b"b\n")?;
44
45    let mut index = Index::new();
46    for (rel, oid) in [
47        (b"a.txt".as_slice(), blob_a),
48        (b"sub/b.txt".as_slice(), blob_b),
49    ] {
50        let entry = IndexEntry {
51            ctime_sec: 0,
52            ctime_nsec: 0,
53            mtime_sec: 0,
54            mtime_nsec: 0,
55            dev: 0,
56            ino: 0,
57            mode: MODE_REGULAR,
58            uid: 0,
59            gid: 0,
60            size: 0,
61            oid,
62            flags: (rel.len().min(0xfff)) as u16,
63            flags_extended: None,
64            path: rel.to_vec(),
65            base_index_pos: 0,
66        };
67        index.add_or_replace(entry);
68    }
69    repo.write_index(&mut index)?;
70    let index = repo.load_index()?;
71    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
72
73    let commit = CommitData {
74        tree: tree_oid,
75        parents: Vec::new(),
76        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
77        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
78        author_raw: Vec::new(),
79        committer_raw: Vec::new(),
80        encoding: None,
81        message: "tree walk\n".to_owned(),
82        raw_message: None,
83    };
84    let commit_oid = repo
85        .odb
86        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
87    refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_oid)?;
88
89    let head_commit = resolve_revision(&repo, "HEAD")?;
90    let commit_obj = repo.odb.read(&head_commit)?;
91    let parsed = grit_lib::objects::parse_commit(&commit_obj.data)?;
92    println!("walking tree at {}", parsed.tree);
93    walk_tree(&repo, parsed.tree, "")?;
94
95    Ok(())
96}
Source

pub fn load_index_at(&self, path: &Path) -> Result<Index>

Like Repository::load_index, but reads from an explicit index file path (e.g. GIT_INDEX_FILE or a worktree-specific index).

Source

pub fn write_index(&self, index: &mut Index) -> Result<()>

Write the index to the default path after optionally collapsing skip-worktree subtrees into sparse-directory placeholders (when sparse index is enabled).

Examples found in repository?
examples/index_add.rs (line 36)
9fn main() -> grit_lib::error::Result<()> {
10    let root = tempfile::tempdir()?;
11    let repo = init_repository(root.path(), false, "main", None, "files")?;
12
13    let blob_oid = repo.odb.write(ObjectKind::Blob, b"staged content\n")?;
14
15    let path = b"notes.txt".to_vec();
16    let entry = IndexEntry {
17        ctime_sec: 0,
18        ctime_nsec: 0,
19        mtime_sec: 0,
20        mtime_nsec: 0,
21        dev: 0,
22        ino: 0,
23        mode: MODE_REGULAR,
24        uid: 0,
25        gid: 0,
26        size: 0,
27        oid: blob_oid,
28        flags: (path.len().min(0xfff)) as u16,
29        flags_extended: None,
30        path,
31        base_index_pos: 0,
32    };
33
34    let mut index = Index::new();
35    index.add_or_replace(entry);
36    repo.write_index(&mut index)?;
37
38    let round_trip = repo.load_index()?;
39    println!("index entries: {}", round_trip.entries.len());
40    let first = &round_trip.entries[0];
41    println!(
42        "first path: {}, oid: {}",
43        String::from_utf8_lossy(&first.path),
44        first.oid
45    );
46
47    Ok(())
48}
More examples
Hide additional examples
examples/rev_list.rs (line 36)
12fn make_initial_commit(repo: &Repository) -> grit_lib::error::Result<grit_lib::objects::ObjectId> {
13    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
14
15    let blob_oid = repo.odb.write(ObjectKind::Blob, b"log line\n")?;
16    let path = b"file.txt".to_vec();
17    let entry = IndexEntry {
18        ctime_sec: 0,
19        ctime_nsec: 0,
20        mtime_sec: 0,
21        mtime_nsec: 0,
22        dev: 0,
23        ino: 0,
24        mode: MODE_REGULAR,
25        uid: 0,
26        gid: 0,
27        size: 0,
28        oid: blob_oid,
29        flags: (path.len().min(0xfff)) as u16,
30        flags_extended: None,
31        path,
32        base_index_pos: 0,
33    };
34    let mut index = Index::new();
35    index.add_or_replace(entry);
36    repo.write_index(&mut index)?;
37    let index = repo.load_index()?;
38    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
39
40    let commit = CommitData {
41        tree: tree_oid,
42        parents: Vec::new(),
43        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
44        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
45        author_raw: Vec::new(),
46        committer_raw: Vec::new(),
47        encoding: None,
48        message: "root\n".to_owned(),
49        raw_message: None,
50    };
51    let oid = repo
52        .odb
53        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
54    refs::write_ref(&repo.git_dir, "refs/heads/main", &oid)?;
55    Ok(oid)
56}
examples/merge_base.rs (line 39)
11fn commit_tree(
12    repo: &grit_lib::repo::Repository,
13    parent: Option<grit_lib::objects::ObjectId>,
14    message: &str,
15) -> grit_lib::error::Result<grit_lib::objects::ObjectId> {
16    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
17
18    let blob_oid = repo.odb.write(ObjectKind::Blob, b"content\n")?;
19    let path = b"file.txt".to_vec();
20    let entry = IndexEntry {
21        ctime_sec: 0,
22        ctime_nsec: 0,
23        mtime_sec: 0,
24        mtime_nsec: 0,
25        dev: 0,
26        ino: 0,
27        mode: MODE_REGULAR,
28        uid: 0,
29        gid: 0,
30        size: 0,
31        oid: blob_oid,
32        flags: (path.len().min(0xfff)) as u16,
33        flags_extended: None,
34        path,
35        base_index_pos: 0,
36    };
37    let mut index = Index::new();
38    index.add_or_replace(entry);
39    repo.write_index(&mut index)?;
40    let index = repo.load_index()?;
41    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
42
43    let mut parents = Vec::new();
44    if let Some(p) = parent {
45        parents.push(p);
46    }
47    let commit = CommitData {
48        tree: tree_oid,
49        parents,
50        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
51        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
52        author_raw: Vec::new(),
53        committer_raw: Vec::new(),
54        encoding: None,
55        message: format!("{message}\n"),
56        raw_message: None,
57    };
58    repo.odb
59        .write(ObjectKind::Commit, &serialize_commit(&commit))
60}
examples/commit_tree.rs (line 40)
12fn main() -> grit_lib::error::Result<()> {
13    let root = tempfile::tempdir()?;
14    let repo = init_repository(root.path(), false, "main", None, "files")?;
15
16    let blob_oid = repo
17        .odb
18        .write(ObjectKind::Blob, b"hello from grit-lib examples\n")?;
19    let path = b"README".to_vec();
20    let entry = IndexEntry {
21        ctime_sec: 0,
22        ctime_nsec: 0,
23        mtime_sec: 0,
24        mtime_nsec: 0,
25        dev: 0,
26        ino: 0,
27        mode: MODE_REGULAR,
28        uid: 0,
29        gid: 0,
30        size: 0,
31        oid: blob_oid,
32        flags: (path.len().min(0xfff)) as u16,
33        flags_extended: None,
34        path,
35        base_index_pos: 0,
36    };
37
38    let mut index = Index::new();
39    index.add_or_replace(entry);
40    repo.write_index(&mut index)?;
41
42    let index = repo.load_index()?;
43    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
44    println!("tree: {tree_oid}");
45
46    let commit = CommitData {
47        tree: tree_oid,
48        parents: Vec::new(),
49        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
50        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
51        author_raw: Vec::new(),
52        committer_raw: Vec::new(),
53        encoding: None,
54        message: "initial example commit\n".to_owned(),
55        raw_message: None,
56    };
57    let raw = serialize_commit(&commit);
58    let commit_oid = repo.odb.write(ObjectKind::Commit, &raw)?;
59    println!("commit: {commit_oid}");
60
61    refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_oid)?;
62    println!("updated refs/heads/main -> {commit_oid}");
63
64    Ok(())
65}
examples/rev_parse.rs (line 37)
11fn main() -> grit_lib::error::Result<()> {
12    let root = tempfile::tempdir()?;
13    let repo = init_repository(root.path(), false, "main", None, "files")?;
14
15    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
16    let blob_oid = repo.odb.write(ObjectKind::Blob, b"x\n")?;
17    let path = b"a".to_vec();
18    let entry = IndexEntry {
19        ctime_sec: 0,
20        ctime_nsec: 0,
21        mtime_sec: 0,
22        mtime_nsec: 0,
23        dev: 0,
24        ino: 0,
25        mode: MODE_REGULAR,
26        uid: 0,
27        gid: 0,
28        size: 0,
29        oid: blob_oid,
30        flags: 1,
31        flags_extended: None,
32        path,
33        base_index_pos: 0,
34    };
35    let mut index = Index::new();
36    index.add_or_replace(entry);
37    repo.write_index(&mut index)?;
38    let index = repo.load_index()?;
39    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
40    let commit = CommitData {
41        tree: tree_oid,
42        parents: Vec::new(),
43        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
44        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
45        author_raw: Vec::new(),
46        committer_raw: Vec::new(),
47        encoding: None,
48        message: "r\n".to_owned(),
49        raw_message: None,
50    };
51    let oid = repo
52        .odb
53        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
54    refs::write_ref(&repo.git_dir, "refs/heads/main", &oid)?;
55
56    let head = resolve_revision(&repo, "HEAD")?;
57    let full = resolve_revision(&repo, &oid.to_hex())?;
58    println!("HEAD resolves to {head}");
59    println!("full hex resolves to {full}");
60    assert_eq!(head, full);
61
62    Ok(())
63}
examples/walk_tree.rs (line 69)
36fn main() -> grit_lib::error::Result<()> {
37    let root = tempfile::tempdir()?;
38    let repo = init_repository(root.path(), false, "main", None, "files")?;
39
40    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
41
42    let blob_a = repo.odb.write(ObjectKind::Blob, b"a\n")?;
43    let blob_b = repo.odb.write(ObjectKind::Blob, b"b\n")?;
44
45    let mut index = Index::new();
46    for (rel, oid) in [
47        (b"a.txt".as_slice(), blob_a),
48        (b"sub/b.txt".as_slice(), blob_b),
49    ] {
50        let entry = IndexEntry {
51            ctime_sec: 0,
52            ctime_nsec: 0,
53            mtime_sec: 0,
54            mtime_nsec: 0,
55            dev: 0,
56            ino: 0,
57            mode: MODE_REGULAR,
58            uid: 0,
59            gid: 0,
60            size: 0,
61            oid,
62            flags: (rel.len().min(0xfff)) as u16,
63            flags_extended: None,
64            path: rel.to_vec(),
65            base_index_pos: 0,
66        };
67        index.add_or_replace(entry);
68    }
69    repo.write_index(&mut index)?;
70    let index = repo.load_index()?;
71    let tree_oid = write_tree_from_index(&repo.odb, &index, "")?;
72
73    let commit = CommitData {
74        tree: tree_oid,
75        parents: Vec::new(),
76        author: "Example <example@example.com> 1700000000 +0000".to_owned(),
77        committer: "Example <example@example.com> 1700000000 +0000".to_owned(),
78        author_raw: Vec::new(),
79        committer_raw: Vec::new(),
80        encoding: None,
81        message: "tree walk\n".to_owned(),
82        raw_message: None,
83    };
84    let commit_oid = repo
85        .odb
86        .write(ObjectKind::Commit, &serialize_commit(&commit))?;
87    refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_oid)?;
88
89    let head_commit = resolve_revision(&repo, "HEAD")?;
90    let commit_obj = repo.odb.read(&head_commit)?;
91    let parsed = grit_lib::objects::parse_commit(&commit_obj.data)?;
92    println!("walking tree at {}", parsed.tree);
93    walk_tree(&repo, parsed.tree, "")?;
94
95    Ok(())
96}
Source

pub fn write_index_at(&self, path: &Path, index: &mut Index) -> Result<()>

Like Repository::write_index, but writes to an explicit index file path.

Source

pub fn write_index_at_split( &self, path: &Path, index: &mut Index, split: WriteSplitIndexRequest, ) -> Result<()>

Write the index to path, optionally emitting a split index (shared base + link extension).

Source

pub fn refs_dir(&self) -> PathBuf

Path to the refs/ directory.

Source

pub fn head_path(&self) -> PathBuf

Path to HEAD.

Source

pub fn bloom_pathspec_cwd(&self) -> Option<String>

Relative path from the work tree root to the process current directory, /-separated.

Used for :(top) / :/ pathspec Bloom lookups. Returns None for bare repositories or when paths cannot be resolved; callers should treat None like an empty prefix.

Source

pub fn is_bare(&self) -> bool

Whether this is a bare repository (no working tree).

Examples found in repository?
examples/repo_init_and_open.rs (line 17)
8fn main() -> grit_lib::error::Result<()> {
9    let root = tempfile::tempdir()?;
10    let path = root.path();
11
12    let repo = init_repository(path, false, "main", None, "files")?;
13    println!("opened after init: git_dir = {}", repo.git_dir.display());
14    println!("work tree: {}", repo.work_tree.as_ref().unwrap().display());
15
16    let again = Repository::open(&repo.git_dir, repo.work_tree.as_deref())?;
17    println!("re-open by path: bare = {}", again.is_bare());
18
19    let marker = path.join("marker.txt");
20    fs::write(&marker, b"inside work tree\n")?;
21    let sub = path.join("subdir");
22    fs::create_dir_all(&sub)?;
23    assert!(std::env::set_current_dir(&sub).is_ok());
24    let discovered = Repository::discover(None)?;
25    println!(
26        "discover from subdir: same git_dir = {}",
27        discovered.git_dir == repo.git_dir
28    );
29
30    Ok(())
31}
Source

pub fn read_replaced(&self, oid: &ObjectId) -> Result<Object>

Read an object, transparently following replace refs.

If refs/replace/<hex> exists for the requested OID and GIT_NO_REPLACE_OBJECTS is not set, this reads the replacement object instead. Otherwise it behaves identically to self.odb.read(oid).

Source§

impl Repository

Source

pub fn enforce_safe_directory(&self) -> Result<()>

Enforce safe.directory ownership checks, matching upstream behavior.

When GIT_TEST_ASSUME_DIFFERENT_OWNER=1, ownership is considered unsafe unless a matching safe.directory value is configured in system/global/ command scopes (repository-local config is ignored).

Source

pub fn enforce_safe_directory_git_dir(&self) -> Result<()>

Enforce safe.directory checks using the repository git-dir path.

Used by operations that explicitly open another repository by path (e.g. local clone source).

Source

pub fn enforce_safe_directory_git_dir_with_path( &self, checked: &Path, ) -> Result<()>

Enforce safe.directory checks against an explicit checked path.

Source

pub fn verify_safe_for_clone_source(&self) -> Result<()>

Verify the repository is safe to use as a git clone source (local clone).

When GIT_TEST_ASSUME_DIFFERENT_OWNER is set, applies the same safe.directory rules as discovery. Otherwise checks filesystem ownership of the git directory only (matching Git’s die_upon_dubious_ownership for clone).

Trait Implementations§

Source§

impl Debug for Repository

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.