upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/git.rs6
-rw-r--r--src/main.rs3
-rw-r--r--src/sub_commands/mod.rs1
-rw-r--r--src/sub_commands/push.rs182
-rw-r--r--tests/push.rs477
5 files changed, 669 insertions, 0 deletions
diff --git a/src/git.rs b/src/git.rs
index f4f73a5..e2d8196 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -384,6 +384,12 @@ fn sha1_to_oid(hash: &Sha1Hash) -> Result<Oid> {
384 Oid::from_bytes(hash.as_byte_array()).context("Sha1Hash bytes failed to produce a valid Oid") 384 Oid::from_bytes(hash.as_byte_array()).context("Sha1Hash bytes failed to produce a valid Oid")
385} 385}
386 386
387pub fn str_to_sha1(s: &str) -> Result<Sha1Hash> {
388 Ok(oid_to_sha1(
389 &Oid::from_str(s).context("string is not a sha1 hash")?,
390 ))
391}
392
387fn git_sig_to_tag_vec(sig: &git2::Signature) -> Vec<String> { 393fn git_sig_to_tag_vec(sig: &git2::Signature) -> Vec<String> {
388 vec![ 394 vec![
389 sig.name().unwrap_or("").to_string(), 395 sig.name().unwrap_or("").to_string(),
diff --git a/src/main.rs b/src/main.rs
index 8c6f0d0..996b697 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -40,6 +40,8 @@ enum Commands {
40 Prs(sub_commands::prs::SubCommandArgs), 40 Prs(sub_commands::prs::SubCommandArgs),
41 /// pull latest commits in pr linked to checked out branch 41 /// pull latest commits in pr linked to checked out branch
42 Pull, 42 Pull,
43 /// push commits to current checked out pr branch
44 Push,
43} 45}
44 46
45#[tokio::main] 47#[tokio::main]
@@ -54,5 +56,6 @@ async fn main() -> Result<()> {
54 } 56 }
55 Commands::Prs(args) => futures::executor::block_on(sub_commands::prs::launch(&cli, args)), 57 Commands::Prs(args) => futures::executor::block_on(sub_commands::prs::launch(&cli, args)),
56 Commands::Pull => futures::executor::block_on(sub_commands::pull::launch()), 58 Commands::Pull => futures::executor::block_on(sub_commands::pull::launch()),
59 Commands::Push => futures::executor::block_on(sub_commands::push::launch(&cli)),
57 } 60 }
58} 61}
diff --git a/src/sub_commands/mod.rs b/src/sub_commands/mod.rs
index 12a7f0f..8be9004 100644
--- a/src/sub_commands/mod.rs
+++ b/src/sub_commands/mod.rs
@@ -2,3 +2,4 @@ pub mod claim;
2pub mod login; 2pub mod login;
3pub mod prs; 3pub mod prs;
4pub mod pull; 4pub mod pull;
5pub mod push;
diff --git a/src/sub_commands/push.rs b/src/sub_commands/push.rs
new file mode 100644
index 0000000..968aa0a
--- /dev/null
+++ b/src/sub_commands/push.rs
@@ -0,0 +1,182 @@
1use anyhow::{bail, Context, Result};
2use nostr::prelude::sha1::Hash as Sha1Hash;
3
4#[cfg(not(test))]
5use crate::client::Client;
6#[cfg(test)]
7use crate::client::MockConnect;
8use crate::{
9 client::Connect,
10 git::{str_to_sha1, Repo, RepoActions},
11 login,
12 repo_ref::{self, RepoRef},
13 sub_commands::prs::{
14 create::{generate_patch_event, send_events, PATCH_KIND, PR_KIND},
15 list::{get_most_recent_patch_with_ancestors, tag_value},
16 },
17 Cli,
18};
19
20pub async fn launch(cli_args: &Cli) -> Result<()> {
21 let git_repo = Repo::discover().context("cannot find a git repository")?;
22
23 let (main_or_master_branch_name, _) = git_repo
24 .get_main_or_master_branch()
25 .context("no main or master branch")?;
26
27 let root_commit = git_repo
28 .get_root_commit(main_or_master_branch_name)
29 .context("failed to get root commit of the repository")?;
30
31 let branch_name = git_repo
32 .get_checked_out_branch_name()
33 .context("cannot get checked out branch name")?;
34
35 if branch_name == main_or_master_branch_name {
36 bail!("checkout a branch associated with a PR first")
37 }
38 #[cfg(not(test))]
39 let mut client = Client::default();
40 #[cfg(test)]
41 let mut client = <MockConnect as std::default::Default>::default();
42
43 let repo_ref = repo_ref::fetch(
44 root_commit.to_string(),
45 &client,
46 client.get_more_fallback_relays().clone(),
47 )
48 .await?;
49
50 let (pr_event, commit_events) =
51 fetch_pr_and_most_recent_patch_chain(&client, &repo_ref, &root_commit, &branch_name)
52 .await?;
53
54 // TODO: fix these scenarios:
55 // - local PR branch is 2 behind and 1 ahead. intructions: ...
56 // - PR has been rebased. (against commit in main) instructions: ...
57 // - PR has been rebased. (against commit not in repo) instructions: ..
58
59 let most_recent_pr_patch_chain = get_most_recent_patch_with_ancestors(commit_events)
60 .context("cannot get most recent patch for PR")?;
61
62 let branch_tip = git_repo.get_tip_of_local_branch(&branch_name)?;
63
64 let most_recent_patch_commit_id = str_to_sha1(
65 &tag_value(&most_recent_pr_patch_chain[0], "commit")
66 .context("latest patch event doesnt have a commit tag")?,
67 )
68 .context("latest patch event commit tag isn't a valid SHA1 hash")?;
69
70 if most_recent_patch_commit_id.eq(&branch_tip) {
71 bail!("nostr pr already up-to-date with local branch");
72 }
73
74 if most_recent_pr_patch_chain.iter().any(|e| {
75 let c = tag_value(e, "parent-commit").unwrap_or_default();
76 c.eq(&branch_tip.to_string())
77 }) {
78 bail!("nostr pr is ahead of local branch");
79 }
80
81 let (ahead, behind) = git_repo
82 .get_commits_ahead_behind(&most_recent_patch_commit_id, &branch_tip)
83 .context("the latest patch in pr doesnt share an ancestor with your branch.")?;
84
85 if !behind.is_empty() {
86 bail!(
87 "your local pr branch is {} behind patches on nostr. consider rebasing or force pushing",
88 behind.len()
89 )
90 }
91
92 println!(
93 "{} commits ahead. preparing to create creating patch events.",
94 ahead.len()
95 );
96
97 let (keys, user_ref) = login::launch(&cli_args.nsec, &cli_args.password, Some(&client)).await?;
98
99 client.set_keys(&keys).await;
100
101 let mut patch_events: Vec<nostr::Event> = vec![];
102 for commit in &ahead {
103 patch_events.push(
104 generate_patch_event(&git_repo, &root_commit, commit, pr_event.id, &keys)
105 .context("cannot make patch event from commit")?,
106 );
107 }
108 println!("pushing {} commits", ahead.len());
109
110 send_events(
111 &client,
112 patch_events,
113 user_ref.relays.write(),
114 repo_ref.relays.clone(),
115 !cli_args.disable_cli_spinners,
116 )
117 .await?;
118
119 println!("pushed {} commits", ahead.len());
120
121 Ok(())
122}
123
124async fn fetch_pr_and_most_recent_patch_chain(
125 #[cfg(test)] client: &crate::client::MockConnect,
126 #[cfg(not(test))] client: &Client,
127 repo_ref: &RepoRef,
128 root_commit: &Sha1Hash,
129 branch_name: &String,
130) -> Result<(nostr::Event, Vec<nostr::Event>)> {
131 println!("finding PR event...");
132
133 let pr_event: nostr::Event = client
134 .get_events(
135 repo_ref.relays.clone(),
136 vec![
137 nostr::Filter::default()
138 .kind(nostr::Kind::Custom(PR_KIND))
139 .reference(format!("r-{root_commit}")),
140 ],
141 )
142 .await?
143 .iter()
144 .find(|e| {
145 e.kind.as_u64() == PR_KIND
146 && e.tags
147 .iter()
148 .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("r-{root_commit}")))
149 && tag_value(e, "branch-name")
150 .unwrap_or_default()
151 .eq(branch_name)
152 })
153 .context("cannot find a PR event associated with the checked out branch name")?
154 .to_owned();
155
156 println!("found PR event. finding commits...");
157
158 let commits_events: Vec<nostr::Event> = client
159 .get_events(
160 repo_ref.relays.clone(),
161 vec![
162 nostr::Filter::default()
163 .kind(nostr::Kind::Custom(PATCH_KIND))
164 .event(pr_event.id)
165 .reference(format!("r-{root_commit}")),
166 ],
167 )
168 .await?
169 .iter()
170 .filter(|e| {
171 e.kind.as_u64() == PATCH_KIND
172 && e.tags
173 .iter()
174 .any(|t| t.as_vec().len() > 2 && t.as_vec()[1].eq(&pr_event.id.to_string()))
175 && e.tags
176 .iter()
177 .any(|t| t.as_vec().len() > 1 && t.as_vec()[1].eq(&format!("r-{root_commit}")))
178 })
179 .map(std::borrow::ToOwned::to_owned)
180 .collect();
181 Ok((pr_event, commits_events))
182}
diff --git a/tests/push.rs b/tests/push.rs
new file mode 100644
index 0000000..4fdb6eb
--- /dev/null
+++ b/tests/push.rs
@@ -0,0 +1,477 @@
1use anyhow::Result;
2use futures::join;
3use serial_test::serial;
4use test_utils::{git::GitTestRepo, relay::Relay, *};
5
6static FEATURE_BRANCH_NAME_1: &str = "feature-example-t";
7static FEATURE_BRANCH_NAME_2: &str = "feature-example-f";
8static FEATURE_BRANCH_NAME_3: &str = "feature-example-c";
9
10static PR_TITLE_1: &str = "pr a";
11static PR_TITLE_2: &str = "pr b";
12static PR_TITLE_3: &str = "pr c";
13
14fn cli_tester_create_prs() -> Result<GitTestRepo> {
15 let git_repo = GitTestRepo::default();
16 git_repo.populate()?;
17 cli_tester_create_pr(
18 &git_repo,
19 FEATURE_BRANCH_NAME_1,
20 "a",
21 PR_TITLE_1,
22 "pr a description",
23 )?;
24 cli_tester_create_pr(
25 &git_repo,
26 FEATURE_BRANCH_NAME_2,
27 "b",
28 PR_TITLE_2,
29 "pr b description",
30 )?;
31 cli_tester_create_pr(
32 &git_repo,
33 FEATURE_BRANCH_NAME_3,
34 "c",
35 PR_TITLE_3,
36 "pr c description",
37 )?;
38 Ok(git_repo)
39}
40
41fn create_and_populate_branch(
42 test_repo: &GitTestRepo,
43 branch_name: &str,
44 prefix: &str,
45 only_one_commit: bool,
46) -> Result<()> {
47 test_repo.checkout("main")?;
48 test_repo.create_branch(branch_name)?;
49 test_repo.checkout(branch_name)?;
50 std::fs::write(
51 test_repo.dir.join(format!("{}3.md", prefix)),
52 "some content",
53 )?;
54 test_repo.stage_and_commit(format!("add {}3.md", prefix).as_str())?;
55 if !only_one_commit {
56 std::fs::write(
57 test_repo.dir.join(format!("{}4.md", prefix)),
58 "some content",
59 )?;
60 test_repo.stage_and_commit(format!("add {}4.md", prefix).as_str())?;
61 }
62 Ok(())
63}
64
65fn cli_tester_create_pr(
66 test_repo: &GitTestRepo,
67 branch_name: &str,
68 prefix: &str,
69 title: &str,
70 description: &str,
71) -> Result<()> {
72 create_and_populate_branch(test_repo, branch_name, prefix, false)?;
73
74 let mut p = CliTester::new_from_dir(
75 &test_repo.dir,
76 [
77 "--nsec",
78 TEST_KEY_1_NSEC,
79 "--password",
80 TEST_PASSWORD,
81 "--disable-cli-spinners",
82 "prs",
83 "create",
84 "--title",
85 format!("\"{title}\"").as_str(),
86 "--description",
87 format!("\"{description}\"").as_str(),
88 ],
89 );
90 p.expect_end_eventually()?;
91 Ok(())
92}
93
94mod when_main_is_checked_out {
95 use super::*;
96
97 #[test]
98 fn cli_returns_error() -> Result<()> {
99 let test_repo = GitTestRepo::default();
100 test_repo.populate()?;
101 create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", false)?;
102 test_repo.checkout("main")?;
103 let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]);
104 p.expect("Error: checkout a branch associated with a PR first\r\n")?;
105 p.expect_end()?;
106 Ok(())
107 }
108}
109
110mod when_pr_isnt_associated_with_branch_name {
111 use super::*;
112
113 mod cli_prompts {
114 use super::*;
115 async fn run_async_cli_show_error() -> Result<()> {
116 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
117 Relay::new(8051, None, None),
118 Relay::new(8052, None, None),
119 Relay::new(8053, None, None),
120 Relay::new(8055, None, None),
121 Relay::new(8056, None, None),
122 );
123
124 r51.events.push(generate_test_key_1_relay_list_event());
125 r51.events.push(generate_test_key_1_metadata_event("fred"));
126 r51.events.push(generate_repo_ref_event());
127
128 r55.events.push(generate_repo_ref_event());
129 r55.events.push(generate_test_key_1_metadata_event("fred"));
130 r55.events.push(generate_test_key_1_relay_list_event());
131
132 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
133 cli_tester_create_prs()?;
134
135 let test_repo = GitTestRepo::default();
136 test_repo.populate()?;
137
138 test_repo.create_branch("random-name")?;
139 test_repo.checkout("random-name")?;
140
141 let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]);
142 p.expect("finding PR event...\r\n")?;
143 p.expect(
144 "Error: cannot find a PR event associated with the checked out branch name\r\n",
145 )?;
146
147 p.expect_end()?;
148
149 for p in [51, 52, 53, 55, 56] {
150 relay::shutdown_relay(8000 + p)?;
151 }
152 Ok(())
153 });
154
155 // launch relay
156 let _ = join!(
157 r51.listen_until_close(),
158 r52.listen_until_close(),
159 r53.listen_until_close(),
160 r55.listen_until_close(),
161 r56.listen_until_close(),
162 );
163 cli_tester_handle.join().unwrap()?;
164 Ok(())
165 }
166
167 #[test]
168 #[serial]
169 fn cli_show_error() -> Result<()> {
170 futures::executor::block_on(run_async_cli_show_error())
171 }
172 }
173}
174
175mod when_branch_is_checked_out {
176 use super::*;
177
178 mod when_branch_is_up_to_date {
179 use super::*;
180
181 mod cli_prompts {
182 use super::*;
183 async fn run_async_cli_show_up_to_date() -> Result<()> {
184 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
185 Relay::new(8051, None, None),
186 Relay::new(8052, None, None),
187 Relay::new(8053, None, None),
188 Relay::new(8055, None, None),
189 Relay::new(8056, None, None),
190 );
191
192 r51.events.push(generate_test_key_1_relay_list_event());
193 r51.events.push(generate_test_key_1_metadata_event("fred"));
194 r51.events.push(generate_repo_ref_event());
195
196 r55.events.push(generate_repo_ref_event());
197 r55.events.push(generate_test_key_1_metadata_event("fred"));
198 r55.events.push(generate_test_key_1_relay_list_event());
199
200 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
201 cli_tester_create_prs()?;
202
203 let test_repo = GitTestRepo::default();
204 test_repo.populate()?;
205
206 create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", false)?;
207
208 let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]);
209 p.expect("finding PR event...\r\n")?;
210 p.expect("found PR event. finding commits...\r\n")?;
211 p.expect("Error: nostr pr already up-to-date with local branch\r\n")?;
212 p.expect_end()?;
213
214 for p in [51, 52, 53, 55, 56] {
215 relay::shutdown_relay(8000 + p)?;
216 }
217 Ok(())
218 });
219
220 // launch relay
221 let _ = join!(
222 r51.listen_until_close(),
223 r52.listen_until_close(),
224 r53.listen_until_close(),
225 r55.listen_until_close(),
226 r56.listen_until_close(),
227 );
228 cli_tester_handle.join().unwrap()?;
229 Ok(())
230 }
231
232 #[test]
233 #[serial]
234 fn cli_show_up_to_date() -> Result<()> {
235 futures::executor::block_on(run_async_cli_show_up_to_date())
236 }
237 }
238 }
239
240 mod when_branch_is_behind {
241 use super::*;
242
243 mod cli_prompts {
244 use super::*;
245 async fn run_async_cli_show_up_to_date() -> Result<()> {
246 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
247 Relay::new(8051, None, None),
248 Relay::new(8052, None, None),
249 Relay::new(8053, None, None),
250 Relay::new(8055, None, None),
251 Relay::new(8056, None, None),
252 );
253
254 r51.events.push(generate_test_key_1_relay_list_event());
255 r51.events.push(generate_test_key_1_metadata_event("fred"));
256 r51.events.push(generate_repo_ref_event());
257
258 r55.events.push(generate_repo_ref_event());
259 r55.events.push(generate_test_key_1_metadata_event("fred"));
260 r55.events.push(generate_test_key_1_relay_list_event());
261
262 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
263 cli_tester_create_prs()?;
264
265 let test_repo = GitTestRepo::default();
266 test_repo.populate()?;
267
268 create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", true)?;
269
270 let mut p = CliTester::new_from_dir(&test_repo.dir, ["push"]);
271 p.expect("finding PR event...\r\n")?;
272 p.expect("found PR event. finding commits...\r\n")?;
273 p.expect("Error: nostr pr is ahead of local branch\r\n")?;
274 p.expect_end()?;
275
276 for p in [51, 52, 53, 55, 56] {
277 relay::shutdown_relay(8000 + p)?;
278 }
279 Ok(())
280 });
281
282 // launch relay
283 let _ = join!(
284 r51.listen_until_close(),
285 r52.listen_until_close(),
286 r53.listen_until_close(),
287 r55.listen_until_close(),
288 r56.listen_until_close(),
289 );
290 cli_tester_handle.join().unwrap()?;
291 Ok(())
292 }
293
294 #[test]
295 #[serial]
296 fn cli_show_up_to_date() -> Result<()> {
297 futures::executor::block_on(run_async_cli_show_up_to_date())
298 }
299 }
300 }
301
302 mod when_branch_is_ahead {
303 use super::*;
304
305 mod cli_prompts {
306 use test_utils::relay::expect_send_with_progress;
307
308 use super::*;
309
310 async fn run_async_cli_applied_1_commit() -> Result<()> {
311 // fallback (51,52) user write (53, 55) repo (55, 56)
312 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
313 Relay::new(8051, None, None),
314 Relay::new(8052, None, None),
315 Relay::new(8053, None, None),
316 Relay::new(8055, None, None),
317 Relay::new(8056, None, None),
318 );
319
320 r51.events.push(generate_test_key_1_relay_list_event());
321 r51.events.push(generate_test_key_1_metadata_event("fred"));
322 r51.events.push(generate_repo_ref_event());
323
324 r55.events.push(generate_repo_ref_event());
325 r55.events.push(generate_test_key_1_metadata_event("fred"));
326 r55.events.push(generate_test_key_1_relay_list_event());
327
328 let cli_tester_handle =
329 std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> {
330 let originating_repo = cli_tester_create_prs()?;
331
332 let test_repo = GitTestRepo::default();
333 test_repo.populate()?;
334
335 create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", false)?;
336
337 std::fs::write(test_repo.dir.join("a5.md"), "some content")?;
338 test_repo.stage_and_commit("add a5.md".to_string().as_str())?;
339
340 let mut p = CliTester::new_from_dir(
341 &test_repo.dir,
342 [
343 "--nsec",
344 TEST_KEY_1_NSEC,
345 "--password",
346 TEST_PASSWORD,
347 "--disable-cli-spinners",
348 "push",
349 ],
350 );
351 p.expect("finding PR event...\r\n")?;
352 p.expect("found PR event. finding commits...\r\n")?;
353 p.expect(
354 "1 commits ahead. preparing to create creating patch events.\r\n",
355 )?;
356 p.expect("searching for your details...\r\n")?;
357 p.expect("\r")?;
358 p.expect("logged in as fred\r\n")?;
359 p.expect("pushing 1 commits\r\n")?;
360
361 expect_send_with_progress(
362 &mut p,
363 vec![
364 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
365 (" [my-relay] ws://localhost:8053", true, ""),
366 (" [repo-relay] ws://localhost:8056", true, ""),
367 ],
368 1,
369 )?;
370 p.expect_eventually("pushed 1 commits\r\n")?;
371 p.expect_end()?;
372
373 for p in [51, 52, 53, 55, 56] {
374 relay::shutdown_relay(8000 + p)?;
375 }
376 Ok((originating_repo, test_repo))
377 });
378
379 // launch relay
380 let _ = join!(
381 r51.listen_until_close(),
382 r52.listen_until_close(),
383 r53.listen_until_close(),
384 r55.listen_until_close(),
385 r56.listen_until_close(),
386 );
387 cli_tester_handle.join().unwrap()?;
388
389 Ok(())
390 }
391
392 #[test]
393 #[serial]
394 fn cli_applied_1_commit() -> Result<()> {
395 futures::executor::block_on(run_async_cli_applied_1_commit())
396 }
397 }
398
399 async fn prep_and_run() -> Result<(GitTestRepo, Vec<nostr::Event>)> {
400 // fallback (51,52) user write (53, 55) repo (55, 56)
401 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
402 Relay::new(8051, None, None),
403 Relay::new(8052, None, None),
404 Relay::new(8053, None, None),
405 Relay::new(8055, None, None),
406 Relay::new(8056, None, None),
407 );
408
409 r51.events.push(generate_test_key_1_relay_list_event());
410 r51.events.push(generate_test_key_1_metadata_event("fred"));
411 r51.events.push(generate_repo_ref_event());
412
413 r55.events.push(generate_repo_ref_event());
414 r55.events.push(generate_test_key_1_metadata_event("fred"));
415 r55.events.push(generate_test_key_1_relay_list_event());
416
417 let cli_tester_handle = std::thread::spawn(move || -> Result<GitTestRepo> {
418 cli_tester_create_prs()?;
419
420 let test_repo = GitTestRepo::default();
421 test_repo.populate()?;
422
423 create_and_populate_branch(&test_repo, FEATURE_BRANCH_NAME_1, "a", false)?;
424
425 let mut p = CliTester::new_from_dir(
426 &test_repo.dir,
427 [
428 "--nsec",
429 TEST_KEY_1_NSEC,
430 "--password",
431 TEST_PASSWORD,
432 "--disable-cli-spinners",
433 "push",
434 ],
435 );
436 p.expect_end_eventually()?;
437
438 for p in [51, 52, 53, 55, 56] {
439 relay::shutdown_relay(8000 + p)?;
440 }
441 Ok(test_repo)
442 });
443
444 // launch relay
445 let _ = join!(
446 r51.listen_until_close(),
447 r52.listen_until_close(),
448 r53.listen_until_close(),
449 r55.listen_until_close(),
450 r56.listen_until_close(),
451 );
452 let res = cli_tester_handle.join().unwrap()?;
453
454 Ok((res, r55.events.clone()))
455 }
456 #[test]
457 #[serial]
458 fn commits_issued_as_patch_event() -> Result<()> {
459 let (test_repo, r55_events) = futures::executor::block_on(prep_and_run())?;
460
461 let commit_id = test_repo
462 .get_tip_of_local_branch(FEATURE_BRANCH_NAME_1)?
463 .to_string();
464 assert!(r55_events.iter().any(|e| {
465 e.tags
466 .iter()
467 .any(|t| t.as_vec()[0].eq("commit") && t.as_vec()[1].eq(&commit_id))
468 }));
469 Ok(())
470 }
471 }
472
473 mod when_branch_has_been_rebased {
474 // use super::*;
475 // TODO
476 }
477}