1use std::collections::HashMap;
2
3use crate::commit::commits_to_conventional_commits;
4use crate::error::Result;
5use crate::{
6 commit::{
7 Commit,
8 Range,
9 },
10 config::Bump,
11 config::BumpType,
12};
13#[cfg(feature = "remote")]
14use crate::{
15 contributor::RemoteContributor,
16 remote::{
17 RemoteCommit,
18 RemotePullRequest,
19 RemoteReleaseMetadata,
20 },
21};
22
23use next_version::{
24 NextVersion,
25 VersionUpdater,
26};
27use semver::Version;
28use serde::{
29 Deserialize,
30 Serialize,
31};
32use serde_json::value::Value;
33
34#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
36#[serde(rename_all(serialize = "camelCase"))]
37pub struct Release<'a> {
38 pub version: Option<String>,
40 pub message: Option<String>,
42 #[serde(deserialize_with = "commits_to_conventional_commits")]
44 pub commits: Vec<Commit<'a>>,
45 #[serde(rename = "commit_id")]
47 pub commit_id: Option<String>,
48 pub timestamp: i64,
50 pub previous: Option<Box<Release<'a>>>,
52 pub repository: Option<String>,
54 #[serde(rename = "commit_range")]
56 pub commit_range: Option<Range>,
57 #[serde(rename = "submodule_commits")]
61 pub submodule_commits: HashMap<String, Vec<Commit<'a>>>,
62 pub extra: Option<Value>,
64 #[cfg(feature = "github")]
66 pub github: RemoteReleaseMetadata,
67 #[cfg(feature = "gitlab")]
69 pub gitlab: RemoteReleaseMetadata,
70 #[cfg(feature = "gitea")]
72 pub gitea: RemoteReleaseMetadata,
73 #[cfg(feature = "bitbucket")]
75 pub bitbucket: RemoteReleaseMetadata,
76}
77
78#[cfg(feature = "github")]
79crate::update_release_metadata!(github, update_github_metadata);
80
81#[cfg(feature = "gitlab")]
82crate::update_release_metadata!(gitlab, update_gitlab_metadata);
83
84#[cfg(feature = "gitea")]
85crate::update_release_metadata!(gitea, update_gitea_metadata);
86
87#[cfg(feature = "bitbucket")]
88crate::update_release_metadata!(bitbucket, update_bitbucket_metadata);
89
90impl Release<'_> {
91 pub fn calculate_next_version(&self) -> Result<String> {
96 self.calculate_next_version_with_config(&Bump::default())
97 }
98
99 pub(super) fn calculate_next_version_with_config(
104 &self,
105 config: &Bump,
106 ) -> Result<String> {
107 match self
108 .previous
109 .as_ref()
110 .and_then(|release| release.version.clone())
111 {
112 Some(version) => {
113 let mut semver = Version::parse(&version);
114 let mut prefix = None;
115 if semver.is_err() && version.split('.').count() >= 2 {
116 let mut found_numeric = false;
117 for (i, c) in version.char_indices() {
118 if c.is_numeric() && !found_numeric {
119 found_numeric = true;
120 let version_prefix = version[..i].to_string();
121 let remaining = version[i..].to_string();
122 let version = Version::parse(&remaining);
123 if version.is_ok() {
124 semver = version;
125 prefix = Some(version_prefix);
126 break;
127 }
128 } else if !c.is_numeric() && found_numeric {
129 found_numeric = false;
130 }
131 }
132 }
133 let mut next_version = VersionUpdater::new()
134 .with_features_always_increment_minor(
135 config.features_always_bump_minor.unwrap_or(true),
136 )
137 .with_breaking_always_increment_major(
138 config.breaking_always_bump_major.unwrap_or(true),
139 );
140 if let Some(custom_major_increment_regex) =
141 &config.custom_major_increment_regex
142 {
143 next_version = next_version.with_custom_major_increment_regex(
144 custom_major_increment_regex,
145 )?;
146 }
147 if let Some(custom_minor_increment_regex) =
148 &config.custom_minor_increment_regex
149 {
150 next_version = next_version.with_custom_minor_increment_regex(
151 custom_minor_increment_regex,
152 )?;
153 }
154 let next_version = if let Some(bump_type) = &config.bump_type {
155 match bump_type {
156 BumpType::Major => semver?.increment_major().to_string(),
157 BumpType::Minor => semver?.increment_minor().to_string(),
158 BumpType::Patch => semver?.increment_patch().to_string(),
159 }
160 } else {
161 next_version
162 .increment(
163 &semver?,
164 self.commits
165 .iter()
166 .map(|commit| commit.message.trim_end().to_string())
167 .collect::<Vec<String>>(),
168 )
169 .to_string()
170 };
171 if let Some(prefix) = prefix {
172 Ok(format!("{prefix}{next_version}"))
173 } else {
174 Ok(next_version)
175 }
176 }
177 None => Ok(config.get_initial_tag()),
178 }
179 }
180}
181
182#[derive(Serialize)]
184pub struct Releases<'a> {
185 pub releases: &'a Vec<Release<'a>>,
187}
188
189impl Releases<'_> {
190 pub fn as_json(&self) -> Result<String> {
192 Ok(serde_json::to_string(self.releases)?)
193 }
194}
195
196#[cfg(test)]
197mod test {
198 use super::*;
199 use pretty_assertions::assert_eq;
200 #[test]
201 fn bump_version() -> Result<()> {
202 fn build_release<'a>(version: &str, commits: &'a [&str]) -> Release<'a> {
203 Release {
204 version: None,
205 message: None,
206 extra: None,
207 commits: commits
208 .iter()
209 .map(|v| Commit::from(v.to_string()))
210 .collect(),
211 commit_range: None,
212 commit_id: None,
213 timestamp: 0,
214 previous: Some(Box::new(Release {
215 version: Some(String::from(version)),
216 ..Default::default()
217 })),
218 repository: Some(String::from("/root/repo")),
219 submodule_commits: HashMap::new(),
220 #[cfg(feature = "github")]
221 github: crate::remote::RemoteReleaseMetadata {
222 contributors: vec![],
223 },
224 #[cfg(feature = "gitlab")]
225 gitlab: crate::remote::RemoteReleaseMetadata {
226 contributors: vec![],
227 },
228 #[cfg(feature = "gitea")]
229 gitea: crate::remote::RemoteReleaseMetadata {
230 contributors: vec![],
231 },
232 #[cfg(feature = "bitbucket")]
233 bitbucket: crate::remote::RemoteReleaseMetadata {
234 contributors: vec![],
235 },
236 }
237 }
238
239 let test_shared = [
240 ("1.0.0", "1.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
241 ("1.0.0", "1.0.1", vec!["fix: add xyz", "fix: aaaaaa"]),
242 ("1.0.0", "2.0.0", vec!["feat!: add xyz", "feat: zzz"]),
243 ("1.0.0", "2.0.0", vec!["feat!: add xyz\n", "feat: zzz\n"]),
244 ("2.0.0", "2.0.1", vec!["fix: something"]),
245 ("foo/1.0.0", "foo/1.1.0", vec![
246 "feat: add xyz",
247 "fix: fix xyz",
248 ]),
249 ("bar/1.0.0", "bar/2.0.0", vec![
250 "fix: add xyz",
251 "fix!: aaaaaa",
252 ]),
253 ("zzz-123/test/1.0.0", "zzz-123/test/1.0.1", vec![
254 "fix: aaaaaa",
255 ]),
256 ("v100.0.0", "v101.0.0", vec!["feat!: something"]),
257 ("v1.0.0-alpha.1", "v1.0.0-alpha.2", vec!["fix: minor"]),
258 ("testing/v1.0.0-beta.1", "testing/v1.0.0-beta.2", vec![
259 "feat: nice",
260 ]),
261 ("tauri-v1.5.4", "tauri-v1.6.0", vec!["feat: something"]),
262 (
263 "rocket/rocket-v4.0.0-rc.1",
264 "rocket/rocket-v4.0.0-rc.2",
265 vec!["chore!: wow"],
266 ),
267 (
268 "aaa#/@#$@9384!#%^#@#@!#!239432413-idk-9999.2200.5932-alpha.419",
269 "aaa#/@#$@9384!#%^#@#@!#!239432413-idk-9999.2200.5932-alpha.420",
270 vec!["feat: damn this is working"],
271 ),
272 ];
273
274 for (version, expected_version, commits) in test_shared.iter().chain(
275 [
276 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
277 ("0.0.1", "0.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
278 ("0.0.1", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
279 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
280 ("0.1.0", "0.2.0", vec!["feat: add xyz", "fix: fix xyz"]),
281 ("0.1.0", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
282 ]
283 .iter(),
284 ) {
285 let release = build_release(version, commits);
286 let next_version = release.calculate_next_version()?;
287 assert_eq!(expected_version, &next_version);
288 let next_version =
289 release.calculate_next_version_with_config(&Bump::default())?;
290 assert_eq!(expected_version, &next_version);
291 }
292
293 for (version, expected_version, commits) in test_shared.iter().chain(
294 [
295 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
296 ("0.0.1", "0.0.2", vec!["feat: add xyz", "fix: fix xyz"]),
297 ("0.0.1", "0.0.2", vec!["feat!: add xyz", "feat: zzz"]),
298 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
299 ("0.1.0", "0.1.1", vec!["feat: add xyz", "fix: fix xyz"]),
300 ("0.1.0", "0.2.0", vec!["feat!: add xyz", "feat: zzz"]),
301 ]
302 .iter(),
303 ) {
304 let release = build_release(version, commits);
305 let next_version =
306 release.calculate_next_version_with_config(&Bump {
307 features_always_bump_minor: Some(false),
308 breaking_always_bump_major: Some(false),
309 initial_tag: None,
310 custom_major_increment_regex: None,
311 custom_minor_increment_regex: None,
312 bump_type: None,
313 })?;
314 assert_eq!(expected_version, &next_version);
315 }
316
317 for (version, expected_version, commits) in test_shared.iter().chain(
318 [
319 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
320 ("0.0.1", "0.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
321 ("0.0.1", "0.1.0", vec!["feat!: add xyz", "feat: zzz"]),
322 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
323 ("0.1.0", "0.2.0", vec!["feat: add xyz", "fix: fix xyz"]),
324 ("0.1.0", "0.2.0", vec!["feat!: add xyz", "feat: zzz"]),
325 ]
326 .iter(),
327 ) {
328 let release = build_release(version, commits);
329 let next_version =
330 release.calculate_next_version_with_config(&Bump {
331 features_always_bump_minor: Some(true),
332 breaking_always_bump_major: Some(false),
333 initial_tag: None,
334 custom_major_increment_regex: None,
335 custom_minor_increment_regex: None,
336 bump_type: None,
337 })?;
338 assert_eq!(expected_version, &next_version);
339 }
340
341 for (version, expected_version, commits) in test_shared.iter().chain(
342 [
343 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
344 ("0.0.1", "0.0.2", vec!["feat: add xyz", "fix: fix xyz"]),
345 ("0.0.1", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
346 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
347 ("0.1.0", "0.1.1", vec!["feat: add xyz", "fix: fix xyz"]),
348 ("0.1.0", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
349 ]
350 .iter(),
351 ) {
352 let release = build_release(version, commits);
353 let next_version =
354 release.calculate_next_version_with_config(&Bump {
355 features_always_bump_minor: Some(false),
356 breaking_always_bump_major: Some(true),
357 initial_tag: None,
358 custom_major_increment_regex: None,
359 custom_minor_increment_regex: None,
360 bump_type: None,
361 })?;
362 assert_eq!(expected_version, &next_version);
363 }
364
365 let empty_release = Release {
366 previous: Some(Box::new(Release {
367 version: None,
368 ..Default::default()
369 })),
370 ..Default::default()
371 };
372 assert_eq!("0.1.0", empty_release.calculate_next_version()?);
373 for (features_always_bump_minor, breaking_always_bump_major) in
374 [(true, true), (true, false), (false, true), (false, false)]
375 {
376 assert_eq!(
377 "0.1.0",
378 empty_release.calculate_next_version_with_config(&Bump {
379 features_always_bump_minor: Some(features_always_bump_minor),
380 breaking_always_bump_major: Some(breaking_always_bump_major),
381 initial_tag: None,
382 custom_major_increment_regex: None,
383 custom_minor_increment_regex: None,
384 bump_type: None,
385 })?
386 );
387 }
388 Ok(())
389 }
390
391 #[cfg(feature = "github")]
392 #[test]
393 fn update_github_metadata() -> Result<()> {
394 use crate::remote::github::{
395 GitHubCommit,
396 GitHubCommitAuthor,
397 GitHubCommitDetails,
398 GitHubCommitDetailsAuthor,
399 GitHubPullRequest,
400 PullRequestLabel,
401 };
402
403 let mut release = Release {
404 version: None,
405 message: None,
406 extra: None,
407 commits: vec![
408 Commit::from(String::from(
409 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
410 integration",
411 )),
412 Commit::from(String::from(
413 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github \
414 integration",
415 )),
416 Commit::from(String::from(
417 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
418 )),
419 Commit::from(String::from(
420 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
421 )),
422 Commit::from(String::from(
423 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
424 )),
425 Commit::from(String::from(
426 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
427 )),
428 ],
429 commit_range: None,
430 commit_id: None,
431 timestamp: 0,
432 previous: Some(Box::new(Release {
433 version: Some(String::from("1.0.0")),
434 ..Default::default()
435 })),
436 repository: Some(String::from("/root/repo")),
437 submodule_commits: HashMap::new(),
438 github: RemoteReleaseMetadata {
439 contributors: vec![],
440 },
441 #[cfg(feature = "gitlab")]
442 gitlab: RemoteReleaseMetadata {
443 contributors: vec![],
444 },
445 #[cfg(feature = "gitea")]
446 gitea: RemoteReleaseMetadata {
447 contributors: vec![],
448 },
449 #[cfg(feature = "bitbucket")]
450 bitbucket: RemoteReleaseMetadata {
451 contributors: vec![],
452 },
453 };
454 release.update_github_metadata(
455 vec![
456 GitHubCommit {
457 sha: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
458 author: Some(GitHubCommitAuthor {
459 login: Some(String::from("orhun")),
460 }),
461 commit: Some(GitHubCommitDetails {
462 author: GitHubCommitDetailsAuthor {
463 date: String::from("2021-07-18T15:14:39+03:00"),
464 },
465 }),
466 },
467 GitHubCommit {
468 sha: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
469 author: Some(GitHubCommitAuthor {
470 login: Some(String::from("orhun")),
471 }),
472 commit: Some(GitHubCommitDetails {
473 author: GitHubCommitDetailsAuthor {
474 date: String::from("2021-07-18T15:12:19+03:00"),
475 },
476 }),
477 },
478 GitHubCommit {
479 sha: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
480 author: Some(GitHubCommitAuthor {
481 login: Some(String::from("nuhro")),
482 }),
483 commit: Some(GitHubCommitDetails {
484 author: GitHubCommitDetailsAuthor {
485 date: String::from("2021-07-18T15:07:23+03:00"),
486 },
487 }),
488 },
489 GitHubCommit {
490 sha: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
491 author: Some(GitHubCommitAuthor {
492 login: Some(String::from("awesome_contributor")),
493 }),
494 commit: Some(GitHubCommitDetails {
495 author: GitHubCommitDetailsAuthor {
496 date: String::from("2021-07-18T15:05:10+03:00"),
497 },
498 }),
499 },
500 GitHubCommit {
501 sha: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
502 author: Some(GitHubCommitAuthor {
503 login: Some(String::from("orhun")),
504 }),
505 commit: Some(GitHubCommitDetails {
506 author: GitHubCommitDetailsAuthor {
507 date: String::from("2021-07-18T15:03:30+03:00"),
508 },
509 }),
510 },
511 GitHubCommit {
512 sha: String::from("6c34967147560ea09658776d4901709139b4ad66"),
513 author: Some(GitHubCommitAuthor {
514 login: Some(String::from("someone")),
515 }),
516 commit: Some(GitHubCommitDetails {
517 author: GitHubCommitDetailsAuthor {
518 date: String::from("2021-07-18T15:00:38+03:00"),
519 },
520 }),
521 },
522 GitHubCommit {
523 sha: String::from("0c34967147560e809658776d4901709139b4ad68"),
524 author: Some(GitHubCommitAuthor {
525 login: Some(String::from("idk")),
526 }),
527 commit: Some(GitHubCommitDetails {
528 author: GitHubCommitDetailsAuthor {
529 date: String::from("2021-07-18T15:00:38+03:00"),
530 },
531 }),
532 },
533 GitHubCommit {
534 sha: String::from("kk34967147560e809658776d4901709139b4ad68"),
535 author: None,
536 commit: None,
537 },
538 GitHubCommit {
539 sha: String::new(),
540 author: None,
541 commit: None,
542 },
543 ]
544 .into_iter()
545 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
546 .collect(),
547 vec![
548 GitHubPullRequest {
549 title: Some(String::from("1")),
550 number: 42,
551 merge_commit_sha: Some(String::from(
552 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
553 )),
554 labels: vec![PullRequestLabel {
555 name: String::from("rust"),
556 }],
557 },
558 GitHubPullRequest {
559 title: Some(String::from("2")),
560 number: 66,
561 merge_commit_sha: Some(String::from(
562 "21f6aa587fcb772de13f2fde0e92697c51f84162",
563 )),
564 labels: vec![PullRequestLabel {
565 name: String::from("rust"),
566 }],
567 },
568 GitHubPullRequest {
569 title: Some(String::from("3")),
570 number: 53,
571 merge_commit_sha: Some(String::from(
572 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973",
573 )),
574 labels: vec![PullRequestLabel {
575 name: String::from("deps"),
576 }],
577 },
578 GitHubPullRequest {
579 title: Some(String::from("4")),
580 number: 1000,
581 merge_commit_sha: Some(String::from(
582 "4d3ffe4753b923f4d7807c490e650e6624a12074",
583 )),
584 labels: vec![PullRequestLabel {
585 name: String::from("deps"),
586 }],
587 },
588 GitHubPullRequest {
589 title: Some(String::from("5")),
590 number: 999999,
591 merge_commit_sha: Some(String::from(
592 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05",
593 )),
594 labels: vec![PullRequestLabel {
595 name: String::from("github"),
596 }],
597 },
598 ]
599 .into_iter()
600 .map(|v| Box::new(v) as Box<dyn RemotePullRequest>)
601 .collect(),
602 )?;
603 #[allow(deprecated)]
604 let expected_commits = vec![
605 Commit {
606 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
607 message: String::from("add github integration"),
608 github: RemoteContributor {
609 username: Some(String::from("orhun")),
610 pr_title: Some(String::from("1")),
611 pr_number: Some(42),
612 pr_labels: vec![String::from("rust")],
613 is_first_time: false,
614 },
615 remote: Some(RemoteContributor {
616 username: Some(String::from("orhun")),
617 pr_title: Some(String::from("1")),
618 pr_number: Some(42),
619 pr_labels: vec![String::from("rust")],
620 is_first_time: false,
621 }),
622 ..Default::default()
623 },
624 Commit {
625 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
626 message: String::from("fix github integration"),
627 github: RemoteContributor {
628 username: Some(String::from("orhun")),
629 pr_title: Some(String::from("2")),
630 pr_number: Some(66),
631 pr_labels: vec![String::from("rust")],
632 is_first_time: false,
633 },
634 remote: Some(RemoteContributor {
635 username: Some(String::from("orhun")),
636 pr_title: Some(String::from("2")),
637 pr_number: Some(66),
638 pr_labels: vec![String::from("rust")],
639 is_first_time: false,
640 }),
641 ..Default::default()
642 },
643 Commit {
644 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
645 message: String::from("update metadata"),
646 github: RemoteContributor {
647 username: Some(String::from("nuhro")),
648 pr_title: Some(String::from("3")),
649 pr_number: Some(53),
650 pr_labels: vec![String::from("deps")],
651 is_first_time: false,
652 },
653 remote: Some(RemoteContributor {
654 username: Some(String::from("nuhro")),
655 pr_title: Some(String::from("3")),
656 pr_number: Some(53),
657 pr_labels: vec![String::from("deps")],
658 is_first_time: false,
659 }),
660 ..Default::default()
661 },
662 Commit {
663 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
664 message: String::from("do some stuff"),
665 github: RemoteContributor {
666 username: Some(String::from("awesome_contributor")),
667 pr_title: Some(String::from("4")),
668 pr_number: Some(1000),
669 pr_labels: vec![String::from("deps")],
670 is_first_time: false,
671 },
672 remote: Some(RemoteContributor {
673 username: Some(String::from("awesome_contributor")),
674 pr_title: Some(String::from("4")),
675 pr_number: Some(1000),
676 pr_labels: vec![String::from("deps")],
677 is_first_time: false,
678 }),
679 ..Default::default()
680 },
681 Commit {
682 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
683 message: String::from("alright"),
684 github: RemoteContributor {
685 username: Some(String::from("orhun")),
686 pr_title: Some(String::from("5")),
687 pr_number: Some(999999),
688 pr_labels: vec![String::from("github")],
689 is_first_time: false,
690 },
691 remote: Some(RemoteContributor {
692 username: Some(String::from("orhun")),
693 pr_title: Some(String::from("5")),
694 pr_number: Some(999999),
695 pr_labels: vec![String::from("github")],
696 is_first_time: false,
697 }),
698 ..Default::default()
699 },
700 Commit {
701 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
702 message: String::from("should be fine"),
703 github: RemoteContributor {
704 username: Some(String::from("someone")),
705 pr_title: None,
706 pr_number: None,
707 pr_labels: vec![],
708 is_first_time: false,
709 },
710 remote: Some(RemoteContributor {
711 username: Some(String::from("someone")),
712 pr_title: None,
713 pr_number: None,
714 pr_labels: vec![],
715 is_first_time: false,
716 }),
717 ..Default::default()
718 },
719 ];
720 assert_eq!(expected_commits, release.commits);
721
722 release
723 .github
724 .contributors
725 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
726
727 let expected_metadata = RemoteReleaseMetadata {
728 contributors: vec![
729 RemoteContributor {
730 username: Some(String::from("someone")),
731 pr_title: None,
732 pr_number: None,
733 pr_labels: vec![],
734 is_first_time: true,
735 },
736 RemoteContributor {
737 username: Some(String::from("orhun")),
738 pr_title: Some(String::from("1")),
739 pr_number: Some(42),
740 pr_labels: vec![String::from("rust")],
741 is_first_time: true,
742 },
743 RemoteContributor {
744 username: Some(String::from("nuhro")),
745 pr_title: Some(String::from("3")),
746 pr_number: Some(53),
747 pr_labels: vec![String::from("deps")],
748 is_first_time: true,
749 },
750 RemoteContributor {
751 username: Some(String::from("awesome_contributor")),
752 pr_title: Some(String::from("4")),
753 pr_number: Some(1000),
754 pr_labels: vec![String::from("deps")],
755 is_first_time: true,
756 },
757 ],
758 };
759 assert_eq!(expected_metadata, release.github);
760
761 Ok(())
762 }
763
764 #[cfg(feature = "gitlab")]
765 #[test]
766 fn update_gitlab_metadata() -> Result<()> {
767 use crate::remote::gitlab::{
768 GitLabCommit,
769 GitLabMergeRequest,
770 GitLabUser,
771 };
772
773 let mut release = Release {
774 version: None,
775 message: None,
776 extra: None,
777 commits: vec![
778 Commit::from(String::from(
779 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
780 integration",
781 )),
782 Commit::from(String::from(
783 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github \
784 integration",
785 )),
786 Commit::from(String::from(
787 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
788 )),
789 Commit::from(String::from(
790 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
791 )),
792 Commit::from(String::from(
793 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
794 )),
795 Commit::from(String::from(
796 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
797 )),
798 ],
799 commit_range: None,
800 commit_id: None,
801 timestamp: 0,
802 previous: Some(Box::new(Release {
803 version: Some(String::from("1.0.0")),
804 ..Default::default()
805 })),
806 repository: Some(String::from("/root/repo")),
807 submodule_commits: HashMap::new(),
808 #[cfg(feature = "github")]
809 github: RemoteReleaseMetadata {
810 contributors: vec![],
811 },
812 #[cfg(feature = "gitlab")]
813 gitlab: RemoteReleaseMetadata {
814 contributors: vec![],
815 },
816 #[cfg(feature = "gitea")]
817 gitea: RemoteReleaseMetadata {
818 contributors: vec![],
819 },
820 #[cfg(feature = "bitbucket")]
821 bitbucket: RemoteReleaseMetadata {
822 contributors: vec![],
823 },
824 };
825 release.update_gitlab_metadata(
826 vec![
827 GitLabCommit {
828 id: String::from(
829 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
830 ),
831 author_name: String::from("orhun"),
832 short_id: String::from(""),
833 title: String::from(""),
834 author_email: String::from(""),
835 authored_date: String::from(""),
836 committer_name: String::from(""),
837 committer_email: String::from(""),
838 committed_date: String::from(""),
839 created_at: String::from(""),
840 message: String::from(""),
841 parent_ids: vec![],
842 web_url: String::from(""),
843 },
844 GitLabCommit {
845 id: String::from(
846 "21f6aa587fcb772de13f2fde0e92697c51f84162",
847 ),
848 author_name: String::from("orhun"),
849 short_id: String::from(""),
850 title: String::from(""),
851 author_email: String::from(""),
852 authored_date: String::from(""),
853 committer_name: String::from(""),
854 committer_email: String::from(""),
855 committed_date: String::from(""),
856 created_at: String::from(""),
857 message: String::from(""),
858 parent_ids: vec![],
859 web_url: String::from(""),
860 },
861 GitLabCommit {
862 id: String::from(
863 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973",
864 ),
865 author_name: String::from("nuhro"),
866 short_id: String::from(""),
867 title: String::from(""),
868 author_email: String::from(""),
869 authored_date: String::from(""),
870 committer_name: String::from(""),
871 committer_email: String::from(""),
872 committed_date: String::from(""),
873 created_at: String::from(""),
874 message: String::from(""),
875 parent_ids: vec![],
876 web_url: String::from(""),
877 },
878 GitLabCommit {
879 id: String::from(
880 "4d3ffe4753b923f4d7807c490e650e6624a12074",
881 ),
882 author_name: String::from("awesome_contributor"),
883 short_id: String::from(""),
884 title: String::from(""),
885 author_email: String::from(""),
886 authored_date: String::from(""),
887 committer_name: String::from(""),
888 committer_email: String::from(""),
889 committed_date: String::from(""),
890 created_at: String::from(""),
891 message: String::from(""),
892 parent_ids: vec![],
893 web_url: String::from(""),
894 },
895 GitLabCommit {
896 id: String::from(
897 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05",
898 ),
899 author_name: String::from("orhun"),
900 short_id: String::from(""),
901 title: String::from(""),
902 author_email: String::from(""),
903 authored_date: String::from(""),
904 committer_name: String::from(""),
905 committer_email: String::from(""),
906 committed_date: String::from(""),
907 created_at: String::from(""),
908 message: String::from(""),
909 parent_ids: vec![],
910 web_url: String::from(""),
911 },
912 GitLabCommit {
913 id: String::from(
914 "6c34967147560ea09658776d4901709139b4ad66",
915 ),
916 author_name: String::from("someone"),
917 short_id: String::from(""),
918 title: String::from(""),
919 author_email: String::from(""),
920 authored_date: String::from(""),
921 committer_name: String::from(""),
922 committer_email: String::from(""),
923 committed_date: String::from(""),
924 created_at: String::from(""),
925 message: String::from(""),
926 parent_ids: vec![],
927 web_url: String::from(""),
928 },
929 GitLabCommit {
930 id: String::from(
931 "0c34967147560e809658776d4901709139b4ad68",
932 ),
933 author_name: String::from("idk"),
934 short_id: String::from(""),
935 title: String::from(""),
936 author_email: String::from(""),
937 authored_date: String::from(""),
938 committer_name: String::from(""),
939 committer_email: String::from(""),
940 committed_date: String::from(""),
941 created_at: String::from(""),
942 message: String::from(""),
943 parent_ids: vec![],
944 web_url: String::from(""),
945 },
946 GitLabCommit {
947 id: String::from(
948 "kk34967147560e809658776d4901709139b4ad68",
949 ),
950 author_name: String::from("orhun"),
951 short_id: String::from(""),
952 title: String::from(""),
953 author_email: String::from(""),
954 authored_date: String::from(""),
955 committer_name: String::from(""),
956 committer_email: String::from(""),
957 committed_date: String::from(""),
958 created_at: String::from(""),
959 message: String::from(""),
960 parent_ids: vec![],
961 web_url: String::from(""),
962 },
963 ]
964 .into_iter()
965 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
966 .collect(),
967 vec![Box::new(GitLabMergeRequest {
968 title: String::from("1"),
969 merge_commit_sha: Some(String::from(
970 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
971 )),
972 id: 1,
973 iid: 1,
974 project_id: 1,
975 description: String::from(""),
976 state: String::from(""),
977 created_at: String::from(""),
978 author: GitLabUser {
979 id: 1,
980 name: String::from("42"),
981 username: String::from("42"),
982 state: String::from("42"),
983 avatar_url: None,
984 web_url: String::from("42"),
985 },
986 sha: String::from(
987 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
988 ),
989 web_url: String::from(""),
990 squash_commit_sha: None,
991 labels: vec![String::from("rust")],
992 })],
993 )?;
994 #[allow(deprecated)]
995 let expected_commits = vec![
996 Commit {
997 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
998 message: String::from("add github integration"),
999 gitlab: RemoteContributor {
1000 username: Some(String::from("orhun")),
1001 pr_title: Some(String::from("1")),
1002 pr_number: Some(1),
1003 pr_labels: vec![String::from("rust")],
1004 is_first_time: false,
1005 },
1006 remote: Some(RemoteContributor {
1007 username: Some(String::from("orhun")),
1008 pr_title: Some(String::from("1")),
1009 pr_number: Some(1),
1010 pr_labels: vec![String::from("rust")],
1011 is_first_time: false,
1012 }),
1013 ..Default::default()
1014 },
1015 Commit {
1016 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1017 message: String::from("fix github integration"),
1018 gitlab: RemoteContributor {
1019 username: Some(String::from("orhun")),
1020 pr_title: None,
1021 pr_number: None,
1022 pr_labels: vec![],
1023 is_first_time: false,
1024 },
1025 remote: Some(RemoteContributor {
1026 username: Some(String::from("orhun")),
1027 pr_title: None,
1028 pr_number: None,
1029 pr_labels: vec![],
1030 is_first_time: false,
1031 }),
1032 ..Default::default()
1033 },
1034 Commit {
1035 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1036 message: String::from("update metadata"),
1037 gitlab: RemoteContributor {
1038 username: Some(String::from("nuhro")),
1039 pr_title: None,
1040 pr_number: None,
1041 pr_labels: vec![],
1042 is_first_time: false,
1043 },
1044 remote: Some(RemoteContributor {
1045 username: Some(String::from("nuhro")),
1046 pr_title: None,
1047 pr_number: None,
1048 pr_labels: vec![],
1049 is_first_time: false,
1050 }),
1051 ..Default::default()
1052 },
1053 Commit {
1054 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1055 message: String::from("do some stuff"),
1056 gitlab: RemoteContributor {
1057 username: Some(String::from("awesome_contributor")),
1058 pr_title: None,
1059 pr_number: None,
1060 pr_labels: vec![],
1061 is_first_time: false,
1062 },
1063 remote: Some(RemoteContributor {
1064 username: Some(String::from("awesome_contributor")),
1065 pr_title: None,
1066 pr_number: None,
1067 pr_labels: vec![],
1068 is_first_time: false,
1069 }),
1070 ..Default::default()
1071 },
1072 Commit {
1073 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1074 message: String::from("alright"),
1075 gitlab: RemoteContributor {
1076 username: Some(String::from("orhun")),
1077 pr_title: None,
1078 pr_number: None,
1079 pr_labels: vec![],
1080 is_first_time: false,
1081 },
1082 remote: Some(RemoteContributor {
1083 username: Some(String::from("orhun")),
1084 pr_title: None,
1085 pr_number: None,
1086 pr_labels: vec![],
1087 is_first_time: false,
1088 }),
1089 ..Default::default()
1090 },
1091 Commit {
1092 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1093 message: String::from("should be fine"),
1094 gitlab: RemoteContributor {
1095 username: Some(String::from("someone")),
1096 pr_title: None,
1097 pr_number: None,
1098 pr_labels: vec![],
1099 is_first_time: false,
1100 },
1101 remote: Some(RemoteContributor {
1102 username: Some(String::from("someone")),
1103 pr_title: None,
1104 pr_number: None,
1105 pr_labels: vec![],
1106 is_first_time: false,
1107 }),
1108 ..Default::default()
1109 },
1110 ];
1111 assert_eq!(expected_commits, release.commits);
1112
1113 release
1114 .github
1115 .contributors
1116 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1117
1118 let expected_metadata = RemoteReleaseMetadata {
1119 contributors: vec![
1120 RemoteContributor {
1121 username: Some(String::from("orhun")),
1122 pr_title: Some(String::from("1")),
1123 pr_number: Some(1),
1124 pr_labels: vec![String::from("rust")],
1125 is_first_time: false,
1126 },
1127 RemoteContributor {
1128 username: Some(String::from("nuhro")),
1129 pr_title: None,
1130 pr_number: None,
1131 pr_labels: vec![],
1132 is_first_time: true,
1133 },
1134 RemoteContributor {
1135 username: Some(String::from("awesome_contributor")),
1136 pr_title: None,
1137 pr_number: None,
1138 pr_labels: vec![],
1139 is_first_time: true,
1140 },
1141 RemoteContributor {
1142 username: Some(String::from("someone")),
1143 pr_title: None,
1144 pr_number: None,
1145 pr_labels: vec![],
1146 is_first_time: true,
1147 },
1148 ],
1149 };
1150 assert_eq!(expected_metadata, release.gitlab);
1151
1152 Ok(())
1153 }
1154
1155 #[cfg(feature = "gitea")]
1156 #[test]
1157 fn update_gitea_metadata() -> Result<()> {
1158 use crate::remote::gitea::{
1159 GiteaCommit,
1160 GiteaCommitAuthor,
1161 GiteaPullRequest,
1162 PullRequestLabel,
1163 };
1164
1165 let mut release = Release {
1166 version: None,
1167 message: None,
1168 extra: None,
1169 commits: vec![
1170 Commit::from(String::from(
1171 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
1172 integration",
1173 )),
1174 Commit::from(String::from(
1175 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github \
1176 integration",
1177 )),
1178 Commit::from(String::from(
1179 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
1180 )),
1181 Commit::from(String::from(
1182 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
1183 )),
1184 Commit::from(String::from(
1185 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
1186 )),
1187 Commit::from(String::from(
1188 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
1189 )),
1190 ],
1191 commit_range: None,
1192 commit_id: None,
1193 timestamp: 0,
1194 previous: Some(Box::new(Release {
1195 version: Some(String::from("1.0.0")),
1196 ..Default::default()
1197 })),
1198 repository: Some(String::from("/root/repo")),
1199 submodule_commits: HashMap::new(),
1200 #[cfg(feature = "github")]
1201 github: RemoteReleaseMetadata {
1202 contributors: vec![],
1203 },
1204 #[cfg(feature = "gitlab")]
1205 gitlab: RemoteReleaseMetadata {
1206 contributors: vec![],
1207 },
1208 #[cfg(feature = "gitea")]
1209 gitea: RemoteReleaseMetadata {
1210 contributors: vec![],
1211 },
1212 #[cfg(feature = "bitbucket")]
1213 bitbucket: RemoteReleaseMetadata {
1214 contributors: vec![],
1215 },
1216 };
1217 release.update_gitea_metadata(
1218 vec![
1219 GiteaCommit {
1220 sha: String::from(
1221 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
1222 ),
1223 author: Some(GiteaCommitAuthor {
1224 login: Some(String::from("orhun")),
1225 }),
1226 created: String::from("2021-07-18T15:14:39+03:00"),
1227 },
1228 GiteaCommit {
1229 sha: String::from(
1230 "21f6aa587fcb772de13f2fde0e92697c51f84162",
1231 ),
1232 author: Some(GiteaCommitAuthor {
1233 login: Some(String::from("orhun")),
1234 }),
1235 created: String::from("2021-07-18T15:12:19+03:00"),
1236 },
1237 GiteaCommit {
1238 sha: String::from(
1239 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973",
1240 ),
1241 author: Some(GiteaCommitAuthor {
1242 login: Some(String::from("nuhro")),
1243 }),
1244 created: String::from("2021-07-18T15:07:23+03:00"),
1245 },
1246 GiteaCommit {
1247 sha: String::from(
1248 "4d3ffe4753b923f4d7807c490e650e6624a12074",
1249 ),
1250 author: Some(GiteaCommitAuthor {
1251 login: Some(String::from("awesome_contributor")),
1252 }),
1253 created: String::from("2021-07-18T15:05:10+03:00"),
1254 },
1255 GiteaCommit {
1256 sha: String::from(
1257 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05",
1258 ),
1259 author: Some(GiteaCommitAuthor {
1260 login: Some(String::from("orhun")),
1261 }),
1262 created: String::from("2021-07-18T15:03:30+03:00"),
1263 },
1264 GiteaCommit {
1265 sha: String::from(
1266 "6c34967147560ea09658776d4901709139b4ad66",
1267 ),
1268 author: Some(GiteaCommitAuthor {
1269 login: Some(String::from("someone")),
1270 }),
1271 created: String::from("2021-07-18T15:00:38+03:00"),
1272 },
1273 GiteaCommit {
1274 sha: String::from(
1275 "0c34967147560e809658776d4901709139b4ad68",
1276 ),
1277 author: Some(GiteaCommitAuthor {
1278 login: Some(String::from("idk")),
1279 }),
1280 created: String::from("2021-07-18T15:00:38+03:00"),
1281 },
1282 GiteaCommit {
1283 sha: String::from(
1284 "kk34967147560e809658776d4901709139b4ad68",
1285 ),
1286 author: None,
1287 created: String::new(),
1288 },
1289 GiteaCommit {
1290 sha: String::new(),
1291 author: None,
1292 created: String::new(),
1293 },
1294 ]
1295 .into_iter()
1296 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
1297 .collect(),
1298 vec![
1299 GiteaPullRequest {
1300 title: Some(String::from("1")),
1301 number: 42,
1302 merge_commit_sha: Some(String::from(
1303 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
1304 )),
1305 labels: vec![PullRequestLabel {
1306 name: String::from("rust"),
1307 }],
1308 },
1309 GiteaPullRequest {
1310 title: Some(String::from("2")),
1311 number: 66,
1312 merge_commit_sha: Some(String::from(
1313 "21f6aa587fcb772de13f2fde0e92697c51f84162",
1314 )),
1315 labels: vec![PullRequestLabel {
1316 name: String::from("rust"),
1317 }],
1318 },
1319 GiteaPullRequest {
1320 title: Some(String::from("3")),
1321 number: 53,
1322 merge_commit_sha: Some(String::from(
1323 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973",
1324 )),
1325 labels: vec![PullRequestLabel {
1326 name: String::from("deps"),
1327 }],
1328 },
1329 GiteaPullRequest {
1330 title: Some(String::from("4")),
1331 number: 1000,
1332 merge_commit_sha: Some(String::from(
1333 "4d3ffe4753b923f4d7807c490e650e6624a12074",
1334 )),
1335 labels: vec![PullRequestLabel {
1336 name: String::from("deps"),
1337 }],
1338 },
1339 GiteaPullRequest {
1340 title: Some(String::from("5")),
1341 number: 999999,
1342 merge_commit_sha: Some(String::from(
1343 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05",
1344 )),
1345 labels: vec![PullRequestLabel {
1346 name: String::from("github"),
1347 }],
1348 },
1349 ]
1350 .into_iter()
1351 .map(|v| Box::new(v) as Box<dyn RemotePullRequest>)
1352 .collect(),
1353 )?;
1354 #[allow(deprecated)]
1355 let expected_commits = vec![
1356 Commit {
1357 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1358 message: String::from("add github integration"),
1359 gitea: RemoteContributor {
1360 username: Some(String::from("orhun")),
1361 pr_title: Some(String::from("1")),
1362 pr_number: Some(42),
1363 pr_labels: vec![String::from("rust")],
1364 is_first_time: false,
1365 },
1366 remote: Some(RemoteContributor {
1367 username: Some(String::from("orhun")),
1368 pr_title: Some(String::from("1")),
1369 pr_number: Some(42),
1370 pr_labels: vec![String::from("rust")],
1371 is_first_time: false,
1372 }),
1373 ..Default::default()
1374 },
1375 Commit {
1376 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1377 message: String::from("fix github integration"),
1378 gitea: RemoteContributor {
1379 username: Some(String::from("orhun")),
1380 pr_title: Some(String::from("2")),
1381 pr_number: Some(66),
1382 pr_labels: vec![String::from("rust")],
1383 is_first_time: false,
1384 },
1385 remote: Some(RemoteContributor {
1386 username: Some(String::from("orhun")),
1387 pr_title: Some(String::from("2")),
1388 pr_number: Some(66),
1389 pr_labels: vec![String::from("rust")],
1390 is_first_time: false,
1391 }),
1392 ..Default::default()
1393 },
1394 Commit {
1395 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1396 message: String::from("update metadata"),
1397 gitea: RemoteContributor {
1398 username: Some(String::from("nuhro")),
1399 pr_title: Some(String::from("3")),
1400 pr_number: Some(53),
1401 pr_labels: vec![String::from("deps")],
1402 is_first_time: false,
1403 },
1404 remote: Some(RemoteContributor {
1405 username: Some(String::from("nuhro")),
1406 pr_title: Some(String::from("3")),
1407 pr_number: Some(53),
1408 pr_labels: vec![String::from("deps")],
1409 is_first_time: false,
1410 }),
1411 ..Default::default()
1412 },
1413 Commit {
1414 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1415 message: String::from("do some stuff"),
1416 gitea: RemoteContributor {
1417 username: Some(String::from("awesome_contributor")),
1418 pr_title: Some(String::from("4")),
1419 pr_number: Some(1000),
1420 pr_labels: vec![String::from("deps")],
1421 is_first_time: false,
1422 },
1423 remote: Some(RemoteContributor {
1424 username: Some(String::from("awesome_contributor")),
1425 pr_title: Some(String::from("4")),
1426 pr_number: Some(1000),
1427 pr_labels: vec![String::from("deps")],
1428 is_first_time: false,
1429 }),
1430 ..Default::default()
1431 },
1432 Commit {
1433 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1434 message: String::from("alright"),
1435 gitea: RemoteContributor {
1436 username: Some(String::from("orhun")),
1437 pr_title: Some(String::from("5")),
1438 pr_number: Some(999999),
1439 pr_labels: vec![String::from("github")],
1440 is_first_time: false,
1441 },
1442 remote: Some(RemoteContributor {
1443 username: Some(String::from("orhun")),
1444 pr_title: Some(String::from("5")),
1445 pr_number: Some(999999),
1446 pr_labels: vec![String::from("github")],
1447 is_first_time: false,
1448 }),
1449 ..Default::default()
1450 },
1451 Commit {
1452 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1453 message: String::from("should be fine"),
1454 gitea: RemoteContributor {
1455 username: Some(String::from("someone")),
1456 pr_title: None,
1457 pr_number: None,
1458 pr_labels: vec![],
1459 is_first_time: false,
1460 },
1461 remote: Some(RemoteContributor {
1462 username: Some(String::from("someone")),
1463 pr_title: None,
1464 pr_number: None,
1465 pr_labels: vec![],
1466 is_first_time: false,
1467 }),
1468 ..Default::default()
1469 },
1470 ];
1471 assert_eq!(expected_commits, release.commits);
1472
1473 release
1474 .gitea
1475 .contributors
1476 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1477
1478 let expected_metadata = RemoteReleaseMetadata {
1479 contributors: vec![
1480 RemoteContributor {
1481 username: Some(String::from("someone")),
1482 pr_title: None,
1483 pr_number: None,
1484 pr_labels: vec![],
1485 is_first_time: true,
1486 },
1487 RemoteContributor {
1488 username: Some(String::from("orhun")),
1489 pr_title: Some(String::from("1")),
1490 pr_number: Some(42),
1491 pr_labels: vec![String::from("rust")],
1492 is_first_time: true,
1493 },
1494 RemoteContributor {
1495 username: Some(String::from("nuhro")),
1496 pr_title: Some(String::from("3")),
1497 pr_number: Some(53),
1498 pr_labels: vec![String::from("deps")],
1499 is_first_time: true,
1500 },
1501 RemoteContributor {
1502 username: Some(String::from("awesome_contributor")),
1503 pr_title: Some(String::from("4")),
1504 pr_number: Some(1000),
1505 pr_labels: vec![String::from("deps")],
1506 is_first_time: true,
1507 },
1508 ],
1509 };
1510 assert_eq!(expected_metadata, release.gitea);
1511
1512 Ok(())
1513 }
1514
1515 #[cfg(feature = "bitbucket")]
1516 #[test]
1517 fn update_bitbucket_metadata() -> Result<()> {
1518 use crate::remote::bitbucket::{
1519 BitbucketCommit,
1520 BitbucketCommitAuthor,
1521 BitbucketPullRequest,
1522 BitbucketPullRequestMergeCommit,
1523 };
1524
1525 let mut release = Release {
1526 version: None,
1527 message: None,
1528 extra: None,
1529 commits: vec![
1530 Commit::from(String::from(
1531 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add bitbucket \
1532 integration",
1533 )),
1534 Commit::from(String::from(
1535 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix bitbucket \
1536 integration",
1537 )),
1538 Commit::from(String::from(
1539 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
1540 )),
1541 Commit::from(String::from(
1542 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
1543 )),
1544 Commit::from(String::from(
1545 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
1546 )),
1547 Commit::from(String::from(
1548 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
1549 )),
1550 ],
1551 commit_range: None,
1552 commit_id: None,
1553 timestamp: 0,
1554 previous: Some(Box::new(Release {
1555 version: Some(String::from("1.0.0")),
1556 ..Default::default()
1557 })),
1558 repository: Some(String::from("/root/repo")),
1559 submodule_commits: HashMap::new(),
1560 #[cfg(feature = "github")]
1561 github: RemoteReleaseMetadata {
1562 contributors: vec![],
1563 },
1564 #[cfg(feature = "gitlab")]
1565 gitlab: RemoteReleaseMetadata {
1566 contributors: vec![],
1567 },
1568 #[cfg(feature = "gitea")]
1569 gitea: RemoteReleaseMetadata {
1570 contributors: vec![],
1571 },
1572 #[cfg(feature = "bitbucket")]
1573 bitbucket: RemoteReleaseMetadata {
1574 contributors: vec![],
1575 },
1576 };
1577 release.update_bitbucket_metadata(
1578 vec![
1579 BitbucketCommit {
1580 hash: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1581 author: Some(BitbucketCommitAuthor {
1582 login: Some(String::from("orhun")),
1583 }),
1584 date: String::from("2021-07-18T15:14:39+03:00"),
1585 },
1586 BitbucketCommit {
1587 hash: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1588 author: Some(BitbucketCommitAuthor {
1589 login: Some(String::from("orhun")),
1590 }),
1591 date: String::from("2021-07-18T15:12:19+03:00"),
1592 },
1593 BitbucketCommit {
1594 hash: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1595 author: Some(BitbucketCommitAuthor {
1596 login: Some(String::from("nuhro")),
1597 }),
1598 date: String::from("2021-07-18T15:07:23+03:00"),
1599 },
1600 BitbucketCommit {
1601 hash: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1602 author: Some(BitbucketCommitAuthor {
1603 login: Some(String::from("awesome_contributor")),
1604 }),
1605 date: String::from("2021-07-18T15:05:10+03:00"),
1606 },
1607 BitbucketCommit {
1608 hash: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1609 author: Some(BitbucketCommitAuthor {
1610 login: Some(String::from("orhun")),
1611 }),
1612 date: String::from("2021-07-18T15:03:30+03:00"),
1613 },
1614 BitbucketCommit {
1615 hash: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1616 author: Some(BitbucketCommitAuthor {
1617 login: Some(String::from("someone")),
1618 }),
1619 date: String::from("2021-07-18T15:00:38+03:00"),
1620 },
1621 BitbucketCommit {
1622 hash: String::from("0c34967147560e809658776d4901709139b4ad68"),
1623 author: Some(BitbucketCommitAuthor {
1624 login: Some(String::from("idk")),
1625 }),
1626 date: String::from("2021-07-18T15:00:01+03:00"),
1627 },
1628 BitbucketCommit {
1629 hash: String::from("kk34967147560e809658776d4901709139b4ad68"),
1630 author: Some(BitbucketCommitAuthor {
1631 login: Some(String::from("orhun")),
1632 }),
1633 date: String::from("2021-07-14T21:25:24+03:00"),
1634 },
1635 ]
1636 .into_iter()
1637 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
1638 .collect(),
1639 vec![Box::new(BitbucketPullRequest {
1640 id: 1,
1641 title: Some(String::from("1")),
1642 author: BitbucketCommitAuthor {
1643 login: Some(String::from("42")),
1644 },
1645 merge_commit: BitbucketPullRequestMergeCommit {
1646 hash: String::from("1d244937ee6c"),
1648 },
1649 })],
1650 )?;
1651 #[allow(deprecated)]
1652 let expected_commits = vec![
1653 Commit {
1654 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1655 message: String::from("add bitbucket integration"),
1656 bitbucket: RemoteContributor {
1657 username: Some(String::from("orhun")),
1658 pr_title: Some(String::from("1")),
1659 pr_number: Some(1),
1660 pr_labels: vec![],
1661 is_first_time: false,
1662 },
1663 remote: Some(RemoteContributor {
1664 username: Some(String::from("orhun")),
1665 pr_title: Some(String::from("1")),
1666 pr_number: Some(1),
1667 pr_labels: vec![],
1668 is_first_time: false,
1669 }),
1670 ..Default::default()
1671 },
1672 Commit {
1673 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1674 message: String::from("fix bitbucket integration"),
1675 bitbucket: RemoteContributor {
1676 username: Some(String::from("orhun")),
1677 pr_title: None,
1678 pr_number: None,
1679 pr_labels: vec![],
1680 is_first_time: false,
1681 },
1682 remote: Some(RemoteContributor {
1683 username: Some(String::from("orhun")),
1684 pr_title: None,
1685 pr_number: None,
1686 pr_labels: vec![],
1687 is_first_time: false,
1688 }),
1689 ..Default::default()
1690 },
1691 Commit {
1692 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1693 message: String::from("update metadata"),
1694 bitbucket: RemoteContributor {
1695 username: Some(String::from("nuhro")),
1696 pr_title: None,
1697 pr_number: None,
1698 pr_labels: vec![],
1699 is_first_time: false,
1700 },
1701 remote: Some(RemoteContributor {
1702 username: Some(String::from("nuhro")),
1703 pr_title: None,
1704 pr_number: None,
1705 pr_labels: vec![],
1706 is_first_time: false,
1707 }),
1708 ..Default::default()
1709 },
1710 Commit {
1711 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1712 message: String::from("do some stuff"),
1713 bitbucket: RemoteContributor {
1714 username: Some(String::from("awesome_contributor")),
1715 pr_title: None,
1716 pr_number: None,
1717 pr_labels: vec![],
1718 is_first_time: false,
1719 },
1720 remote: Some(RemoteContributor {
1721 username: Some(String::from("awesome_contributor")),
1722 pr_title: None,
1723 pr_number: None,
1724 pr_labels: vec![],
1725 is_first_time: false,
1726 }),
1727 ..Default::default()
1728 },
1729 Commit {
1730 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1731 message: String::from("alright"),
1732 bitbucket: RemoteContributor {
1733 username: Some(String::from("orhun")),
1734 pr_title: None,
1735 pr_number: None,
1736 pr_labels: vec![],
1737 is_first_time: false,
1738 },
1739 remote: Some(RemoteContributor {
1740 username: Some(String::from("orhun")),
1741 pr_title: None,
1742 pr_number: None,
1743 pr_labels: vec![],
1744 is_first_time: false,
1745 }),
1746 ..Default::default()
1747 },
1748 Commit {
1749 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1750 message: String::from("should be fine"),
1751 bitbucket: RemoteContributor {
1752 username: Some(String::from("someone")),
1753 pr_title: None,
1754 pr_number: None,
1755 pr_labels: vec![],
1756 is_first_time: false,
1757 },
1758 remote: Some(RemoteContributor {
1759 username: Some(String::from("someone")),
1760 pr_title: None,
1761 pr_number: None,
1762 pr_labels: vec![],
1763 is_first_time: false,
1764 }),
1765 ..Default::default()
1766 },
1767 ];
1768 assert_eq!(expected_commits, release.commits);
1769
1770 release
1771 .bitbucket
1772 .contributors
1773 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1774
1775 let expected_metadata = RemoteReleaseMetadata {
1776 contributors: vec![
1777 RemoteContributor {
1778 username: Some(String::from("nuhro")),
1779 pr_title: None,
1780 pr_number: None,
1781 pr_labels: vec![],
1782 is_first_time: true,
1783 },
1784 RemoteContributor {
1785 username: Some(String::from("awesome_contributor")),
1786 pr_title: None,
1787 pr_number: None,
1788 pr_labels: vec![],
1789 is_first_time: true,
1790 },
1791 RemoteContributor {
1792 username: Some(String::from("someone")),
1793 pr_title: None,
1794 pr_number: None,
1795 pr_labels: vec![],
1796 is_first_time: true,
1797 },
1798 RemoteContributor {
1799 username: Some(String::from("orhun")),
1800 pr_title: Some(String::from("1")),
1801 pr_number: Some(1),
1802 pr_labels: vec![],
1803 is_first_time: false,
1804 },
1805 ],
1806 };
1807 assert_eq!(expected_metadata, release.bitbucket);
1808
1809 Ok(())
1810 }
1811}