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: PathBufAbsolute 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: OdbLoose object database.
explicit_git_dir: boolDiscovery 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: boolGIT_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
impl Repository
Sourcepub fn open(git_dir: &Path, work_tree: Option<&Path>) -> Result<Self>
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?
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}Sourcepub fn open_skipping_format_validation(
git_dir: &Path,
work_tree: Option<&Path>,
) -> Result<Self>
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).
Sourcepub fn discover(start: Option<&Path>) -> Result<Self>
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?
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}Sourcepub fn effective_pathspec_cwd(&self) -> PathBuf
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.
Sourcepub fn index_path(&self) -> PathBuf
pub fn index_path(&self) -> PathBuf
Path to the index file.
Sourcepub fn index_path_for_env(&self) -> Result<PathBuf>
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.
Sourcepub fn load_index(&self) -> Result<Index>
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?
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
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}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}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}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}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}Sourcepub fn load_index_at(&self, path: &Path) -> Result<Index>
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).
Sourcepub fn write_index(&self, index: &mut Index) -> Result<()>
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?
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
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}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}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}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}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}Sourcepub fn write_index_at(&self, path: &Path, index: &mut Index) -> Result<()>
pub fn write_index_at(&self, path: &Path, index: &mut Index) -> Result<()>
Like Repository::write_index, but writes to an explicit index file path.
Sourcepub fn write_index_at_split(
&self,
path: &Path,
index: &mut Index,
split: WriteSplitIndexRequest,
) -> Result<()>
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).
Sourcepub fn bloom_pathspec_cwd(&self) -> Option<String>
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.
Sourcepub fn is_bare(&self) -> bool
pub fn is_bare(&self) -> bool
Whether this is a bare repository (no working tree).
Examples found in repository?
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}Sourcepub fn read_replaced(&self, oid: &ObjectId) -> Result<Object>
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
impl Repository
Sourcepub fn enforce_safe_directory(&self) -> Result<()>
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).
Sourcepub fn enforce_safe_directory_git_dir(&self) -> Result<()>
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).
Sourcepub fn enforce_safe_directory_git_dir_with_path(
&self,
checked: &Path,
) -> Result<()>
pub fn enforce_safe_directory_git_dir_with_path( &self, checked: &Path, ) -> Result<()>
Enforce safe.directory checks against an explicit checked path.
Sourcepub fn verify_safe_for_clone_source(&self) -> Result<()>
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).