Skip to main content

finalize_cherry_pick_message

Function finalize_cherry_pick_message 

Source
pub fn finalize_cherry_pick_message(
    original_message: &str,
    append_source: bool,
    signoff: bool,
    committer_name: &str,
    committer_email: &str,
    config: &ConfigSet,
    picked_commit_hex: &str,
) -> String
Expand description

Apply -x / -s rewriting plus optional commit.cleanup when -x is set.

Examples found in repository?
examples/cherry_pick.rs (lines 161-169)
48fn main() -> grit_lib::error::Result<()> {
49    let root = tempfile::tempdir()?;
50    let repo = init_repository(root.path(), false, "main", None, "files")?;
51
52    use grit_lib::index::{Index, IndexEntry, MODE_REGULAR};
53
54    // Base commit on main: one file.
55    let blob_a = repo.odb.write(ObjectKind::Blob, b"base\n")?;
56    let mut index = Index::new();
57    index.add_or_replace(IndexEntry {
58        ctime_sec: 0,
59        ctime_nsec: 0,
60        mtime_sec: 0,
61        mtime_nsec: 0,
62        dev: 0,
63        ino: 0,
64        mode: MODE_REGULAR,
65        uid: 0,
66        gid: 0,
67        size: 0,
68        oid: blob_a,
69        flags: 7,
70        flags_extended: None,
71        path: b"base.txt".to_vec(),
72        base_index_pos: 0,
73    });
74    repo.write_index(&mut index)?;
75    let index = repo.load_index()?;
76    let tree_a = write_tree_from_index(&repo.odb, &index, "")?;
77    let commit_a = commit_from_tree(&repo, tree_a, &[], "initial\n")?;
78    refs::write_ref(&repo.git_dir, "refs/heads/main", &commit_a)?;
79
80    // Topic commit: parent A, adds picked.txt (not on main yet).
81    let blob_pick = repo.odb.write(ObjectKind::Blob, b"hello from topic\n")?;
82    let mut index = Index::new();
83    index.add_or_replace(IndexEntry {
84        ctime_sec: 0,
85        ctime_nsec: 0,
86        mtime_sec: 0,
87        mtime_nsec: 0,
88        dev: 0,
89        ino: 0,
90        mode: MODE_REGULAR,
91        uid: 0,
92        gid: 0,
93        size: 0,
94        oid: blob_a,
95        flags: 7,
96        flags_extended: None,
97        path: b"base.txt".to_vec(),
98        base_index_pos: 0,
99    });
100    index.add_or_replace(IndexEntry {
101        ctime_sec: 0,
102        ctime_nsec: 0,
103        mtime_sec: 0,
104        mtime_nsec: 0,
105        dev: 0,
106        ino: 0,
107        mode: MODE_REGULAR,
108        uid: 0,
109        gid: 0,
110        size: 0,
111        oid: blob_pick,
112        flags: 9,
113        flags_extended: None,
114        path: b"picked.txt".to_vec(),
115        base_index_pos: 0,
116    });
117    repo.write_index(&mut index)?;
118    let index = repo.load_index()?;
119    let tree_b = write_tree_from_index(&repo.odb, &index, "")?;
120    let commit_b = commit_from_tree(&repo, tree_b, &[commit_a], "add picked file\n")?;
121    refs::write_ref(&repo.git_dir, "refs/heads/topic", &commit_b)?;
122
123    // Cherry-pick `topic` onto `main` (still at A).
124    let head = resolve_revision(&repo, "main")?;
125    let picked = resolve_revision(&repo, "topic")?;
126    let picked_obj = repo.odb.read(&picked)?;
127    let picked_data = parse_commit(&picked_obj.data)?;
128    let parent = picked_data.parents.first().copied().ok_or_else(|| {
129        grit_lib::error::Error::CorruptObject("picked commit has no parent".into())
130    })?;
131
132    let base_tree = tree_of_commit(&repo, parent)?;
133    let ours_tree = tree_of_commit(&repo, head)?;
134    let theirs_tree = picked_data.tree;
135
136    let merged = merge_trees_three_way(
137        &repo,
138        base_tree,
139        ours_tree,
140        theirs_tree,
141        MergeFavor::default(),
142        WhitespaceMergeOptions::default(),
143        grit_lib::merge_trees::TreeMergeConflictPresentation {
144            label_ours: "HEAD",
145            label_theirs: grit_lib::merge_trees::TheirsConflictLabel::Fixed("picked"),
146            label_base: "parent of picked commit",
147            style: grit_lib::merge_file::ConflictStyle::Merge,
148            checkout_merge: false,
149        },
150    )?;
151
152    if !merged.conflict_content.is_empty() {
153        return Err(grit_lib::error::Error::Message(format!(
154            "merge produced {} conflict path(s); this example expects a clean pick",
155            merged.conflict_content.len()
156        )));
157    }
158
159    let new_tree = write_tree_from_index(&repo.odb, &merged.index, "")?;
160    let config = ConfigSet::load_repo_local_only(&repo.git_dir)?;
161    let msg = commit_trailers::finalize_cherry_pick_message(
162        &picked_data.message,
163        true,
164        false,
165        "Example",
166        "example@example.com",
167        &config,
168        &picked.to_hex(),
169    );
170    let new_commit = commit_from_tree(&repo, new_tree, &[head], &msg)?;
171    refs::write_ref(&repo.git_dir, "refs/heads/main", &new_commit)?;
172
173    println!("cherry-picked {} onto {}", picked, head);
174    println!("new main: {new_commit}");
175    let out = repo.odb.read(&new_commit)?;
176    println!("message:\n{}", parse_commit(&out.data)?.message);
177
178    Ok(())
179}