git_calver/
releaser.rs

1use chrono::prelude::Datelike;
2use chrono::prelude::Local;
3use chrono::DateTime;
4use git2::Error;
5use git2::Oid;
6use git2::Repository;
7
8use crate::calver::CalVer;
9use crate::calver::ToCalVer;
10use crate::repo_release::Release;
11use crate::repo_release::RepositoryWithRelease;
12
13pub struct Releaser<'a> {
14    repo: &'a Repository,
15}
16
17impl<'a> Releaser<'a> {
18    pub fn new(repo: &Repository) -> Releaser {
19        Releaser { repo }
20    }
21
22    pub fn last_release(&self) -> Release {
23        self.repo
24            .find_latest_release()
25            .unwrap_or_else(Release::zero)
26    }
27
28    pub fn next_version(&self) -> CalVer {
29        self.next_version_of(self.last_release().version)
30    }
31
32    pub fn next_version_of(&self, current: CalVer) -> CalVer {
33        let t: DateTime<Local> = Local::now();
34        let date_ver = format!("{}.{}", t.year() % 100, t.month());
35        let mut i = 0;
36        loop {
37            let v = format!("{}.{}", date_ver, i)
38                .calver()
39                .unwrap_or_else(|| CalVer::new(i));
40            if v > current {
41                return v;
42            }
43            i += 1;
44        }
45    }
46    pub fn is_releasable(&self) -> bool {
47        let last_id = self.last_release().commit_id;
48        let head_commit = self
49            .repo
50            .head()
51            .ok()
52            .and_then(|head| head.peel_to_commit().ok());
53        if let Some(commit) = head_commit {
54            commit.id() != last_id || last_id == Oid::zero()
55        } else {
56            false
57        }
58    }
59
60    pub fn bump(&self, message: &str, lightweught: bool) -> Result<CalVer, Error> {
61        let v = self.next_version();
62        self.bump_to(v, message, lightweught)
63    }
64
65    pub fn bump_to(
66        &self,
67        version: CalVer,
68        message: &str,
69        lightweught: bool,
70    ) -> Result<CalVer, Error> {
71        let result = if lightweught {
72            self.repo.tag_lightweight(
73                format!("{}", version).as_str(),
74                self.repo.head()?.peel_to_commit()?.as_object(),
75                false,
76            )
77        } else {
78            self.repo.tag(
79                format!("{}", version).as_str(),
80                self.repo.head()?.peel_to_commit()?.as_object(),
81                &self.repo.signature()?,
82                message,
83                false,
84            )
85        };
86        match result {
87            Ok(_) => Ok(version),
88            Err(err) => Err(err),
89        }
90    }
91}