use anyhow::Result;
use colored::Colorize;
use crate::cli::SetupScope;
use crate::pkg;
pub fn run(
verbose: bool,
fallback: bool,
no_pm: bool,
force: bool,
scope: Option<SetupScope>
) -> Result<()> {
println!("{} Syncing package databases...", "::".bold().blue());
if force {
println!(
"{} Force sync enabled, removing existing databases...",
"::".bold().yellow()
);
}
let pkg_scope = match scope {
Some(SetupScope::User) => Some(crate::pkg::types::Scope::User),
Some(SetupScope::System) => Some(crate::pkg::types::Scope::System),
None => None
};
pkg::sync::run(verbose, fallback, no_pm, force, pkg_scope)?;
println!("{}", "Sync complete.".green());
Ok(())
}
pub fn run_local(
verbose: bool,
fallback: bool,
force: bool,
frozen: bool
) -> Result<()> {
if frozen {
crate::pkg::frozen::set_frozen(true);
}
println!(
"{} Syncing project-local package databases...",
"::".bold().blue()
);
pkg::sync::run_local(verbose, fallback, force, frozen)?;
println!("{}", "Local sync complete.".green());
Ok(())
}
fn warn_third_party(name: &str, registry_type: &str) {
if registry_type != "official" {
eprintln!(
"{} {} is a third-party registry. Use with caution and verify its \
authenticity before installing packages.",
"!".yellow().bold(),
name.cyan()
);
}
}
pub fn set_registry(url_or_handle: &str) -> Result<()> {
let handle_or_url_storage;
let handle_or_url = if url_or_handle == "default" {
handle_or_url_storage = pkg::builtin_registries::get_set()?
.map_or_else(|| "zoidberg".to_string(), |r| r.handle);
&handle_or_url_storage
} else {
url_or_handle
};
let builtin = pkg::builtin_registries::get(handle_or_url);
if let Some(ref reg) = builtin {
warn_third_party(®.name, ®.registry_type);
}
pkg::config::set_default_registry(handle_or_url)?;
let (display_handle, display_url) = match builtin {
Some(ref reg) => (reg.handle.as_str(), reg.git.as_str()),
None => (handle_or_url, handle_or_url)
};
println!("Default registry set to: {}", display_handle.cyan());
if !display_url.is_empty() && display_url != display_handle {
println!(" Git: {display_url}");
}
println!("The new registry will be used the next time you run 'zoi sync'");
Ok(())
}
pub fn add_registry(handle_or_url: &str) -> Result<()> {
let resolved_storage;
let handle_or_url = if handle_or_url == "default" {
resolved_storage = pkg::builtin_registries::get_set()?
.map_or_else(|| "zoidberg".to_string(), |r| r.handle);
&resolved_storage
} else {
handle_or_url
};
let path = std::path::Path::new(handle_or_url);
if path.is_dir() {
let final_url =
std::fs::canonicalize(path)?.to_string_lossy().to_string();
pkg::config::add_added_registry(&final_url)?;
let url_cyan = final_url.cyan();
println!("Registry '{url_cyan}' added.");
println!("It will be synced on the next 'zoi sync' run.");
return Ok(());
}
if let Some(reg) = pkg::builtin_registries::get(handle_or_url) {
warn_third_party(®.name, ®.registry_type);
pkg::config::add_added_registry(handle_or_url)?;
println!("Registry {} added.", reg.handle.cyan());
println!(" Name: {}", reg.name);
println!(" Git: {}", reg.git);
println!("It will be synced on the next 'zoi sync' run.");
return Ok(());
}
if pkg::sync::is_repo_yaml_url(handle_or_url)
&& let Ok(registry) =
pkg::sync::resolve_registry_from_url(handle_or_url)
{
pkg::config::add_resolved_registry(registry.clone())?;
let handle = registry.handle.cyan();
println!("Registry {handle} added.");
if let Some(name) = ®istry.name {
println!(" Name: {name}");
}
if let Some(description) = ®istry.description {
println!(" Description: {description}");
}
println!(" Source: {}", registry.url.cyan());
println!("It will be synced on the next 'zoi sync' run.");
return Ok(());
}
pkg::config::add_added_registry(handle_or_url)?;
let url_cyan = handle_or_url.cyan();
println!("Registry '{url_cyan}' added.");
println!("It will be synced on the next 'zoi sync' run.");
Ok(())
}
pub fn remove_registry(handle: &str) -> Result<()> {
pkg::config::remove_added_registry(handle)?;
let handle_cyan = handle.cyan();
println!("Registry '{handle_cyan}' removed.");
Ok(())
}
pub fn list_registries() -> Result<()> {
let config = pkg::config::read_config()?;
let all_builtins = pkg::builtin_registries::load_all();
let mut configured_handles: Vec<&str> = Vec::new();
println!("{} Configured Registries", "::".bold().blue());
if let Some(ref default) = config.default_registry {
let handle = &default.handle;
let display_name = default.name.as_deref().unwrap_or(handle);
let display_desc = default.description.as_deref();
configured_handles.push(handle.as_str());
let handle_str = if handle.is_empty() {
"<not synced>".italic().to_string()
} else {
handle.cyan().to_string()
};
println!("[Set] {handle_str}: {}", display_name.white());
if let Some(desc) = display_desc {
println!(" - {desc}");
}
println!(" - Git: {}", default.url);
} else {
println!("[Set] {} not set", "<none>".dimmed());
}
for reg in &config.added_registries {
let handle = ®.handle;
let display_name = reg.name.as_deref().unwrap_or(handle);
let display_desc = reg.description.as_deref();
configured_handles.push(handle.as_str());
let handle_str = if handle.is_empty() {
"<not synced>".italic().to_string()
} else {
handle.cyan().to_string()
};
println!();
println!("[Added] {handle_str}: {}", display_name.white());
if let Some(desc) = display_desc {
println!(" - {desc}");
}
println!(" - Git: {}", reg.url);
}
let unadded: Vec<_> = all_builtins
.iter()
.filter(|r| !configured_handles.contains(&r.handle.as_str()))
.collect();
if !unadded.is_empty() {
println!();
println!("{} Available Registries", "::".bold().blue());
for reg in unadded {
let handle_str = reg.handle.cyan().to_string();
println!("[Unadded] {handle_str}: {}", reg.name.white());
println!(" - {}", reg.description);
println!(" - Git: {}", reg.git);
}
}
Ok(())
}