@@ -5,6 +5,7 @@ mod completion;
55mod debug;
66mod diagnostics;
77mod doctor;
8+ mod feed;
89mod hook;
910mod init;
1011mod inline;
@@ -43,6 +44,7 @@ use eyre::{
4344 WrapErr ,
4445 bail,
4546} ;
47+ use feed:: Feed ;
4648use fig_auth:: is_logged_in;
4749use fig_ipc:: local:: open_ui_element;
4850use fig_log:: {
@@ -176,7 +178,12 @@ pub enum CliRootCommands {
176178 Telemetry ( telemetry:: TelemetrySubcommand ) ,
177179 /// Version
178180 #[ command( hide = true ) ]
179- Version ,
181+ Version {
182+ /// Show the changelog (use --changelog=all for all versions, or --changelog=x.x.x for a
183+ /// specific version)
184+ #[ arg( long, num_args = 0 ..=1 , default_missing_value = "" ) ]
185+ changelog : Option < String > ,
186+ } ,
180187 /// Open the dashboard
181188 Dashboard ,
182189 /// AI assistant in your terminal
@@ -214,7 +221,7 @@ impl CliRootCommands {
214221 CliRootCommands :: Integrations ( _) => "integrations" ,
215222 CliRootCommands :: Translate ( _) => "translate" ,
216223 CliRootCommands :: Telemetry ( _) => "telemetry" ,
217- CliRootCommands :: Version => "version" ,
224+ CliRootCommands :: Version { .. } => "version" ,
218225 CliRootCommands :: Dashboard => "dashboard" ,
219226 CliRootCommands :: Chat { .. } => "chat" ,
220227 CliRootCommands :: Inline ( _) => "inline" ,
@@ -324,7 +331,7 @@ impl Cli {
324331 CliRootCommands :: Integrations ( subcommand) => subcommand. execute ( ) . await ,
325332 CliRootCommands :: Translate ( args) => args. execute ( ) . await ,
326333 CliRootCommands :: Telemetry ( subcommand) => subcommand. execute ( ) . await ,
327- CliRootCommands :: Version => Self :: print_version ( ) ,
334+ CliRootCommands :: Version { changelog } => Self :: print_version ( changelog ) ,
328335 CliRootCommands :: Dashboard => launch_dashboard ( false ) . await ,
329336 CliRootCommands :: Chat ( args) => q_chat:: launch_chat ( args) . await ,
330337 CliRootCommands :: Inline ( subcommand) => subcommand. execute ( & cli_context) . await ,
@@ -361,9 +368,80 @@ impl Cli {
361368 Ok ( ExitCode :: SUCCESS )
362369 }
363370
371+ fn print_changelog_entry ( entry : & feed:: Entry ) -> Result < ( ) > {
372+ println ! ( "Version {} ({})" , entry. version, entry. date) ;
373+
374+ if entry. changes . is_empty ( ) {
375+ println ! ( " No changes recorded for this version." ) ;
376+ } else {
377+ for change in & entry. changes {
378+ let type_label = match change. change_type . as_str ( ) {
379+ "added" => "Added" ,
380+ "fixed" => "Fixed" ,
381+ "changed" => "Changed" ,
382+ other => other,
383+ } ;
384+
385+ println ! ( " - {}: {}" , type_label, change. description) ;
386+ }
387+ }
388+
389+ println ! ( ) ;
390+ Ok ( ( ) )
391+ }
392+
364393 #[ allow( clippy:: unused_self) ]
365- fn print_version ( ) -> Result < ExitCode > {
366- let _ = writeln ! ( stdout( ) , "{}" , Self :: command( ) . render_version( ) ) ;
394+ fn print_version ( changelog : Option < String > ) -> Result < ExitCode > {
395+ // If no changelog is requested, display normal version information
396+ if changelog. is_none ( ) {
397+ let _ = writeln ! ( stdout( ) , "{}" , Self :: command( ) . render_version( ) ) ;
398+ return Ok ( ExitCode :: SUCCESS ) ;
399+ }
400+
401+ let changelog_value = changelog. unwrap_or_default ( ) ;
402+ let feed = Feed :: load ( ) ;
403+
404+ // Display changelog for all versions
405+ if changelog_value == "all" {
406+ let entries = feed. get_all_changelogs ( ) ;
407+ if entries. is_empty ( ) {
408+ println ! ( "No changelog information available." ) ;
409+ } else {
410+ println ! ( "Changelog for all versions:" ) ;
411+ for entry in entries {
412+ Self :: print_changelog_entry ( & entry) ?;
413+ }
414+ }
415+ return Ok ( ExitCode :: SUCCESS ) ;
416+ }
417+
418+ // Display changelog for a specific version (--changelog=x.x.x)
419+ if !changelog_value. is_empty ( ) {
420+ match feed. get_version_changelog ( & changelog_value) {
421+ Some ( entry) => {
422+ println ! ( "Changelog for version {}:" , changelog_value) ;
423+ Self :: print_changelog_entry ( & entry) ?;
424+ return Ok ( ExitCode :: SUCCESS ) ;
425+ } ,
426+ None => {
427+ println ! ( "No changelog information available for version {}." , changelog_value) ;
428+ return Ok ( ExitCode :: SUCCESS ) ;
429+ } ,
430+ }
431+ }
432+
433+ // Display changelog for the current version (--changelog only)
434+ let current_version = env ! ( "CARGO_PKG_VERSION" ) ;
435+ match feed. get_version_changelog ( current_version) {
436+ Some ( entry) => {
437+ println ! ( "Changelog for version {}:" , current_version) ;
438+ Self :: print_changelog_entry ( & entry) ?;
439+ } ,
440+ None => {
441+ println ! ( "No changelog information available for version {}." , current_version) ;
442+ } ,
443+ }
444+
367445 Ok ( ExitCode :: SUCCESS )
368446 }
369447}
@@ -575,6 +653,27 @@ mod test {
575653 ) ;
576654 }
577655
656+ #[ test]
657+ fn test_version_changelog ( ) {
658+ assert_parse ! ( [ "version" , "--changelog" ] , CliRootCommands :: Version {
659+ changelog: Some ( "" . to_string( ) ) ,
660+ } ) ;
661+ }
662+
663+ #[ test]
664+ fn test_version_changelog_all ( ) {
665+ assert_parse ! ( [ "version" , "--changelog=all" ] , CliRootCommands :: Version {
666+ changelog: Some ( "all" . to_string( ) ) ,
667+ } ) ;
668+ }
669+
670+ #[ test]
671+ fn test_version_changelog_specific ( ) {
672+ assert_parse ! ( [ "version" , "--changelog=1.8.0" ] , CliRootCommands :: Version {
673+ changelog: Some ( "1.8.0" . to_string( ) ) ,
674+ } ) ;
675+ }
676+
578677 #[ test]
579678 fn test_chat_with_context_profile ( ) {
580679 assert_parse ! (
0 commit comments