use std::path::PathBuf;
use crate::cli::FileArgs;
use crate::config::Config;
use crate::error::{Error, Result};
use crate::nix::Nix;
use crate::profile::get_flake_dir;
use crate::state::{get_state_path, PackageState};
pub fn run(config: &Config, args: FileArgs) -> Result<()> {
let flake_dir = get_flake_dir(config)?;
let state_path = get_state_path(&flake_dir);
let state = PackageState::load(&state_path)?;
let path = if let Some(custom) = state
.custom_packages
.iter()
.find(|p| p.name == args.package)
{
let store_path = Nix::flake_prefetch(&custom.input_url)?;
store_path.join("flake.nix")
} else if let Some(resolved) = state
.resolved_packages
.iter()
.find(|p| p.name == args.package)
{
let system = Nix::current_system()?;
Nix::get_package_source_path(&resolved.commit_hash, &resolved.attribute_path, &system)?
} else if state.packages.contains(&args.package) {
let system = Nix::current_system()?;
Nix::get_package_source_path("nixos-unstable", &args.package, &system)?
} else if let Some(local_path) = find_local_package(&flake_dir, &args.package) {
local_path
} else {
return Err(Error::PackageNotInstalled(args.package));
};
println!("{}", path.display());
Ok(())
}
fn find_local_package(flake_dir: &std::path::Path, package_name: &str) -> Option<PathBuf> {
let packages_dir = flake_dir.join("packages");
if !packages_dir.exists() {
return None;
}
if let Ok(entries) = std::fs::read_dir(&packages_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
let flake_file = path.join("flake.nix");
if flake_file.exists() {
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
if name == package_name {
return Some(flake_file);
}
}
}
} else if path.extension().is_some_and(|e| e == "nix") {
if let Some(name) = parse_package_name(&path) {
if name == package_name {
return Some(path);
}
}
}
}
}
None
}
fn parse_package_name(path: &std::path::Path) -> Option<String> {
let content = std::fs::read_to_string(path).ok()?;
crate::flake::parser::parse_local_package_attr(&content, "pname")
.or_else(|| crate::flake::parser::parse_local_package_attr(&content, "name"))
}