From 8a8b02815058901a32a39cbc3640f97cf4682107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Val=C3=A9rio?= Date: Fri, 27 Nov 2020 00:11:30 +0000 Subject: [PATCH] step forty eight: merge in working directory --- src/base.rs | 29 ++++++++++++++++++++++++++++- src/diff.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/base.rs b/src/base.rs index 070037d..a9edbb0 100644 --- a/src/base.rs +++ b/src/base.rs @@ -6,6 +6,9 @@ use walkdir::WalkDir; #[path = "data.rs"] mod data; +#[path = "diff.rs"] +mod diff; + pub struct Commit { pub tree: String, pub parent: String, @@ -259,7 +262,16 @@ pub fn reset(oid: String) { ) } -pub fn merge(_oid: String) {} +pub fn merge(oid: String) { + let head = data::get_ref("HEAD".to_owned(), true); + assert!(head.value != ""); + + let c_head = get_commit(head.value); + let c_other = get_commit(oid); + + read_tree_merged(c_head.tree, c_other.tree); + println!("Merged in working tree"); +} fn is_ignored(path: &String) -> bool { if path.contains(".rgit") { @@ -351,3 +363,18 @@ fn empty_current_directory(dir: &str) -> io::Result<()> { fn is_branch(name: String) -> bool { return data::get_ref(name, true).value != ""; } + +fn read_tree_merged(head_tree: String, commit_tree: String) { + empty_current_directory(".").unwrap(); + let head_tree = get_tree(head_tree, "".to_owned()); + let commit_tree = get_tree(commit_tree, "".to_owned()); + for (path, blob) in diff::merge_trees(head_tree, commit_tree) { + let mut dirs = Path::new(&path).ancestors(); + dirs.next(); + + let dir = dirs.next().unwrap().to_str().unwrap(); + + fs::create_dir_all(dir).expect("Cannot create required dirs"); + fs::write(path, blob).expect("Cannot write required object"); + } +} diff --git a/src/diff.rs b/src/diff.rs index f9b3e4e..80d70b9 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -90,3 +90,37 @@ pub fn changed_files( } return result; } + +pub fn merge_trees(t_head: HashMap, t_other: HashMap) -> HashMap { + let mut tree = HashMap::new(); + let trees = vec![t_head, t_other]; + for (path, oids) in compare_trees(trees).iter() { + tree.insert(path.clone(), merge_blobs(oids[0].clone(), oids[1].clone())); + } + return tree; +} + +fn merge_blobs(o_head: String, o_other: String) -> String { + let f_head = NamedTempFile::new().unwrap(); + let f_other = NamedTempFile::new().unwrap(); + + if o_head != "" { + let content = data::get_object(o_head, "blob".to_owned()); + fs::write(f_head.path(), content).unwrap(); + } + + if o_other != "" { + let content = data::get_object(o_other, "blob".to_owned()); + fs::write(f_other.path(), content).unwrap(); + } + + let output = Command::new("diff") + .arg("-DHEAD") + .arg(f_head.path()) + .arg(f_other.path()) + .stdout(Stdio::piped()) + .output() + .expect("Failed to merge file"); + + return String::from_utf8_lossy(&output.stdout).to_string(); +}