upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/funcs/apply_patches.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:14:47 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:14:47 +0000
commit0067804cc00e94ce2b7043e67f9ff50968525479 (patch)
tree2accdc6d4e9b73df4f20499238ec24f24a52a1b8 /src/funcs/apply_patches.rs
parent5c5feaa732363e32e2a980a887fa42b4394b1a5e (diff)
v0.0.1-alpha funcs
Diffstat (limited to 'src/funcs/apply_patches.rs')
-rw-r--r--src/funcs/apply_patches.rs95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/funcs/apply_patches.rs b/src/funcs/apply_patches.rs
new file mode 100644
index 0000000..7d3147e
--- /dev/null
+++ b/src/funcs/apply_patches.rs
@@ -0,0 +1,95 @@
1use std::{path::PathBuf, process::Command, fs::{self, File}, io::Write};
2
3use git2::Repository;
4use nostr::Event;
5
6use crate::{utils::save_event, ngit_tag::{tag_extract_value, tag_is_commit}};
7
8
9pub fn apply_patches(
10 git_repo: &Repository,
11 repo_dir_path: &PathBuf,
12 patches_correctly_ordered:&mut Vec<Event>,
13
14) {
15 // check git is installed
16 match Command::new("git").output() {
17 Ok(_o) => (),
18 Err(_e) => {
19 panic!("git isn't installed :( Install git and then you can use ngit :)");
20 }
21 }
22 let ngit_path = repo_dir_path.join(".ngit");
23
24 println!("{} commits to apply",patches_correctly_ordered.len());
25 fs::create_dir(ngit_path.join("patches/mbox"))
26 .expect("patches/mbox to be created by create_dir");
27 for (i, event) in patches_correctly_ordered.iter().enumerate() {
28 save_event(
29 ngit_path.join(format!(
30 "patches/{}.json",
31 tag_extract_value(
32 &event.tags.iter().find(|t| tag_is_commit(t))
33 .expect("each patch contains commit tag")
34 )
35 )),
36 &event,
37 )
38 .expect("patch to be saved with [commit_id].json using save_event");
39 // extract mbox patch and save to file for 'git am' to recieve
40 let patch_path = format!("patches/mbox/{:0>5}.patch",i);
41 let mut f = File::create(ngit_path.join(&patch_path))
42 .expect("patch file can be created at patch_path location");
43 f.write_all(&event.content.as_bytes())
44 .expect("can use write_all to write event content to patch file");
45 // gitoxide or libgit2 do not support applying patches whilst maintaining the commit ids so we fall back to indirectly using git
46 // it turns out that git am doesnt retain commit ids. for now we will modify the committer author and timestamp to correct the commit id.
47 match Command::new("git")
48 .current_dir(&repo_dir_path)
49 .args([
50 "am",
51 ngit_path.join(&patch_path).to_string_lossy().to_string().as_str(),
52 ])
53 .output() {
54 Ok(_o) => {
55 let mut revwalk = git_repo.revwalk()
56 .expect("revwalk not to error");
57 revwalk.push_head()
58 .expect("revwalk.push_head not to error");
59
60 for (i, oid) in revwalk.enumerate() {
61 if i == 0 {
62 let old_commit = git_repo.find_commit(
63 oid
64 .expect("oid of newly added commit")
65 )
66 .expect("commit from newly added commit oid");
67 // create commit using amend with relects the original commit id (assumes committer should be identical to author
68 // TODO: in git push add a tag if the committer information is different to author. Then here use that info instead.
69 let updated_commit_oid = old_commit.amend(
70 None,
71 None,
72 Some(&old_commit.author()),
73 None,
74 None,
75 None,
76 )
77 .expect("ammend commit to produce new oid");
78 // replace the commit with the wrong oid with the newly created one with the correct oid
79 git_repo.head()
80 .expect("to return head of git_repo")
81 .set_target(
82 updated_commit_oid,
83 "ref commit with fix committer details",
84 )
85 .expect("branch to be updated with fixed commt");
86 }
87 };
88 },
89 Err(_e) => { panic!(":( git error: {:#?}",_e); },
90 }
91 }
92 // clear up by removing mbox directory
93 fs::remove_dir_all(ngit_path.join("patches/mbox"))
94 .expect("patches/mbox to be removed recursively now we are done with it");
95}