Skip to main content

git_explore/manage/
build_context.rs

1//! source from https://github.com/kodemaniak/cargo-gitv/blob/main/src/build_context.rs
2
3use 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        // .with_context(|| "Failed to generate valid dev version.")
28    }
29}
30
31// pub fn load_build_context() -> Result<BuildContext> {
32//     let mut cmd = cargo_metadata::MetadataCommand::new();
33//     cmd.manifest_path("./Cargo.toml");
34//     let cargo_metadata = cmd
35//         .exec()
36//         .context("Could not find the cargo metadata. Tried ./Cargo.toml")?;
37
38//     let git_repository = Repository::open("./")
39//       .context("Could not find a git repository. Please run from the top-level folder of a git repository.")?;
40
41//     let git_sha = get_git_sha(&git_repository)?;
42//     let git_latest_version = get_git_latest_version(&git_repository)?;
43//     let cargo_version = get_cargo_version(&cargo_metadata)?;
44//     let git_commit_timestamp = get_git_commit_timestamp(&git_repository).ok();
45
46//     let build_context = BuildContext {
47//         git_repository,
48//         cargo_metadata,
49//         git_sha,
50//         git_latest_version,
51//         git_commit_timestamp,
52//         cargo_version,
53//     };
54
55//     Ok(build_context)
56// }
57
58pub 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}