upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/sub_commands
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:23:23 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2023-05-21 11:23:23 +0000
commit73f0333128b5296c7ad718a7b4f2b3db8c7e8a0f (patch)
treeb836108e6d1ee018ba1cc36d947af3f69dc44a88 /src/sub_commands
parent8d211bad54d15208caeea093329acb7f8273944c (diff)
clone
Diffstat (limited to 'src/sub_commands')
-rw-r--r--src/sub_commands/clone.rs223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/sub_commands/clone.rs b/src/sub_commands/clone.rs
new file mode 100644
index 0000000..5fd5070
--- /dev/null
+++ b/src/sub_commands/clone.rs
@@ -0,0 +1,223 @@
1use std::{path::PathBuf, env::current_dir};
2use dialoguer::{theme::ColorfulTheme, Input};
3use clap::{Args};
4use git2::{Repository};
5use nostr_sdk::{prelude::*, blocking::Client};
6
7use crate::{config::{load_config, MyConfig}, repos::{repo::Repo}, utils::{save_event, create_client, get_stored_keys, load_event}, cli_helpers::select_relays, fetch_pull_push::fetch_pull_push, funcs::find_select_recent_repos::find_select_recent_repos};
8
9#[derive(Args)]
10struct Clone {
11 /// Repo nevent
12 #[arg(short, long)]
13 repo: String,
14}
15
16#[derive(Args)]
17pub struct CloneSubCommand {
18 /// Repo nevent
19 #[arg(short, long)]
20 repo: Option<String>,
21}
22
23pub fn clone_from_relays(
24 relays: Vec<String>,
25 sub_command_args: &CloneSubCommand,
26) {
27
28 let mut cfg = load_config();
29
30 let keys = match get_stored_keys(&mut cfg) {
31 None => Keys::generate(),
32 Some(k) => k.clone(),
33 };
34
35 let (repo_id, selected_relays, client) = match &sub_command_args.repo {
36 Some(name) => {
37 let (repo_id, selected_relays) = select_repo_id_and_relays(
38 &Some(name.clone()),
39 &relays,
40 &mut cfg,
41 );
42 let client = create_client(&keys, selected_relays.clone())
43 .expect("create_client returns client");
44 (repo_id, selected_relays, client)
45 },
46 None => {
47 let selected_relays = if relays.is_empty() {
48 select_relays(&mut cfg, &relays)
49 .expect("select_relays() never to error")
50 } else { relays.clone() };
51 let client = create_client(&keys, selected_relays.clone())
52 .expect("create_client returns client");
53 // find repository
54 let repo_id = find_select_recent_repos(&client);
55 (repo_id, selected_relays, client)
56 }
57 };
58 // find repo
59 let repo = get_repo(
60 &mut cfg,
61 &client,
62 &selected_relays,
63 repo_id,
64 );
65 println!("Repo found!...");
66
67 // setup directory
68 let (repo_dir_path, _git_repo) = setup_dir(&repo);
69
70 // add relays specified in repo
71 client.add_relays(repo.relays.clone().iter().map(|url| (url, None)).collect())
72 .expect("relays specified in repo to be added to client");
73
74 fetch_pull_push(
75 None,
76 true,
77 false,
78 None,
79 true,
80 Some(repo_dir_path),
81 Some(client),
82
83 );
84}
85
86fn get_repo(
87 cfg:&mut MyConfig,
88 client: &Client,
89 relays:&Vec<String>,
90 repo_id: EventId,
91) -> Repo {
92 let json_path = current_dir().unwrap().join(".ngit/repo.json");
93
94 if json_path.exists() {
95 Repo::new_from_event(
96 load_event(json_path)
97 .expect("load_event to load repo from repo.json that exists")
98 )
99 .expect("new_from_event to load repo event gathered from repo.json")
100 } else {
101 loop {
102 let repo_events = client.get_events_of(
103 vec![
104 Filter::new().id(repo_id),
105 ],
106 None,
107 )
108 .expect("get_events_of to not return an error");
109
110 match repo_events.iter().find(|e|
111 e.id == repo_id
112 ) {
113 None => {
114 println!("repository is not on selected relays. add more relays. {:?}",relays);
115 let new_relays = select_relays(cfg, relays)
116 .expect("select_relays not to error");
117 client.add_relays(new_relays.iter().map(|url| (url, None)).collect())
118 .expect("extra relays to find repository to be added to client");
119 },
120 Some(e) => {
121 break Repo::new_from_event(e.clone())
122 .expect(format!("new_from_event to return Repo from repo_event: {:?}",e).as_str());
123 },
124 }
125 }
126 }
127}
128
129fn select_repo_id_and_relays(
130 repo_string_param:&Option<String>,
131 relays:&Vec<String>,
132 cfg:&mut MyConfig,
133) -> (EventId, Vec<String>) {
134
135 // get repo_id and selected_relays
136 let mut selected_relays:Vec<String> = vec![];
137 let _repo_id: EventId;
138 loop {
139 let repo_string = match repo_string_param {
140 None => {
141 let response: String = Input::with_theme(&ColorfulTheme::default())
142 .with_prompt("Repo nevent note or hex")
143 .report(true)
144 .interact_text()
145 .unwrap();
146 response
147 }
148 Some(ref r) => { r.clone() },
149 };
150 let repo_id = match Nip19Event::from_bech32(&repo_string.clone()) {
151 Ok(n19) => { selected_relays = n19.relays; n19.event_id }
152 Err(_) => {
153 match EventId::from_bech32(repo_string.clone()) {
154 Ok(id) => { id }
155 Err(_) => {
156 match EventId::from_hex(repo_string.clone()) {
157 Ok(id) => { id }
158 Err(_) => {
159 println!("not a valid nevent, note or hex string. try again.");
160 continue;
161 }
162 }
163 }
164 }
165 }
166 };
167 if selected_relays.is_empty() {
168 if relays.is_empty() {
169 selected_relays = select_relays(cfg, &relays)
170 .expect("select_relays() never to error");
171 }
172 else {
173 selected_relays = relays.clone();
174 }
175 }
176 break (repo_id, selected_relays);
177 }
178}
179
180fn setup_dir(repo: &Repo,) -> (PathBuf, Repository) {
181 // setup directory
182 println!("creating directory...");
183
184 let repo_dir_name = loop {
185 let proposed_name = Input::with_theme(&ColorfulTheme::default())
186 .with_prompt("clone in sub-folder named")
187 .default(match &repo.name {
188 None => { "".to_string() },
189 Some(name) => { name.clone() }
190 })
191 .interact_text()
192 .unwrap();
193 if std::env::current_dir().unwrap().join(&proposed_name).exists() {
194 println!("directory already exists. try another one...");
195 }
196 else { break proposed_name; }
197 };
198 let repo_dir_path = std::env::current_dir().unwrap().join(&repo_dir_name);
199 let ngit_path = repo_dir_path.join(".ngit");
200
201 // create .ngit folder and store the repo and group reference and associated events (?)
202 for p in [
203 "groups",
204 "branches",
205 "patches",
206 "merges",
207 "prs",
208 "issues",
209 "comments",
210 ] { std::fs::create_dir_all(ngit_path.join(p)).unwrap(); }
211
212 // initialise git
213 let git_repo = git2::Repository::init(repo_dir_path.clone())
214 .expect("git repo to be created in a empty repository");
215
216 // save repo.json
217 save_event(
218 ngit_path.join("repo.json"),
219 &repo.events[0],
220 )
221 .expect("save_event to repo.json to in .ngit directory");
222 (repo_dir_path, git_repo)
223}