git_calver/
repo_release.rs

1use std::vec::Vec;
2
3use git2::Oid;
4use git2::Repository;
5
6use crate::calver::CalVer;
7use crate::calver::ToCalVer;
8use crate::repo::RepositoryExt;
9
10#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
11pub struct Release {
12    pub version: CalVer,
13    pub commit_id: Oid,
14}
15
16impl Release {
17    pub fn zero() -> Release {
18        Release {
19            commit_id: Oid::zero(),
20            version: CalVer::zero(),
21        }
22    }
23}
24
25pub trait RepositoryWithRelease {
26    fn find_releases(&self) -> Vec<Release>;
27    fn find_latest_release(&self) -> Option<Release>;
28}
29
30impl RepositoryWithRelease for Repository {
31    fn find_releases(&self) -> Vec<Release> {
32        let tag_names = self
33            .tag_names(None)
34            .ok()
35            .map(|a| {
36                a.iter()
37                    .flatten()
38                    .map(|s| s.to_string())
39                    .collect::<Vec<_>>()
40            })
41            .unwrap_or_default();
42        let all_releases = tag_names
43            .iter()
44            .flat_map(|t| t.calver())
45            .flat_map(|v| {
46                self.resolve_reference_from_short_name(v.to_string().as_str())
47                    .ok()
48                    .and_then(|r| r.peel_to_commit().ok())
49                    .map(|c| Release {
50                        commit_id: c.id(),
51                        version: v,
52                    })
53            })
54            .collect::<Vec<_>>();
55        if let Some(head) = self.head().ok().and_then(|r| r.peel_to_commit().ok()) {
56            let mut releases = self
57                .iter_commit_id(&head)
58                .flat_map(|cid| {
59                    all_releases
60                        .iter()
61                        .filter(|r| cid == r.commit_id)
62                        .copied()
63                        .next()
64                })
65                .collect::<Vec<_>>();
66            releases.sort();
67            releases.reverse();
68            releases
69        } else {
70            vec![]
71        }
72    }
73
74    fn find_latest_release(&self) -> Option<Release> {
75        self.find_releases().into_iter().next()
76    }
77}