@@ -59,8 +59,8 @@ impl Parser {
5959
6060 fn parse_raw ( & self , reader : & mut impl BufRead ) -> Result < ( Host , Vec < Host > ) , ParseError > {
6161 let mut global_host = Host :: new ( Vec :: new ( ) ) ;
62- let mut is_in_host_block = false ;
6362 let mut hosts = Vec :: new ( ) ;
63+ let mut current_host: Option < Host > = None ;
6464
6565 let mut line = String :: new ( ) ;
6666 while reader. read_line ( & mut line) ? > 0 {
@@ -84,10 +84,16 @@ impl Parser {
8484 }
8585 }
8686 EntryType :: Host => {
87+ if let Some ( host) = current_host. take ( ) {
88+ hosts. push ( host) ;
89+ }
8790 let patterns = parse_patterns ( & entry. 1 ) ;
88- hosts. push ( Host :: new ( patterns) ) ;
89- is_in_host_block = true ;
90-
91+ if patterns. contains ( & "*" . to_string ( ) ) {
92+ global_host = Host :: new ( patterns. clone ( ) ) ;
93+ hosts. push ( global_host. clone ( ) ) ;
94+ } else {
95+ current_host = Some ( Host :: new ( patterns) ) ;
96+ }
9197 continue ;
9298 }
9399 EntryType :: Include => {
@@ -124,41 +130,25 @@ impl Parser {
124130 let mut file = BufReader :: new ( File :: open ( path) ?) ;
125131 let ( included_global_host, included_hosts) = self . parse_raw ( & mut file) ?;
126132
127- if is_in_host_block {
128- // Can't include hosts inside a host block
129- if !included_hosts. is_empty ( ) {
130- return Err ( InvalidIncludeError {
131- line,
132- details : InvalidIncludeErrorDetails :: HostsInsideHostBlock ,
133- }
134- . into ( ) ) ;
135- }
136-
137- hosts
138- . last_mut ( )
139- . unwrap ( )
140- . extend_entries ( & included_global_host) ;
141- } else {
142- if !included_global_host. is_empty ( ) {
143- global_host. extend_entries ( & included_global_host) ;
144- }
145-
146- hosts. extend ( included_hosts) ;
147- }
133+ global_host. extend_entries ( & included_global_host) ;
134+ hosts. extend ( included_hosts) ;
148135 }
149-
150136 continue ;
151137 }
152138 _ => { }
153139 }
154140
155- if is_in_host_block {
156- hosts . last_mut ( ) . unwrap ( ) . update ( entry) ;
141+ if let Some ( host ) = current_host . as_mut ( ) {
142+ host . update ( entry) ;
157143 } else {
158144 global_host. update ( entry) ;
159145 }
160146 }
161147
148+ if let Some ( host) = current_host {
149+ hosts. push ( host) ;
150+ }
151+
162152 Ok ( ( global_host, hosts) )
163153 }
164154}
@@ -218,3 +208,45 @@ fn parse_patterns(entry_value: &str) -> Vec<String> {
218208
219209 patterns
220210}
211+
212+ #[ cfg( test) ]
213+ mod tests {
214+ use super :: * ;
215+ use std:: io:: Cursor ;
216+
217+ #[ test]
218+ fn test_basic_host_parsing ( ) {
219+ let config = "\n Host example\n User test\n Port 2222\n " ;
220+ let mut reader = Cursor :: new ( config) ;
221+ let result = Parser :: new ( ) . parse_raw ( & mut reader) ;
222+ assert ! ( result. is_ok( ) ) ;
223+ let ( _, hosts) = result. unwrap ( ) ;
224+ assert_eq ! ( hosts. len( ) , 1 ) ;
225+ let host = hosts. first ( ) . unwrap ( ) ;
226+ assert ! ( host. get( & EntryType :: User ) . is_some( ) ) ;
227+ assert_eq ! ( host. get( & EntryType :: User ) . unwrap( ) , "test" ) ;
228+ assert ! ( host. get( & EntryType :: Port ) . is_some( ) ) ;
229+ assert_eq ! ( host. get( & EntryType :: Port ) . unwrap( ) , "2222" ) ;
230+ }
231+
232+ #[ test]
233+ fn test_include_directive ( ) {
234+ let config = "\n Include other_config\n Host example\n User test\n " ;
235+ let mut reader = Cursor :: new ( config) ;
236+ let result = Parser :: new ( ) . parse_raw ( & mut reader) ;
237+ assert ! ( result. is_ok( ) ) ;
238+ }
239+
240+ #[ test]
241+ fn test_host_wildcard ( ) {
242+ let config = "\n Host *\n Compression yes\n Host test\n Compression no\n " ;
243+ let mut reader = Cursor :: new ( config) ;
244+ let result = Parser :: new ( ) . parse_raw ( & mut reader) ;
245+ assert ! ( result. is_ok( ) ) ;
246+ let ( global_host, hosts) = result. unwrap ( ) ;
247+ assert ! ( !global_host. is_empty( ) ) ;
248+ assert ! ( global_host. get( & EntryType :: Compression ) . is_some( ) ) ;
249+ assert_eq ! ( global_host. get( & EntryType :: Compression ) . unwrap( ) , "yes" ) ;
250+ assert_eq ! ( hosts. len( ) , 2 ) ;
251+ }
252+ }
0 commit comments