license_scout 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +3 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +11 -0
- data/Gemfile +24 -0
- data/LICENSE +201 -0
- data/README.md +26 -0
- data/Rakefile +39 -0
- data/bin/license_scout +39 -0
- data/lib/license_scout/collector.rb +137 -0
- data/lib/license_scout/dependency.rb +20 -0
- data/lib/license_scout/dependency_manager/base.rb +55 -0
- data/lib/license_scout/dependency_manager/bundler/LICENSE.md +23 -0
- data/lib/license_scout/dependency_manager/bundler/_bundler_script.rb +47 -0
- data/lib/license_scout/dependency_manager/bundler.rb +159 -0
- data/lib/license_scout/dependency_manager/rebar.rb +92 -0
- data/lib/license_scout/dependency_manager.rb +27 -0
- data/lib/license_scout/exceptions.rb +74 -0
- data/lib/license_scout/license_file_analyzer/any_matcher.rb +37 -0
- data/lib/license_scout/license_file_analyzer/definitions.rb +212 -0
- data/lib/license_scout/license_file_analyzer/header_matcher.rb +34 -0
- data/lib/license_scout/license_file_analyzer/matcher.rb +46 -0
- data/lib/license_scout/license_file_analyzer/template.rb +45 -0
- data/lib/license_scout/license_file_analyzer/templates/Apache2-short.txt +11 -0
- data/lib/license_scout/license_file_analyzer/templates/Apache2.txt +172 -0
- data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause-bullets.txt +18 -0
- data/lib/license_scout/license_file_analyzer/templates/BSD-2-Clause.txt +19 -0
- data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause-alt-format.txt +24 -0
- data/lib/license_scout/license_file_analyzer/templates/BSD-3-Clause.txt +21 -0
- data/lib/license_scout/license_file_analyzer/templates/BSD.txt +24 -0
- data/lib/license_scout/license_file_analyzer/templates/EPLICENSE.txt +286 -0
- data/lib/license_scout/license_file_analyzer/templates/GPL-2.0.txt +339 -0
- data/lib/license_scout/license_file_analyzer/templates/GPL-3.0.txt +674 -0
- data/lib/license_scout/license_file_analyzer/templates/ISC.txt +2 -0
- data/lib/license_scout/license_file_analyzer/templates/LGPL-3.0.txt +165 -0
- data/lib/license_scout/license_file_analyzer/templates/MIT.txt +9 -0
- data/lib/license_scout/license_file_analyzer/templates/MPL2.txt +373 -0
- data/lib/license_scout/license_file_analyzer/templates/Python-2.0.txt +47 -0
- data/lib/license_scout/license_file_analyzer/templates/Ruby.txt +52 -0
- data/lib/license_scout/license_file_analyzer/text.rb +46 -0
- data/lib/license_scout/license_file_analyzer.rb +26 -0
- data/lib/license_scout/net_fetcher.rb +104 -0
- data/lib/license_scout/options.rb +45 -0
- data/lib/license_scout/overrides.rb +149 -0
- data/lib/license_scout/version.rb +20 -0
- data/lib/license_scout.rb +19 -0
- data/license_scout.gemspec +46 -0
- metadata +190 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright 2016, Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "license_scout/dependency_manager/base"
|
19
|
+
require "license_scout/net_fetcher"
|
20
|
+
require "license_scout/exceptions"
|
21
|
+
|
22
|
+
require "bundler"
|
23
|
+
require "mixlib/shellout"
|
24
|
+
require "ffi_yajl"
|
25
|
+
require "pathname"
|
26
|
+
|
27
|
+
module LicenseScout
|
28
|
+
module DependencyManager
|
29
|
+
class Bundler < Base
|
30
|
+
|
31
|
+
def name
|
32
|
+
"ruby_bundler"
|
33
|
+
end
|
34
|
+
|
35
|
+
def detected?
|
36
|
+
# We only check for the existence of Gemfile in order to declare a
|
37
|
+
# project a Bundler project. If the Gemfile.lock does not exist
|
38
|
+
# we will raise a specific error to indicate that "bundle install"
|
39
|
+
# needs to be run before proceeding.
|
40
|
+
File.exists?(gemfile_path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def dependency_data
|
44
|
+
bundler_script = File.join(File.dirname(__FILE__), "bundler/_bundler_script.rb")
|
45
|
+
|
46
|
+
Dir.chdir(project_dir) do
|
47
|
+
json_dep_data = with_clean_env do
|
48
|
+
ruby_bin_path = options.ruby_bin || "ruby"
|
49
|
+
s = Mixlib::ShellOut.new("#{ruby_bin_path} #{bundler_script}", environment: options.environment)
|
50
|
+
s.run_command
|
51
|
+
s.error!
|
52
|
+
s.stdout
|
53
|
+
end
|
54
|
+
FFI_Yajl::Parser.parse(json_dep_data)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def dependencies
|
59
|
+
if !File.exists?(lockfile_path)
|
60
|
+
raise LicenseScout::Exceptions::DependencyManagerNotRun.new(project_dir, name)
|
61
|
+
end
|
62
|
+
|
63
|
+
dependencies = []
|
64
|
+
dependency_data.each do |gem_data|
|
65
|
+
dependency_name = gem_data["name"]
|
66
|
+
dependency_version = gem_data["version"]
|
67
|
+
dependency_license = nil
|
68
|
+
dependency_license_files = []
|
69
|
+
|
70
|
+
if dependency_name == "bundler"
|
71
|
+
# Bundler is weird. It inserts itself as a dependency, but is a
|
72
|
+
# special case, so rubygems cannot correctly report the license.
|
73
|
+
# Additionally, rubygems reports the gem path as a path inside
|
74
|
+
# bundler's lib/ dir, so we have to munge it.
|
75
|
+
dependency_license = "MIT"
|
76
|
+
dependency_license_files = [File.join(File.dirname(__FILE__), "bundler/LICENSE.md")]
|
77
|
+
else
|
78
|
+
# Check license override and license_files override separately since
|
79
|
+
# only one might be set in the overrides.
|
80
|
+
dependency_license = options.overrides.license_for(name, dependency_name, dependency_version) || gem_data["license"]
|
81
|
+
|
82
|
+
override_license_files = options.overrides.license_files_for(name, dependency_name, dependency_version)
|
83
|
+
if override_license_files.empty?
|
84
|
+
dependency_license_files = auto_detect_license_files(gem_data["path"])
|
85
|
+
else
|
86
|
+
dependency_license_files = override_license_files.resolve_locations(gem_data["path"])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
dependencies << Dependency.new(
|
91
|
+
dependency_name,
|
92
|
+
dependency_version,
|
93
|
+
dependency_license,
|
94
|
+
dependency_license_files
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
dependencies
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
#
|
104
|
+
# Execute the given command, removing any Ruby-specific environment
|
105
|
+
# variables. This is an "enhanced" version of +Bundler.with_clean_env+,
|
106
|
+
# which only removes Bundler-specific values. We need to remove all
|
107
|
+
# values, specifically:
|
108
|
+
#
|
109
|
+
# - _ORIGINAL_GEM_PATH
|
110
|
+
# - GEM_PATH
|
111
|
+
# - GEM_HOME
|
112
|
+
# - GEM_ROOT
|
113
|
+
# - BUNDLE_BIN_PATH
|
114
|
+
# - BUNDLE_GEMFILE
|
115
|
+
# - RUBYLIB
|
116
|
+
# - RUBYOPT
|
117
|
+
# - RUBY_ENGINE
|
118
|
+
# - RUBY_ROOT
|
119
|
+
# - RUBY_VERSION
|
120
|
+
#
|
121
|
+
# The original environment restored at the end of this call.
|
122
|
+
#
|
123
|
+
# @param [Proc] block
|
124
|
+
# the block to execute with the cleaned environment
|
125
|
+
#
|
126
|
+
def with_clean_env(&block)
|
127
|
+
original = ENV.to_hash
|
128
|
+
|
129
|
+
ENV.delete("_ORIGINAL_GEM_PATH")
|
130
|
+
ENV.delete_if { |k, _| k.start_with?("BUNDLE_") }
|
131
|
+
ENV.delete_if { |k, _| k.start_with?("GEM_") }
|
132
|
+
ENV.delete_if { |k, _| k.start_with?("RUBY") }
|
133
|
+
|
134
|
+
yield
|
135
|
+
ensure
|
136
|
+
ENV.replace(original.to_hash)
|
137
|
+
end
|
138
|
+
|
139
|
+
def auto_detect_license_files(gem_path)
|
140
|
+
unless File.exist?(gem_path)
|
141
|
+
raise LicenseScout::Exceptions::InaccessibleDependency.new "Autodetected gem path '#{gem_path}' does not exist"
|
142
|
+
end
|
143
|
+
|
144
|
+
Dir.glob("#{gem_path}/*").select do |f|
|
145
|
+
POSSIBLE_LICENSE_FILES.include?(File.basename(f))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def gemfile_path
|
150
|
+
File.join(project_dir, "Gemfile")
|
151
|
+
end
|
152
|
+
|
153
|
+
def lockfile_path
|
154
|
+
File.join(project_dir, "Gemfile.lock")
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright 2016, Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "license_scout/dependency_manager/base"
|
19
|
+
require "license_scout/net_fetcher"
|
20
|
+
require "license_scout/exceptions"
|
21
|
+
require "license_scout/license_file_analyzer"
|
22
|
+
|
23
|
+
require "mixlib/shellout"
|
24
|
+
|
25
|
+
module LicenseScout
|
26
|
+
module DependencyManager
|
27
|
+
class Rebar < Base
|
28
|
+
|
29
|
+
def name
|
30
|
+
"erlang_rebar"
|
31
|
+
end
|
32
|
+
|
33
|
+
def detected?
|
34
|
+
File.exist?(rebar_config_path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def dependencies
|
38
|
+
dependencies = []
|
39
|
+
|
40
|
+
Dir.glob("#{project_deps_dir}/*").each do |dep_dir|
|
41
|
+
next unless File.directory?(dep_dir)
|
42
|
+
|
43
|
+
dep_name = File.basename(dep_dir)
|
44
|
+
dep_version = git_rev_parse(dep_dir)
|
45
|
+
|
46
|
+
override_license_files = options.overrides.license_files_for(name, dep_name, dep_version)
|
47
|
+
license_files =
|
48
|
+
if override_license_files.empty?
|
49
|
+
Dir.glob("#{dep_dir}/*").select { |f| POSSIBLE_LICENSE_FILES.include?(File.basename(f)) }
|
50
|
+
else
|
51
|
+
override_license_files.resolve_locations(dep_dir)
|
52
|
+
end
|
53
|
+
|
54
|
+
license_name = options.overrides.license_for(name, dep_name, dep_version) || scan_licenses(license_files)
|
55
|
+
|
56
|
+
dep = Dependency.new(dep_name, dep_version, license_name, license_files)
|
57
|
+
|
58
|
+
dependencies << dep
|
59
|
+
end
|
60
|
+
|
61
|
+
dependencies
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def git_rev_parse(dependency_dir)
|
67
|
+
s = Mixlib::ShellOut.new("git rev-parse HEAD", cwd: dependency_dir)
|
68
|
+
s.run_command
|
69
|
+
s.error!
|
70
|
+
s.stdout.strip
|
71
|
+
end
|
72
|
+
|
73
|
+
def project_deps_dir
|
74
|
+
File.join(project_dir, "deps")
|
75
|
+
end
|
76
|
+
|
77
|
+
def rebar_config_path
|
78
|
+
File.join(project_dir, "rebar.config")
|
79
|
+
end
|
80
|
+
|
81
|
+
def scan_licenses(license_files)
|
82
|
+
if license_files.empty?
|
83
|
+
nil
|
84
|
+
else
|
85
|
+
found_license = LicenseScout::LicenseFileAnalyzer.find_by_text(IO.read(license_files.first))
|
86
|
+
found_license ? found_license.short_name : nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright 2016, Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "license_scout/dependency_manager/bundler"
|
19
|
+
require "license_scout/dependency_manager/rebar"
|
20
|
+
|
21
|
+
module LicenseScout
|
22
|
+
module DependencyManager
|
23
|
+
def self.implementations
|
24
|
+
[Bundler, Rebar]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright 2016, Chef Software Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module LicenseScout
|
19
|
+
module Exceptions
|
20
|
+
class Error < RuntimeError; end
|
21
|
+
|
22
|
+
class ProjectDirectoryMissing < Error
|
23
|
+
def initialize(project_dir)
|
24
|
+
@project_dir = project_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"Could not locate or access the provided project directory '#{@project_dir}'."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class UnsupportedProjectType < Error
|
33
|
+
def initialize(project_dir)
|
34
|
+
@project_dir = project_dir
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"Could not find a supported dependency manager for the project in the provided directory '#{@project_dir}'."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class DependencyManagerNotRun < Error
|
43
|
+
def initialize(project_dir, dependency_manager_name)
|
44
|
+
@project_dir = project_dir
|
45
|
+
@dependency_manager_name = dependency_manager_name
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_s
|
49
|
+
"Dependency manager '#{@dependency_manager_name}' is not yet run for project at '#{@project_dir}'."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class InaccessibleDependency < Error; end
|
54
|
+
class InvalidOverride < Error; end
|
55
|
+
|
56
|
+
class NetworkError < Error
|
57
|
+
|
58
|
+
attr_reader :from_url
|
59
|
+
attr_reader :network_error
|
60
|
+
|
61
|
+
def initialize(from_url, network_error)
|
62
|
+
@from_url = from_url
|
63
|
+
@network_error = network_error
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_s
|
67
|
+
[
|
68
|
+
"Network error while fetching '#{from_url}'",
|
69
|
+
network_error.to_s,
|
70
|
+
].join("\n")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copied from https://github.com/pivotal/LicenseFinder
|
2
|
+
#
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012 Pivotal Labs
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
module LicenseScout
|
26
|
+
module LicenseFileAnalyzer
|
27
|
+
class AnyMatcher
|
28
|
+
def initialize(*matchers)
|
29
|
+
@matchers = matchers
|
30
|
+
end
|
31
|
+
|
32
|
+
def matches_text?(text)
|
33
|
+
@matchers.any? { |m| m.matches_text? text }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
# Copied from https://github.com/pivotal/LicenseFinder
|
2
|
+
#
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012 Pivotal Labs
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
require "license_scout/license_file_analyzer/matcher"
|
26
|
+
require "license_scout/license_file_analyzer/any_matcher"
|
27
|
+
require "license_scout/license_file_analyzer/header_matcher"
|
28
|
+
require "license_scout/license_file_analyzer/template"
|
29
|
+
|
30
|
+
module LicenseScout
|
31
|
+
module LicenseFileAnalyzer
|
32
|
+
|
33
|
+
class License
|
34
|
+
|
35
|
+
attr_reader :matcher
|
36
|
+
attr_reader :short_name
|
37
|
+
|
38
|
+
def initialize(short_name:, matcher: nil)
|
39
|
+
@short_name = short_name
|
40
|
+
@matcher = matcher || Matcher.from_template(Template.named(short_name))
|
41
|
+
end
|
42
|
+
|
43
|
+
def matches_text?(text)
|
44
|
+
matcher.matches_text?(text)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
module Definitions
|
50
|
+
extend self
|
51
|
+
|
52
|
+
def all
|
53
|
+
[
|
54
|
+
apache2,
|
55
|
+
bsd,
|
56
|
+
gplv2,
|
57
|
+
gplv3,
|
58
|
+
isc,
|
59
|
+
lgpl,
|
60
|
+
mit,
|
61
|
+
mpl2,
|
62
|
+
bsd_3_clause,
|
63
|
+
python,
|
64
|
+
ruby,
|
65
|
+
bsd_2_clause,
|
66
|
+
erlang_public,
|
67
|
+
]
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def apache2
|
73
|
+
matcher = AnyMatcher.new(
|
74
|
+
Matcher.from_template(Template.named("Apache2")),
|
75
|
+
Matcher.from_template(Template.named("Apache2-short"))
|
76
|
+
)
|
77
|
+
|
78
|
+
License.new(
|
79
|
+
short_name: "Apache-2.0",
|
80
|
+
matcher: matcher
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def bsd
|
85
|
+
License.new(
|
86
|
+
short_name: "BSD"
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
def gplv2
|
91
|
+
License.new(
|
92
|
+
short_name: "GPL-2.0"
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
def gplv3
|
97
|
+
License.new(
|
98
|
+
short_name: "GPL-3.0"
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
def isc
|
103
|
+
License.new(
|
104
|
+
short_name: "ISC"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def lgpl
|
109
|
+
License.new(
|
110
|
+
short_name: "LGPL-3.0"
|
111
|
+
)
|
112
|
+
end
|
113
|
+
|
114
|
+
def mit
|
115
|
+
url_regexp = %r{MIT Licen[sc]e.*http://(?:www\.)?opensource\.org/licenses/mit-license}
|
116
|
+
header_regexp = /The MIT Licen[sc]e/
|
117
|
+
one_liner_regexp = /is released under the MIT licen[sc]e/
|
118
|
+
|
119
|
+
matcher = AnyMatcher.new(
|
120
|
+
Matcher.from_template(Template.named("MIT")),
|
121
|
+
Matcher.from_regex(url_regexp),
|
122
|
+
HeaderMatcher.new(Matcher.from_regex(header_regexp)),
|
123
|
+
Matcher.from_regex(one_liner_regexp)
|
124
|
+
)
|
125
|
+
|
126
|
+
License.new(
|
127
|
+
short_name: "MIT",
|
128
|
+
matcher: matcher
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
def mpl2
|
133
|
+
header_regexp = /Mozilla Public Licen[sc]e, version 2.0/
|
134
|
+
|
135
|
+
matcher = AnyMatcher.new(
|
136
|
+
Matcher.from_template(Template.named("MPL2")),
|
137
|
+
HeaderMatcher.new(Matcher.from_regex(header_regexp))
|
138
|
+
)
|
139
|
+
|
140
|
+
License.new(
|
141
|
+
short_name: "MPL-2.0",
|
142
|
+
matcher: matcher
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
def bsd_3_clause
|
147
|
+
substitution = [
|
148
|
+
"Neither the name of <organization> nor the names of <possessive> contributors may be used to endorse or promote products derived from this software without specific prior written permission.",
|
149
|
+
"The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission.",
|
150
|
+
]
|
151
|
+
|
152
|
+
template = Template.named("BSD-3-Clause")
|
153
|
+
alternate_content = template.content.gsub(*substitution)
|
154
|
+
|
155
|
+
alt_format_template = Template.named("BSD-3-Clause-alt-format")
|
156
|
+
alt_format_with_alt_content = alt_format_template.content.gsub(*substitution)
|
157
|
+
|
158
|
+
matcher = AnyMatcher.new(
|
159
|
+
Matcher.from_template(template),
|
160
|
+
Matcher.from_text(alternate_content),
|
161
|
+
Matcher.from_template(alt_format_template),
|
162
|
+
Matcher.from_text(alt_format_with_alt_content)
|
163
|
+
)
|
164
|
+
|
165
|
+
License.new(
|
166
|
+
short_name: "BSD-3-Clause",
|
167
|
+
matcher: matcher
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
def python
|
172
|
+
License.new(
|
173
|
+
short_name: "Python-2.0"
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
def ruby
|
178
|
+
url = "http://www.ruby-lang.org/en/LICENSE.txt"
|
179
|
+
|
180
|
+
matcher = AnyMatcher.new(
|
181
|
+
Matcher.from_template(Template.named("Ruby")),
|
182
|
+
Matcher.from_text(url)
|
183
|
+
)
|
184
|
+
|
185
|
+
License.new(
|
186
|
+
short_name: "Ruby",
|
187
|
+
matcher: matcher
|
188
|
+
)
|
189
|
+
end
|
190
|
+
|
191
|
+
def bsd_2_clause
|
192
|
+
matcher = AnyMatcher.new(
|
193
|
+
Matcher.from_template(Template.named("BSD-2-Clause")),
|
194
|
+
Matcher.from_template(Template.named("BSD-2-Clause-bullets"))
|
195
|
+
)
|
196
|
+
|
197
|
+
License.new(
|
198
|
+
short_name: "BSD-2-Clause",
|
199
|
+
matcher: matcher
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
def erlang_public
|
204
|
+
License.new(
|
205
|
+
short_name: "Erlang-Public",
|
206
|
+
matcher: Matcher.from_template(Template.named("EPLICENSE"))
|
207
|
+
)
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copied from https://github.com/pivotal/LicenseFinder
|
2
|
+
#
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012 Pivotal Labs
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
module LicenseScout
|
26
|
+
module LicenseFileAnalyzer
|
27
|
+
HeaderMatcher = Struct.new(:base_matcher) do
|
28
|
+
def matches_text?(text)
|
29
|
+
header = text.split("\n").first || ""
|
30
|
+
base_matcher.matches_text?(header)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copied from https://github.com/pivotal/LicenseFinder
|
2
|
+
#
|
3
|
+
# The MIT License
|
4
|
+
#
|
5
|
+
# Copyright (c) 2012 Pivotal Labs
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in
|
15
|
+
# all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
+
# THE SOFTWARE.
|
24
|
+
|
25
|
+
module LicenseScout
|
26
|
+
module LicenseFileAnalyzer
|
27
|
+
Matcher = Struct.new(:regexp) do
|
28
|
+
def self.from_template(template)
|
29
|
+
from_text(template.content)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.from_text(text)
|
33
|
+
from_regex(Text.compile_to_regex(text))
|
34
|
+
end
|
35
|
+
|
36
|
+
# an alias for Matcher.new, for uniformity of constructors
|
37
|
+
def self.from_regex(regexp)
|
38
|
+
new(regexp)
|
39
|
+
end
|
40
|
+
|
41
|
+
def matches_text?(text)
|
42
|
+
!!(Text.normalize_punctuation(text) =~ regexp)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|