use aube_lockfile::LocalSource;
use std::collections::{BTreeMap, BTreeSet, HashSet};
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
pub trait ReadPackageHook: Send {
fn read_package<'a>(
&'a mut self,
pkg: aube_registry::VersionMetadata,
) -> Pin<Box<dyn Future<Output = Result<aube_registry::VersionMetadata, String>> + Send + 'a>>;
}
#[derive(Debug, Clone, Default)]
pub struct MinimumReleaseAge {
pub minutes: u64,
pub exclude: HashSet<String>,
pub strict: bool,
}
#[derive(Debug, Clone)]
pub struct DependencyPolicy {
pub package_extensions: Vec<PackageExtension>,
pub allowed_deprecated_versions: BTreeMap<String, String>,
pub trust_policy: TrustPolicy,
pub trust_policy_exclude: BTreeSet<String>,
pub trust_policy_ignore_after: Option<u64>,
pub block_exotic_subdeps: bool,
}
impl Default for DependencyPolicy {
fn default() -> Self {
Self {
package_extensions: Vec::new(),
allowed_deprecated_versions: BTreeMap::new(),
trust_policy: TrustPolicy::default(),
trust_policy_exclude: BTreeSet::new(),
trust_policy_ignore_after: None,
block_exotic_subdeps: true,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct PackageExtension {
pub selector: String,
pub dependencies: BTreeMap<String, String>,
pub optional_dependencies: BTreeMap<String, String>,
pub peer_dependencies: BTreeMap<String, String>,
pub peer_dependencies_meta: BTreeMap<String, aube_registry::PeerDepMeta>,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum TrustPolicy {
NoDowngrade,
#[default]
Off,
}
impl MinimumReleaseAge {
pub fn cutoff(&self) -> Option<String> {
if self.minutes == 0 {
return None;
}
let now = SystemTime::now().duration_since(UNIX_EPOCH).ok()?.as_secs();
let cutoff_secs = now.saturating_sub(self.minutes * 60);
Some(format_iso8601_utc(cutoff_secs))
}
}
pub(crate) fn format_iso8601_utc(epoch_secs: u64) -> String {
let days = (epoch_secs / 86_400) as i64;
let secs_of_day = epoch_secs % 86_400;
let h = secs_of_day / 3600;
let m = (secs_of_day % 3600) / 60;
let s = secs_of_day % 60;
let (y, mo, d) = civil_from_days(days);
format!("{y:04}-{mo:02}-{d:02}T{h:02}:{m:02}:{s:02}.000Z")
}
fn civil_from_days(days: i64) -> (i64, u32, u32) {
let z = days + 719_468;
let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
let doe = (z - era * 146_097) as u64;
let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
let y = yoe as i64 + era * 400;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let d = (doy - (153 * mp + 2) / 5 + 1) as u32;
let m = if mp < 10 { mp + 3 } else { mp - 9 } as u32;
let y = if m <= 2 { y + 1 } else { y };
(y, m, d)
}
#[derive(Debug, Clone)]
pub struct ResolvedPackage {
pub dep_path: String,
pub name: String,
pub version: String,
pub integrity: Option<String>,
pub tarball_url: Option<String>,
pub alias_of: Option<String>,
pub local_source: Option<LocalSource>,
pub os: aube_lockfile::PlatformList,
pub cpu: aube_lockfile::PlatformList,
pub libc: aube_lockfile::PlatformList,
pub deprecated: Option<Arc<str>>,
}
impl ResolvedPackage {
pub fn registry_name(&self) -> &str {
self.alias_of.as_deref().unwrap_or(&self.name)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ResolutionMode {
#[default]
Highest,
TimeBased,
}