upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:19:43 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:19:43 +0000
commita579e90666d49a0f9353319525b1790ad7b26c4a (patch)
tree30f783750741eca1703e1edb3174d7e6cedbf0f8
parente98276e79cea0c3e474ca0251c276c474c35ed70 (diff)
repos
-rw-r--r--src/repos/init.rs183
-rw-r--r--src/repos/mod.rs2
-rw-r--r--src/repos/repo.rs101
3 files changed, 286 insertions, 0 deletions
diff --git a/src/repos/init.rs b/src/repos/init.rs
new file mode 100644
index 0000000..3254d3e
--- /dev/null
+++ b/src/repos/init.rs
@@ -0,0 +1,183 @@
1
2use std::fmt::Debug;
3use nostr_sdk::{EventBuilder, Tag, Keys, Event};
4use serde::{Deserialize, Serialize};
5
6use crate::{kind::Kind, ngit_tag::{tag_repo, tag_relays, tag_hashtag, tag_group_with_relays, tag_into_event}};
7
8/// [`InitializeRepo`] error
9#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 /// Error serializing or deserializing JSON data
12 #[error("json error: {0}")]
13 Json(#[from] serde_json::Error),
14}
15
16impl InitializeRepo {
17
18 pub fn initialize(&self,keys:&Keys) -> Event {
19 // let keys = Keys::generate();
20 EventBuilder::new(
21 nostr_sdk::Kind::Custom(
22 match self.root_repo {
23 None => u64::from(Kind::InitializeRepo),
24 _ => u64::from(Kind::InitializeBranch),
25 }
26 ),
27 self.as_json(),
28 &self.generate_tags(),
29 )
30 .to_unsigned_event(keys.public_key())
31 .sign(&keys)
32 .unwrap()
33 }
34
35 fn generate_tags(&self) -> Vec<Tag> {
36 let mut tags =
37 vec![
38 self.maintainers_group.as_ref()
39 .expect("there always to be a maintainers group when initialising")
40 .clone(),
41 tag_hashtag("ngit-event"),
42 tag_hashtag("ngit-format-0.0.1"),
43 ];
44 if !self.relays.is_empty() {
45 tags.push(
46 tag_relays(&self.relays)
47 );
48 }
49
50 match &self.root_repo {
51 None =>(),
52 Some(id) => {
53 tags.push(
54 tag_repo(id)
55 );
56 tags.push(
57 tag_into_event(
58 // its a bit silly / lazy reusing this function just to get the tags formatted with relays when it is not a group
59 tag_group_with_relays(id, &self.relays)
60 )
61 );
62
63 }
64 }
65 tags
66 }
67}
68
69/// InitializeRepo
70#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
71pub struct InitializeRepo {
72 /// Name
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub name: Option<String>,
75 /// Description
76 #[serde(skip_serializing_if = "Option::is_none")]
77 pub about: Option<String>,
78 /// Picture
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub picture: Option<String>,
81 /// relays
82 pub relays: Vec<String>,
83 /// Maintainers Group
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub maintainers_group: Option<Tag>,
86 /// Maintainers Group
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub root_repo: Option<String>,
89}
90
91impl Default for InitializeRepo {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97impl InitializeRepo {
98 /// New empty [`InitializeRepo`]
99 pub fn new() -> Self {
100 Self {
101 name: None,
102 about: None,
103 picture: None,
104 relays: vec![],
105 maintainers_group: None,
106 root_repo:None,
107 }
108 }
109
110 /// Deserialize [`InitializeRepo`] from `JSON` string
111 pub fn from_json<S>(json: S) -> Result<Self, Error>
112 where
113 S: Into<String>,
114 {
115 Ok(serde_json::from_str(&json.into())?)
116 }
117
118 /// Serialize [`InitializeRepo`] to `JSON` string
119 pub fn as_json(&self) -> String {
120 serde_json::json!(self).to_string()
121 }
122
123 /// Set name
124 pub fn name<S>(self, name: S) -> Self
125 where
126 S: Into<String>,
127 {
128 Self {
129 name: Some(name.into()),
130 ..self
131 }
132 }
133
134 /// Set about
135 pub fn about<S>(self, about: S) -> Self
136 where
137 S: Into<String>,
138 {
139 Self {
140 about: Some(about.into()),
141 ..self
142 }
143 }
144
145 /// Set picture
146 pub fn picture<S>(self, picture: S) -> Self
147 where
148 S: Into<String>,
149 {
150 Self {
151 picture: Some(picture.into()),
152 ..self
153 }
154 }
155
156 /// Set relays
157 pub fn relays(mut self, relays: &Vec<String>) -> Self {
158 for m in relays {
159 self.relays.push(m.clone());
160 }
161 self
162 }
163
164 /// Set maintainers_group
165 pub fn maintainers_group(self, group_ref: Tag) -> Self {
166 Self {
167 maintainers_group: Some(group_ref),
168 ..self
169 }
170 }
171
172 /// Set root_repo
173 pub fn root_repo<S>(self, root_repo: S) -> Self
174 where
175 S: Into<String>,
176 {
177 Self {
178 root_repo: Some(root_repo.into()),
179 ..self
180 }
181 }
182
183}
diff --git a/src/repos/mod.rs b/src/repos/mod.rs
new file mode 100644
index 0000000..e95cfbd
--- /dev/null
+++ b/src/repos/mod.rs
@@ -0,0 +1,2 @@
1pub mod repo;
2pub mod init;
diff --git a/src/repos/repo.rs b/src/repos/repo.rs
new file mode 100644
index 0000000..0d3001f
--- /dev/null
+++ b/src/repos/repo.rs
@@ -0,0 +1,101 @@
1
2use std::{path::PathBuf};
3
4use nostr::{EventId, Event, prelude::{Nip19Event, ToBech32}, Tag};
5use nostr_sdk::{Keys};
6
7use crate::{groups::{group::{MembershipCollection, StartFinish}}, utils::load_file};
8
9use super::init::{InitializeRepo, self};
10
11/// [`Repo`] error
12#[derive(Debug, thiserror::Error)]
13pub enum Error {
14 /// Error processing initialisation Repo content json - incorrect format?
15 #[error("Repo cannot be initialised from content: {0}")]
16 InitializeJson(#[from] init::Error),
17}
18
19/// Repo, acts a branch if root_repo is set
20pub struct Repo {
21 pub id: EventId,
22 pub name:Option<String>,
23 about:Option<String>,
24 picture:Option<String>,
25 pub relays:Vec<String>,
26 pub maintainers_group:MembershipCollection,
27 pub events:Vec<Event>,
28 pub root_repo: Option<EventId>,
29 hash: String, // hash of event IDs that make up this state
30}
31
32impl Repo {
33
34 pub fn new(init:&InitializeRepo, keys:&Keys) -> Result<Self,Error> {
35 let event = init.initialize(&keys);
36 Repo::new_from_event(event)
37 }
38
39 pub fn open(repo_dir_path: &PathBuf) -> Self {
40 Repo::new_from_json_event(
41 load_file(
42 repo_dir_path.join(".ngit/repo.json"),
43 )
44 .expect("repo.json load from file")
45 )
46 .expect("repo.json to produce Repo")
47 }
48
49 pub fn new_from_json_event(json_string:String) -> Result<Self,Error> {
50 let event = Event::from_json(json_string)
51 .expect("json_string to be formated as event");
52 Repo::new_from_event(event)
53 }
54
55 pub fn new_from_event(event:Event) -> Result<Self,Error> {
56 match InitializeRepo::from_json(&event.content) {
57 Err(e) => return Err(Error::InitializeJson(e)),
58 Ok(g) => {
59 let start_finish = StartFinish { start: event.created_at, finish: None };
60 // add maintainers_group
61 let mut maintainers_group = MembershipCollection::new();
62 match g.maintainers_group {
63 None => (),
64 Some(t) => {
65 maintainers_group.add_group_dates(
66 Tag::parse(t.into())
67 .expect("maintainers_group to parse into Tag"),
68 start_finish.clone(),
69 )
70 }
71 }
72 Ok(Self {
73 id: event.id,
74 name: g.name,
75 about: g.about,
76 picture: g.picture,
77 relays: g.relays,
78 maintainers_group,
79 events:vec![event],
80 root_repo:None,
81 hash: "hash".to_string(), // hash of event IDs that make up this state
82 })
83 }
84 }
85 }
86
87 pub fn nevent(&self) -> String {
88 let e = Nip19Event {
89 event_id: self.id.clone(),
90 relays: if self.relays.len() > 1 {
91 vec![self.relays[0].clone(),self.relays[1].clone()]
92 }
93 else if self.relays.len() == 1 {
94 vec![self.relays[0].clone()]
95 }
96 else { vec![] }
97 };
98 e.to_bech32()
99 .expect("Nip19Event to produce nevent String")
100 }
101}