Skip to main content

merge_base/
merge_base.rs

1//! Compute a merge base with [`merge_base::merge_bases_first_vs_rest`] after creating two branch tips.
2//!
3//! Run: `cargo run -p grit-lib --example merge_base`
4
5use grit_lib::merge_base::merge_bases_first_vs_rest;
6use grit_lib::objects::{serialize_commit, CommitData, ObjectKind};
7use grit_lib::refs;
8use grit_lib::repo::init_repository;
9use grit_lib::write_tree::write_tree_from_index;
10
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}
61
62fn main() -> grit_lib::error::Result<()> {
63    let root = tempfile::tempdir()?;
64    let repo = init_repository(root.path(), false, "main", None, "files")?;
65
66    let base = commit_tree(&repo, None, "common root")?;
67    refs::write_ref(&repo.git_dir, "refs/heads/main", &base)?;
68
69    let feature_tip = commit_tree(&repo, Some(base), "feature work")?;
70    refs::write_ref(&repo.git_dir, "refs/heads/feature", &feature_tip)?;
71
72    let main_tip = base;
73    let bases = merge_bases_first_vs_rest(&repo, feature_tip, &[main_tip])?;
74    println!("merge base(s) of feature and main: {bases:?}");
75    assert!(bases.contains(&main_tip));
76
77    Ok(())
78}