|
1 | 1 | use std::fs; |
| 2 | +use std::io::ErrorKind; |
2 | 3 | use std::path::PathBuf; |
| 4 | +use std::process::Command; |
3 | 5 |
|
4 | 6 | use anyhow::{anyhow, Context, Result}; |
5 | 7 | use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password, Select}; |
@@ -78,6 +80,10 @@ pub fn run_setup() -> Result<()> { |
78 | 80 | .default(default_model.to_string()) |
79 | 81 | .interact_text()?; |
80 | 82 |
|
| 83 | + if provider_kind == ProviderKind::Ollama { |
| 84 | + check_ollama(&model)?; |
| 85 | + } |
| 86 | + |
81 | 87 | let push = Confirm::with_theme(&theme) |
82 | 88 | .with_prompt("Push by default after commit?") |
83 | 89 | .default(true) |
@@ -114,6 +120,52 @@ fn ensure_ignore_file(path: &PathBuf) -> Result<()> { |
114 | 120 | fs::write(path, content).context("failed to write ignore file") |
115 | 121 | } |
116 | 122 |
|
| 123 | +fn check_ollama(model: &str) -> Result<()> { |
| 124 | + let output = match Command::new("ollama").arg("list").output() { |
| 125 | + Ok(output) => output, |
| 126 | + Err(err) if err.kind() == ErrorKind::NotFound => { |
| 127 | + ui::warn("ollama not found"); |
| 128 | + ui::info("install ollama from https://ollama.com"); |
| 129 | + return Ok(()); |
| 130 | + } |
| 131 | + Err(err) => return Err(err.into()), |
| 132 | + }; |
| 133 | + |
| 134 | + if !output.status.success() { |
| 135 | + let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); |
| 136 | + ui::warn("ollama is installed but not running"); |
| 137 | + if !stderr.is_empty() { |
| 138 | + ui::warn(&format!("ollama list failed: {stderr}")); |
| 139 | + } |
| 140 | + ui::info("start ollama with: ollama serve"); |
| 141 | + return Ok(()); |
| 142 | + } |
| 143 | + |
| 144 | + let stdout = String::from_utf8_lossy(&output.stdout); |
| 145 | + let models = parse_ollama_models(&stdout); |
| 146 | + if models.is_empty() { |
| 147 | + ui::warn("no ollama models installed"); |
| 148 | + ui::info("pull one with: ollama pull <model>"); |
| 149 | + return Ok(()); |
| 150 | + } |
| 151 | + |
| 152 | + if !models.iter().any(|name| name == model) { |
| 153 | + ui::warn(&format!("model not found in ollama: {model}")); |
| 154 | + ui::info(&format!("pull it with: ollama pull {model}")); |
| 155 | + } |
| 156 | + |
| 157 | + Ok(()) |
| 158 | +} |
| 159 | + |
| 160 | +fn parse_ollama_models(output: &str) -> Vec<String> { |
| 161 | + output |
| 162 | + .lines() |
| 163 | + .filter_map(|line| line.split_whitespace().next()) |
| 164 | + .filter(|name| *name != "NAME") |
| 165 | + .map(|name| name.to_string()) |
| 166 | + .collect() |
| 167 | +} |
| 168 | + |
117 | 169 | #[cfg(unix)] |
118 | 170 | fn set_config_permissions(path: &PathBuf) -> Result<()> { |
119 | 171 | use std::os::unix::fs::PermissionsExt; |
|
0 commit comments