@@ -28,6 +28,8 @@ use crate::git;
2828use crate :: header:: matcher:: HeaderMatcher ;
2929use crate :: header:: model:: default_headers;
3030use crate :: header:: model:: deserialize_header_definitions;
31+ use crate :: header:: model:: HeaderDef ;
32+ use crate :: license:: bundled_headers;
3133use crate :: license:: HeaderSource ;
3234use crate :: selection:: Selection ;
3335
@@ -56,6 +58,10 @@ pub fn check_license_header<C: Callback>(
5658 . with_context ( || format ! ( "cannot parse config file: {name}" ) ) ?
5759 } ;
5860
61+ let config_dir = run_config
62+ . parent ( )
63+ . context ( "cannot get parent directory of config file" ) ?;
64+
5965 let basedir = config. base_dir . clone ( ) ;
6066 anyhow:: ensure!(
6167 basedir. is_dir( ) ,
@@ -107,10 +113,9 @@ pub fn check_license_header<C: Callback>(
107113 }
108114 }
109115 }
116+
110117 for additional_header in & config. additional_headers {
111- let additional_defs = fs:: read_to_string ( additional_header)
112- . with_context ( || format ! ( "cannot load header definitions: {additional_header}" ) )
113- . and_then ( deserialize_header_definitions) ?;
118+ let additional_defs = load_additional_headers ( additional_header, & config, config_dir) ?;
114119 for ( k, v) in additional_defs {
115120 match defs. entry ( k) {
116121 Entry :: Occupied ( mut ent) => {
@@ -123,11 +128,12 @@ pub fn check_license_header<C: Callback>(
123128 }
124129 }
125130 }
131+
126132 defs
127133 } ;
128134
129135 let header_matcher = {
130- let header_source = HeaderSource :: from_config ( & config) ?;
136+ let header_source = load_header_sources ( & config, config_dir ) ?;
131137 HeaderMatcher :: new ( header_source. content )
132138 } ;
133139
@@ -164,3 +170,90 @@ pub fn check_license_header<C: Callback>(
164170
165171 Ok ( ( ) )
166172}
173+
174+ fn load_additional_headers (
175+ additional_header : impl AsRef < Path > ,
176+ config : & Config ,
177+ config_dir : & Path ,
178+ ) -> anyhow:: Result < HashMap < String , HeaderDef > > {
179+ let additional_header = additional_header. as_ref ( ) ;
180+
181+ // 1. Based on config directory.
182+ let path = {
183+ let mut path = config_dir. to_path_buf ( ) ;
184+ path. push ( additional_header) ;
185+ path
186+ } ;
187+ if let Ok ( content) = fs:: read_to_string ( & path) {
188+ return deserialize_header_definitions ( content)
189+ . with_context ( || format ! ( "cannot load header definitions: {}" , path. display( ) ) ) ;
190+ }
191+
192+ // 2. Based on the base_dir.
193+ let path = {
194+ let mut path = config. base_dir . clone ( ) ;
195+ path. push ( additional_header) ;
196+ path
197+ } ;
198+ if let Ok ( content) = fs:: read_to_string ( & path) {
199+ return deserialize_header_definitions ( content)
200+ . with_context ( || format ! ( "cannot load header definitions: {}" , path. display( ) ) ) ;
201+ }
202+
203+ // 3. Based on current working directory.
204+ if let Ok ( content) = fs:: read_to_string ( additional_header) {
205+ return deserialize_header_definitions ( content) . with_context ( || {
206+ format ! (
207+ "cannot load header definitions: {}" ,
208+ additional_header. display( )
209+ )
210+ } ) ;
211+ }
212+
213+ Err ( anyhow:: anyhow!(
214+ "cannot find header definitions: {}" ,
215+ additional_header. display( )
216+ ) )
217+ }
218+
219+ fn load_header_sources ( config : & Config , config_dir : & Path ) -> anyhow:: Result < HeaderSource > {
220+ // 1. inline_header takes priority.
221+ if let Some ( content) = config. inline_header . as_ref ( ) . cloned ( ) {
222+ return Ok ( HeaderSource { content } ) ;
223+ }
224+
225+ // 2. Then, try to load from header_path.
226+ let header_path = config
227+ . header_path
228+ . as_ref ( )
229+ . context ( "no header source found (both inline_header and header_path are None)" ) ?;
230+
231+ // 2.1 Based on config directory.
232+ let path = {
233+ let mut path = config_dir. to_path_buf ( ) ;
234+ path. push ( header_path) ;
235+ path
236+ } ;
237+ if let Ok ( content) = fs:: read_to_string ( path) {
238+ return Ok ( HeaderSource { content } ) ;
239+ }
240+
241+ // 2.2 Based on the base_dir.
242+ let path = {
243+ let mut path = config. base_dir . clone ( ) ;
244+ path. push ( header_path) ;
245+ path
246+ } ;
247+ if let Ok ( content) = fs:: read_to_string ( path) {
248+ return Ok ( HeaderSource { content } ) ;
249+ }
250+
251+ // 2.3 Based on current working directory.
252+ if let Ok ( content) = fs:: read_to_string ( header_path) {
253+ return Ok ( HeaderSource { content } ) ;
254+ }
255+
256+ // 3. Finally, fallback to try bundled headers.
257+ bundled_headers ( header_path)
258+ . with_context ( || format ! ( "no header source found (header_path is invalid: {header_path})" ) )
259+ }
0 commit comments