git_explore/manage/
build_context.rs1use crate::*;
4pub use anyhow::{anyhow, Context, Result};
5pub struct BuildContext {
6 pub git_repository: Repository,
7 pub cargo_metadata: Metadata,
8 pub git_sha: String,
9 pub git_latest_version: Option<Version>,
10 pub git_commit_timestamp: Option<DateTime<Utc>>,
11 pub cargo_version: Version,
12}
13
14impl BuildContext {
15 pub fn dev_version(&self) -> Result<Version> {
16 let timestamp: DateTime<Utc> = self
17 .git_commit_timestamp
18 .unwrap_or_else(|| SystemTime::now().into());
19 let timestamp_formatted = timestamp.format("%Y%m%d%H%M%S");
20
21 let dev_version = format!(
22 "{}-dev.{}+{}",
23 self.cargo_version, timestamp_formatted, self.git_sha
24 );
25
26 Ok(Version::parse(&dev_version).unwrap())
27 }
29}
30
31pub fn get_git_sha(git_repository: &Repository) -> Result<String> {
59 let mut sha = git_repository
60 .head()?
61 .target()
62 .ok_or_else(|| anyhow!("Could not determin git commit SHA!"))?
63 .to_string();
64 sha.truncate(7);
65
66 Ok(sha)
67}
68
69pub fn get_git_latest_version(git_repository: &Repository) -> Result<Option<Version>> {
70 let mut tags: Vec<Version> = git_repository
71 .tag_names(Some("v*"))?
72 .into_iter()
73 .flatten()
74 .flat_map(|v| v.strip_prefix('v'))
75 .flat_map(semver::Version::parse)
76 .collect();
77 tags.sort();
78 tags.reverse();
79
80 let current_release_version = tags.first().cloned();
81
82 Ok(current_release_version)
83}
84
85pub fn get_git_commit_timestamp(git_repository: &Repository) -> Result<DateTime<Utc>> {
86 let head_ref = git_repository.find_reference("HEAD")?;
87 let head_direct = head_ref.resolve()?;
88 let head_refspec = head_direct.name().expect("invalid name");
89 let head_oid = git_repository.refname_to_id(head_refspec)?;
90 let commit = git_repository.find_commit(head_oid)?;
91 let commit_timestamp = commit.time().seconds();
92 let timestamp: DateTime<Utc> =
93 DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(commit_timestamp, 0), Utc);
94
95 Ok(timestamp)
96}
97
98pub trait CargoVersion {
99 fn cargo_version(&self) -> Result<Version>;
100}
101impl CargoVersion for Metadata {
102 fn cargo_version(&self) -> Result<Version> {
103 let root = self.workspace_members.first().unwrap();
104 let package = self
105 .packages
106 .iter()
107 .find(|p| p.id == *root)
108 .ok_or_else(|| anyhow!("Could not determine cargo package version."))?;
109 Ok(package.version.clone())
110 }
111}
112impl CargoVersion for &str {
113 fn cargo_version(&self) -> Result<Version> {
114 let mut cmd = cargo_metadata::MetadataCommand::new();
115 cmd.manifest_path(self);
116 let cargo_metadata = cmd
117 .exec()
118 .context("Could not find the cargo metadata. Tried ./Cargo.toml")?;
119 cargo_metadata.cargo_version()
120 }
121}