@@ -4,7 +4,7 @@ use spdx_expression::SpdxExpression;
44use std:: collections:: BTreeMap ;
55use tracing:: instrument;
66use trustify_common:: db:: chunk:: EntityChunkedIter ;
7- use trustify_entity:: license;
7+ use trustify_entity:: { license, licensing_infos } ;
88use uuid:: Uuid ;
99
1010const NAMESPACE : Uuid = Uuid :: from_bytes ( [
@@ -22,7 +22,7 @@ impl LicenseInfo {
2222 Uuid :: new_v5 ( & NAMESPACE , self . license . to_lowercase ( ) . as_bytes ( ) )
2323 }
2424
25- pub fn spdx_info ( & self ) -> ( Vec < String > , Vec < String > ) {
25+ pub fn spdx_info ( & self ) -> ( Vec < String > , Vec < String > , Vec < String > ) {
2626 SpdxExpression :: parse ( & self . license )
2727 . map ( |parsed| {
2828 let spdx_licenses = parsed
@@ -38,9 +38,16 @@ impl LicenseInfo {
3838 . map ( |e| e. to_string ( ) )
3939 . collect :: < Vec < _ > > ( ) ;
4040
41- ( spdx_licenses, spdx_license_exceptions)
41+ let custom_license_refs = parsed
42+ . licenses ( )
43+ . iter ( )
44+ . filter ( |e| e. license_ref )
45+ . map ( |e| format ! ( "LicenseRef-{}" , e. identifier) )
46+ . collect :: < Vec < _ > > ( ) ;
47+
48+ ( spdx_licenses, spdx_license_exceptions, custom_license_refs)
4249 } )
43- . unwrap_or ( ( vec ! [ ] , vec ! [ ] ) )
50+ . unwrap_or ( ( vec ! [ ] , vec ! [ ] , vec ! [ ] ) )
4451 }
4552}
4653
@@ -51,19 +58,50 @@ pub struct LicenseCreator {
5158 /// Uses a [`BTreeMap`] to ensure we have a stable insertion order, avoiding deadlocks on the
5259 /// database.
5360 pub licenses : BTreeMap < Uuid , license:: ActiveModel > ,
61+
62+ pub custom_license_list : Vec < licensing_infos:: ActiveModel > ,
5463}
5564
5665impl LicenseCreator {
5766 pub fn new ( ) -> Self {
5867 Self {
5968 licenses : Default :: default ( ) ,
69+ custom_license_list : vec ! [ ] ,
6070 }
6171 }
6272
73+ pub fn put_custom_license_list (
74+ & mut self ,
75+ custom_license_list : Vec < licensing_infos:: ActiveModel > ,
76+ ) {
77+ self . custom_license_list = custom_license_list;
78+ }
79+
6380 pub fn add ( & mut self , info : & LicenseInfo ) {
6481 let uuid = info. uuid ( ) ;
6582
66- let ( spdx_licenses, spdx_exceptions) = info. spdx_info ( ) ;
83+ let ( spdx_licenses, spdx_exceptions, custom_license_refs) = info. spdx_info ( ) ;
84+ let missing_custom_refs: Vec < _ > = custom_license_refs
85+ . iter ( )
86+ . filter ( |ref_id| {
87+ !self
88+ . custom_license_list
89+ . iter ( )
90+ . any ( |c| c. license_id == Set ( ( * ref_id) . to_string ( ) ) )
91+ } )
92+ . cloned ( )
93+ . collect ( ) ;
94+ if !missing_custom_refs. is_empty ( ) {
95+ log:: warn!(
96+ "The following custom license refs are missing from custom_license_list: {:?}" ,
97+ missing_custom_refs
98+ ) ;
99+ }
100+ let custom_license_refs_value = if custom_license_refs. is_empty ( ) {
101+ None
102+ } else {
103+ Some ( self . construct_custom_license ( custom_license_refs. clone ( ) ) )
104+ } ;
67105
68106 self . licenses . entry ( uuid) . or_insert ( license:: ActiveModel {
69107 id : Set ( uuid) ,
@@ -78,9 +116,30 @@ impl LicenseCreator {
78116 } else {
79117 Set ( Some ( spdx_exceptions) )
80118 } ,
119+ custom_license_refs : Set ( custom_license_refs_value) ,
81120 } ) ;
82121 }
83122
123+ fn construct_custom_license ( & self , custom_license_ids : Vec < String > ) -> Vec < String > {
124+ use std:: collections:: HashMap ;
125+ // Build a HashMap from license_id to name for fast lookup
126+ let license_map: HashMap < & String , & String > = self
127+ . custom_license_list
128+ . iter ( )
129+ . filter_map ( |c| {
130+ if let ( Set ( license_id) , Set ( name) ) = ( & c. license_id , & c. name ) {
131+ Some ( ( license_id, name) )
132+ } else {
133+ None
134+ }
135+ } )
136+ . collect ( ) ;
137+ custom_license_ids
138+ . into_iter ( )
139+ . filter_map ( |id| license_map. get ( & id) . map ( |name| format ! ( "{}:{}" , id, name) ) )
140+ . collect ( )
141+ }
142+
84143 #[ instrument( skip_all, fields( num = self . licenses. len( ) ) , err( level=tracing:: Level :: INFO ) ) ]
85144 pub async fn create < C > ( self , db : & C ) -> Result < ( ) , DbErr >
86145 where
0 commit comments