licensee 9.11.0 → 9.12.0

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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/bin/licensee +1 -0
  3. data/lib/licensee.rb +4 -2
  4. data/lib/licensee/commands/detect.rb +2 -0
  5. data/lib/licensee/commands/diff.rb +5 -1
  6. data/lib/licensee/commands/license_path.rb +2 -0
  7. data/lib/licensee/commands/version.rb +2 -0
  8. data/lib/licensee/content_helper.rb +20 -10
  9. data/lib/licensee/hash_helper.rb +2 -0
  10. data/lib/licensee/license.rb +2 -0
  11. data/lib/licensee/license_field.rb +2 -0
  12. data/lib/licensee/license_meta.rb +2 -0
  13. data/lib/licensee/license_rules.rb +2 -0
  14. data/lib/licensee/matchers.rb +2 -0
  15. data/lib/licensee/matchers/cabal.rb +15 -1
  16. data/lib/licensee/matchers/cargo.rb +2 -0
  17. data/lib/licensee/matchers/copyright.rb +2 -0
  18. data/lib/licensee/matchers/cran.rb +2 -0
  19. data/lib/licensee/matchers/dice.rb +3 -1
  20. data/lib/licensee/matchers/dist_zilla.rb +2 -0
  21. data/lib/licensee/matchers/exact.rb +2 -0
  22. data/lib/licensee/matchers/gemspec.rb +2 -0
  23. data/lib/licensee/matchers/matcher.rb +2 -0
  24. data/lib/licensee/matchers/npm_bower.rb +2 -0
  25. data/lib/licensee/matchers/package.rb +2 -0
  26. data/lib/licensee/matchers/reference.rb +2 -0
  27. data/lib/licensee/matchers/spdx.rb +2 -0
  28. data/lib/licensee/project_files.rb +2 -0
  29. data/lib/licensee/project_files/license_file.rb +5 -3
  30. data/lib/licensee/project_files/package_manager_file.rb +2 -0
  31. data/lib/licensee/project_files/project_file.rb +11 -4
  32. data/lib/licensee/project_files/readme_file.rb +2 -0
  33. data/lib/licensee/projects.rb +2 -0
  34. data/lib/licensee/projects/fs_project.rb +2 -0
  35. data/lib/licensee/projects/git_project.rb +16 -8
  36. data/lib/licensee/projects/github_project.rb +2 -0
  37. data/lib/licensee/projects/project.rb +4 -2
  38. data/lib/licensee/rule.rb +2 -0
  39. data/lib/licensee/version.rb +3 -1
  40. data/spec/bin_spec.rb +2 -0
  41. data/spec/fixture_spec.rb +46 -0
  42. data/spec/fixtures/detect.json +6 -4
  43. data/spec/fixtures/fixtures.yml +110 -0
  44. data/spec/fixtures/html/license.html +262 -0
  45. data/spec/fixtures/license-hashes.json +30 -27
  46. data/spec/fixtures/mit-optional/LICENSE.txt +21 -0
  47. data/spec/integration_spec.rb +20 -0
  48. data/spec/licensee/commands/detect_spec.rb +5 -1
  49. data/spec/licensee/commands/license_path_spec.rb +2 -0
  50. data/spec/licensee/commands/version_spec.rb +2 -0
  51. data/spec/licensee/content_helper_spec.rb +22 -5
  52. data/spec/licensee/hash_helper_spec.rb +2 -0
  53. data/spec/licensee/license_field_spec.rb +2 -0
  54. data/spec/licensee/license_meta_spec.rb +2 -0
  55. data/spec/licensee/license_rules_spec.rb +2 -0
  56. data/spec/licensee/license_spec.rb +4 -2
  57. data/spec/licensee/matchers/cabal_matcher_spec.rb +93 -0
  58. data/spec/licensee/matchers/cargo_matcher_spec.rb +2 -0
  59. data/spec/licensee/matchers/copyright_matcher_spec.rb +4 -2
  60. data/spec/licensee/matchers/cran_matcher_spec.rb +2 -0
  61. data/spec/licensee/matchers/dice_matcher_spec.rb +2 -0
  62. data/spec/licensee/matchers/dist_zilla_matcher_spec.rb +2 -0
  63. data/spec/licensee/matchers/exact_matcher_spec.rb +2 -0
  64. data/spec/licensee/matchers/gemspec_matcher_spec.rb +2 -0
  65. data/spec/licensee/matchers/matcher_spec.rb +2 -0
  66. data/spec/licensee/matchers/npm_bower_matcher_spec.rb +2 -0
  67. data/spec/licensee/matchers/package_matcher_spec.rb +2 -0
  68. data/spec/licensee/matchers/reference_matcher_spec.rb +2 -0
  69. data/spec/licensee/matchers/spdx_matcher_spec.rb +2 -0
  70. data/spec/licensee/project_files/license_file_spec.rb +3 -1
  71. data/spec/licensee/project_files/package_info_spec.rb +2 -0
  72. data/spec/licensee/project_files/project_file_spec.rb +3 -0
  73. data/spec/licensee/project_files/readme_file_spec.rb +2 -0
  74. data/spec/licensee/project_spec.rb +2 -0
  75. data/spec/licensee/projects/git_project_spec.rb +23 -0
  76. data/spec/licensee/projects/github_project_spec.rb +2 -0
  77. data/spec/licensee/rule_spec.rb +2 -0
  78. data/spec/licensee_spec.rb +3 -1
  79. data/spec/spec_helper.rb +16 -3
  80. data/spec/vendored_license_spec.rb +9 -7
  81. data/vendor/choosealicense.com/_licenses/0bsd.txt +39 -0
  82. data/vendor/choosealicense.com/_licenses/afl-3.0.txt +7 -5
  83. data/vendor/choosealicense.com/_licenses/bsd-3-clause-clear.txt +1 -1
  84. data/vendor/choosealicense.com/_licenses/bsd-3-clause.txt +1 -1
  85. data/vendor/choosealicense.com/_licenses/cecill-2.1.txt +579 -0
  86. data/vendor/choosealicense.com/_licenses/epl-1.0.txt +1 -1
  87. data/vendor/choosealicense.com/_licenses/epl-2.0.txt +1 -1
  88. data/vendor/choosealicense.com/_licenses/odbl-1.0.txt +573 -0
  89. data/vendor/choosealicense.com/_licenses/osl-3.0.txt +1 -1
  90. data/vendor/choosealicense.com/_licenses/unlicense.txt +1 -1
  91. data/vendor/choosealicense.com/_licenses/upl-1.0.txt +3 -3
  92. metadata +40 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 613429f0350489c8dbdbdc80973d2557ad655efd2b89786096f290cf52632344
