use semver::Version;
use serde::Serialize;
pub const MAX_RETRY_ATTEMPTS: u32 = 3;
pub const RETRY_DELAY_MS: u64 = 2000;
pub const VERSION_UPDATE_DELAY_MS: u64 = 1000;
pub const PROGRESS_TICK_MS: u64 = 100;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PackageSource {
Crates,
Git {
url: String,
rev: Option<String>,
},
Path {
dir: String,
},
}
impl PackageSource {
pub fn is_crates(&self) -> bool {
matches!(self, PackageSource::Crates)
}
pub fn marker(&self) -> &'static str {
match self {
PackageSource::Crates => "",
PackageSource::Git { .. } => "[git]",
PackageSource::Path { .. } => "[path]",
}
}
}
#[derive(Debug)]
pub struct PackageInfo {
pub name: String,
pub current_version: Option<String>,
pub latest_version: Option<String>,
pub source: PackageSource,
}
#[derive(Debug, Clone)]
pub struct UpdateResult {
pub package_name: String,
pub old_version: Option<String>,
pub new_version: Option<String>,
pub success: bool,
}
impl PackageInfo {
#[allow(dead_code)]
pub fn new(name: String, current_version: Option<String>) -> Self {
Self::with_source(name, current_version, PackageSource::Crates)
}
pub fn with_source(
name: String,
current_version: Option<String>,
source: PackageSource,
) -> Self {
Self {
name,
current_version,
latest_version: None,
source,
}
}
pub fn has_update(&self) -> bool {
match (&self.current_version, &self.latest_version) {
(Some(current), Some(latest)) => {
match (Version::parse(current), Version::parse(latest)) {
(Ok(c), Ok(l)) => l > c,
_ => current != latest,
}
}
_ => false,
}
}
pub fn is_prerelease(&self) -> bool {
self.latest_version
.as_ref()
.and_then(|v| Version::parse(v).ok())
.map(|v| !v.pre.is_empty())
.unwrap_or(false)
}
}
#[derive(Debug, Clone, Serialize)]
pub struct JsonReport<'a> {
pub schema_version: u32,
pub format: &'static str,
pub include_prerelease: bool,
pub dry_run: bool,
pub registry_url: Option<&'a str>,
pub updates_available: Vec<JsonUpdateCandidate<'a>>,
pub fresh: Vec<&'a str>,
pub skipped: Vec<JsonSkipped<'a>>,
pub results: Vec<JsonResult<'a>>,
pub summary: JsonSummary,
pub aborted: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct JsonUpdateCandidate<'a> {
pub name: &'a str,
pub current: Option<&'a str>,
pub latest: &'a str,
pub source: &'static str,
pub prerelease: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct JsonSkipped<'a> {
pub name: &'a str,
pub source: &'static str,
pub reason: &'static str,
}
#[derive(Debug, Clone, Serialize)]
pub struct JsonResult<'a> {
pub name: &'a str,
pub old_version: Option<&'a str>,
pub new_version: Option<&'a str>,
pub success: bool,
}
#[derive(Debug, Clone, Serialize)]
pub struct JsonSummary {
pub checked: usize,
pub available: usize,
pub succeeded: usize,
pub failed: usize,
pub skipped: usize,
pub duration_ms: u128,
}
impl PackageSource {
pub fn kind_str(&self) -> &'static str {
match self {
PackageSource::Crates => "crates",
PackageSource::Git { .. } => "git",
PackageSource::Path { .. } => "path",
}
}
}
impl UpdateResult {
pub fn new(
package_name: String,
old_version: Option<String>,
new_version: Option<String>,
success: bool,
) -> Self {
Self {
package_name,
old_version,
new_version,
success,
}
}
}