mirror of
https://github.com/ruvnet/RuView
synced 2026-07-31 18:51:42 +00:00
535043731c
HAP accessory signing seed no longer reachable via derived Debug. /api/history/period and /api/logbook no longer break the default (unfiltered) call shape above 32 entities. fire_event's event_type validation relaxed to match real HA's contract. homecore-migrate gained a --force flag for re-running imports. Public v2051 release notes corrected. 110 tests across the 3 touched crates, 0 failed, clippy clean.
157 lines
5.7 KiB
Rust
157 lines
5.7 KiB
Rust
//! `homecore-migrate` binary — CLI entry point.
|
|
|
|
use clap::Parser;
|
|
use homecore_migrate::cli::{Cli, Command};
|
|
use serde::Serialize;
|
|
|
|
#[derive(Serialize)]
|
|
struct ImportSummary {
|
|
kind: &'static str,
|
|
imported: usize,
|
|
warning_count: usize,
|
|
warnings: Vec<serde_json::Value>,
|
|
destination: std::path::PathBuf,
|
|
}
|
|
|
|
fn print_summary(summary: &ImportSummary) -> anyhow::Result<()> {
|
|
println!("{}", serde_json::to_string(summary)?);
|
|
Ok(())
|
|
}
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
tracing_subscriber::fmt::init();
|
|
let cli = Cli::parse();
|
|
|
|
match cli.command {
|
|
Command::Inspect(args) => {
|
|
println!(
|
|
"Inspecting HA .storage directory: {}",
|
|
args.storage.display()
|
|
);
|
|
// Probe entity_registry
|
|
let entity_path = args.storage.join("core.entity_registry");
|
|
if entity_path.exists() {
|
|
match homecore_migrate::entity_registry::read_entity_registry(&entity_path) {
|
|
Ok(entries) => println!(" core.entity_registry: {} entities", entries.len()),
|
|
Err(e) => println!(" core.entity_registry: ERROR — {e}"),
|
|
}
|
|
}
|
|
// Probe device_registry
|
|
let device_path = args.storage.join("core.device_registry");
|
|
if device_path.exists() {
|
|
match homecore_migrate::device_registry::read_device_registry(&device_path) {
|
|
Ok(devices) => println!(" core.device_registry: {} devices", devices.len()),
|
|
Err(e) => println!(" core.device_registry: ERROR — {e}"),
|
|
}
|
|
}
|
|
// Probe config_entries
|
|
let ce_path = args.storage.join("core.config_entries");
|
|
if ce_path.exists() {
|
|
match homecore_migrate::config_entries::inspect_config_entries(&ce_path) {
|
|
Ok(s) => println!(
|
|
" core.config_entries: {} entries, domains: {}",
|
|
s.count,
|
|
s.domains.join(", ")
|
|
),
|
|
Err(e) => println!(" core.config_entries: ERROR — {e}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
Command::ImportEntities(args) => {
|
|
let entity_path = args.storage.join("core.entity_registry");
|
|
let entries = homecore_migrate::entity_registry::read_entity_registry(&entity_path)?;
|
|
let destination = homecore_migrate::entity_registry::write_entity_registry_with(
|
|
&args.to,
|
|
&entries,
|
|
args.force,
|
|
)?;
|
|
print_summary(&ImportSummary {
|
|
kind: "entity_registry",
|
|
imported: entries.len(),
|
|
warning_count: 0,
|
|
warnings: vec![],
|
|
destination,
|
|
})?;
|
|
}
|
|
|
|
Command::ImportDevices(args) => {
|
|
let device_path = args.storage.join("core.device_registry");
|
|
let devices = homecore_migrate::device_registry::read_device_registry(&device_path)?;
|
|
let destination = homecore_migrate::device_registry::write_device_registry_with(
|
|
&args.to,
|
|
&devices,
|
|
args.force,
|
|
)?;
|
|
print_summary(&ImportSummary {
|
|
kind: "device_registry",
|
|
imported: devices.len(),
|
|
warning_count: 0,
|
|
warnings: vec![],
|
|
destination,
|
|
})?;
|
|
}
|
|
|
|
Command::InspectConfigEntries(args) => {
|
|
let ce_path = args.storage.join("core.config_entries");
|
|
let summary = homecore_migrate::config_entries::inspect_config_entries(&ce_path)?;
|
|
println!(
|
|
"config_entries: {} total, domains: {}",
|
|
summary.count,
|
|
summary.domains.join(", ")
|
|
);
|
|
}
|
|
|
|
Command::ImportConfigEntries(args) => {
|
|
let source = args.storage.join("core.config_entries");
|
|
let converted = homecore_migrate::config_entries::convert_config_entries(&source)?;
|
|
let imported = converted.data.entries.len();
|
|
let warning_count = converted.data.warnings.len();
|
|
let warnings = converted
|
|
.data
|
|
.warnings
|
|
.iter()
|
|
.map(serde_json::to_value)
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
let destination = homecore_migrate::config_entries::write_config_entries_with(
|
|
&args.to,
|
|
&converted,
|
|
args.force,
|
|
)?;
|
|
print_summary(&ImportSummary {
|
|
kind: "config_entries",
|
|
imported,
|
|
warning_count,
|
|
warnings,
|
|
destination,
|
|
})?;
|
|
}
|
|
|
|
Command::InspectSecrets(args) => {
|
|
let secrets_path = args.config_dir.join("secrets.yaml");
|
|
let secrets = homecore_migrate::secrets::read_secrets(&secrets_path)?;
|
|
println!("{} secrets found:", secrets.len());
|
|
let mut keys: Vec<_> = secrets.keys().collect();
|
|
keys.sort();
|
|
for k in keys {
|
|
println!(" {} = <redacted>", k);
|
|
}
|
|
}
|
|
|
|
Command::InspectAutomations(args) => {
|
|
let auto_path = args.config_dir.join("automations.yaml");
|
|
let summary = homecore_migrate::automations::read_automations(&auto_path)?;
|
|
println!("{} automations:", summary.count);
|
|
for a in &summary.automations {
|
|
println!(
|
|
" id={} alias={}",
|
|
a.id,
|
|
a.alias.as_deref().unwrap_or("<unnamed>")
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|