4
- data.tar.gz: 87fca6ceddb6972dd946720355e6efb2661793d671ff92ce8934e281affa6ad5
3
+ metadata.gz: d7dc009b0467cfb305e8dac051ed4e78d2f35d0454f2e14cef0952338540f8ae
4
+ data.tar.gz: 3c27bb3dd3cea6d62fab826b81fab93d9152893851b541c91d69406cdf9fcbd8
5
5
  SHA512:
6
- metadata.gz: 7bcb1c30bdebf4cad0a84ef7fd9dd4afe922ba8acac1a9124bdd96dc64d4ef736787f1b70c4ab0d01c3c05ba3547300caa3c882b2d99ea15117f72335f56b0a5
7
- data.tar.gz: bb2f30c4f70a4610f55a530c36b65852270558b8b36342b1fe8ad1113afa4dca711214545b3abbeb19cdba8d7e2d05643b0e138c8964a5b3f51106ce8c1bf3db
6
+ metadata.gz: 07f19b33f70b0b73611d34e474f2aa4e4d7f62c7451cdf70f76774beceac2c75ab3d1cc5048061a848b979a54032aad6dd1ba278c79cd798029efd6873d54425
7
+ data.tar.gz: 96c5e66f65307e7feb2c00b3f06661b093c60995d049f7fd19cc27b76881965a1d33768a16b0a3a3b085e9392ef828dce9cf692ee04255dd9ea2c6d22da38da6
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'dotenv/load'
4
5
  require 'thor'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'licensee/version'
