Class: Licenserec::CompatibilityFilter
- Inherits:
-
Object
- Object
- Licenserec::CompatibilityFilter
- Defined in:
- lib/licensecompatibility.rb
Class Method Summary collapse
-
.compatibility_filter(repo_path, ninka_path, recommand_scale = "popular") ⇒ Object
兼容许可证筛选,输入1为项目路径,输入2为ninka路径,输入3为许可证推荐范围,其中默认值“popular”包含MIT等20种常见开源许可证,“all”包含本知识库支持的6种开源许可证。输出1为仅满足次级兼容的许可证列表,输出2为仅满足组合兼容的许可证列表,输出3为既满足次级兼容又满足组合兼容的许可证列表。.
-
.compatibility_lookup(licenseA, licenseB) ⇒ Object
兼容性查询,输入1为许可证A(通常指项目中第三方组件的许可证),输入2为许可证B(通常指项目许可证),输出为“0”(不兼容)、“1”(次级兼容)、“2”(组合兼容)、“1,2”(次级兼容或组合兼容)。.
-
.compatibility_meaning ⇒ Object
次级兼容、组合兼容和不兼容的含义.
-
.license_detection(repo_path, ninka_path) ⇒ Object
识别项目所包含的许可证,输入1为项目路径,输入2为ninka路径,输出1为文件路径及对应许可证信息的哈希表,输出2为项目包含的许可证集合.
-
.ninka_process(filepath, ninka_path) ⇒ Object
第三方工具Ninka识别文件许可证,一个文件可能包含多个许可证,输入1为文件的路径,输入2为ninka路径,输出为许可证列表。.
-
.show_files(f_path, repofiles_pathlist) ⇒ Object
遍历文件夹,返回所有文件的路径列表.
Instance Method Summary collapse
-
#initialize ⇒ CompatibilityFilter
constructor
A new instance of CompatibilityFilter.
Constructor Details
#initialize ⇒ CompatibilityFilter
Returns a new instance of CompatibilityFilter.
10 11 |
# File 'lib/licensecompatibility.rb', line 10 def initialize() end |
Class Method Details
.compatibility_filter(repo_path, ninka_path, recommand_scale = "popular") ⇒ Object
兼容许可证筛选,输入1为项目路径,输入2为ninka路径,输入3为许可证推荐范围,其中默认值“popular”包含MIT等20种常见开源许可证,“all”包含本知识库支持的6种开源许可证。输出1为仅满足次级兼容的许可证列表,输出2为仅满足组合兼容的许可证列表,输出3为既满足次级兼容又满足组合兼容的许可证列表。
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/licensecompatibility.rb', line 109 def self.compatibility_filter(repo_path,ninka_path,recommand_scale="popular") filelicense_hash,licenseA_set = CompatibilityFilter.license_detection(repo_path,ninka_path) cur_path=String(Pathname.new(File.dirname(__FILE__)).realpath) c_table = CSV.read(cur_path+"\\compatibility_63.csv",headers:true) all_license = c_table['license'] if recommand_scale == "popular" 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] elsif recommand_scale == "all" licenseB_list = all_license.dup else puts "范围错误,请输入'popular'或'all'。" end checked_license = [] recommend_licenses_1 = licenseB_list.dup recommend_licenses_2 = licenseB_list.dup recommend_licenses_12 = licenseB_list.dup licenseA_set.each { |licenseA| if licenseA.include? " or " dual_checked = 0 licenseB_list.each { |licenseB| licenseAs = licenseA.split(" or ") is_remove_secondary = 1 is_remove_combine = 1 is_remove_both = 1 licenseAs.each{ |lA| if all_license.include? lA compatibilityAB = CompatibilityFilter.compatibility_lookup(lA,licenseB) dual_checked = 1 if compatibilityAB == "1" or compatibilityAB == '1,2' is_remove_secondary = 0 end if compatibilityAB == "2" or compatibilityAB == '1,2' is_remove_combine = 0 end if compatibilityAB == "1,2" is_remove_both = 0 end end } if is_remove_secondary and dual_checked ==1 recommend_licenses_1.delete(licenseB) end if is_remove_combine and dual_checked ==1 recommend_licenses_2.delete(licenseB) end if is_remove_both and dual_checked ==1 recommend_licenses_12.delete(licenseB) end } if dual_checked == 1 checked_license.push(licenseA) end else if all_license.include? licenseA checked_license.push(licenseA) licenseB_list.each { |licenseB| compatibilityAB = CompatibilityFilter.compatibility_lookup(licenseA,licenseB) if compatibilityAB != "1" and compatibilityAB != '1,2' recommend_licenses_1.delete(licenseB) end if compatibilityAB != "2" and compatibilityAB != '1,2' recommend_licenses_2.delete(licenseB) end if compatibilityAB != "1,2" recommend_licenses_12.delete(licenseB) end } end end } return recommend_licenses_1,recommend_licenses_2,recommend_licenses_12,checked_license end |
.compatibility_lookup(licenseA, licenseB) ⇒ Object
兼容性查询,输入1为许可证A(通常指项目中第三方组件的许可证),输入2为许可证B(通常指项目许可证),输出为“0”(不兼容)、“1”(次级兼容)、“2”(组合兼容)、“1,2”(次级兼容或组合兼容)。
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/licensecompatibility.rb', line 95 def self.compatibility_lookup(licenseA,licenseB) compatibility_AB = '1,2' cur_path=String(Pathname.new(File.dirname(__FILE__)).realpath) c_table = CSV.read(cur_path+"\\compatibility_63.csv",headers:true) CSV.foreach(cur_path+"\\compatibility_63.csv") do |row| if row[0]==licenseA no_row = $. compatibility_AB = c_table[no_row-2][licenseB] end end return compatibility_AB end |
.compatibility_meaning ⇒ Object
次级兼容、组合兼容和不兼容的含义
14 15 16 17 18 19 20 |
# File 'lib/licensecompatibility.rb', line 14 def self.compatibility_meaning() compatibility_meaning_hash = Hash.new compatibility_meaning_hash.store("次级兼容","开源许可证A授权的作品(无论是否经过修改)与开源许可证B授权的作品组合,所产生的衍生作品整体可合法地使用开源许可证B重新授权时,则认为开源许可证A次级兼容开源许可证B。本知识库中使用‘1’表示次级兼容。") compatibility_meaning_hash.store("组合兼容","开源许可证A授权的作品(无论是否经过修改)可以与开源许可证B授权的作品可以合法地组合而不违反任一开源许可证时,可以认为开源许可证A组合兼容开源许可证B。本知识库中使用‘2’表示组合兼容。") compatibility_meaning_hash.store("不兼容","不满足次级兼容或组合兼容的条件,则不兼容。本知识库中使用‘0’表示不兼容。") return compatibility_meaning_hash end |
.license_detection(repo_path, ninka_path) ⇒ Object
识别项目所包含的许可证,输入1为项目路径,输入2为ninka路径,输出1为文件路径及对应许可证信息的哈希表,输出2为项目包含的许可证集合
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/licensecompatibility.rb', line 47 def self.license_detection(repo_path,ninka_path) # 遍历项目文件夹,获取项目中所有文件路径 repofiles_pathlist = [] repofiles_pathlist = show_files(repo_path,repofiles_pathlist) # 创建子进程,获取每个文件的许可证信息 other_licenses = ["SeeFile", "UNKNOWN"] licenses_set = Set.new file_licenses_hash = {} repofiles_pathlist.each do |filepath| # 异常处理 begin file_licenses = CompatibilityFilter.ninka_process(filepath,ninka_path) dual_licenses = Set.new dual_licenses_str = "" if file_licenses.length <= 1 if other_licenses.include? file_licenses[0] licenses_set.add("Other") file_licenses_hash.store(filepath,"Other") elsif file_licenses[0].include? "NONE" licenses_set.add("") file_licenses_hash.store(filepath,"NONE") elsif file_licenses[0].nil? licenses_set.add("") file_licenses_hash.store(filepath,"NONE") else licenses_set.add(file_licenses[0]) file_licenses_hash.store(filepath,file_licenses[0]) end else file_licenses.each do |license_in_onefile| if dual_licenses.include? license_in_onefile == false dual_licenses_str = dual_licenses_str + license_in_onefile + ' or ' dual_licenses.add(license_in_onefile) end end licenses_set.add(dual_licenses_str[0,dual_licenses_str.length-4]) file_licenses_hash.store(filepath,dual_licenses_str[0,dual_licenses_str.length-4]) end licenses_set.delete("") rescue puts $! end end licenses_set.delete(nil) return file_licenses_hash,licenses_set end |
.ninka_process(filepath, ninka_path) ⇒ Object
第三方工具Ninka识别文件许可证,一个文件可能包含多个许可证,输入1为文件的路径,输入2为ninka路径,输出为许可证列表。
37 38 39 40 41 42 43 44 |
# File 'lib/licensecompatibility.rb', line 37 def self.ninka_process(filepath,ninka_path) io = IO.popen("perl " + ninka_path + " " + filepath) io_stdout = io.gets.split(";") file_license_list = io_stdout[1].split(",") # puts "++++++++++++++" # puts file_license_list return file_license_list end |
.show_files(f_path, repofiles_pathlist) ⇒ Object
遍历文件夹,返回所有文件的路径列表
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/licensecompatibility.rb', line 23 def self.show_files(f_path,repofiles_pathlist) if File.directory? f_path Dir.foreach(f_path) do |file| if file != "." and file != ".." show_files(f_path + "/" + file,repofiles_pathlist) end end else repofiles_pathlist.push(f_path) end return repofiles_pathlist end |