@@ -5,6 +5,7 @@ mod completion;
5
5
mod debug;
6
6
mod diagnostics;
7
7
mod doctor;
8
+ mod feed;
8
9
mod hook;
9
10
mod init;
10
11
mod inline;
@@ -43,6 +44,7 @@ use eyre::{
43
44
WrapErr ,
44
45
bail,
45
46
} ;
47
+ use feed:: Feed ;
46
48
use fig_auth:: is_logged_in;
47
49
use fig_ipc:: local:: open_ui_element;
48
50
use fig_log:: {
@@ -176,7 +178,12 @@ pub enum CliRootCommands {
176
178
Telemetry ( telemetry:: TelemetrySubcommand ) ,
177
179
/// Version
178
180
#[ 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
+ } ,
180
187
/// Open the dashboard
181
188
Dashboard ,
182
189
/// AI assistant in your terminal
@@ -214,7 +221,7 @@ impl CliRootCommands {
214
221
CliRootCommands :: Integrations ( _) => "integrations" ,
215
222
CliRootCommands :: Translate ( _) => "translate" ,
216
223
CliRootCommands :: Telemetry ( _) => "telemetry" ,
217
- CliRootCommands :: Version => "version" ,
224
+ CliRootCommands :: Version { .. } => "version" ,
218
225
CliRootCommands :: Dashboard => "dashboard" ,
219
226
CliRootCommands :: Chat { .. } => "chat" ,
220
227
CliRootCommands :: Inline ( _) => "inline" ,
@@ -324,7 +331,7 @@ impl Cli {
324
331
CliRootCommands :: Integrations ( subcommand) => subcommand. execute ( ) . await ,
325
332
CliRootCommands :: Translate ( args) => args. execute ( ) . await ,
326
333
CliRootCommands :: Telemetry ( subcommand) => subcommand. execute ( ) . await ,
327
- CliRootCommands :: Version => Self :: print_version ( ) ,
334
+ CliRootCommands :: Version { changelog } => Self :: print_version ( changelog ) ,
328
335
CliRootCommands :: Dashboard => launch_dashboard ( false ) . await ,
329
336
CliRootCommands :: Chat ( args) => q_chat:: launch_chat ( args) . await ,
330
337
CliRootCommands :: Inline ( subcommand) => subcommand. execute ( & cli_context) . await ,
@@ -361,9 +368,80 @@ impl Cli {
361
368
Ok ( ExitCode :: SUCCESS )
362
369
}
363
370
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
+
364
393
#[ 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
+
367
445
Ok ( ExitCode :: SUCCESS )
368
446
}
369
447
}
@@ -575,6 +653,27 @@ mod test {
575
653
) ;
576
654
}
577
655
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
+
578
677
#[ test]
579
678
fn test_chat_with_context_profile ( ) {
580
679
assert_parse ! (
0 commit comments