@@ -13,7 +13,7 @@ pub(crate) enum Node<L> {
1313 Root { childs : Vec < Node < L > > } ,
1414 Directory { name : PathBuf , childs : Vec < Node < L > > , license : Option < L > } ,
1515 File { name : PathBuf , license : L } ,
16- FileGroup { names : Vec < PathBuf > , license : L } ,
16+ Group { files : Vec < PathBuf > , directories : Vec < PathBuf > , license : L } ,
1717 Empty ,
1818}
1919
@@ -22,7 +22,7 @@ impl Node<LicenseId> {
2222 self . merge_directories ( ) ;
2323 self . collapse_in_licensed_directories ( ) ;
2424 self . merge_directory_licenses ( ) ;
25- self . merge_file_groups ( ) ;
25+ self . merge_groups ( ) ;
2626 self . remove_empty ( ) ;
2727 }
2828
@@ -64,8 +64,8 @@ impl Node<LicenseId> {
6464 Node :: Root { .. } => {
6565 panic ! ( "can't have a root inside another element" ) ;
6666 }
67- Node :: FileGroup { .. } => {
68- panic ! ( "FileGroup should not be present at this stage" ) ;
67+ Node :: Group { .. } => {
68+ panic ! ( "Group should not be present at this stage" ) ;
6969 }
7070 Node :: Directory { license : Some ( _) , .. } => {
7171 panic ! ( "license should not be set at this stage" ) ;
@@ -86,8 +86,8 @@ impl Node<LicenseId> {
8686 }
8787 Node :: Empty => { }
8888 Node :: File { .. } => { }
89- Node :: FileGroup { .. } => {
90- panic ! ( "FileGroup should not be present at this stage" ) ;
89+ Node :: Group { .. } => {
90+ panic ! ( "Group should not be present at this stage" ) ;
9191 }
9292 Node :: Directory { license : Some ( _) , .. } => {
9393 panic ! ( "license should not be set at this stage" ) ;
@@ -132,7 +132,7 @@ impl Node<LicenseId> {
132132 }
133133 }
134134 Node :: File { .. } => { }
135- Node :: FileGroup { .. } => { }
135+ Node :: Group { .. } => panic ! ( "group should not be present at this stage" ) ,
136136 Node :: Empty => { }
137137 }
138138 }
@@ -165,8 +165,8 @@ impl Node<LicenseId> {
165165 Node :: Root { .. } => {
166166 panic ! ( "can't have a root inside another element" ) ;
167167 }
168- Node :: FileGroup { .. } => {
169- panic ! ( "FileGroup should not be present at this stage" ) ;
168+ Node :: Group { .. } => {
169+ panic ! ( "Group should not be present at this stage" ) ;
170170 }
171171 Node :: Directory { name : child_child_name, .. } => {
172172 * child_child_name = child_name. join ( & child_child_name) ;
@@ -185,38 +185,74 @@ impl Node<LicenseId> {
185185 }
186186 Node :: Empty => { }
187187 Node :: File { .. } => { }
188- Node :: FileGroup { .. } => { }
188+ Node :: Group { .. } => panic ! ( "Group should not be present at this stage" ) ,
189189 }
190190 }
191191
192192 /// This pass groups multiple files in a directory with the same license into a single
193- /// "FileGroup", so that the license of all those files can be reported as a group.
193+ /// "Group", so that the license of all those files can be reported as a group.
194+ ///
195+ /// This also merges directories *without exceptions*.
194196 ///
195197 /// Crucially this pass runs after collapse_in_licensed_directories, so the most common license
196198 /// will already be marked as the directory's license and won't be turned into a group.
197- fn merge_file_groups ( & mut self ) {
199+ fn merge_groups ( & mut self ) {
200+ #[ derive( Default ) ]
201+ struct Grouped {
202+ files : Vec < PathBuf > ,
203+ directories : Vec < PathBuf > ,
204+ }
198205 match self {
199206 Node :: Root { childs } | Node :: Directory { childs, .. } => {
200- let mut grouped = BTreeMap :: new ( ) ;
207+ let mut grouped: BTreeMap < LicenseId , Grouped > = BTreeMap :: new ( ) ;
201208
202209 for child in & mut * childs {
203- child. merge_file_groups ( ) ;
204- if let Node :: File { name, license } = child {
205- grouped. entry ( * license) . or_insert_with ( Vec :: new) . push ( name. clone ( ) ) ;
206- * child = Node :: Empty ;
210+ child. merge_groups ( ) ;
211+ match child {
212+ Node :: Directory { name, childs, license : Some ( license) } => {
213+ if childs. is_empty ( ) {
214+ grouped
215+ . entry ( * license)
216+ . or_insert_with ( Grouped :: default)
217+ . directories
218+ . push ( name. clone ( ) ) ;
219+ * child = Node :: Empty ;
220+ }
221+ }
222+ Node :: File { name, license } => {
223+ grouped
224+ . entry ( * license)
225+ . or_insert_with ( Grouped :: default)
226+ . files
227+ . push ( name. clone ( ) ) ;
228+ * child = Node :: Empty ;
229+ }
230+ _ => { }
207231 }
208232 }
209233
210- for ( license, mut names) in grouped. into_iter ( ) {
211- if names. len ( ) == 1 {
212- childs. push ( Node :: File { license, name : names. pop ( ) . unwrap ( ) } ) ;
234+ for ( license, mut grouped) in grouped. into_iter ( ) {
235+ if grouped. files . len ( ) + grouped. directories . len ( ) <= 1 {
236+ if let Some ( name) = grouped. files . pop ( ) {
237+ childs. push ( Node :: File { license, name } ) ;
238+ } else if let Some ( name) = grouped. directories . pop ( ) {
239+ childs. push ( Node :: Directory {
240+ name,
241+ childs : Vec :: new ( ) ,
242+ license : Some ( license) ,
243+ } ) ;
244+ }
213245 } else {
214- childs. push ( Node :: FileGroup { license, names } ) ;
246+ childs. push ( Node :: Group {
247+ license,
248+ files : grouped. files ,
249+ directories : grouped. directories ,
250+ } ) ;
215251 }
216252 }
217253 }
218254 Node :: File { .. } => { }
219- Node :: FileGroup { .. } => panic ! ( "FileGroup should not be present at this stage" ) ,
255+ Node :: Group { .. } => panic ! ( "FileGroup should not be present at this stage" ) ,
220256 Node :: Empty => { }
221257 }
222258 }
@@ -231,7 +267,7 @@ impl Node<LicenseId> {
231267 }
232268 childs. retain ( |child| !matches ! ( child, Node :: Empty ) ) ;
233269 }
234- Node :: FileGroup { .. } => { }
270+ Node :: Group { .. } => { }
235271 Node :: File { .. } => { }
236272 Node :: Empty => { }
237273 }
@@ -278,16 +314,22 @@ pub(crate) fn expand_interned_licenses(
278314) -> Node < & License > {
279315 match node {
280316 Node :: Root { childs } => Node :: Root {
281- childs : childs. into_iter ( ) . map ( |child| expand_interned_licenses ( child, interner) ) . collect ( ) ,
317+ childs : childs
318+ . into_iter ( )
319+ . map ( |child| expand_interned_licenses ( child, interner) )
320+ . collect ( ) ,
282321 } ,
283322 Node :: Directory { name, childs, license } => Node :: Directory {
284- childs : childs. into_iter ( ) . map ( |child| expand_interned_licenses ( child, interner) ) . collect ( ) ,
323+ childs : childs
324+ . into_iter ( )
325+ . map ( |child| expand_interned_licenses ( child, interner) )
326+ . collect ( ) ,
285327 license : license. map ( |license| interner. resolve ( license) ) ,
286328 name,
287329 } ,
288330 Node :: File { name, license } => Node :: File { name, license : interner. resolve ( license) } ,
289- Node :: FileGroup { names , license } => {
290- Node :: FileGroup { names , license : interner. resolve ( license) }
331+ Node :: Group { files , directories , license } => {
332+ Node :: Group { files , directories , license : interner. resolve ( license) }
291333 }
292334 Node :: Empty => Node :: Empty ,
293335 }
0 commit comments