11use std:: path:: Path ;
2- use std:: process;
32
43use colored:: Colorize ;
5- use sem_core:: git:: bridge:: GitBridge ;
6- use sem_core:: git:: types:: DiffScope ;
74use sem_core:: parser:: changelog:: {
85 build_changelog, render_markdown, ChangelogResult ,
96} ;
107use sem_core:: parser:: differ:: compute_semantic_diff;
118use sem_core:: parser:: graph:: EntityGraph ;
129use sem_core:: parser:: plugins:: create_default_registry;
1310
11+ use super :: common:: { self , open_git_or_exit} ;
12+
1413pub struct ChangelogOptions {
1514 pub cwd : String ,
1615 pub from : Option < String > ,
@@ -34,67 +33,16 @@ pub enum ChangelogFormat {
3433pub fn changelog_command ( opts : ChangelogOptions ) {
3534 let root = Path :: new ( & opts. cwd ) ;
3635 let registry = create_default_registry ( ) ;
36+ let git = open_git_or_exit ( root) ;
3737
38- let git = match GitBridge :: open ( root) {
39- Ok ( g) => g,
40- Err ( _) => {
41- eprintln ! ( "\x1b [31mError: Not inside a Git repository.\x1b [0m" ) ;
42- process:: exit ( 1 ) ;
43- }
44- } ;
45-
46- // Get file changes
47- let file_changes = if let Some ( ref sha) = opts. commit {
48- let scope = DiffScope :: Commit { sha : sha. clone ( ) } ;
49- match git. get_changed_files ( & scope) {
50- Ok ( files) => files,
51- Err ( e) => {
52- eprintln ! ( "\x1b [31mError: {e}\x1b [0m" ) ;
53- process:: exit ( 1 ) ;
54- }
55- }
56- } else if let ( Some ( ref from) , Some ( ref to) ) = ( & opts. from , & opts. to ) {
57- let scope = DiffScope :: Range {
58- from : from. clone ( ) ,
59- to : to. clone ( ) ,
60- } ;
61- match git. get_changed_files ( & scope) {
62- Ok ( files) => files,
63- Err ( e) => {
64- eprintln ! ( "\x1b [31mError: {e}\x1b [0m" ) ;
65- process:: exit ( 1 ) ;
66- }
67- }
68- } else if opts. staged {
69- let scope = DiffScope :: Staged ;
70- match git. get_changed_files ( & scope) {
71- Ok ( files) => files,
72- Err ( e) => {
73- eprintln ! ( "\x1b [31mError: {e}\x1b [0m" ) ;
74- process:: exit ( 1 ) ;
75- }
76- }
77- } else {
78- match git. detect_and_get_files ( ) {
79- Ok ( ( _scope, files) ) => files,
80- Err ( _) => {
81- eprintln ! ( "\x1b [31mError: Not inside a Git repository.\x1b [0m" ) ;
82- process:: exit ( 1 ) ;
83- }
84- }
85- } ;
86-
87- // Filter by extensions
88- let file_changes = if opts. file_exts . is_empty ( ) {
89- file_changes
90- } else {
91- let exts: Vec < String > = opts. file_exts . iter ( ) . map ( |e| {
92- if e. starts_with ( '.' ) { e. clone ( ) } else { format ! ( ".{}" , e) }
93- } ) . collect ( ) ;
94- file_changes. into_iter ( ) . filter ( |fc| {
95- exts. iter ( ) . any ( |ext| fc. file_path . ends_with ( ext. as_str ( ) ) )
96- } ) . collect ( )
97- } ;
38+ let file_changes = common:: resolve_file_changes (
39+ & git,
40+ opts. commit . as_deref ( ) ,
41+ opts. from . as_deref ( ) ,
42+ opts. to . as_deref ( ) ,
43+ opts. staged ,
44+ ) ;
45+ let file_changes = common:: filter_by_exts ( file_changes, & opts. file_exts ) ;
9846
9947 if file_changes. is_empty ( ) {
10048 println ! ( "{}" , "No changes detected." . dimmed( ) ) ;
@@ -110,7 +58,7 @@ pub fn changelog_command(opts: ChangelogOptions) {
11058 }
11159
11260 // Build entity graph
113- let ext_filter = super :: graph :: normalize_exts ( & opts. file_exts ) ;
61+ let ext_filter = common :: normalize_exts ( & opts. file_exts ) ;
11462 let all_files = sem_core:: utils:: files:: find_supported_files ( root, & registry, & ext_filter) ;
11563 let graph = EntityGraph :: build ( root, & all_files, & registry) ;
11664
0 commit comments