licenserec 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,296 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "licenserec/version"
4
+ require 'set'
5
+ require 'open3'
6
+ require 'csv'
7
+
8
+ module Licenserec
9
+ class CompatibilityFilter
10
+ def initialize()
11
+ end
12
+
13
+ # 次级兼容、组合兼容和不兼容的含义
14
+ def self.compatibility_meaning()
15
+ compatibility_meaning_hash = Hash.new
16
+ compatibility_meaning_hash.store("次级兼容","开源许可证A授权的作品(无论是否经过修改)与开源许可证B授权的作品组合,所产生的衍生作品整体可合法地使用开源许可证B重新授权时,则认为开源许可证A次级兼容开源许可证B。本知识库中使用‘1’表示次级兼容。")
17
+ compatibility_meaning_hash.store("组合兼容","开源许可证A授权的作品(无论是否经过修改)可以与开源许可证B授权的作品可以合法地组合而不违反任一开源许可证时,可以认为开源许可证A组合兼容开源许可证B。本知识库中使用‘2’表示组合兼容。")
18
+ compatibility_meaning_hash.store("不兼容","不满足次级兼容或组合兼容的条件,则不兼容。本知识库中使用‘0’表示不兼容。")
19
+ return compatibility_meaning_hash
20
+ end
21
+
22
+ # 遍历文件夹,返回所有文件的路径列表
23
+ def self.show_files(f_path,repofiles_pathlist)
24
+ if File.directory? f_path
25
+ Dir.foreach(f_path) do |file|
26
+ if file != "." and file != ".."
27
+ show_files(f_path + "/" + file,repofiles_pathlist)
28
+ end
29
+ end
30
+ else
31
+ repofiles_pathlist.push(f_path)
32
+ end
33
+ return repofiles_pathlist
34
+ end
35
+
36
+ # 第三方工具Ninka识别文件许可证,一个文件可能包含多个许可证,输入1为文件的路径,输入2为ninka路径,输出为许可证列表。
37
+ def self.ninka_process(filepath,ninka_path)
38
+ io = IO.popen("perl " + ninka_path + " " + filepath)
39
+ io_stdout = io.gets.split(";")
40
+ file_license_list = io_stdout[1].split(",")
41
+ # puts "++++++++++++++"
42
+ # puts file_license_list
43
+ return file_license_list
44
+ end
45
+
46
+ # 识别项目所包含的许可证,输入1为项目路径,输入2为ninka路径,输出1为文件路径及对应许可证信息的哈希表,输出2为项目包含的许可证集合
47
+ def self.license_detection(repo_path,ninka_path)
48
+ # 遍历项目文件夹,获取项目中所有文件路径
49
+ repofiles_pathlist = []
50
+ repofiles_pathlist = show_files(repo_path,repofiles_pathlist)
51
+ # 创建子进程,获取每个文件的许可证信息
52
+ other_licenses = ["SeeFile", "UNKNOWN"]
53
+ licenses_set = Set.new
54
+ file_licenses_hash = {}
55
+ repofiles_pathlist.each do |filepath|
56
+ # 异常处理
57
+ begin
58
+ file_licenses = CompatibilityFilter.ninka_process(filepath,ninka_path)
59
+ dual_licenses = Set.new
60
+ dual_licenses_str = ""
61
+ if file_licenses.length <= 1
62
+ if other_licenses.include? file_licenses[0]
63
+ licenses_set.add("Other")
64
+ file_licenses_hash.store(filepath,"Other")
65
+ elsif file_licenses[0].include? "NONE"
66
+ licenses_set.add("")
67
+ file_licenses_hash.store(filepath,"NONE")
68
+ elsif file_licenses[0].nil?
69
+ licenses_set.add("")
70
+ file_licenses_hash.store(filepath,"NONE")
71
+ else
72
+ licenses_set.add(file_licenses[0])
73
+ file_licenses_hash.store(filepath,file_licenses[0])
74
+ end
75
+ else
76
+ file_licenses.each do |license_in_onefile|
77
+ if dual_licenses.include? license_in_onefile == false
78
+ dual_licenses_str = dual_licenses_str + license_in_onefile + ' or '
79
+ dual_licenses.add(license_in_onefile)
80
+ end
81
+ end
82
+ licenses_set.add(dual_licenses_str[0,dual_licenses_str.length-4])
83
+ file_licenses_hash.store(filepath,dual_licenses_str[0,dual_licenses_str.length-4])
84
+ end
85
+ licenses_set.delete("")
86
+ rescue
87
+ puts $!
88
+ end
89
+ end
90
+ licenses_set.delete(nil)
91
+ return file_licenses_hash,licenses_set
92
+ end
93
+
94
+ # 兼容性查询,输入1为许可证A(通常指项目中第三方组件的许可证),输入2为许可证B(通常指项目许可证),输出为"0"(不兼容)、"1"(次级兼容)、"2"(组合兼容)、"1,2"(次级兼容或组合兼容)。
95
+ def self.compatibility_lookup(licenseA,licenseB)
96
+ compatibility_AB = '1,2'
97
+ c_table = CSV.read("lib\\compatibility_63.csv",headers:true)
98
+ CSV.foreach("lib\\compatibility_63.csv") do |row|
99
+ if row[0]==licenseA
100
+ no_row = $.
101
+ compatibility_AB = c_table[no_row-2][licenseB]
102
+ end
103
+ end
104
+ return compatibility_AB
105
+ end
106
+
107
+ # 兼容许可证筛选,输入1为项目路径,输入2为ninka路径,输入3为许可证推荐范围,其中默认值“popular”包含MIT等20种常见开源许可证,“all”包含本知识库支持的6种开源许可证。输出1为仅满足次级兼容的许可证列表,输出2为仅满足组合兼容的许可证列表,输出3为既满足次级兼容又满足组合兼容的许可证列表。
108
+ def self.compatibility_filter(repo_path,ninka_path,recommand_scale="popular")
109
+ filelicense_hash,licenseA_set = CompatibilityFilter.license_detection(repo_path,ninka_path)
110
+ c_table = CSV.read("lib\\compatibility_63.csv",headers:true)
111
+ all_license = c_table['license']
112
+ if recommand_scale == "popular"
113
+ licenseB_list = %w[MIT Apache-2.0 GPL-3.0 BSD-3-Clause GPL-2.0 AGPL-3.0 MPL-2.0 LGPL-3.0 BSD-2-Clause Unlicense ISC EPL-1.0 CC0-1.0 LGPL-2.1 WTFPL Zlib EPL-2.0 Artistic-2.0 MulanPSL-2.0 MulanPubL-2.0]
114
+ elsif recommand_scale == "all"
115
+ licenseB_list = all_license.dup
116
+ else
117
+ puts "范围错误,请输入'popular'或'all'。"
118
+ end
119
+ checked_license = []
120
+ recommend_licenses_1 = licenseB_list.dup
121
+ recommend_licenses_2 = licenseB_list.dup
122
+ recommend_licenses_12 = licenseB_list.dup
123
+ licenseA_set.each { |licenseA|
124
+ if licenseA.include? " or "
125
+ dual_checked = 0
126
+ licenseB_list.each { |licenseB|
127
+ licenseAs = licenseA.split(" or ")
128
+ is_remove_secondary = 1
129
+ is_remove_combine = 1
130
+ is_remove_both = 1
131
+ licenseAs.each{ |lA|
132
+ if all_license.include? lA
133
+ compatibilityAB = CompatibilityFilter.compatibility_lookup(lA,licenseB)
134
+ dual_checked = 1
135
+ if compatibilityAB == "1" or compatibilityAB == '1,2'
136
+ is_remove_secondary = 0
137
+ end
138
+ if compatibilityAB == "2" or compatibilityAB == '1,2'
139
+ is_remove_combine = 0
140
+ end
141
+ if compatibilityAB == "1,2"
142
+ is_remove_both = 0
143
+ end
144
+ end
145
+ }
146
+ if is_remove_secondary and dual_checked ==1
147
+ recommend_licenses_1.delete(licenseB)
148
+ end
149
+ if is_remove_combine and dual_checked ==1
150
+ recommend_licenses_2.delete(licenseB)
151
+ end
152
+ if is_remove_both and dual_checked ==1
153
+ recommend_licenses_12.delete(licenseB)
154
+ end
155
+ }
156
+ if dual_checked == 1
157
+ checked_license.push(licenseA)
158
+ end
159
+ else
160
+ if all_license.include? licenseA
161
+ checked_license.push(licenseA)
162
+ licenseB_list.each { |licenseB|
163
+ compatibilityAB = CompatibilityFilter.compatibility_lookup(licenseA,licenseB)
164
+ if compatibilityAB != "1" and compatibilityAB != '1,2'
165
+ recommend_licenses_1.delete(licenseB)
166
+ end
167
+ if compatibilityAB != "2" and compatibilityAB != '1,2'
168
+ recommend_licenses_2.delete(licenseB)
169
+ end
170
+ if compatibilityAB != "1,2"
171
+ recommend_licenses_12.delete(licenseB)
172
+ end
173
+ }
174
+ end
175
+ end
176
+ }
177
+ return recommend_licenses_1,recommend_licenses_2,recommend_licenses_12,checked_license
178
+ end
179
+
180
+ end
181
+
182
+ class CompatibilityCheck
183
+ def initialize()
184
+ end
185
+
186
+ # 兼容性检查,输入1为项目路径,输入2为ninka路径,输出为“OK”,或项目种包含互不兼容许可证的提示信息的集合、对应文件路径的列表
187
+ def self.compatibilitycheck(repo_path,ninka_path)
188
+ file_licenses_hash,licenses_set = CompatibilityFilter.license_detection(repo_path,ninka_path)
189
+ c_table = CSV.read("lib\\compatibility_63.csv",headers:true)
190
+ check_license_list = c_table["license"]
191
+ conflict_copyleft_infoset = Set.new
192
+ conflict_licenses = Set.new
193
+ licenses_set.each do |licenseA|
194
+ licenses_set.each do |licenseB|
195
+ if (licenseA.include? " or ") == false
196
+ iscompatibility = 0
197
+ ischeck = 0
198
+ if (licenseB.include? " or ") == false
199
+ ischeck = 1
200
+ compatibility_result_ab = CompatibilityFilter.compatibility_lookup(licenseA, licenseB)
201
+ compatibility_result_ba = CompatibilityFilter.compatibility_lookup(licenseB, licenseA)
202
+ if compatibility_result_ab != '0' or compatibility_result_ba != '0'
203
+ iscompatibility = 1
204
+ end
205
+ if iscompatibility == 0 and ischeck == 1
206
+ if (conflict_copyleft_infoset.include? licenseA+ "和" + licenseB + "互不兼容。") == false and (conflict_copyleft_infoset.include? licenseB+ "和" + licenseA + "互不兼容。") == false
207
+ conflict_copyleft_infoset.add(licenseA + "和" + licenseB + "互不兼容。")
208
+ conflict_licenses.add(licenseA)
209
+ conflict_licenses.add(licenseB)
210
+ end
211
+ end
212
+ else
213
+ licenseBs = licenseB.split(' or ')
214
+ licenseBs.each do |lB|
215
+ if check_license_list.include? lB
216
+ ischeck = 1
217
+ compatibility_result_ab = CompatibilityFilter.compatibility_lookup(licenseA, lB)
218
+ compatibility_result_ba = CompatibilityFilter.compatibility_lookup(lB, licenseA)
219
+ if compatibility_result_ab != '0' or compatibility_result_ba != '0'
220
+ iscompatibility = 1
221
+ end
222
+ end
223
+ end
224
+ if iscompatibility == 0 and ischeck == 1
225
+ if (conflict_copyleft_infoset.include? licenseA+ "和" + licenseB + "互不兼容。") == false and (conflict_copyleft_infoset.include? licenseB+ "和" + licenseA + "互不兼容。") == false
226
+ conflict_copyleft_infoset.add(licenseA + "和" + licenseB + "互不兼容。")
227
+ conflict_licenses.add(licenseA)
228
+ conflict_licenses.add(licenseB)
229
+ end
230
+ end
231
+ end
232
+ else
233
+ iscompatibility = 0
234
+ ischeck = 0
235
+ licenseAs = licenseA.split(' or ')
236
+ if (licenseB.include? " or ") == false
237
+ licenseAs.each do |lA|
238
+ if check_license_list.include? lA
239
+ ischeck = 1
240
+ compatibility_result_ab = CompatibilityFilter.compatibility_lookup(lA, licenseB)
241
+ compatibility_result_ba = CompatibilityFilter.compatibility_lookup(licenseB, lA)
242
+ if compatibility_result_ab != '0' or compatibility_result_ba != '0'
243
+ iscompatibility = 1
244
+ if iscompatibility == 0 and ischeck == 1
245
+ if (conflict_copyleft_infoset.include? licenseA+ "和" + licenseB + "互不兼容。") == false and (conflict_copyleft_infoset.include? licenseB+ "和" + licenseA + "互不兼容。") == false
246
+ conflict_copyleft_infoset.add(licenseA + "和" + licenseB + "互不兼容。")
247
+ conflict_licenses.add(licenseA)
248
+ conflict_licenses.add(licenseB)
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+ else
255
+ licenseBs = licenseB.split(' or ')
256
+ licenseAs.each do |lA|
257
+ licenseBs.each do |lB|
258
+ if check_license_list.include? lA and check_license_list.include? lB
259
+ ischeck = 1
260
+ compatibility_result_ab = CompatibilityFilter.compatibility_lookup(lA, lB)
261
+ compatibility_result_ba = CompatibilityFilter.compatibility_lookup(lB, lA)
262
+ if compatibility_result_ab != '0' or compatibility_result_ba != '0'
263
+ iscompatibility = 1
264
+ end
265
+ if iscompatibility == 0 and ischeck == 1
266
+ if (conflict_copyleft_infoset.include? licenseA+ "和" + licenseB + "互不兼容。") == false and (conflict_copyleft_infoset.include? licenseB+ "和" + licenseA + "互不兼容。") == false
267
+ conflict_copyleft_infoset.add(licenseA + "和" + licenseB + "互不兼容。")
268
+ conflict_licenses.add(licenseA)
269
+ conflict_licenses.add(licenseB)
270
+ end
271
+ end
272
+ end
273
+ end
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
279
+ conflict_filepath = []
280
+ if conflict_copyleft_infoset.nil?
281
+ return "OK",nil
282
+ else
283
+ conflict_licenses.each do |one_license|
284
+ file_licenses_hash.each do |file_path,file_license|
285
+ if file_license == one_license
286
+ conflict_filepath.push(file_path + "----------" + file_license)
287
+ end
288
+ end
289
+ end
290
+ return conflict_copyleft_infoset,conflict_filepath
291
+ end
292
+ end
293
+ end
294
+
295
+ end
296
+
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Licenserec
4
+ VERSION = "1.0.2"
5
+ end
data/lib/licenserec.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "licenserec/version"
4
+
5
+ module Licenserec
6
+ class Error < StandardError; end
7
+ # Your code goes here...
8
+ require 'licensecompatibility'
9
+ require 'licensetypeguide'
10
+ require 'licensetermchoice'
11
+ require 'licensecompare'
12
+ require 'licensesort'
13
+ end
@@ -0,0 +1,64 @@
1
+ license,info,preamble,define,copyright,patent,trademark,copyleft,interaction,modification,retain_attr,enhance_attr,acceptance,patent_term,vio_term,disclaimer,law,instruction,compatible_version,secondary_license,gpl_combine
2
+ CC0-1.0,1,1,0,-1,-1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0
3
+ Unlicense,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0
4
+ WTFPL,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
5
+ 0BSD,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0
6
+ MIT-0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0
7
+ Fair,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
8
+ MIT,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
9
+ ISC,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
10
+ FSFAP,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
11
+ Imlib2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
12
+ BSD-1-Clause,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
13
+ BSD-2-Clause,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
14
+ BSD-2-Clause-Patent,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,"GPL-2.0,GPL-2.0+",0
15
+ BSD-3-Clause,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0
16
+ BSD-3-Clause-Clear,1,0,0,0,-1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0
17
+ NCSA,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0
18
+ BSL-1.0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
19
+ NTP,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0
20
+ Ruby,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
21
+ UPL-1.0,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
22
+ EFL-2.0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
23
+ MirOS,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0
24
+ CC-BY-4.0,1,1,1,1,-1,1,0,0,1,1,0,0,0,1,1,0,0,0,0,0
25
+ ClArtistic,1,1,1,0,0,1,0,0,1,1,0,0,0,0,1,0,0,0,0,0
26
+ Zlib,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0
27
+ LiLiQ-P-1.1,1,1,1,1,0,1,0,0,1,1,0,0,0,1,1,Québec,0,0,0,0
28
+ MulanPSL-2.0,1,0,1,1,1,1,0,0,0,1,0,0,1,0,1,0,1,0,"Apache-2.0,GPL-2.0,GPL-2.0+",0
29
+ Apache-2.0,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,0,1,0,0,0
30
+ Artistic-2.0,1,1,1,0,1,1,0,0,1,1,0,0,1,0,1,0,0,0,"AGPL-3.0,AGPL-3.0+,CC-BY-SA-4.0,CECILL-2.1,EPL-1.0,EUPL-1.1,EUPL-1.2,GPL-2.0,GPL-2.0+,GPL-3.0,GPL-3.0+,LiLiQ-Rplus-1.1,MulanPubL-2.0,NPOSL-3.0,OSL-3.0,RPL-1.5,SimPL-2.0",0
31
+ ECL-2.0,1,0,1,1,1,1,0,0,1,1,0,0,1,0,1,0,1,0,0,0
32
+ AFL-3.0,1,0,1,1,1,1,0,0,1,1,0,1,1,1,1,0,0,0,0,0
33
+ BSD-4-Clause,1,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0
34
+ AAL,1,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0
35
+ CDDL-1.0,1,0,1,1,1,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0
36
+ CPAL-1.0,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,California,1,0,0,0
37
+ EPL-2.0,1,0,1,1,1,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0
38
+ LiLiQ-R-1.1,1,1,1,1,0,1,1,0,1,1,0,0,0,1,1,Québec,0,0,"CDDL-1.0,CPL-1.0,CECILL-2.1,CECILL-C,EPL-1.0,EUPL-1.1,LiLiQ-Rplus-1.1,GPL-2.0,GPL-3.0,LGPL-2.1,LGPL-3.0,MPL-2.0,GPL-2.0+,GPL-3.0+,LGPL-2.1+,LGPL-3.0+",0
39
+ MPL-2.0,1,0,1,1,1,1,1,0,0,1,0,0,1,1,1,0,1,0,"GPL-2.0,GPL-3.0,LGPL-2.1,LGPL-3.0,AGPL-3.0,GPL-2.0+,GPL-3.0+,LGPL-2.1+,LGPL-3.0+,AGPL-3.0+",0
40
+ MS-RL,1,0,1,1,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0
41
+ NOSL,1,0,1,1,1,1,1,0,1,1,0,0,1,1,1,Victoria,0,0,0,0
42
+ OGTSL,1,1,1,0,0,1,2,0,1,1,0,0,0,0,1,0,0,0,0,0
43
+ MS-PL,1,0,1,1,1,1,3,0,0,1,0,0,1,0,1,0,0,0,0,0
44
+ CC-BY-SA-4.0,1,1,1,1,-1,1,3,0,1,1,0,0,0,1,1,0,0,0,0,0
45
+ CECILL-2.1,1,1,1,1,1,0,3,0,1,1,0,0,0,1,1,French,0,0,"GPL-2.0,GPL-3.0,AGPL-3.0,EUPL-1.1,EUPL-1.2,GPL-2.0+,GPL-3.0+,AGPL-3.0+",0
46
+ EPL-1.0,1,0,1,1,1,0,3,0,1,1,0,0,1,1,1,New York,0,EPL-2.0,0,0
47
+ EUPL-1.1,1,0,1,1,1,1,3,0,1,1,0,0,0,1,1, European Union,0,EUPL-1.2,"GPL-2.0,OSL-2.1,OSL-3.0,CPL-1.0,EPL-1.0,CECILL-2.0,GPL-2.0+",0
48
+ EUPL-1.2,1,0,1,1,1,1,3,0,1,1,0,0,0,1,1, European Union,0,0,"GPL-2.0,GPL-3.0,AGPL-3.0,OSL-2.1,OSL-3.0,EPL-1.0,CECILL-2.0,CECILL-2.1,MPL-2.0,LGPL-2.1,LGPL-3.0,CC-BY-SA-3.0,EUPL-1.1,EUPL-1.2,LiLiQ-R,LiLiQ-R+,GPL-2.0+,GPL-3.0+,AGPL-3.0+,LGPL-2.1+,LGPL-3.0+",0
49
+ LGPL-2.1+,1,1,1,0,0,0,2,0,1,1,0,0,0,1,1,0,1,"LGPL-3.0,LGPL-2.1,LGPL-3.0+","GPL-2.0,GPL-2.0+,GPL-3.0,GPL-3.0+","GPL-2.0,GPL-2.0+,GPL-3.0,GPL-3.0+,LGPL-2.1,LGPL-2.1+,LGPL-3.0,LGPL-3.0+"
50
+ LGPL-2.1,1,1,1,0,0,0,2,0,1,1,0,0,0,1,1,0,1,LGPL-2.1+,"GPL-2.0,GPL-2.0+,GPL-3.0,GPL-3.0+","GPL-2.0,GPL-2.0+,GPL-3.0,GPL-3.0+,LGPL-2.1,LGPL-2.1+,LGPL-3.0,LGPL-3.0+"
51
+ LGPL-3.0+,1,1,1,1,1,0,2,0,1,1,0,0,1,1,1,0,1,LGPL-3.0,"GPL-3.0,GPL-3.0+","GPL-3.0,GPL-3.0+,LGPL-2.1,LGPL-2.1+,LGPL-3.0,LGPL-3.0+"
52
+ LGPL-3.0,1,1,1,1,1,0,2,0,1,1,0,0,1,1,1,0,1,LGPL-3.0+,"GPL-3.0,GPL-3.0+","GPL-3.0,GPL-3.0+,LGPL-2.1,LGPL-2.1+,LGPL-3.0,LGPL-3.0+"
53
+ GPL-2.0+,1,1,1,0,0,0,3,0,1,1,0,0,0,1,1,0,1,"GPL-3.0,GPL-2.0,GPL-3.0+",0,"AGPL-3.0,AGPL-3.0+,GPL-2.0"
54
+ GPL-2.0,1,1,1,0,0,0,3,0,1,1,0,0,0,1,1,0,1,GPL-2.0+,0,GPL-2.0+
55
+ GPL-3.0+,1,1,1,1,1,0,3,0,1,1,0,0,1,1,1,0,1,GPL-3.0,0,"AGPL-3.0,AGPL-3.0+,GPL-3.0"
56
+ GPL-3.0,1,1,1,1,1,0,3,0,1,1,0,0,1,1,1,0,1,GPL-3.0+,0,"AGPL-3.0,AGPL-3.0+,GPL-3.0+"
57
+ AGPL-3.0+,1,1,1,1,1,0,3,1,1,1,0,0,1,1,1,0,1,AGPL-3.0,0,AGPL-3.0
58
+ AGPL-3.0,1,1,1,1,1,0,3,1,1,1,0,0,1,1,1,0,1,AGPL-3.0+,0,AGPL-3.0+
59
+ SimPL-2.0,1,0,0,1,0,0,3,0,1,1,0,0,0,1,1,0,0,0,"GPL-2.0,GPL-2.0+",0
60
+ LiLiQ-Rplus-1.1,1,1,1,1,0,1,3,0,1,1,0,0,0,1,1,Québec,0,0,"CPL-1.0,CECILL-2.1,EPL-1.0,EUPL-1.1,GPL-2.0,GPL-3.0,GPL-2.0+,GPL-3.0+",0
61
+ RPL-1.5,1,1,1,1,1,1,3,1,1,1,0,0,1,1,1,Colorado,1,0,0,0
62
+ NPOSL-3.0,1,0,0,1,1,1,3,1,1,1,0,1,1,1,1,0,0,0,0,0
63
+ MulanPubL-2.0,1,0,1,1,1,1,3,1,0,1,0,0,1,1,1,0,1,0,"AGPL-3.0,AGPL-3.0+",0
64
+ OSL-3.0,1,0,1,1,1,1,3,1,1,1,0,1,1,1,1,0,0,0,0,0
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "licenserec/version"
4
+ require 'csv'
5
+
6
+
7
+ module Licenserec
8
+ class LicenseSort
9
+ def initialize()
10
+ end
11
+
12
+ # 将csv转为哈希值。输入1为csv表,输入2为是否包含首行(默认包含),输入3为列数i(转为hash的key),输入4为列数j(转为hash的value);输出为哈希表。
13
+ def self.csv_to_hash(csv_table,header=true,i=0,j=1)
14
+ sort_hash = Hash.new
15
+ CSV.foreach(csv_table) do |row|
16
+ if header
17
+ if $. != 1
18
+ sort_hash.store(row[i],row[j])
19
+ end
20
+ else
21
+ sort_hash.store(row[i],row[j])
22
+ end
23
+ end
24
+ return sort_hash
25
+ end
26
+
27
+ # 从排序哈希表中查询排序值。输入1为许可证SPDX,输入2为参照排序哈希表;输出为该许可证的排序值。
28
+ def self.sortvalue_lookup(one_license,sort_hash)
29
+ sortvalue = -1
30
+ if sort_hash.has_key? one_license
31
+ sortvalue = sort_hash.values_at(one_license)
32
+ end
33
+ return Float(sortvalue[0])
34
+ end
35
+
36
+ # 对指定许可证列表进行排序。输入1为指定的许可证列表,输入2为升降序(默认降序),输入3为参照排序哈希表(key为许可证SPDX,value为参照值,默认按文本复杂度);输出排序后的许可证列表。
37
+ def self.license_sort(license_list,desc=true,sort_hash=LicenseSort.csv_to_hash("lib\\license_readability.csv",header=true,i=0,j=4))
38
+ sort_res=[]
39
+ license_initsort = Hash.new
40
+ for one_license in license_list do
41
+ license_initsort[one_license] = LicenseSort.sortvalue_lookup(one_license,sort_hash)
42
+ end
43
+ if desc
44
+ license_sort_desc = license_initsort.sort{|a, b| b[1]<=>a[1]}
45
+ for sort_value in license_sort_desc do
46
+ sort_res.push(sort_value[0]) # 降序结果
47
+ end
48
+ else
49
+ license_sort_asc = license_initsort.sort{|a, b| a[1]<=>b[1]}
50
+ for sort_value in license_sort_asc do
51
+ sort_res.push(sort_value[0]) # 升序结果
52
+ end
53
+ end
54
+ return sort_res
55
+ end
56
+
57
+ end
58
+ end
59
+