From 6f44c872a347907737cc1d2f9e49da201142044e Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Sun, 21 May 2023 11:21:01 +0000 Subject: merge, patch, pull requests and repo_config --- src/merge.rs | 35 +++++++++++++++ src/patch.rs | 65 +++++++++++++++++++++++++++ src/pull_request.rs | 39 ++++++++++++++++ src/repo_config.rs | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 src/merge.rs create mode 100644 src/patch.rs create mode 100644 src/pull_request.rs create mode 100644 src/repo_config.rs (limited to 'src') diff --git a/src/merge.rs b/src/merge.rs new file mode 100644 index 0000000..5f5b15f --- /dev/null +++ b/src/merge.rs @@ -0,0 +1,35 @@ +use nostr::{Event, EventBuilder, Keys }; + + +use crate::{ngit_tag::{tag_repo, tag_branch, tag_commit, tag_branch_merge_from, tag_patch, tag_hashtag, tag_into_event}, kind::Kind}; + +pub fn initialize_merge( + keys: &Keys, + repoistory:&String, + to_branch_id: &String, + from_branch_id: &String, + commit_id: &String, + patch_id: &String, +) -> Event { + let tags = vec![ + tag_repo(repoistory), + tag_into_event(tag_repo(repoistory)), + tag_branch(to_branch_id), + tag_into_event(tag_branch(to_branch_id)), + tag_branch_merge_from(from_branch_id), + tag_into_event(tag_branch_merge_from(from_branch_id)), + tag_patch(patch_id), + tag_into_event(tag_patch(patch_id)), + tag_commit(commit_id), + tag_hashtag("ngit-event"), + tag_hashtag("ngit-format-0.0.1"), +]; + EventBuilder::new( + Kind::Merge.into_sdk_custom_kind(), + "MERGE", + &tags, + ) + .to_unsigned_event(keys.public_key()) + .sign(&keys) + .unwrap() +} diff --git a/src/patch.rs b/src/patch.rs new file mode 100644 index 0000000..fc1137c --- /dev/null +++ b/src/patch.rs @@ -0,0 +1,65 @@ +use nostr::{Event, EventBuilder, Keys }; +use std::str; + +use crate::{ngit_tag::{tag_repo, tag_branch, tag_commit_parent, tag_commit, tag_initial_commit, tag_patch_parent, tag_is_commit, tag_extract_value, tag_commit_message, tag_hashtag, tag_into_event}, kind::Kind}; + +pub fn initialize_patch( + keys: &Keys, + repoistory:&String, + branch: &String, + patch:&[u8], + message: &String, + commit_ids: &Vec, + patch_parent_id:Option, + parent_commit_id:Option, +) -> Event { + let mut tags = vec![ + tag_repo(repoistory), + tag_into_event(tag_repo(repoistory)), + tag_branch(branch), + tag_into_event(tag_branch(branch)), + tag_commit_message(message), + tag_hashtag("ngit-event"), + tag_hashtag("ngit-format-0.0.1"), +]; + for id in commit_ids { + tags.push(tag_commit(id)); + } + match parent_commit_id { + None => { tags.push(tag_initial_commit()); }, + Some(id) => { tags.push(tag_commit_parent(&id)); } + }; + match patch_parent_id { + None => (), + Some(id) => { + tags.push(tag_patch_parent(&id)); + tags.push(tag_into_event(tag_patch_parent(&id))); + } + }; + let content = str::from_utf8(patch) + .expect("patch Vec to convert to string"); + EventBuilder::new( + Kind::Patch.into_sdk_custom_kind(), + content, + &tags, + ) + .to_unsigned_event(keys.public_key()) + .sign(&keys) + .unwrap() +} + +pub fn patch_is_commit(event:&Event, oid:&String) -> bool { + event.tags.iter().any( + |t|tag_is_commit(t) + && tag_extract_value(t) == oid.clone() + ) +} + +pub fn patch_commit_id(event:&Event) -> String { + match event.tags.iter().find( + |t|tag_is_commit(t) + ) { + None => { String::new() }, + Some(t) => { tag_extract_value(t) }, + } +} \ No newline at end of file diff --git a/src/pull_request.rs b/src/pull_request.rs new file mode 100644 index 0000000..a87fa45 --- /dev/null +++ b/src/pull_request.rs @@ -0,0 +1,39 @@ +use nostr::{Event, EventBuilder, Keys }; + + +use crate::{ngit_tag::{tag_repo, tag_branch, tag_branch_merge_from, tag_hashtag, tag_into_event}, kind::Kind}; + +pub fn initialize_pull_request( + keys: &Keys, + repoistory:&String, + to_branch_id: &String, + from_branch_id: &String, + title: &String, + description: &String, + hashtags: Vec, + +) -> Event { + let mut tags = vec![ + tag_repo(repoistory), + tag_into_event(tag_repo(repoistory)), + tag_branch(to_branch_id), + tag_into_event(tag_branch(to_branch_id)), + tag_branch_merge_from(from_branch_id), + tag_into_event(tag_branch_merge_from(from_branch_id)), + tag_hashtag("ngit-event"), + tag_hashtag("ngit-format-0.0.1"), +]; + for t in hashtags.iter() { + tags.push( + nostr::Tag::Hashtag(t.to_string()) + ) + } + EventBuilder::new( + Kind::PullRequest.into_sdk_custom_kind(), + format!("PullRequest\n{title}\n\n{description}"), + &tags, + ) + .to_unsigned_event(keys.public_key()) + .sign(&keys) + .unwrap() +} diff --git a/src/repo_config.rs b/src/repo_config.rs new file mode 100644 index 0000000..a26575f --- /dev/null +++ b/src/repo_config.rs @@ -0,0 +1,125 @@ +use std::{path::PathBuf, fs::File, io::Write}; + +use nostr::Timestamp; +use serde::{Deserialize, Serialize}; + +use crate::utils::load_file; + +#[derive(Serialize, Deserialize)] +pub struct RepoConfig { + version: u8, + branch_mappings: Vec<(String, String, Option)>, + last_branch_ref_update_time: Option, + repo_dir_path: PathBuf, +} + + +impl RepoConfig { + + pub fn open(repo_dir_path: &PathBuf) -> Self { + let path = repo_dir_path.join(".ngit/config.json"); + if path.exists() { + let repo_config: Self = serde_json::from_str( + load_file(path) + .expect("config json to load from file") + .as_str() + ) + .expect("config.json to deserialize into RepoConfig"); + repo_config + } + else { + Self { + version: 0, + branch_mappings: vec![], + last_branch_ref_update_time: None, + repo_dir_path:repo_dir_path.clone(), + + } + } + } + + fn save(&self) { + let path = self.repo_dir_path.join(".ngit/config.json"); + let mut f = File::create(path) + .expect("config.json to open using File::Create"); + f.write_all( + serde_json::json!(self).to_string().as_bytes() + ) + .expect("write_all to write serialized RepoConfig to config.json"); + } + + pub fn set_mapping(&mut self, branch_name:&String, branch_id:&String) { + for i in 0..self.branch_mappings.len() { + if branch_name.clone() == self.branch_mappings[i].0 { + self.branch_mappings[i].1 = branch_id.clone(); + self.save(); + return; + } + } + self.branch_mappings.push( + (branch_name.clone(), branch_id.clone(), None) + ); + self.save(); + } + + pub fn set_last_branch_ref_update_time(&mut self, timestamp:Timestamp) { + self.last_branch_ref_update_time = Some(timestamp); + self.save(); + } + + pub fn last_branch_ref_update_time(&self) -> &Option { + &self.last_branch_ref_update_time + } + + pub fn set_last_patch_update_time(&mut self, branch_id: String, timestamp:Timestamp) { + for i in 0..self.branch_mappings.len() { + if branch_id.clone() == self.branch_mappings[i].1 { + self.branch_mappings[i].2 = Some(timestamp); + self.save(); + return; + } + } + } + + pub fn last_patch_update_time(&self, branch_id: String) -> &Option { + for mapping in self.branch_mappings.iter() { + if branch_id.clone() == mapping.1 { + return &mapping.2; + } + } + return &None; + } + + pub fn branch_id_from_name (&self,branch_name:&String) -> Option<&String> { + for mapping in self.branch_mappings.iter() { + if branch_name.clone() == mapping.0 + && self.check_local_branch_exists(&mapping.0) + { + return Some(&mapping.1); + } + } + return None; + } + + pub fn branch_name_from_id (&self,branch_id:&String) -> Option<&String> { + for mapping in self.branch_mappings.iter() { + if branch_id.clone() == mapping.1 + && self.check_local_branch_exists(&mapping.0) + { + return Some(&mapping.0); + } + } + return None; + } + + fn check_local_branch_exists(&self, branch_name: &String) -> bool { + match git2::Repository::open(&self.repo_dir_path) + .expect("git repo not initialized. run ngit init first") + .find_branch(branch_name, git2::BranchType::Local) + { + Ok(_) => true, + Err(_) => false, + } + } + +} -- cgit v1.2.3