1use anyhow::Result;
2use std::env;
3use std::path::PathBuf;
4
5use crate::registry::{get_registry_path, Registry};
6
7#[derive(Debug)]
9pub enum MigrationCheck {
10 NoMigration(PathBuf),
12 MigratedToSqlite {
14 yaml_path: PathBuf,
15 sqlite_path: PathBuf,
16 },
17 PossibleStaleYaml {
19 yaml_path: PathBuf,
20 sqlite_path: PathBuf,
21 },
22}
23
24pub fn check_migration_status(yaml_path: &PathBuf) -> MigrationCheck {
26 let sqlite_path = yaml_path.with_extension("db");
28
29 if yaml_path.exists() && sqlite_path.exists() {
30 if let Ok(content) = std::fs::read_to_string(yaml_path) {
33 let first_lines: String = content.lines().take(5).collect::<Vec<_>>().join("\n");
35 if first_lines.contains("migrated_to:") {
36 return MigrationCheck::MigratedToSqlite {
37 yaml_path: yaml_path.clone(),
38 sqlite_path,
39 };
40 }
41 }
42 return MigrationCheck::PossibleStaleYaml {
44 yaml_path: yaml_path.clone(),
45 sqlite_path,
46 };
47 }
48
49 if sqlite_path.exists() && !yaml_path.exists() {
51 return MigrationCheck::NoMigration(sqlite_path);
52 }
53
54 MigrationCheck::NoMigration(yaml_path.clone())
56}
57
58pub fn determine_requirements_path(project_option: Option<&str>) -> Result<PathBuf> {
62 let use_local_file = project_option.is_none() && env::var("REQ_DB_NAME").is_err();
65
66 let current_dir_db = PathBuf::from("requirements.db");
68 if use_local_file && current_dir_db.exists() {
69 return Ok(current_dir_db);
70 }
71
72 let current_dir_path = PathBuf::from("requirements.yaml");
73 if use_local_file && current_dir_path.exists() {
74 return Ok(current_dir_path);
75 }
76
77 let registry_path = get_registry_path()?;
79 if !registry_path.exists() {
80 Registry::create_default(®istry_path)?;
81 }
82
83 let registry = Registry::load(®istry_path)?;
85
86 if let Some(project_name) = project_option {
88 if let Some(project) = registry.get_project(project_name) {
89 return Ok(PathBuf::from(&project.path));
90 } else {
91 anyhow::bail!("Project '{}' not found in registry", project_name);
92 }
93 }
94
95 if let Ok(env_project) = env::var("REQ_DB_NAME") {
97 if let Some(project) = registry.get_project(&env_project) {
98 return Ok(PathBuf::from(&project.path));
99 } else {
100 anyhow::bail!(
101 "Project '{}' from REQ_DB_NAME not found in registry",
102 env_project
103 );
104 }
105 }
106
107 if registry.projects.len() == 1 {
109 let (_, project) = registry.projects.iter().next().unwrap();
110 return Ok(PathBuf::from(&project.path));
111 }
112
113 if let Some((_, default_project)) = registry.get_default_project() {
115 return Ok(PathBuf::from(&default_project.path));
116 }
117
118 anyhow::bail!(
120 "Could not determine requirements file. Please specify a project with -p, \
121 set REQ_DB_NAME environment variable, or run `aida init` in your project directory"
122 )
123}
124
125pub fn list_available_projects() -> Result<Vec<(String, String)>> {
127 let registry_path = get_registry_path()?;
128 if !registry_path.exists() {
129 Registry::create_default(®istry_path)?;
130 }
131
132 let registry = Registry::load(®istry_path)?;
133 let mut projects = Vec::new();
134
135 for (name, project) in ®istry.projects {
136 projects.push((name.clone(), project.description.clone()));
137 }
138
139 Ok(projects)
140}