2
4
  require 'forwardable'
3
5
  require 'pathname'
@@ -19,7 +21,7 @@ module Licensee
19
21
  CONFIDENCE_THRESHOLD = 98
20
22
 
21
23
  # Base domain from which to build license URLs
22
- DOMAIN = 'http://choosealicense.com'.freeze
24
+ DOMAIN = 'http://choosealicense.com'
23
25
 
24
26
  class << self
25
27
  attr_writer :confidence_threshold
@@ -49,7 +51,7 @@ module Licensee
49
51
  end
50
52
 
51
53
  # Inverse of the confidence threshold, represented as a float
52
- # By default this will be 0.05
54
+ # By default this will be 0.02
53
55
  def inverse_confidence_threshold
54
56
  @inverse_confidence_threshold ||=
55
57
  (1 - Licensee.confidence_threshold / 100.0).round(2)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class LicenseeCLI < Thor
2
4
  # Methods to call when displaying information about ProjectFiles
3
5
  MATCHED_FILE_METHODS = %i[
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'tmpdir'
2
4
 
3
5
  class LicenseeCLI < Thor
@@ -47,7 +49,9 @@ class LicenseeCLI < Thor
47
49
  end
48
50
 
49
51
  def expected_license
50
- @expected_license ||= Licensee::License.find options[:license] if options[:license]
52
+ if options[:license]
53
+ @expected_license ||= Licensee::License.find options[:license]
54
+ end
51
55
  return @expected_license if @expected_license
52
56
 
53
57
  if options[:license]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class LicenseeCLI < Thor
2
4
  desc 'license-path [PATH]', "Returns the path to the given project's license file"
3
5
  def license_path(_path)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class LicenseeCLI < Thor
2
4
  desc 'version', 'Return the Licensee version'
3
5
  def version
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
  require 'digest'
3
5
 
@@ -22,7 +24,8 @@ module Licensee
22
24
  bullet: /\n\n\s*(?:[*-]|\(?[\da-z]{1,2}[)\.])\s+/i,
23
25
  developed_by: /#{START_REGEX}developed by:.*?\n\n/im,
24
26
  quote_begin: /[`'"‘“]/,
25
- quote_end: /[`'"’”]/
27
+ quote_end: /[`'"’”]/,
28
+ mit_optional: /\(including the next paragraph\)/i
26
29
  }.freeze
27
30
  NORMALIZATIONS = {
28
31
  lists: { from: /^\s*(?:\d\.|\*)\s+([^\n])/, to: '- \1' },
@@ -85,13 +88,12 @@ module Licensee
85
88
  hrs markdown_headings borders title version url copyright
86
89
  block_markup span_markup link_markup
87
90
  all_rights_reserved developed_by end_of_terms whitespace
91
+ mit_optional
88
92
  ].freeze
89
93
 
90
94
  # A set of each word in the license, without duplicates
91
95
  def wordset
92
- @wordset ||= if content_normalized
93
- content_normalized.scan(/(?:\w(?:'s|(?<=s)')?)+/).to_set
94
- end
96
+ @wordset ||= content_normalized&.scan(/(?:\w(?:'s|(?<=s)')?)+/)&.to_set
95
97
  end
96
98
 
97
99
  # Number of characteres in the normalized content
@@ -115,8 +117,10 @@ module Licensee
115
117
  # Given another license or project file, calculates the similarity
116
118
  # as a percentage of words in common
117
119
  def similarity(other)
118
- overlap = (wordset & other.wordset).size
119
- total = wordset.size + other.wordset.size
120
+ wordset_fieldless = wordset - LicenseField.keys
121
+ fields_removed = wordset.size - wordset_fieldless.size
122
+ overlap = (wordset_fieldless & other.wordset).size
123
+ total = wordset_fieldless.size + other.wordset.size - fields_removed
120
124
  100.0 * (overlap * 2.0 / total)
121
125
  end
122
126
 
@@ -132,7 +136,7 @@ module Licensee
132
136
  def content_without_title_and_version
133
137
  @content_without_title_and_version ||= begin
134
138
  @_content = nil
135
- ops = %i[hrs comments markdown_headings title version]
139
+ ops = %i[html hrs comments markdown_headings title version]
136
140
  ops.each { |op| strip(op) }
137
141
  _content
138
142
  end
@@ -183,7 +187,7 @@ module Licensee
183
187
  end
184
188
 
185
189
  def self.format_percent(float)
186
- "#{format('%.2f', float)}%"
190
+ "#{format('%<float>.2f', float: float)}%"
187
191
  end
188
192
 
189
193
  def self.title_regex
@@ -206,11 +210,9 @@ module Licensee
206
210
 
207
211
  private
208
212
 
209
- # rubocop:disable Naming/MemoizedInstanceVariableName
210
213
  def _content
211
214
  @_content ||= content.to_s.dup.strip
212
215
  end
213
- # rubocop:enable Naming/MemoizedInstanceVariableName
214
216
 
215
217
  def strip(regex_or_sym)
216
218
  return unless _content
@@ -265,6 +267,14 @@ module Licensee
265
267
  normalize(REGEXES[:link_markup], '\1')
266
268
  end
267
269
 
270
+ def strip_html
271
+ return unless respond_to?(:filename) && filename
272
+ return unless File.extname(filename) =~ /\.html?/i
273
+
274
+ require 'reverse_markdown'
275
+ @_content = ReverseMarkdown.convert(_content, unknown_tags: :bypass)
276
+ end
277
+
268
278
  def normalize(from_or_key, to = nil)
269
279
  operation = { from: from_or_key, to: to } if to
270
280
  operation ||= NORMALIZATIONS[from_or_key]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module HashHelper
3
5
  def to_h
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  module Licensee
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  class LicenseField < Struct.new(:name, :description)
3
5
  class << self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  class LicenseMeta < Struct.new(
3
5
  :title, :spdx_id, :source, :description, :how, :conditions, :permissions,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  # Exposes #conditions, #permissions, and #limitation arrays of LicenseRules
3
5
  class LicenseRules < Struct.new(:conditions, :permissions, :limitations)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  autoload :Matcher, 'licensee/matchers/matcher'
@@ -1,15 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Cabal < Licensee::Matchers::Package
4
6
  # While we could parse the cabal file, prefer
5
7
  # a lenient regex for speed and security. Moar parsing moar problems.
6
8
  LICENSE_REGEX = /^\s*license\s*\:\s*([a-z\-0-9\.]+)\s*$/ix.freeze
9
+ LICENSE_CONVERSIONS = {
10
+ 'GPL-2' => 'GPL-2.0',
11
+ 'GPL-3' => 'GPL-3.0',
12
+ 'LGPL-3' => 'LGPL-3.0',
13
+ 'AGPL-3' => 'AGPL-3.0',
14
+ 'BSD2' => 'BSD-2-Clause',
15
+ 'BSD3' => 'BSD-3-Clause'
16
+ }.freeze
7
17
 
8
18
  private
9
19
 
10
20
  def license_property
11
21
  match = @file.content.match LICENSE_REGEX
12
- match[1].downcase if match && match[1]
22
+ spdx_name(match[1]).downcase if match && match[1]
23
+ end
24
+
25
+ def spdx_name(cabal_name)
26
+ LICENSE_CONVERSIONS[cabal_name] || cabal_name
13
27
  end
14
28
  end
15
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Cargo < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Copyright < Licensee::Matchers::Matcher
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Cran < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Dice < Licensee::Matchers::Matcher
@@ -49,7 +51,7 @@ module Licensee
49
51
 
50
52
  # Confidence that the matched license is a match
51
53
  def confidence
52
- @confidence ||= match ? file.similarity(match) : 0
54
+ @confidence ||= match ? match.similarity(file) : 0
53
55
  end
54
56
 
55
57
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class DistZilla < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Exact < Licensee::Matchers::Matcher
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Gemspec < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Matcher
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class NpmBower < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Package < Licensee::Matchers::Matcher
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  # Matches README files that include a license by reference
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Matchers
3
5
  class Spdx < Licensee::Matchers::Package
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module ProjectFiles
3
5
  autoload :ProjectFile, 'licensee/project_files/project_file'
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module ProjectFiles
3
5
  class LicenseFile < Licensee::ProjectFiles::ProjectFile
4
6
  include Licensee::ContentHelper
5
7
 
6
8
  # List of extensions to give preference to
7
- PREFERRED_EXT = %w[md markdown txt].freeze
9
+ PREFERRED_EXT = %w[md markdown txt html].freeze
8
10
  PREFERRED_EXT_REGEX = /\.#{Regexp.union(PREFERRED_EXT)}\z/.freeze
9
11
 
10
12
  # Regex to match any extension except .spdx or .header
@@ -72,11 +74,11 @@ module Licensee
72
74
  end
73
75
 
74
76
  def gpl?
75
- license && license.gpl?
77
+ license&.gpl?
76
78
  end
77
79
 
78
80
  def license
79
- if matcher && matcher.match
81
+ if matcher&.match
80
82
  matcher.match
81
83
  else
82
84
  License.find('other')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module ProjectFiles
3
5
  class PackageManagerFile < Licensee::ProjectFiles::ProjectFile
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A project file is a file within a project that contains license information
2
4
  # Currently extended by LicenseFile, PackageManagerFile, and ReadmeFile
3
5
  #
@@ -13,6 +15,7 @@ module Licensee
13
15
  include Licensee::HashHelper
14
16
  HASH_METHODS = %i[
15
17
  filename content content_hash content_normalized matcher matched_license
18
+ attribution
16
19
  ].freeze
17
20
 
18
21
  ENCODING = Encoding::UTF_8
@@ -32,7 +35,7 @@ module Licensee
32
35
  #
33
36
  # Returns a new Licensee::ProjectFile
34
37
  def initialize(content, metadata = {})
35
- @content = content
38
+ @content = content.dup
36
39
  @content.force_encoding(ENCODING)
37
40
  unless @content.valid_encoding?
38
41
  @content.encode!(ENCODING, ENCODING_OPTIONS)
@@ -70,17 +73,17 @@ module Licensee
70
73
 
71
74
  # Returns the percent confident with the match
72
75
  def confidence
73
- matcher && matcher.confidence
76
+ matcher&.confidence
74
77
  end
75
78
 
76
79
  def license
77
- matcher && matcher.match
80
+ matcher&.match
78
81
  end
79
82
 
80
83
  alias match license
81
84
 
82
85
  def matched_license
83
- license.spdx_id if license
86
+ license&.spdx_id
84
87
  end
85
88
 
86
89
  # Is this file a COPYRIGHT file with only a copyright statement?
@@ -99,6 +102,10 @@ module Licensee
99
102
  def content_normalized
100
103
  nil
101
104
  end
105
+
106
+ def attribution
107
+ nil
108
+ end
102
109
  end
103
110
  end
104
111
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module ProjectFiles
3
5
  class ReadmeFile < Licensee::ProjectFiles::LicenseFile
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Licensee
2
4
  module Projects
3
5
  autoload :Project, 'licensee/projects/project'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Filesystem-based project
2
4
  #
3
5
  # Analyze a folder on the filesystem for license information