use std::path::Path;
use fallow_config::WorkspaceInfo;
use fallow_types::flag_retirement::{FlagAgeMode, FlagRetirementReport, RetirementFlagKind};
use fallow_types::workspace::WorkspaceDiagnosticKind;
use rustc_hash::FxHashSet;
use crate::clock::AnalysisClock;
use crate::flag_age::{FlagAgeRequest, PickaxeProgress, apply_flag_ages};
use crate::flag_retirement::{
AGE_GATE_AGE_OFF, AGE_GATE_NO_HISTORY, RetirementOptions, RetirementSiteInput, aggregate_flags,
finish_report, max_age_gate,
};
use crate::flag_vendor::{VendorExport, VendorMatch, apply_vendor_state};
pub struct RetirementRequest<'a> {
pub root: &'a Path,
pub workspaces: &'a [WorkspaceInfo],
pub sites: Vec<RetirementSiteInput>,
pub in_scope: &'a dyn Fn(&Path) -> bool,
pub whole_project: bool,
pub age_mode: FlagAgeMode,
pub cache_dir: Option<&'a Path>,
pub progress: Option<&'a (dyn Fn(PickaxeProgress) + Sync)>,
pub vendor_export: Option<&'a VendorExport>,
pub vendor_key_prefix: Option<&'a str>,
pub max_flag_age: Option<u64>,
pub options: RetirementOptions,
}
pub struct RetirementBuild {
pub report: FlagRetirementReport,
pub diagnostics: Vec<WorkspaceDiagnosticKind>,
}
#[must_use]
pub fn build_retirement_report(request: RetirementRequest<'_>) -> RetirementBuild {
let root = request.root;
let code_flag_names: FxHashSet<String> = request
.sites
.iter()
.map(|site| site.flag_name.clone())
.collect();
let project_sdk_labels: FxHashSet<String> = request
.sites
.iter()
.filter(|site| site.kind == RetirementFlagKind::SdkCall)
.filter_map(|site| site.sdk_name.clone())
.collect();
let mut rows = aggregate_flags(request.sites, root, request.workspaces, request.in_scope);
let age = apply_flag_ages(
&mut rows,
&FlagAgeRequest {
root,
mode: request.age_mode,
cache_dir: request.cache_dir,
progress: request.progress,
},
);
let vendor_state = request.vendor_export.map(|export| {
apply_vendor_state(
&mut rows,
&VendorMatch {
export,
key_prefix: request.vendor_key_prefix,
code_flag_names: &code_flag_names,
project_sdk_labels: &project_sdk_labels,
add_vendor_only: request.whole_project,
clock_epoch_secs: AnalysisClock::for_repo(root).epoch_secs(),
},
)
});
let skip_reason = if request.age_mode == FlagAgeMode::Off {
Some(AGE_GATE_AGE_OFF)
} else if age.generated_at_clock.is_none() {
Some(AGE_GATE_NO_HISTORY)
} else {
None
};
let max_flag_age = request
.max_flag_age
.map(|days| max_age_gate(&rows, days, skip_reason));
let mut report = finish_report(
rows,
request.age_mode,
age.generated_at_clock,
&request.options,
);
report.vendor_state = vendor_state;
report.max_flag_age = max_flag_age;
RetirementBuild {
report,
diagnostics: age.diagnostics,
}
}