upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/funcs/find_latest_patch.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/funcs/find_latest_patch.rs')
-rw-r--r--src/funcs/find_latest_patch.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/funcs/find_latest_patch.rs b/src/funcs/find_latest_patch.rs
new file mode 100644
index 0000000..717d6c1
--- /dev/null
+++ b/src/funcs/find_latest_patch.rs
@@ -0,0 +1,137 @@
1use std::path::PathBuf;
2
3use nostr::{ Event };
4
5use crate::{ngit_tag::{tag_is_branch, tag_extract_value, tag_is_commit}, branch_refs::BranchRefs, utils::load_event, kind::Kind};
6
7/// finds latest patch that needs applying. It might not be the latest created_at date if an earlier patch was 'merged' more recently
8pub fn find_latest_patch(
9 branch_id: &String,
10 patch_events:&Vec<Event>,
11 merges_into_branch: &Vec<Event>,
12 branch_refs:&BranchRefs,
13 repo_dir_path: &PathBuf,
14) -> Option<Event> {
15
16 // ensure only patch events make it into patch_events - we cant rely on relays for this
17 let patch_events:Vec<Event> = patch_events.iter().filter(|p|
18 // kind is patch
19 p.kind == nostr_sdk::Kind::Custom(u64::from(Kind::Patch))
20 ).map(|p|p.clone()).collect();
21
22 let directly_authorised_patches: Vec<Event> = patch_events.iter().filter(|p|
23 // kind is patch
24 p.kind == nostr_sdk::Kind::Custom(u64::from(Kind::Patch))
25 // on branch
26 && p.tags.iter().any(
27 |t|tag_is_branch(t)
28 && tag_extract_value(t) == branch_id.clone()
29 )
30 // authorized
31 && match &branch_refs.is_authorized(Some(&branch_id), &p.pubkey) {
32 None => { false },
33 Some(is_authorized) => { is_authorized.clone() }
34 }
35 ).map(|p|p.clone()).collect();
36
37 let latest_authorized_patch = find_latest_event(&directly_authorised_patches);
38
39 let authorised_merges: Vec<Event> = merges_into_branch.iter().filter(|m|
40 // kind is merge
41 m.kind == nostr_sdk::Kind::Custom(u64::from(Kind::Merge))
42 // into branch
43 && m.tags.iter().any(
44 |t|tag_is_branch(t)
45 && tag_extract_value(t) == branch_id.clone()
46 )
47 // merge authorized
48 && match &branch_refs.is_authorized(Some(&branch_id), &m.pubkey) {
49 None => { false },
50 Some(is_authorized) => { is_authorized.clone() }
51 }
52 ).map(|p|p.clone()).collect();
53
54 let latest_authorised_merge = find_latest_event(&authorised_merges);
55
56 // find latest patch
57
58 match latest_authorised_merge {
59 // no merge - return patch or None
60 None => latest_authorized_patch,
61 Some(m) => {
62 match latest_authorized_patch {
63 // merge but no patch, return the patch related to the merge
64 None => {
65 Some(get_merge_patch(
66 &m,
67 &patch_events,
68 repo_dir_path,
69 ))
70 },
71 // a merge and a patch
72 Some(p) => {
73 // return the patch if it is later than merge
74 if m.created_at < p.created_at {
75 Some(p.clone())
76 }
77 // return the patch related to the merge if the merge is later
78 else {
79 Some(get_merge_patch(
80 &m,
81 &patch_events,
82 repo_dir_path,
83 ))
84 }
85 }
86 }
87 }
88 }
89}
90
91fn find_latest_event(events:&Vec<Event>) -> Option<Event> {
92 let mut latest = match events.get(0) {
93 None => { return None },
94 Some(e) => e.clone(),
95 };
96 for e in events.iter() {
97 if e.created_at > latest.created_at {
98 latest = e.clone();
99 }
100 }
101 Some(latest)
102}
103
104fn get_merge_patch(
105 merge: &Event,
106 patch_events: &Vec<Event>,
107 repo_dir_path: &PathBuf,
108) -> Event{
109 let commit_id = tag_extract_value(
110 merge.tags.iter().find(|tag| tag_is_commit(tag))
111 .expect("merge event will have a commit tag")
112 );
113 // search in patch_events vector
114 match patch_events.iter().find(|p|
115 tag_extract_value(
116 p.tags.iter().find(|tag| tag_is_commit(tag))
117 .expect("patch event will have a commit tag")
118 ) == *commit_id
119 ) {
120 // found merge patch in patch_events
121 Some(patch) => patch.clone(),
122 None => {
123 let patch_path = repo_dir_path.join(format!(
124 ".ngit/patches/{}.json",
125 commit_id
126 ));
127 if patch_path.exists() {
128 // found merge patch in .ngit/patches
129 load_event(patch_path)
130 .expect("patch at path that exists renders as event")
131 }
132 else {
133 panic!("cannot find patch from merge event in event vector or .ngit folder");
134 }
135 },
136 }
137}