1use std::collections::HashMap;
2
3use next_version::{NextVersion, VersionUpdater};
4use semver::Version;
5use serde::{Deserialize, Serialize};
6use serde_json::value::Value;
7
8use crate::commit::{Commit, Range, commits_to_conventional_commits};
9use crate::config::{Bump, BumpType};
10use crate::error::Result;
11use crate::statistics::Statistics;
12#[cfg(feature = "remote")]
13use crate::{
14 contributor::RemoteContributor,
15 remote::{RemoteCommit, RemotePullRequest, RemoteReleaseMetadata},
16};
17
18#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
20#[serde(rename_all(serialize = "camelCase"))]
21pub struct Release<'a> {
22 pub version: Option<String>,
24 pub message: Option<String>,
26 #[serde(deserialize_with = "commits_to_conventional_commits")]
28 pub commits: Vec<Commit<'a>>,
29 #[serde(rename = "commit_id")]
31 pub commit_id: Option<String>,
32 pub timestamp: Option<i64>,
34 pub previous: Option<Box<Release<'a>>>,
36 pub repository: Option<String>,
38 #[serde(rename = "commit_range")]
40 pub commit_range: Option<Range>,
41 #[serde(rename = "submodule_commits")]
45 pub submodule_commits: HashMap<String, Vec<Commit<'a>>>,
46 pub statistics: Option<Statistics>,
48 pub extra: Option<Value>,
50 #[cfg(feature = "github")]
52 pub github: RemoteReleaseMetadata,
53 #[cfg(feature = "gitlab")]
55 pub gitlab: RemoteReleaseMetadata,
56 #[cfg(feature = "gitea")]
58 pub gitea: RemoteReleaseMetadata,
59 #[cfg(feature = "bitbucket")]
61 pub bitbucket: RemoteReleaseMetadata,
62}
63
64#[cfg(feature = "github")]
65crate::update_release_metadata!(github, update_github_metadata);
66
67#[cfg(feature = "gitlab")]
68crate::update_release_metadata!(gitlab, update_gitlab_metadata);
69
70#[cfg(feature = "gitea")]
71crate::update_release_metadata!(gitea, update_gitea_metadata);
72
73#[cfg(feature = "bitbucket")]
74crate::update_release_metadata!(bitbucket, update_bitbucket_metadata);
75
76impl Release<'_> {
77 pub fn calculate_next_version(&self) -> Result<String> {
82 self.calculate_next_version_with_config(&Bump::default())
83 }
84
85 pub fn with_statistics(mut self) -> Self {
91 self.statistics = Some((&self).into());
92 self
93 }
94
95 pub(super) fn calculate_next_version_with_config(&self, config: &Bump) -> Result<String> {
100 match self
101 .previous
102 .as_ref()
103 .and_then(|release| release.version.clone())
104 {
105 Some(version) => {
106 let mut semver = Version::parse(&version);
107 let mut prefix = None;
108 if semver.is_err() && version.split('.').count() >= 2 {
109 let mut found_numeric = false;
110 for (i, c) in version.char_indices() {
111 if c.is_numeric() && !found_numeric {
112 found_numeric = true;
113 let version_prefix = version[..i].to_string();
114 let remaining = version[i..].to_string();
115 let version = Version::parse(&remaining);
116 if version.is_ok() {
117 semver = version;
118 prefix = Some(version_prefix);
119 break;
120 }
121 } else if !c.is_numeric() && found_numeric {
122 found_numeric = false;
123 }
124 }
125 }
126 let mut next_version = VersionUpdater::new()
127 .with_features_always_increment_minor(
128 config.features_always_bump_minor.unwrap_or(true),
129 )
130 .with_breaking_always_increment_major(
131 config.breaking_always_bump_major.unwrap_or(true),
132 );
133 if let Some(custom_major_increment_regex) = &config.custom_major_increment_regex {
134 next_version = next_version
135 .with_custom_major_increment_regex(custom_major_increment_regex)?;
136 }
137 if let Some(custom_minor_increment_regex) = &config.custom_minor_increment_regex {
138 next_version = next_version
139 .with_custom_minor_increment_regex(custom_minor_increment_regex)?;
140 }
141 let next_version = if let Some(bump_type) = &config.bump_type {
142 match bump_type {
143 BumpType::Major => semver?.increment_major().to_string(),
144 BumpType::Minor => semver?.increment_minor().to_string(),
145 BumpType::Patch => semver?.increment_patch().to_string(),
146 }
147 } else {
148 next_version
149 .increment(
150 &semver?,
151 self.commits
152 .iter()
153 .map(|commit| commit.message.trim_end().to_string())
154 .collect::<Vec<String>>(),
155 )
156 .to_string()
157 };
158 if let Some(prefix) = prefix {
159 Ok(format!("{prefix}{next_version}"))
160 } else {
161 Ok(next_version)
162 }
163 }
164 None => Ok(config.get_initial_tag()),
165 }
166 }
167}
168
169#[derive(Serialize)]
171pub struct Releases<'a> {
172 pub releases: &'a Vec<Release<'a>>,
174}
175
176impl Releases<'_> {
177 pub fn as_json(&self) -> Result<String> {
179 Ok(serde_json::to_string(self.releases)?)
180 }
181}
182
183#[cfg(test)]
184mod test {
185 use pretty_assertions::assert_eq;
186
187 use super::*;
188 #[test]
189 fn bump_version() -> Result<()> {
190 fn build_release<'a>(version: &str, commits: &'a [&str]) -> Release<'a> {
191 Release {
192 version: None,
193 message: None,
194 extra: None,
195 commits: commits
196 .iter()
197 .map(|v| Commit::from(v.to_string()))
198 .collect(),
199 commit_range: None,
200 commit_id: None,
201 timestamp: None,
202 previous: Some(Box::new(Release {
203 version: Some(String::from(version)),
204 ..Default::default()
205 })),
206 repository: Some(String::from("/root/repo")),
207 submodule_commits: HashMap::new(),
208 statistics: None,
209 #[cfg(feature = "github")]
210 github: crate::remote::RemoteReleaseMetadata {
211 contributors: vec![],
212 },
213 #[cfg(feature = "gitlab")]
214 gitlab: crate::remote::RemoteReleaseMetadata {
215 contributors: vec![],
216 },
217 #[cfg(feature = "gitea")]
218 gitea: crate::remote::RemoteReleaseMetadata {
219 contributors: vec![],
220 },
221 #[cfg(feature = "bitbucket")]
222 bitbucket: crate::remote::RemoteReleaseMetadata {
223 contributors: vec![],
224 },
225 }
226 }
227
228 let test_shared = [
229 ("1.0.0", "1.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
230 ("1.0.0", "1.0.1", vec!["fix: add xyz", "fix: aaaaaa"]),
231 ("1.0.0", "2.0.0", vec!["feat!: add xyz", "feat: zzz"]),
232 ("1.0.0", "2.0.0", vec!["feat!: add xyz\n", "feat: zzz\n"]),
233 ("2.0.0", "2.0.1", vec!["fix: something"]),
234 ("foo/1.0.0", "foo/1.1.0", vec![
235 "feat: add xyz",
236 "fix: fix xyz",
237 ]),
238 ("bar/1.0.0", "bar/2.0.0", vec![
239 "fix: add xyz",
240 "fix!: aaaaaa",
241 ]),
242 ("zzz-123/test/1.0.0", "zzz-123/test/1.0.1", vec![
243 "fix: aaaaaa",
244 ]),
245 ("v100.0.0", "v101.0.0", vec!["feat!: something"]),
246 ("v1.0.0-alpha.1", "v1.0.0-alpha.2", vec!["fix: minor"]),
247 ("testing/v1.0.0-beta.1", "testing/v1.0.0-beta.2", vec![
248 "feat: nice",
249 ]),
250 ("tauri-v1.5.4", "tauri-v1.6.0", vec!["feat: something"]),
251 (
252 "rocket/rocket-v4.0.0-rc.1",
253 "rocket/rocket-v4.0.0-rc.2",
254 vec!["chore!: wow"],
255 ),
256 (
257 "aaa#/@#$@9384!#%^#@#@!#!239432413-idk-9999.2200.5932-alpha.419",
258 "aaa#/@#$@9384!#%^#@#@!#!239432413-idk-9999.2200.5932-alpha.420",
259 vec!["feat: damn this is working"],
260 ),
261 ];
262
263 for (version, expected_version, commits) in test_shared.iter().chain(
264 [
265 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
266 ("0.0.1", "0.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
267 ("0.0.1", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
268 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
269 ("0.1.0", "0.2.0", vec!["feat: add xyz", "fix: fix xyz"]),
270 ("0.1.0", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
271 ]
272 .iter(),
273 ) {
274 let release = build_release(version, commits);
275 let next_version = release.calculate_next_version()?;
276 assert_eq!(expected_version, &next_version);
277 let next_version = release.calculate_next_version_with_config(&Bump::default())?;
278 assert_eq!(expected_version, &next_version);
279 }
280
281 for (version, expected_version, commits) in test_shared.iter().chain(
282 [
283 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
284 ("0.0.1", "0.0.2", vec!["feat: add xyz", "fix: fix xyz"]),
285 ("0.0.1", "0.0.2", vec!["feat!: add xyz", "feat: zzz"]),
286 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
287 ("0.1.0", "0.1.1", vec!["feat: add xyz", "fix: fix xyz"]),
288 ("0.1.0", "0.2.0", vec!["feat!: add xyz", "feat: zzz"]),
289 ]
290 .iter(),
291 ) {
292 let release = build_release(version, commits);
293 let next_version = release.calculate_next_version_with_config(&Bump {
294 features_always_bump_minor: Some(false),
295 breaking_always_bump_major: Some(false),
296 initial_tag: None,
297 custom_major_increment_regex: None,
298 custom_minor_increment_regex: None,
299 bump_type: None,
300 })?;
301 assert_eq!(expected_version, &next_version);
302 }
303
304 for (version, expected_version, commits) in test_shared.iter().chain(
305 [
306 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
307 ("0.0.1", "0.1.0", vec!["feat: add xyz", "fix: fix xyz"]),
308 ("0.0.1", "0.1.0", vec!["feat!: add xyz", "feat: zzz"]),
309 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
310 ("0.1.0", "0.2.0", vec!["feat: add xyz", "fix: fix xyz"]),
311 ("0.1.0", "0.2.0", vec!["feat!: add xyz", "feat: zzz"]),
312 ]
313 .iter(),
314 ) {
315 let release = build_release(version, commits);
316 let next_version = release.calculate_next_version_with_config(&Bump {
317 features_always_bump_minor: Some(true),
318 breaking_always_bump_major: Some(false),
319 initial_tag: None,
320 custom_major_increment_regex: None,
321 custom_minor_increment_regex: None,
322 bump_type: None,
323 })?;
324 assert_eq!(expected_version, &next_version);
325 }
326
327 for (version, expected_version, commits) in test_shared.iter().chain(
328 [
329 ("0.0.1", "0.0.2", vec!["fix: fix xyz"]),
330 ("0.0.1", "0.0.2", vec!["feat: add xyz", "fix: fix xyz"]),
331 ("0.0.1", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
332 ("0.1.0", "0.1.1", vec!["fix: fix xyz"]),
333 ("0.1.0", "0.1.1", vec!["feat: add xyz", "fix: fix xyz"]),
334 ("0.1.0", "1.0.0", vec!["feat!: add xyz", "feat: zzz"]),
335 ]
336 .iter(),
337 ) {
338 let release = build_release(version, commits);
339 let next_version = release.calculate_next_version_with_config(&Bump {
340 features_always_bump_minor: Some(false),
341 breaking_always_bump_major: Some(true),
342 initial_tag: None,
343 custom_major_increment_regex: None,
344 custom_minor_increment_regex: None,
345 bump_type: None,
346 })?;
347 assert_eq!(expected_version, &next_version);
348 }
349
350 let empty_release = Release {
351 previous: Some(Box::new(Release {
352 version: None,
353 ..Default::default()
354 })),
355 ..Default::default()
356 };
357 assert_eq!("0.1.0", empty_release.calculate_next_version()?);
358 for (features_always_bump_minor, breaking_always_bump_major) in
359 [(true, true), (true, false), (false, true), (false, false)]
360 {
361 assert_eq!(
362 "0.1.0",
363 empty_release.calculate_next_version_with_config(&Bump {
364 features_always_bump_minor: Some(features_always_bump_minor),
365 breaking_always_bump_major: Some(breaking_always_bump_major),
366 initial_tag: None,
367 custom_major_increment_regex: None,
368 custom_minor_increment_regex: None,
369 bump_type: None,
370 })?
371 );
372 }
373 Ok(())
374 }
375
376 #[test]
377 fn with_statistics() -> Result<()> {
378 let release = Release {
379 commits: vec![],
380 timestamp: Some(1649373910),
381 previous: Some(Box::new(Release {
382 timestamp: Some(1649201110),
383 ..Default::default()
384 })),
385 repository: Some(String::from("/root/repo")),
386 ..Default::default()
387 };
388
389 assert!(release.statistics.is_none());
390 let release = release.with_statistics();
391 assert!(release.statistics.is_some());
392
393 Ok(())
394 }
395
396 #[cfg(feature = "github")]
397 #[test]
398 fn update_github_metadata() -> Result<()> {
399 use crate::remote::github::{
400 GitHubCommit, GitHubCommitAuthor, GitHubCommitDetails, GitHubCommitDetailsAuthor,
401 GitHubPullRequest, PullRequestLabel,
402 };
403
404 let mut release = Release {
405 version: None,
406 message: None,
407 extra: None,
408 commits: vec![
409 Commit::from(String::from(
410 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github integration",
411 )),
412 Commit::from(String::from(
413 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github integration",
414 )),
415 Commit::from(String::from(
416 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
417 )),
418 Commit::from(String::from(
419 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
420 )),
421 Commit::from(String::from(
422 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
423 )),
424 Commit::from(String::from(
425 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
426 )),
427 ],
428 commit_range: None,
429 commit_id: None,
430 timestamp: None,
431 previous: Some(Box::new(Release {
432 version: Some(String::from("1.0.0")),
433 ..Default::default()
434 })),
435 repository: Some(String::from("/root/repo")),
436 submodule_commits: HashMap::new(),
437 statistics: None,
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::{GitLabCommit, GitLabMergeRequest, GitLabUser};
768
769 let mut release = Release {
770 version: None,
771 message: None,
772 extra: None,
773 commits: vec![
774 Commit::from(String::from(
775 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github integration",
776 )),
777 Commit::from(String::from(
778 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github integration",
779 )),
780 Commit::from(String::from(
781 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
782 )),
783 Commit::from(String::from(
784 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
785 )),
786 Commit::from(String::from(
787 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
788 )),
789 Commit::from(String::from(
790 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
791 )),
792 ],
793 commit_range: None,
794 commit_id: None,
795 timestamp: None,
796 previous: Some(Box::new(Release {
797 version: Some(String::from("1.0.0")),
798 ..Default::default()
799 })),
800 repository: Some(String::from("/root/repo")),
801 submodule_commits: HashMap::new(),
802 statistics: None,
803 #[cfg(feature = "github")]
804 github: RemoteReleaseMetadata {
805 contributors: vec![],
806 },
807 #[cfg(feature = "gitlab")]
808 gitlab: RemoteReleaseMetadata {
809 contributors: vec![],
810 },
811 #[cfg(feature = "gitea")]
812 gitea: RemoteReleaseMetadata {
813 contributors: vec![],
814 },
815 #[cfg(feature = "bitbucket")]
816 bitbucket: RemoteReleaseMetadata {
817 contributors: vec![],
818 },
819 };
820 release.update_gitlab_metadata(
821 vec![
822 GitLabCommit {
823 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
824 author_name: String::from("orhun"),
825 short_id: String::from(""),
826 title: String::from(""),
827 author_email: String::from(""),
828 authored_date: String::from(""),
829 committer_name: String::from(""),
830 committer_email: String::from(""),
831 committed_date: String::from(""),
832 created_at: String::from(""),
833 message: String::from(""),
834 parent_ids: vec![],
835 web_url: String::from(""),
836 },
837 GitLabCommit {
838 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
839 author_name: String::from("orhun"),
840 short_id: String::from(""),
841 title: String::from(""),
842 author_email: String::from(""),
843 authored_date: String::from(""),
844 committer_name: String::from(""),
845 committer_email: String::from(""),
846 committed_date: String::from(""),
847 created_at: String::from(""),
848 message: String::from(""),
849 parent_ids: vec![],
850 web_url: String::from(""),
851 },
852 GitLabCommit {
853 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
854 author_name: String::from("nuhro"),
855 short_id: String::from(""),
856 title: String::from(""),
857 author_email: String::from(""),
858 authored_date: String::from(""),
859 committer_name: String::from(""),
860 committer_email: String::from(""),
861 committed_date: String::from(""),
862 created_at: String::from(""),
863 message: String::from(""),
864 parent_ids: vec![],
865 web_url: String::from(""),
866 },
867 GitLabCommit {
868 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
869 author_name: String::from("awesome_contributor"),
870 short_id: String::from(""),
871 title: String::from(""),
872 author_email: String::from(""),
873 authored_date: String::from(""),
874 committer_name: String::from(""),
875 committer_email: String::from(""),
876 committed_date: String::from(""),
877 created_at: String::from(""),
878 message: String::from(""),
879 parent_ids: vec![],
880 web_url: String::from(""),
881 },
882 GitLabCommit {
883 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
884 author_name: String::from("orhun"),
885 short_id: String::from(""),
886 title: String::from(""),
887 author_email: String::from(""),
888 authored_date: String::from(""),
889 committer_name: String::from(""),
890 committer_email: String::from(""),
891 committed_date: String::from(""),
892 created_at: String::from(""),
893 message: String::from(""),
894 parent_ids: vec![],
895 web_url: String::from(""),
896 },
897 GitLabCommit {
898 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
899 author_name: String::from("someone"),
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("0c34967147560e809658776d4901709139b4ad68"),
914 author_name: String::from("idk"),
915 short_id: String::from(""),
916 title: String::from(""),
917 author_email: String::from(""),
918 authored_date: String::from(""),
919 committer_name: String::from(""),
920 committer_email: String::from(""),
921 committed_date: String::from(""),
922 created_at: String::from(""),
923 message: String::from(""),
924 parent_ids: vec![],
925 web_url: String::from(""),
926 },
927 GitLabCommit {
928 id: String::from("kk34967147560e809658776d4901709139b4ad68"),
929 author_name: String::from("orhun"),
930 short_id: String::from(""),
931 title: String::from(""),
932 author_email: String::from(""),
933 authored_date: String::from(""),
934 committer_name: String::from(""),
935 committer_email: String::from(""),
936 committed_date: String::from(""),
937 created_at: String::from(""),
938 message: String::from(""),
939 parent_ids: vec![],
940 web_url: String::from(""),
941 },
942 ]
943 .into_iter()
944 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
945 .collect(),
946 vec![Box::new(GitLabMergeRequest {
947 title: String::from("1"),
948 merge_commit_sha: Some(String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071")),
949 id: 1,
950 iid: 1,
951 project_id: 1,
952 description: String::from(""),
953 state: String::from(""),
954 created_at: String::from(""),
955 author: GitLabUser {
956 id: 1,
957 name: String::from("42"),
958 username: String::from("42"),
959 state: String::from("42"),
960 avatar_url: None,
961 web_url: String::from("42"),
962 },
963 sha: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
964 web_url: String::from(""),
965 squash_commit_sha: None,
966 labels: vec![String::from("rust")],
967 })],
968 )?;
969 #[allow(deprecated)]
970 let expected_commits = vec![
971 Commit {
972 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
973 message: String::from("add github integration"),
974 gitlab: RemoteContributor {
975 username: Some(String::from("orhun")),
976 pr_title: Some(String::from("1")),
977 pr_number: Some(1),
978 pr_labels: vec![String::from("rust")],
979 is_first_time: false,
980 },
981 remote: Some(RemoteContributor {
982 username: Some(String::from("orhun")),
983 pr_title: Some(String::from("1")),
984 pr_number: Some(1),
985 pr_labels: vec![String::from("rust")],
986 is_first_time: false,
987 }),
988 ..Default::default()
989 },
990 Commit {
991 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
992 message: String::from("fix github integration"),
993 gitlab: RemoteContributor {
994 username: Some(String::from("orhun")),
995 pr_title: None,
996 pr_number: None,
997 pr_labels: vec![],
998 is_first_time: false,
999 },
1000 remote: Some(RemoteContributor {
1001 username: Some(String::from("orhun")),
1002 pr_title: None,
1003 pr_number: None,
1004 pr_labels: vec![],
1005 is_first_time: false,
1006 }),
1007 ..Default::default()
1008 },
1009 Commit {
1010 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1011 message: String::from("update metadata"),
1012 gitlab: RemoteContributor {
1013 username: Some(String::from("nuhro")),
1014 pr_title: None,
1015 pr_number: None,
1016 pr_labels: vec![],
1017 is_first_time: false,
1018 },
1019 remote: Some(RemoteContributor {
1020 username: Some(String::from("nuhro")),
1021 pr_title: None,
1022 pr_number: None,
1023 pr_labels: vec![],
1024 is_first_time: false,
1025 }),
1026 ..Default::default()
1027 },
1028 Commit {
1029 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1030 message: String::from("do some stuff"),
1031 gitlab: RemoteContributor {
1032 username: Some(String::from("awesome_contributor")),
1033 pr_title: None,
1034 pr_number: None,
1035 pr_labels: vec![],
1036 is_first_time: false,
1037 },
1038 remote: Some(RemoteContributor {
1039 username: Some(String::from("awesome_contributor")),
1040 pr_title: None,
1041 pr_number: None,
1042 pr_labels: vec![],
1043 is_first_time: false,
1044 }),
1045 ..Default::default()
1046 },
1047 Commit {
1048 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1049 message: String::from("alright"),
1050 gitlab: RemoteContributor {
1051 username: Some(String::from("orhun")),
1052 pr_title: None,
1053 pr_number: None,
1054 pr_labels: vec![],
1055 is_first_time: false,
1056 },
1057 remote: Some(RemoteContributor {
1058 username: Some(String::from("orhun")),
1059 pr_title: None,
1060 pr_number: None,
1061 pr_labels: vec![],
1062 is_first_time: false,
1063 }),
1064 ..Default::default()
1065 },
1066 Commit {
1067 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1068 message: String::from("should be fine"),
1069 gitlab: RemoteContributor {
1070 username: Some(String::from("someone")),
1071 pr_title: None,
1072 pr_number: None,
1073 pr_labels: vec![],
1074 is_first_time: false,
1075 },
1076 remote: Some(RemoteContributor {
1077 username: Some(String::from("someone")),
1078 pr_title: None,
1079 pr_number: None,
1080 pr_labels: vec![],
1081 is_first_time: false,
1082 }),
1083 ..Default::default()
1084 },
1085 ];
1086 assert_eq!(expected_commits, release.commits);
1087
1088 release
1089 .github
1090 .contributors
1091 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1092
1093 let expected_metadata = RemoteReleaseMetadata {
1094 contributors: vec![
1095 RemoteContributor {
1096 username: Some(String::from("orhun")),
1097 pr_title: Some(String::from("1")),
1098 pr_number: Some(1),
1099 pr_labels: vec![String::from("rust")],
1100 is_first_time: false,
1101 },
1102 RemoteContributor {
1103 username: Some(String::from("nuhro")),
1104 pr_title: None,
1105 pr_number: None,
1106 pr_labels: vec![],
1107 is_first_time: true,
1108 },
1109 RemoteContributor {
1110 username: Some(String::from("awesome_contributor")),
1111 pr_title: None,
1112 pr_number: None,
1113 pr_labels: vec![],
1114 is_first_time: true,
1115 },
1116 RemoteContributor {
1117 username: Some(String::from("someone")),
1118 pr_title: None,
1119 pr_number: None,
1120 pr_labels: vec![],
1121 is_first_time: true,
1122 },
1123 ],
1124 };
1125 assert_eq!(expected_metadata, release.gitlab);
1126
1127 Ok(())
1128 }
1129
1130 #[cfg(feature = "gitea")]
1131 #[test]
1132 fn update_gitea_metadata() -> Result<()> {
1133 use crate::remote::gitea::{
1134 GiteaCommit, GiteaCommitAuthor, GiteaPullRequest, PullRequestLabel,
1135 };
1136
1137 let mut release = Release {
1138 version: None,
1139 message: None,
1140 extra: None,
1141 commits: vec![
1142 Commit::from(String::from(
1143 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github integration",
1144 )),
1145 Commit::from(String::from(
1146 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix github integration",
1147 )),
1148 Commit::from(String::from(
1149 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
1150 )),
1151 Commit::from(String::from(
1152 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
1153 )),
1154 Commit::from(String::from(
1155 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
1156 )),
1157 Commit::from(String::from(
1158 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
1159 )),
1160 ],
1161 commit_range: None,
1162 commit_id: None,
1163 timestamp: None,
1164 previous: Some(Box::new(Release {
1165 version: Some(String::from("1.0.0")),
1166 ..Default::default()
1167 })),
1168 repository: Some(String::from("/root/repo")),
1169 submodule_commits: HashMap::new(),
1170 statistics: None,
1171 #[cfg(feature = "github")]
1172 github: RemoteReleaseMetadata {
1173 contributors: vec![],
1174 },
1175 #[cfg(feature = "gitlab")]
1176 gitlab: RemoteReleaseMetadata {
1177 contributors: vec![],
1178 },
1179 #[cfg(feature = "gitea")]
1180 gitea: RemoteReleaseMetadata {
1181 contributors: vec![],
1182 },
1183 #[cfg(feature = "bitbucket")]
1184 bitbucket: RemoteReleaseMetadata {
1185 contributors: vec![],
1186 },
1187 };
1188 release.update_gitea_metadata(
1189 vec![
1190 GiteaCommit {
1191 sha: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1192 author: Some(GiteaCommitAuthor {
1193 login: Some(String::from("orhun")),
1194 }),
1195 created: String::from("2021-07-18T15:14:39+03:00"),
1196 },
1197 GiteaCommit {
1198 sha: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1199 author: Some(GiteaCommitAuthor {
1200 login: Some(String::from("orhun")),
1201 }),
1202 created: String::from("2021-07-18T15:12:19+03:00"),
1203 },
1204 GiteaCommit {
1205 sha: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1206 author: Some(GiteaCommitAuthor {
1207 login: Some(String::from("nuhro")),
1208 }),
1209 created: String::from("2021-07-18T15:07:23+03:00"),
1210 },
1211 GiteaCommit {
1212 sha: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1213 author: Some(GiteaCommitAuthor {
1214 login: Some(String::from("awesome_contributor")),
1215 }),
1216 created: String::from("2021-07-18T15:05:10+03:00"),
1217 },
1218 GiteaCommit {
1219 sha: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1220 author: Some(GiteaCommitAuthor {
1221 login: Some(String::from("orhun")),
1222 }),
1223 created: String::from("2021-07-18T15:03:30+03:00"),
1224 },
1225 GiteaCommit {
1226 sha: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1227 author: Some(GiteaCommitAuthor {
1228 login: Some(String::from("someone")),
1229 }),
1230 created: String::from("2021-07-18T15:00:38+03:00"),
1231 },
1232 GiteaCommit {
1233 sha: String::from("0c34967147560e809658776d4901709139b4ad68"),
1234 author: Some(GiteaCommitAuthor {
1235 login: Some(String::from("idk")),
1236 }),
1237 created: String::from("2021-07-18T15:00:38+03:00"),
1238 },
1239 GiteaCommit {
1240 sha: String::from("kk34967147560e809658776d4901709139b4ad68"),
1241 author: None,
1242 created: String::new(),
1243 },
1244 GiteaCommit {
1245 sha: String::new(),
1246 author: None,
1247 created: String::new(),
1248 },
1249 ]
1250 .into_iter()
1251 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
1252 .collect(),
1253 vec![
1254 GiteaPullRequest {
1255 title: Some(String::from("1")),
1256 number: 42,
1257 merge_commit_sha: Some(String::from(
1258 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071",
1259 )),
1260 labels: vec![PullRequestLabel {
1261 name: String::from("rust"),
1262 }],
1263 },
1264 GiteaPullRequest {
1265 title: Some(String::from("2")),
1266 number: 66,
1267 merge_commit_sha: Some(String::from(
1268 "21f6aa587fcb772de13f2fde0e92697c51f84162",
1269 )),
1270 labels: vec![PullRequestLabel {
1271 name: String::from("rust"),
1272 }],
1273 },
1274 GiteaPullRequest {
1275 title: Some(String::from("3")),
1276 number: 53,
1277 merge_commit_sha: Some(String::from(
1278 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973",
1279 )),
1280 labels: vec![PullRequestLabel {
1281 name: String::from("deps"),
1282 }],
1283 },
1284 GiteaPullRequest {
1285 title: Some(String::from("4")),
1286 number: 1000,
1287 merge_commit_sha: Some(String::from(
1288 "4d3ffe4753b923f4d7807c490e650e6624a12074",
1289 )),
1290 labels: vec![PullRequestLabel {
1291 name: String::from("deps"),
1292 }],
1293 },
1294 GiteaPullRequest {
1295 title: Some(String::from("5")),
1296 number: 999999,
1297 merge_commit_sha: Some(String::from(
1298 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05",
1299 )),
1300 labels: vec![PullRequestLabel {
1301 name: String::from("github"),
1302 }],
1303 },
1304 ]
1305 .into_iter()
1306 .map(|v| Box::new(v) as Box<dyn RemotePullRequest>)
1307 .collect(),
1308 )?;
1309 #[allow(deprecated)]
1310 let expected_commits = vec![
1311 Commit {
1312 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1313 message: String::from("add github integration"),
1314 gitea: RemoteContributor {
1315 username: Some(String::from("orhun")),
1316 pr_title: Some(String::from("1")),
1317 pr_number: Some(42),
1318 pr_labels: vec![String::from("rust")],
1319 is_first_time: false,
1320 },
1321 remote: Some(RemoteContributor {
1322 username: Some(String::from("orhun")),
1323 pr_title: Some(String::from("1")),
1324 pr_number: Some(42),
1325 pr_labels: vec![String::from("rust")],
1326 is_first_time: false,
1327 }),
1328 ..Default::default()
1329 },
1330 Commit {
1331 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1332 message: String::from("fix github integration"),
1333 gitea: RemoteContributor {
1334 username: Some(String::from("orhun")),
1335 pr_title: Some(String::from("2")),
1336 pr_number: Some(66),
1337 pr_labels: vec![String::from("rust")],
1338 is_first_time: false,
1339 },
1340 remote: Some(RemoteContributor {
1341 username: Some(String::from("orhun")),
1342 pr_title: Some(String::from("2")),
1343 pr_number: Some(66),
1344 pr_labels: vec![String::from("rust")],
1345 is_first_time: false,
1346 }),
1347 ..Default::default()
1348 },
1349 Commit {
1350 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1351 message: String::from("update metadata"),
1352 gitea: RemoteContributor {
1353 username: Some(String::from("nuhro")),
1354 pr_title: Some(String::from("3")),
1355 pr_number: Some(53),
1356 pr_labels: vec![String::from("deps")],
1357 is_first_time: false,
1358 },
1359 remote: Some(RemoteContributor {
1360 username: Some(String::from("nuhro")),
1361 pr_title: Some(String::from("3")),
1362 pr_number: Some(53),
1363 pr_labels: vec![String::from("deps")],
1364 is_first_time: false,
1365 }),
1366 ..Default::default()
1367 },
1368 Commit {
1369 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1370 message: String::from("do some stuff"),
1371 gitea: RemoteContributor {
1372 username: Some(String::from("awesome_contributor")),
1373 pr_title: Some(String::from("4")),
1374 pr_number: Some(1000),
1375 pr_labels: vec![String::from("deps")],
1376 is_first_time: false,
1377 },
1378 remote: Some(RemoteContributor {
1379 username: Some(String::from("awesome_contributor")),
1380 pr_title: Some(String::from("4")),
1381 pr_number: Some(1000),
1382 pr_labels: vec![String::from("deps")],
1383 is_first_time: false,
1384 }),
1385 ..Default::default()
1386 },
1387 Commit {
1388 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1389 message: String::from("alright"),
1390 gitea: RemoteContributor {
1391 username: Some(String::from("orhun")),
1392 pr_title: Some(String::from("5")),
1393 pr_number: Some(999999),
1394 pr_labels: vec![String::from("github")],
1395 is_first_time: false,
1396 },
1397 remote: Some(RemoteContributor {
1398 username: Some(String::from("orhun")),
1399 pr_title: Some(String::from("5")),
1400 pr_number: Some(999999),
1401 pr_labels: vec![String::from("github")],
1402 is_first_time: false,
1403 }),
1404 ..Default::default()
1405 },
1406 Commit {
1407 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1408 message: String::from("should be fine"),
1409 gitea: RemoteContributor {
1410 username: Some(String::from("someone")),
1411 pr_title: None,
1412 pr_number: None,
1413 pr_labels: vec![],
1414 is_first_time: false,
1415 },
1416 remote: Some(RemoteContributor {
1417 username: Some(String::from("someone")),
1418 pr_title: None,
1419 pr_number: None,
1420 pr_labels: vec![],
1421 is_first_time: false,
1422 }),
1423 ..Default::default()
1424 },
1425 ];
1426 assert_eq!(expected_commits, release.commits);
1427
1428 release
1429 .gitea
1430 .contributors
1431 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1432
1433 let expected_metadata = RemoteReleaseMetadata {
1434 contributors: vec![
1435 RemoteContributor {
1436 username: Some(String::from("someone")),
1437 pr_title: None,
1438 pr_number: None,
1439 pr_labels: vec![],
1440 is_first_time: true,
1441 },
1442 RemoteContributor {
1443 username: Some(String::from("orhun")),
1444 pr_title: Some(String::from("1")),
1445 pr_number: Some(42),
1446 pr_labels: vec![String::from("rust")],
1447 is_first_time: true,
1448 },
1449 RemoteContributor {
1450 username: Some(String::from("nuhro")),
1451 pr_title: Some(String::from("3")),
1452 pr_number: Some(53),
1453 pr_labels: vec![String::from("deps")],
1454 is_first_time: true,
1455 },
1456 RemoteContributor {
1457 username: Some(String::from("awesome_contributor")),
1458 pr_title: Some(String::from("4")),
1459 pr_number: Some(1000),
1460 pr_labels: vec![String::from("deps")],
1461 is_first_time: true,
1462 },
1463 ],
1464 };
1465 assert_eq!(expected_metadata, release.gitea);
1466
1467 Ok(())
1468 }
1469
1470 #[cfg(feature = "bitbucket")]
1471 #[test]
1472 fn update_bitbucket_metadata() -> Result<()> {
1473 use crate::remote::bitbucket::{
1474 BitbucketCommit, BitbucketCommitAuthor, BitbucketPullRequest,
1475 BitbucketPullRequestMergeCommit,
1476 };
1477
1478 let mut release = Release {
1479 version: None,
1480 message: None,
1481 extra: None,
1482 commits: vec![
1483 Commit::from(String::from(
1484 "1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add bitbucket integration",
1485 )),
1486 Commit::from(String::from(
1487 "21f6aa587fcb772de13f2fde0e92697c51f84162 fix bitbucket integration",
1488 )),
1489 Commit::from(String::from(
1490 "35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
1491 )),
1492 Commit::from(String::from(
1493 "4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
1494 )),
1495 Commit::from(String::from(
1496 "5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
1497 )),
1498 Commit::from(String::from(
1499 "6c34967147560ea09658776d4901709139b4ad66 should be fine",
1500 )),
1501 ],
1502 commit_range: None,
1503 commit_id: None,
1504 timestamp: None,
1505 previous: Some(Box::new(Release {
1506 version: Some(String::from("1.0.0")),
1507 ..Default::default()
1508 })),
1509 repository: Some(String::from("/root/repo")),
1510 submodule_commits: HashMap::new(),
1511 statistics: None,
1512 #[cfg(feature = "github")]
1513 github: RemoteReleaseMetadata {
1514 contributors: vec![],
1515 },
1516 #[cfg(feature = "gitlab")]
1517 gitlab: RemoteReleaseMetadata {
1518 contributors: vec![],
1519 },
1520 #[cfg(feature = "gitea")]
1521 gitea: RemoteReleaseMetadata {
1522 contributors: vec![],
1523 },
1524 #[cfg(feature = "bitbucket")]
1525 bitbucket: RemoteReleaseMetadata {
1526 contributors: vec![],
1527 },
1528 };
1529 release.update_bitbucket_metadata(
1530 vec![
1531 BitbucketCommit {
1532 hash: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1533 author: Some(BitbucketCommitAuthor {
1534 login: Some(String::from("orhun")),
1535 }),
1536 date: String::from("2021-07-18T15:14:39+03:00"),
1537 },
1538 BitbucketCommit {
1539 hash: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1540 author: Some(BitbucketCommitAuthor {
1541 login: Some(String::from("orhun")),
1542 }),
1543 date: String::from("2021-07-18T15:12:19+03:00"),
1544 },
1545 BitbucketCommit {
1546 hash: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1547 author: Some(BitbucketCommitAuthor {
1548 login: Some(String::from("nuhro")),
1549 }),
1550 date: String::from("2021-07-18T15:07:23+03:00"),
1551 },
1552 BitbucketCommit {
1553 hash: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1554 author: Some(BitbucketCommitAuthor {
1555 login: Some(String::from("awesome_contributor")),
1556 }),
1557 date: String::from("2021-07-18T15:05:10+03:00"),
1558 },
1559 BitbucketCommit {
1560 hash: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1561 author: Some(BitbucketCommitAuthor {
1562 login: Some(String::from("orhun")),
1563 }),
1564 date: String::from("2021-07-18T15:03:30+03:00"),
1565 },
1566 BitbucketCommit {
1567 hash: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1568 author: Some(BitbucketCommitAuthor {
1569 login: Some(String::from("someone")),
1570 }),
1571 date: String::from("2021-07-18T15:00:38+03:00"),
1572 },
1573 BitbucketCommit {
1574 hash: String::from("0c34967147560e809658776d4901709139b4ad68"),
1575 author: Some(BitbucketCommitAuthor {
1576 login: Some(String::from("idk")),
1577 }),
1578 date: String::from("2021-07-18T15:00:01+03:00"),
1579 },
1580 BitbucketCommit {
1581 hash: String::from("kk34967147560e809658776d4901709139b4ad68"),
1582 author: Some(BitbucketCommitAuthor {
1583 login: Some(String::from("orhun")),
1584 }),
1585 date: String::from("2021-07-14T21:25:24+03:00"),
1586 },
1587 ]
1588 .into_iter()
1589 .map(|v| Box::new(v) as Box<dyn RemoteCommit>)
1590 .collect(),
1591 vec![Box::new(BitbucketPullRequest {
1592 id: 1,
1593 title: Some(String::from("1")),
1594 author: BitbucketCommitAuthor {
1595 login: Some(String::from("42")),
1596 },
1597 merge_commit: BitbucketPullRequestMergeCommit {
1598 hash: String::from("1d244937ee6c"),
1600 },
1601 })],
1602 )?;
1603 #[allow(deprecated)]
1604 let expected_commits = vec![
1605 Commit {
1606 id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
1607 message: String::from("add bitbucket integration"),
1608 bitbucket: RemoteContributor {
1609 username: Some(String::from("orhun")),
1610 pr_title: Some(String::from("1")),
1611 pr_number: Some(1),
1612 pr_labels: vec![],
1613 is_first_time: false,
1614 },
1615 remote: Some(RemoteContributor {
1616 username: Some(String::from("orhun")),
1617 pr_title: Some(String::from("1")),
1618 pr_number: Some(1),
1619 pr_labels: vec![],
1620 is_first_time: false,
1621 }),
1622 ..Default::default()
1623 },
1624 Commit {
1625 id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
1626 message: String::from("fix bitbucket integration"),
1627 bitbucket: RemoteContributor {
1628 username: Some(String::from("orhun")),
1629 pr_title: None,
1630 pr_number: None,
1631 pr_labels: vec![],
1632 is_first_time: false,
1633 },
1634 remote: Some(RemoteContributor {
1635 username: Some(String::from("orhun")),
1636 pr_title: None,
1637 pr_number: None,
1638 pr_labels: vec![],
1639 is_first_time: false,
1640 }),
1641 ..Default::default()
1642 },
1643 Commit {
1644 id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
1645 message: String::from("update metadata"),
1646 bitbucket: RemoteContributor {
1647 username: Some(String::from("nuhro")),
1648 pr_title: None,
1649 pr_number: None,
1650 pr_labels: vec![],
1651 is_first_time: false,
1652 },
1653 remote: Some(RemoteContributor {
1654 username: Some(String::from("nuhro")),
1655 pr_title: None,
1656 pr_number: None,
1657 pr_labels: vec![],
1658 is_first_time: false,
1659 }),
1660 ..Default::default()
1661 },
1662 Commit {
1663 id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
1664 message: String::from("do some stuff"),
1665 bitbucket: RemoteContributor {
1666 username: Some(String::from("awesome_contributor")),
1667 pr_title: None,
1668 pr_number: None,
1669 pr_labels: vec![],
1670 is_first_time: false,
1671 },
1672 remote: Some(RemoteContributor {
1673 username: Some(String::from("awesome_contributor")),
1674 pr_title: None,
1675 pr_number: None,
1676 pr_labels: vec![],
1677 is_first_time: false,
1678 }),
1679 ..Default::default()
1680 },
1681 Commit {
1682 id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
1683 message: String::from("alright"),
1684 bitbucket: RemoteContributor {
1685 username: Some(String::from("orhun")),
1686 pr_title: None,
1687 pr_number: None,
1688 pr_labels: vec![],
1689 is_first_time: false,
1690 },
1691 remote: Some(RemoteContributor {
1692 username: Some(String::from("orhun")),
1693 pr_title: None,
1694 pr_number: None,
1695 pr_labels: vec![],
1696 is_first_time: false,
1697 }),
1698 ..Default::default()
1699 },
1700 Commit {
1701 id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
1702 message: String::from("should be fine"),
1703 bitbucket: RemoteContributor {
1704 username: Some(String::from("someone")),
1705 pr_title: None,
1706 pr_number: None,
1707 pr_labels: vec![],
1708 is_first_time: false,
1709 },
1710 remote: Some(RemoteContributor {
1711 username: Some(String::from("someone")),
1712 pr_title: None,
1713 pr_number: None,
1714 pr_labels: vec![],
1715 is_first_time: false,
1716 }),
1717 ..Default::default()
1718 },
1719 ];
1720 assert_eq!(expected_commits, release.commits);
1721
1722 release
1723 .bitbucket
1724 .contributors
1725 .sort_by(|a, b| a.pr_number.cmp(&b.pr_number));
1726
1727 let expected_metadata = RemoteReleaseMetadata {
1728 contributors: vec![
1729 RemoteContributor {
1730 username: Some(String::from("nuhro")),
1731 pr_title: None,
1732 pr_number: None,
1733 pr_labels: vec![],
1734 is_first_time: true,
1735 },
1736 RemoteContributor {
1737 username: Some(String::from("awesome_contributor")),
1738 pr_title: None,
1739 pr_number: None,
1740 pr_labels: vec![],
1741 is_first_time: true,
1742 },
1743 RemoteContributor {
1744 username: Some(String::from("someone")),
1745 pr_title: None,
1746 pr_number: None,
1747 pr_labels: vec![],
1748 is_first_time: true,
1749 },
1750 RemoteContributor {
1751 username: Some(String::from("orhun")),
1752 pr_title: Some(String::from("1")),
1753 pr_number: Some(1),
1754 pr_labels: vec![],
1755 is_first_time: false,
1756 },
1757 ],
1758 };
1759 assert_eq!(expected_metadata, release.bitbucket);
1760
1761 Ok(())
1762 }
1763}