use crate::facts::FactsDb;
use crate::{CodeLoreError, Options, Result};
use serde::Serialize;
pub const GIX_VERSION: &str = "0.86.0";
pub const DUCKDB_VERSION: &str = "1.10505.0";
pub const MANIFEST_SCHEMA_VERSION: u32 = 2;
fn grammar_pins() -> std::collections::BTreeMap<String, String> {
let mut m = std::collections::BTreeMap::new();
m.insert("tree-sitter".into(), "0.25.3".into());
m.insert("tree-sitter-rust".into(), "0.23.2".into());
m.insert("tree-sitter-python".into(), "0.23.6".into());
m.insert("tree-sitter-java".into(), "0.23.5".into());
m.insert("tree-sitter-javascript".into(), "0.23.1".into());
m.insert("tree-sitter-typescript".into(), "0.23.1".into());
m
}
const RUST_VERSION: &str = "1.96";
const TARGET_TRIPLE: &str = {
if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
"aarch64-apple-darwin"
} else if cfg!(all(target_os = "macos", target_arch = "x86_64")) {
"x86_64-apple-darwin"
} else if cfg!(all(target_os = "linux", target_arch = "x86_64")) {
"x86_64-unknown-linux-gnu"
} else if cfg!(all(target_os = "linux", target_arch = "aarch64")) {
"aarch64-unknown-linux-gnu"
} else if cfg!(all(target_os = "windows", target_arch = "x86_64")) {
"x86_64-pc-windows-msvc"
} else {
"unknown"
}
};
#[derive(Debug, Serialize)]
pub struct Manifest {
pub schema_version: u32,
pub codelore_version: String,
pub gix_version: String,
pub arrow_version: String,
pub duckdb_version: String,
pub run_started_at: String,
pub repo_path: String,
pub head_sha: String,
pub cache_key_hash: String,
pub after_date: Option<String>,
pub before_date: Option<String>,
pub analysis: String,
pub min_revs: u32,
pub min_shared_revs: u32,
pub min_coupling_pct: u8,
pub max_changeset_size: u32,
pub fisher_significance: f64,
pub include_merges: bool,
pub age_time_now: Option<String>,
pub merge_handling: String,
pub complexity_sample: String,
pub rust_version: String,
pub target_triple: String,
pub grammars: std::collections::BTreeMap<String, String>,
pub options: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub corpus_vintage: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub defect_vintage: Option<String>,
}
impl Manifest {
pub fn capture(db: &FactsDb, opts: &Options, analysis: &str) -> Result<Self> {
let now = time::OffsetDateTime::now_utc();
let run_started_at = format!(
"{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
now.year(),
u8::from(now.month()),
now.day(),
now.hour(),
now.minute(),
now.second()
);
let complexity_sample = match opts.complexity_sample {
crate::options::ComplexitySample::Head => "head",
crate::options::ComplexitySample::Adaptive => "adaptive",
crate::options::ComplexitySample::Full => "full",
};
let head_sha: String = db
.conn()
.query_row(
"SELECT rev FROM commits ORDER BY rowid ASC LIMIT 1",
[],
|r| r.get(0),
)
.unwrap_or_default();
let cache_key_bytes = crate::cache::cache_key(&opts.repo_path, &head_sha, opts);
let cache_key_hash = hex::encode(cache_key_bytes);
let corpus_vintage = crate::calibration::active_vintage(opts)?;
let defect_vintage = crate::defect_calibration::active_vintage(opts)?;
Ok(Self {
schema_version: MANIFEST_SCHEMA_VERSION,
codelore_version: env!("CARGO_PKG_VERSION").to_string(),
gix_version: GIX_VERSION.to_string(),
arrow_version: crate::arrow_facade::ARROW_RUNTIME_VERSION.to_string(),
duckdb_version: DUCKDB_VERSION.to_string(),
run_started_at,
repo_path: opts.repo_path.display().to_string(),
head_sha,
cache_key_hash,
after_date: opts.after.map(|d| d.to_string()),
before_date: opts.before.map(|d| d.to_string()),
analysis: analysis.to_string(),
min_revs: opts.min_revs,
min_shared_revs: opts.min_shared_revs,
min_coupling_pct: opts.min_coupling_pct,
max_changeset_size: opts.max_changeset_size,
fisher_significance: opts.fisher_significance,
include_merges: opts.include_merges,
age_time_now: opts.age_time_now.map(|d| d.to_string()),
merge_handling: if opts.include_merges {
"include"
} else {
"exclude"
}
.to_string(),
complexity_sample: complexity_sample.to_string(),
rust_version: RUST_VERSION.to_string(),
target_triple: TARGET_TRIPLE.to_string(),
grammars: grammar_pins(),
options: opts.canonical_json(),
corpus_vintage,
defect_vintage,
})
}
pub fn to_json(&self) -> Result<String> {
serde_json::to_string_pretty(self)
.map_err(|e| CodeLoreError::Output(format!("manifest json: {e}")))
}
}