11use anyhow:: { Context , Result } ;
2- use auto_commit_rs:: { cli, config, git, prompt, provider} ;
2+ use auto_commit_rs:: { cli, config, git, prompt, provider, update } ;
33use colored:: Colorize ;
44use inquire:: { Confirm , Select , Text } ;
55
@@ -13,14 +13,30 @@ fn main() {
1313fn run ( ) -> Result < ( ) > {
1414 let cli = cli:: parse ( ) ;
1515 let cfg = match & cli. command {
16- Some ( cli:: Command :: Config { .. } ) => None ,
16+ Some ( cli:: Command :: Config { .. } ) | Some ( cli :: Command :: Update ) => None ,
1717 _ => Some ( config:: AppConfig :: load ( ) ?) ,
1818 } ;
1919
20+ // On first run, ask about auto-update preference
21+ if let Some ( ref c) = cfg {
22+ if c. auto_update . is_none ( ) {
23+ prompt_auto_update ( ) ;
24+ }
25+ }
26+
27+ // Check for updates (except for config/update commands)
28+ let update_warning = match & cli. command {
29+ Some ( cli:: Command :: Config { .. } ) | Some ( cli:: Command :: Update ) => None ,
30+ _ => check_for_updates ( cfg. as_ref ( ) ) ,
31+ } ;
32+
2033 match & cli. command {
2134 Some ( cli:: Command :: Config { global } ) => {
2235 cli:: interactive_config ( * global) ?;
2336 }
37+ Some ( cli:: Command :: Update ) => {
38+ run_update_command ( ) ?;
39+ }
2440 Some ( cli:: Command :: Undo ) => {
2541 run_undo ( cfg. as_ref ( ) . expect ( "config should be loaded" ) ) ?;
2642 }
@@ -36,6 +52,11 @@ fn run() -> Result<()> {
3652 }
3753 }
3854
55+ // Show update warning at the end so it doesn't get buried
56+ if let Some ( latest) = update_warning {
57+ update:: print_update_warning ( & latest) ;
58+ }
59+
3960 Ok ( ( ) )
4061}
4162
@@ -301,6 +322,101 @@ fn handle_post_commit_push(cfg: &config::AppConfig, ask_prompt: &str) -> Result<
301322 Ok ( ( ) )
302323}
303324
325+ fn prompt_auto_update ( ) {
326+ let answer = Confirm :: new ( "Would you like to enable automatic updates for cgen?" )
327+ . with_default ( true )
328+ . with_help_message ( "You can change this later with `cgen config --global`" )
329+ . prompt ( ) ;
330+
331+ match answer {
332+ Ok ( yes) => {
333+ if let Err ( e) = config:: save_auto_update_preference ( yes) {
334+ eprintln ! (
335+ "{} Failed to save auto-update preference: {}" ,
336+ "warning:" . yellow( ) . bold( ) ,
337+ e
338+ ) ;
339+ } else {
340+ let status = if yes { "enabled" } else { "disabled" } ;
341+ println ! (
342+ "{} Auto-updates {}.\n " ,
343+ "done!" . green( ) . bold( ) ,
344+ status
345+ ) ;
346+ }
347+ }
348+ Err ( _) => {
349+ // User cancelled - leave as None, will ask again next time
350+ }
351+ }
352+ }
353+
354+ /// Check for updates and either auto-update or return the latest version for a warning.
355+ /// Returns Some(latest_version) if a warning should be shown, None otherwise.
356+ fn check_for_updates ( cfg : Option < & config:: AppConfig > ) -> Option < String > {
357+ let version_check = match update:: check_version ( ) {
358+ Ok ( v) => v,
359+ Err ( _) => return None , // silently ignore network errors
360+ } ;
361+
362+ if !version_check. update_available {
363+ return None ;
364+ }
365+
366+ let auto_update = cfg. and_then ( |c| c. auto_update ) . unwrap_or ( false ) ;
367+
368+ if auto_update {
369+ println ! (
370+ "{} {} → {}" ,
371+ "Auto-updating cgen..." . cyan( ) . bold( ) ,
372+ version_check. current. dimmed( ) ,
373+ version_check. latest. green( ) ,
374+ ) ;
375+ if let Err ( e) = update:: run_update ( ) {
376+ eprintln ! (
377+ "{} Auto-update failed: {}" ,
378+ "warning:" . yellow( ) . bold( ) ,
379+ e
380+ ) ;
381+ return Some ( version_check. latest ) ;
382+ }
383+ println ! (
384+ "{} Restart cgen to use the new version.\n " ,
385+ "note:" . yellow( ) . bold( )
386+ ) ;
387+ return None ;
388+ }
389+
390+ Some ( version_check. latest )
391+ }
392+
393+ fn run_update_command ( ) -> Result < ( ) > {
394+ println ! ( "{}" , "Checking for updates..." . cyan( ) . bold( ) ) ;
395+
396+ match update:: check_version ( ) {
397+ Ok ( v) if v. update_available => {
398+ println ! (
399+ "{} {} → {}" ,
400+ "New version available!" . green( ) . bold( ) ,
401+ v. current. dimmed( ) ,
402+ v. latest. green( ) ,
403+ ) ;
404+ update:: run_update ( ) ?;
405+ }
406+ Ok ( v) => {
407+ println ! (
408+ "{} You are already on the latest version ({})." ,
409+ "Up to date!" . green( ) . bold( ) ,
410+ v. current,
411+ ) ;
412+ }
413+ Err ( e) => {
414+ anyhow:: bail!( "Failed to check for updates: {}" , e) ;
415+ }
416+ }
417+ Ok ( ( ) )
418+ }
419+
304420fn run_undo ( cfg : & config:: AppConfig ) -> Result < ( ) > {
305421 git:: ensure_head_exists ( ) ?;
306422
0 commit comments