@@ -2240,12 +2240,29 @@ pub fn run_ldcup(ctx: &ExecutionContext) -> Result<()> {
22402240pub fn run_ollama_pull ( ctx : & ExecutionContext ) -> Result < ( ) > {
22412241 let ollama = require ( "ollama" ) ?;
22422242
2243+ // Check if the Ollama server is running before printing the separator.
2244+ // `ollama list` fails with "could not connect" if the server is not active.
2245+ let probe = ctx. execute ( & ollama) . always ( ) . arg ( "list" ) . output ( ) ?;
2246+ let probe = match probe {
2247+ ExecutorOutput :: Wet ( output) => output,
2248+ ExecutorOutput :: Dry => {
2249+ print_separator ( "Ollama" ) ;
2250+ return Ok ( ( ) ) ;
2251+ }
2252+ } ;
2253+ if !probe. status . success ( ) {
2254+ let stderr = String :: from_utf8_lossy ( & probe. stderr ) ;
2255+ if stderr. contains ( "could not connect" ) || stderr. contains ( "connection refused" ) {
2256+ return Err (
2257+ SkipStep ( "Ollama server is not running; skipping (start it with 'ollama serve')" . to_string ( ) ) . into ( ) ,
2258+ ) ;
2259+ }
2260+ // Some other error — fall through and let the existing code report it.
2261+ }
2262+
22432263 print_separator ( "Ollama" ) ;
22442264
2245- // We use `ctx.execute(...).always()` so that we can still collect the model
2246- // list even in dry run.
2247- let ollama_list_output = ctx. execute ( & ollama) . always ( ) . arg ( "list" ) . output_checked_utf8 ( ) ?;
2248- let ollama_list_stdout = ollama_list_output. stdout ;
2265+ let ollama_list_stdout = String :: from_utf8_lossy ( & probe. stdout ) . to_string ( ) ;
22492266 // trim the last new-line character, or `stdout.split('\n')` would give us an empty string
22502267 let ollama_list_stdout_trimmed = ollama_list_stdout. trim_end_matches ( '\n' ) ;
22512268 // skip(1) to skip the first `NAME ID SIZE MODIFIED` header line
@@ -2539,14 +2556,23 @@ pub fn run_ytdlp(ctx: &ExecutionContext) -> Result<()> {
25392556
25402557 print_separator ( "yt-dlp" ) ;
25412558
2542- // The -U command was already run above; report its result
2559+ // If the non-sudo attempt succeeded, report it
25432560 if output. status . success ( ) {
25442561 std:: io:: stdout ( ) . lock ( ) . write_all ( & output. stdout ) . unwrap ( ) ;
25452562 std:: io:: stderr ( ) . lock ( ) . write_all ( & output. stderr ) . unwrap ( ) ;
2546- Ok ( ( ) )
2547- } else {
2548- std:: io:: stdout ( ) . lock ( ) . write_all ( & output. stdout ) . unwrap ( ) ;
2549- std:: io:: stderr ( ) . lock ( ) . write_all ( & output. stderr ) . unwrap ( ) ;
2550- Err ( eyre ! ( "yt-dlp self-update failed" ) )
2563+ return Ok ( ( ) ) ;
25512564 }
2565+
2566+ // Check if it failed due to a permission error (e.g., installed to /usr/local/bin)
2567+ let combined_lower = combined. to_lowercase ( ) ;
2568+ if combined_lower. contains ( "unable to write" ) || combined_lower. contains ( "permission denied" ) {
2569+ // Retry with sudo
2570+ let sudo = ctx. require_sudo ( ) ?;
2571+ return sudo. execute ( ctx, & ytdlp) ?. args ( [ "-U" ] ) . status_checked ( ) ;
2572+ }
2573+
2574+ // Some other error
2575+ std:: io:: stdout ( ) . lock ( ) . write_all ( & output. stdout ) . unwrap ( ) ;
2576+ std:: io:: stderr ( ) . lock ( ) . write_all ( & output. stderr ) . unwrap ( ) ;
2577+ Err ( eyre ! ( "yt-dlp self-update failed" ) )
25522578}
0 commit comments