| 1 | |
| 2 | |
| 3 | use crate::command::{GitCommand, GitEnv}; |
| 4 | use crate::error::{Error, Result}; |
| 5 | |
| 6 | |
| 7 | pub fn parse_git_version(output: &str) -> Option<(u32, u32, u32)> { |
| 8 | let token = output |
| 9 | .split_whitespace() |
| 10 | .find(|t| t.starts_with(|c: char| c.is_ascii_digit()))?; |
| 11 | let mut parts = token.split('.'); |
| 12 | let major = leading_number(parts.next()?)?; |
| 13 | let minor = leading_number(parts.next()?)?; |
| 14 | let patch = parts.next().and_then(leading_number).unwrap_or(0); |
| 15 | Some((major, minor, patch)) |
| 16 | } |
| 17 | |
| 18 | |
| 19 | fn leading_number(s: &str) -> Option<u32> { |
| 20 | let digits: String = s.chars().take_while(|c| c.is_ascii_digit()).collect(); |
| 21 | digits.parse().ok() |
| 22 | } |
| 23 | |
| 24 | fn fmt_version((major, minor, patch): (u32, u32, u32)) -> String { |
| 25 | format!("{major}.{minor}.{patch}") |
| 26 | } |
| 27 | |
| 28 | |
| 29 | pub async fn git_version(env: &GitEnv) -> Result<(u32, u32, u32)> { |
| 30 | let out = GitCommand::new(env, "version").output().await?; |
| 31 | let text = String::from_utf8_lossy(&out); |
| 32 | parse_git_version(&text).ok_or_else(|| { |
| 33 | Error::Unavailable(format!("cannot parse git version from {:?}", text.trim())) |
| 34 | }) |
| 35 | } |
| 36 | |
| 37 | |
| 38 | pub async fn require_min_version(env: &GitEnv, min: (u32, u32, u32)) -> Result<()> { |
| 39 | let found = git_version(env).await?; |
| 40 | if found < min { |
| 41 | return Err(Error::TooOld { |
| 42 | found: fmt_version(found), |
| 43 | required: fmt_version(min), |
| 44 | }); |
| 45 | } |
| 46 | Ok(()) |
| 47 | } |