licensee 8.5.0 → 8.6.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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -104
  3. data/bin/licensee +26 -12
  4. data/lib/licensee.rb +1 -0
  5. data/lib/licensee/license.rb +6 -2
  6. data/lib/licensee/matchers/copyright_matcher.rb +2 -0
  7. data/lib/licensee/matchers/cran_matcher.rb +20 -0
  8. data/lib/licensee/matchers/exact_matcher.rb +2 -0
  9. data/lib/licensee/project.rb +2 -1
  10. data/lib/licensee/project_file.rb +8 -2
  11. data/lib/licensee/project_files/license_file.rb +27 -6
  12. data/lib/licensee/project_files/package_info.rb +6 -1
  13. data/lib/licensee/project_files/readme.rb +2 -2
  14. data/lib/licensee/projects/fs_project.rb +0 -1
  15. data/lib/licensee/version.rb +1 -1
  16. data/spec/bin_spec.rb +56 -0
  17. data/spec/fixtures/case-sensitive/LiCeNsE.TxT +0 -0
  18. data/spec/fixtures/gemspec/project.gemspec +1 -0
  19. data/spec/fixtures/lgpl/COPYING.lesser +165 -0
  20. data/spec/fixtures/lgpl/LICENSE +674 -0
  21. data/spec/fixtures/license-folder/README.md +0 -0
  22. data/{test/fixtures/mit-without-title/mit.txt → spec/fixtures/mit/LICENSE.txt} +3 -1
  23. data/{test/fixtures/mit-with-redundant-title/mit.txt → spec/fixtures/mit/README.md} +4 -2
  24. data/spec/fixtures/mpl-without-hrs/LICENSE +362 -0
  25. data/spec/fixtures/readme/README.md +23 -0
  26. data/spec/integration_spec.rb +121 -0
  27. data/spec/licensee/content_helper_spec.rb +77 -0
  28. data/spec/licensee/license_spec.rb +224 -0
  29. data/spec/licensee/matchers/copyright_matcher_spec.rb +47 -0
  30. data/spec/licensee/matchers/cran_matcher_spec.rb +18 -0
  31. data/spec/licensee/matchers/dice_matcher_spec.rb +43 -0
  32. data/spec/licensee/matchers/exact_matcher_spec.rb +26 -0
  33. data/spec/licensee/matchers/gemspec_matcher_spec.rb +29 -0
  34. data/spec/licensee/matchers/npm_bower_matcher_spec.rb +31 -0
  35. data/spec/licensee/matchers/package_matcher_spec.rb +15 -0
  36. data/spec/licensee/project_files/license_file_spec.rb +122 -0
  37. data/spec/licensee/project_files/package_info_spec.rb +51 -0
  38. data/spec/licensee/project_files/readme_spec.rb +77 -0
  39. data/spec/licensee/project_spec.rb +91 -0
  40. data/spec/licensee_spec.rb +41 -0
  41. data/spec/project_file_spec.rb +33 -0
  42. data/spec/spec_helper.rb +78 -0
  43. data/spec/vendored_license_spec.rb +75 -0
  44. data/vendor/choosealicense.com/_licenses/bsl-1.0.txt +48 -0
  45. data/vendor/choosealicense.com/_licenses/lgpl-3.0.txt +1 -1
  46. metadata +39 -111
  47. data/Rakefile +0 -12
  48. data/test/fixtures/apache-2.0/LICENSE +0 -201
  49. data/test/fixtures/bower-with-readme/README.md +0 -1
  50. data/test/fixtures/bower-with-readme/bower.json +0 -3
  51. data/test/fixtures/bower/bower.json +0 -3
  52. data/test/fixtures/bsd-2-clause-without-title/bsd-2-clause.txt +0 -23
  53. data/test/fixtures/bsd-3-clause-without-title/bsd-3-clause.txt +0 -27
  54. data/test/fixtures/case-sensitive.git/HEAD +0 -1
  55. data/test/fixtures/case-sensitive.git/config +0 -6
  56. data/test/fixtures/case-sensitive.git/objects/01/7b4f1eebd1dcb735e950b1d01093e3e2bf85e9 +0 -0
  57. data/test/fixtures/case-sensitive.git/objects/2c/b878e0851c5cf53d7455d9018baa6755a38bd7 +0 -0
  58. data/test/fixtures/case-sensitive.git/objects/fb/ddf40ba5f30225af7cd9841afe374ca5800cb9 +0 -0
  59. data/test/fixtures/case-sensitive.git/refs/heads/master +0 -1
  60. data/test/fixtures/isc-without-title/isc.txt +0 -13
  61. data/test/fixtures/lgpl.git/HEAD +0 -1
  62. data/test/fixtures/lgpl.git/config +0 -5
  63. data/test/fixtures/lgpl.git/objects/1a/cd060ebbbeac294200008657d9502130f93465 +0 -2
  64. data/test/fixtures/lgpl.git/objects/4b/1f98c1e95b6d4dae0b0a160f554be97e5afece +0 -2
  65. data/test/fixtures/lgpl.git/objects/a4/cfa42bc8e1d432fa851c5c4e3f294f01e05fd3 +0 -0
  66. data/test/fixtures/lgpl.git/objects/b7/de6e186bd02935030f5d42867ea7043fb1c27c +0 -0
  67. data/test/fixtures/lgpl.git/objects/dd/d0e017b1bf39218a6ea4f2fadd29a7ea8ebe03 +0 -0
  68. data/test/fixtures/lgpl.git/objects/eb/d853e83a2d317422c52f3922f4c9c5bb4a10b7 +0 -0
  69. data/test/fixtures/lgpl.git/refs/heads/master +0 -1
  70. data/test/fixtures/licence.git/HEAD +0 -1
  71. data/test/fixtures/licence.git/config +0 -6
  72. data/test/fixtures/licence.git/objects/66/0c086dc25f9f3b96e7afd9dee8a11b4e614543 +0 -0
  73. data/test/fixtures/licence.git/objects/68/804815597f79aa323de3257a8fd7b76449943c +0 -0
  74. data/test/fixtures/licence.git/objects/dd/59aed84c5aa4dff7ceda11a1c045f831194067 +0 -0
  75. data/test/fixtures/licence.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  76. data/test/fixtures/licence.git/refs/heads/master +0 -1
  77. data/test/fixtures/license-folder.git/HEAD +0 -1
  78. data/test/fixtures/license-folder.git/config +0 -6
  79. data/test/fixtures/license-folder.git/objects/32/6d0761f0c54d54327ea9e127e02d9bae14d2c8 +0 -2
  80. data/test/fixtures/license-folder.git/objects/93/109217bbe2937fc3a8d8933fddd80ed6292481 +0 -0
  81. data/test/fixtures/license-folder.git/objects/c6/6e45436e4f3fda934dc7268bccbc59c37a67b4 +0 -0
  82. data/test/fixtures/license-folder.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  83. data/test/fixtures/license-folder.git/refs/heads/master +0 -1
  84. data/test/fixtures/licenses.git/HEAD +0 -1
  85. data/test/fixtures/licenses.git/config +0 -4
  86. data/test/fixtures/licenses.git/objects/51/a11d50f29a14774ded8f7b90ba9938dce78a92 +0 -3
  87. data/test/fixtures/licenses.git/objects/5e/df454e6517673d5e64a33cf284308b9c6b1075 +0 -0
  88. data/test/fixtures/licenses.git/objects/e1/b4dc13f4bf683ce8f2943e051c3e91e778d043 +0 -0
  89. data/test/fixtures/licenses.git/objects/info/packs +0 -2
  90. data/test/fixtures/licenses.git/objects/pack/pack-4a7088171ae3ca900f010a4be6f1c2c96490c338.idx +0 -0
  91. data/test/fixtures/licenses.git/objects/pack/pack-4a7088171ae3ca900f010a4be6f1c2c96490c338.pack +0 -0
  92. data/test/fixtures/licenses.git/packed-refs +0 -4
  93. data/test/fixtures/licenses.git/refs/heads/master +0 -1
  94. data/test/fixtures/mit-without-title-rewrapped/mit.txt +0 -19
  95. data/test/fixtures/mpl-without-hrs.git/HEAD +0 -1
  96. data/test/fixtures/mpl-without-hrs.git/config +0 -5
  97. data/test/fixtures/mpl-without-hrs.git/objects/45/26aa2d1d78ea20fb0faf59f2360a68fa897774 +0 -0
  98. data/test/fixtures/mpl-without-hrs.git/objects/ba/f5649b61fac4ed64ec2949fe5cd616b85a8298 +0 -0
  99. data/test/fixtures/mpl-without-hrs.git/objects/be/2cc4dfb609fb6c38f6365ec345bded3350dd63 +0 -0
  100. data/test/fixtures/mpl-without-hrs.git/refs/heads/master +0 -1
  101. data/test/fixtures/named-license-file-prefix.git/HEAD +0 -1
  102. data/test/fixtures/named-license-file-prefix.git/config +0 -6
  103. data/test/fixtures/named-license-file-prefix.git/objects/64/3983d3f82ecc2a7d8e4227946220ebffd477d2 +0 -4
  104. data/test/fixtures/named-license-file-prefix.git/objects/c9/b229e500e529fdbd4f50746ba207e91d0677b6 +0 -7
  105. data/test/fixtures/named-license-file-prefix.git/objects/d1/9223f355283b3ce0c51a2c527f685d0f403157 +0 -0
  106. data/test/fixtures/named-license-file-prefix.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  107. data/test/fixtures/named-license-file-prefix.git/refs/heads/master +0 -1
  108. data/test/fixtures/named-license-file-suffix.git/HEAD +0 -1
  109. data/test/fixtures/named-license-file-suffix.git/config +0 -6
  110. data/test/fixtures/named-license-file-suffix.git/objects/36/465372136f81a2089f486298ca77ef41611198 +0 -0
  111. data/test/fixtures/named-license-file-suffix.git/objects/4a/2a139e7fbd24eef5c5ef3d22f490e89405f6a3 +0 -3
  112. data/test/fixtures/named-license-file-suffix.git/objects/c9/b229e500e529fdbd4f50746ba207e91d0677b6 +0 -7
  113. data/test/fixtures/named-license-file-suffix.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  114. data/test/fixtures/named-license-file-suffix.git/refs/heads/master +0 -1
  115. data/test/fixtures/no-license.git/HEAD +0 -1
  116. data/test/fixtures/no-license.git/config +0 -6
  117. data/test/fixtures/no-license.git/objects/82/0c999cf27a6f71431646c404274c578f7a2869 +0 -0
  118. data/test/fixtures/no-license.git/objects/e1/d9b2a3d41c2ea74a520e66da2b5c63b2f6202f +0 -0
  119. data/test/fixtures/no-license.git/objects/ff/1592f44259635df9feda5e02853964b26f9e4d +0 -0
  120. data/test/fixtures/no-license.git/refs/heads/master +0 -1
  121. data/test/fixtures/npm-non-spdx/package.json +0 -3
  122. data/test/fixtures/npm.git/HEAD +0 -1
  123. data/test/fixtures/npm.git/config +0 -4
  124. data/test/fixtures/npm.git/objects/info/packs +0 -2
  125. data/test/fixtures/npm.git/objects/pack/pack-03c0879445cabcc37f91d97c7955465adef26f4a.idx +0 -0
  126. data/test/fixtures/npm.git/objects/pack/pack-03c0879445cabcc37f91d97c7955465adef26f4a.pack +0 -0
  127. data/test/fixtures/npm.git/packed-refs +0 -2
  128. data/test/fixtures/npm/package.json +0 -3
  129. data/test/functions.rb +0 -73
  130. data/test/helper.rb +0 -16
  131. data/test/licensee/matchers/test_copyright_matcher.rb +0 -59
  132. data/test/licensee/matchers/test_dice_matcher.rb +0 -60
  133. data/test/licensee/matchers/test_exact_matcher.rb +0 -25
  134. data/test/licensee/matchers/test_gemspec_matcher.rb +0 -11
  135. data/test/licensee/matchers/test_npm_bower_matcher.rb +0 -27
  136. data/test/licensee/matchers/test_package_matcher.rb +0 -27
  137. data/test/licensee/project_files/test_license_file.rb +0 -73
  138. data/test/licensee/project_files/test_package_info.rb +0 -19
  139. data/test/licensee/project_files/test_readme.rb +0 -47
  140. data/test/licensee/test_content_helper.rb +0 -81
  141. data/test/licensee/test_license.rb +0 -182
  142. data/test/licensee/test_project.rb +0 -134
  143. data/test/licensee/test_project_file.rb +0 -24
  144. data/test/test_licensee.rb +0 -40
  145. data/test/test_licensee_bin.rb +0 -37
  146. data/test/test_licensee_vendor.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '09da33c25905df581cb047d1eed3c138ede5f440'
4
- data.tar.gz: c0d34f622f3f6dde90f32c859b221b6b4af02bce
3
+ metadata.gz: a09cefedc079e0510fbdae2de030984fc477a60b
4
+ data.tar.gz: 1648fed5fcbab4086f7f2d992ee9fea4b03fbe01
5
5
  SHA512:
6
- metadata.gz: 0c253e00b53aa258a70e80fad5a94454ff9ae080d9911f20e999e09eba9db14b306052dbf04b0e66de8ae2256ee87d81b4d458e4fa5317bd84e129bfe5ef2084
7
- data.tar.gz: 7d0e97bbc08a7d687b6011690e8d346d76f97a6c1d9ac5ee2cede3400771c480c05950e904f5f632d01ff0bed0e699233cb3961f8e79f75ed4a91b7265fbac2c
6
+ metadata.gz: 64bb0bb0ccbe7bb4df9d043182ab3b2a598544b2c42212b2489d448b821d170ce7c48aaf9213a56c407f72e061d81710be4b07b7de9efffd226e8940e4c98fd2
7
+ data.tar.gz: 42f5c17fdb81239632a12e41df5c4e66cb8b29600eb23a3674a75f9b51a0aec3961a400edff62430bea76ebd400deac50e344ca59ba7856504d52bc30b58cc50
data/README.md CHANGED
@@ -1,24 +1,38 @@
1
1
  # Licensee
2
- _A Ruby Gem to detect under what license a project is distributed._
3
2
 
4
- [![Build Status](https://travis-ci.org/benbalter/licensee.svg?branch=master)](https://travis-ci.org/benbalter/licensee) [![Gem Version](https://badge.fury.io/rb/licensee.svg)](http://badge.fury.io/rb/licensee)
3
+ *A Ruby Gem to detect under what license a project is distributed.*
4
+
5
+ [![Build Status](https://travis-ci.org/benbalter/licensee.svg?branch=master)](https://travis-ci.org/benbalter/licensee) [![Gem Version](https://badge.fury.io/rb/licensee.svg)](http://badge.fury.io/rb/licensee) [![Coverage Status](https://coveralls.io/repos/github/benbalter/licensee/badge.svg?branch=rspec)](https://coveralls.io/github/benbalter/licensee?branch=rspec)
5
6
 
6
7
  ## The problem
7
- - You've got an open source project. How do you know what you can and can't do with the software?
8
- - You've got a bunch of open source projects, how do you know what their licenses are?
9
- - You've got a project with a license file, but which license is it? Has it been modified?
8
+
9
+ * You've got an open source project. How do you know what you can and can't do with the software?
10
+ * You've got a bunch of open source projects, how do you know what their licenses are?
11
+ * You've got a project with a license file, but which license is it? Has it been modified?
10
12
 
11
13
  ## The solution
14
+
12
15
  Licensee automates the process of reading `LICENSE` files and compares their contents to known licenses using a several strategies (which we call "Matchers"). It attempts to determine a project's license in the following order:
13
- - If the license file has an explicit copyright notice, and nothing more (e.g., `Copyright (c) 2015 Ben Balter`), we'll assume the author intends to retain all rights, and thus the project isn't licensed.
14
- - If the license is an exact match to a known license. If we strip away whitespace and copyright notice, we might get lucky, and direct string comparison in Ruby is cheap.
15
- - If we still can't match the license, we use a fancy math thing called the [Sørensen–Dice coefficient](https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient), which is really good at calculating the similarity between two strings. By calculating the percent changed from the known license to the license file, you can tell, e.g., that a given license is 90% similar to the MIT license, that 10% likely representing the copyright line being properly adapted to the project.
16
16
 
17
- _Special thanks to [@vmg](https://github.com/vmg) for his Git and algorithmic prowess._
17
+ * If the license file has an explicit copyright notice, and nothing more (e.g., `Copyright (c) 2015 Ben Balter`), we'll assume the author intends to retain all rights, and thus the project isn't licensed.
18
+ * If the license is an exact match to a known license. If we strip away whitespace and copyright notice, we might get lucky, and direct string comparison in Ruby is cheap.
19
+ * If we still can't match the license, we use a fancy math thing called the [Sørensen–Dice coefficient](https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient), which is really good at calculating the similarity between two strings. By calculating the percent changed from the known license to the license file, you can tell, e.g., that a given license is 95% similar to the MIT license, that 5% likely representing legally insignificant changes to the license text.
20
+
21
+ *Special thanks to [@vmg](https://github.com/vmg) for his Git and algorithmic prowess.*
18
22
 
19
23
  ## Installation
24
+
20
25
  `gem install licensee` or add `gem 'licensee'` to your project's `Gemfile`.
21
26
 
27
+ ## Documentation
28
+
29
+ See [the docs folder](/docs) for more information. You may be interested in:
30
+
31
+ * [Contributing to Licensee](CONTRIBUTING.md) (and development instructions)
32
+ * [Customizing Licensee's behavior](docs/customizing.md)
33
+ * [Instructions for using Licensee](docs/usage.md)
34
+ * More information about [what Licensee looks at](docs/what-we-look-at.md) (or doesn't, and why)
35
+
22
36
  ## Semantic Versioning
23
37
 
24
38
  This project conforms to [semver](http://semver.org/). As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/) with two digits of precision. For example:
@@ -28,98 +42,3 @@ spec.add_dependency 'licensee', '~> 1.0'
28
42
  This means your project is compatible with licensee 1.0 up until 2.0. You can also set a higher minimum version:
29
43
 
30
44
  spec.add_dependency 'licensee', '~> 1.1'
31
-
32
- ## Command line usage
33
- 1. `cd` into a project directory
34
- 2. execute the `licensee` command
35
-
36
- You'll get an output that looks like:
37
-
38
- ```
39
- License: MIT
40
- Confidence: 98.42%
41
- Matcher: Licensee::GitMatcher
42
- ```
43
-
44
- Alternately, `licensee <directory>` will treat the argument as the project directory, and `licensee <file>` will attempt to match the individual file specified, both with output that looks like the above.
45
-
46
- ## License API
47
-
48
- ```ruby
49
- license = Licensee.license "/path/to/a/project"
50
- => #<Licensee::License name="MIT" match=0.9842154131847726>
51
-
52
- license.key
53
- => "mit"
54
-
55
- license.name
56
- => "MIT License"
57
-
58
- license.meta["source"]
59
- => "http://opensource.org/licenses/MIT"
60
-
61
- license.meta["description"]
62
- => "A permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty."
63
-
64
- license.meta["permissions"]
65
- => ["commercial-use","modifications","distribution","private-use"]
66
- ```
67
-
68
- ## More API
69
- You can gather more information by working with the project object, and the top level Licensee class.
70
-
71
- ```ruby
72
- Licensee::VERSION # The Licensee version
73
- Licensee.licenses # All the licenses Licensee knows about
74
-
75
- project=Licensee.project "/path/to/a/project" # Get a Project (Git checkout or just local Filesystem) (post 6.0.0)
76
-
77
- project.license # The matched license
78
- project.matched_file # Object for the particular file containing the apparent license
79
- project.matched_file.filename # Its filename
80
- project.matched_file.confidence # The confidence level in the license matching
81
- project.matched_file.content # The content of your license file
82
- project.license.content # The Open Source License text it matched against
83
- ```
84
-
85
- ## What it looks at
86
- - `LICENSE`, `LICENSE.txt`, `COPYING`, etc. files in the root of the project, comparing the body to known licenses
87
- - Crowdsourced license content and metadata from [`choosealicense.com`](http://choosealicense.com)
88
-
89
- ## What it doesn't look at
90
- - Dependency licensing
91
- - References to licenses in `README`, `README.md`, etc.
92
- - Every single possible license (just the most popular ones)
93
- - Compliance (e.g., whitelisting certain licenses)
94
-
95
- If you're looking for dependency license checking and compliance, take a look at [LicenseFinder](https://github.com/pivotal/LicenseFinder).
96
-
97
- ## Huh? Why don't you look at X?
98
- Because reasons.
99
-
100
- ### Why not just look at the "license" field of [insert package manager here]?
101
- Because it's not legally binding. A license is a legal contract. You give up certain rights (e.g., the right to sue the author) in exchange for the right to use the software.
102
-
103
- Most popular licenses today _require_ that the license itself be distributed along side the software. Simply putting the letters "MIT" or "GPL" in a configuration file doesn't really meet that requirement.
104
-
105
- Not to mention, it doesn't tell you much about your rights as a user. Is it GPLv2? GPLv2 or later? Those files are designed to be read by computers (who can't enter into contracts), not humans (who can). It's great metadata, but that's about it.
106
-
107
- ### What about looking to see if the author said something in the readme?
108
- You could make an argument that, when linked or sufficiently identified, the terms of the license are incorporated by reference, or at least that the author's intent is there. There's a handful of reasons why this isn't ideal. For one, if you're using the MIT or BSD (ISC) license, along with a few others, there's templematic language, like the copyright notice, which would go unfilled.
109
-
110
- ### What about checking every single file for a copyright header?
111
- Because that's silly in the context of how software is developed today. You wouldn't put a copyright notice on each page of a book. Besides, it's a lot of work, as there's no standardized, cross-platform way to describe a project's license within a comment.
112
-
113
- Checking the actual text into version control is definitive, so that's what this project looks at.
114
-
115
- ## Bootstrapping a local development environment
116
- `script/bootstrap`
117
-
118
- ## Running tests
119
- `script/cibuild`
120
-
121
- ## Updating the licenses
122
- License data is pulled from `choosealicense.com`. To update the license data, simple run `script/vendor-licenses`.
123
-
124
- ## Roadmap
125
- See [proposed enhancements](https://github.com/benbalter/licensee/labels/enhancement).
@@ -14,23 +14,37 @@ matched_file = project.matched_file
14
14
 
15
15
  if license_file
16
16
  puts "License file: #{license_file.filename}"
17
+ puts "License hash: #{license_file.hash}"
17
18
  puts "Attribution: #{license_file.attribution}" if license_file.attribution
18
19
  end
19
20
 
20
- if matched_file
21
- if matched_file.license
22
- puts "License: #{matched_file.license.meta['title']}"
23
- puts "Confidence: #{format_percent(matched_file.confidence)}" if matched_file.confidence
24
- puts "Method: #{matched_file.matcher.class}" if matched_file.matcher
25
- else
26
- puts 'License: Not detected'
21
+ unless matched_file
22
+ puts 'License: Not detected'
23
+ exit 1
24
+ end
25
+
26
+ if matched_file.license
27
+ puts "License: #{matched_file.license.meta['title']}"
28
+
29
+ if matched_file.confidence
30
+ puts "Confidence: #{format_percent(matched_file.confidence)}"
31
+ end
32
+
33
+ puts "Method: #{matched_file.matcher.class}" if matched_file.matcher
34
+ exit 0
35
+ end
36
+
37
+ if matched_file.is_a?(Licensee::Project::LicenseFile)
38
+ matcher = Licensee::Matchers::Dice.new(matched_file)
39
+ licenses = matcher.licenses_by_similiarity
40
+ unless licenses.empty?
27
41
  puts
28
42
  puts "Here's the closest licenses:"
29
- matcher = Licensee::Matchers::Dice.new(matched_file)
30
- matcher.licenses_by_similiarity[0...3].each do |license, similarity|
31
- puts "* #{license.meta['spdx-id']} similarity: #{format_percent(similarity)}"
43
+ licenses[0...3].each do |license, similarity|
44
+ spdx_id = license.meta['spdx-id']
45
+ puts "* #{spdx_id} similarity: #{format_percent(similarity)}"
32
46
  end
33
47
  end
34
- else
35
- puts 'Unknown'
36
48
  end
49
+
50
+ exit 1
@@ -20,6 +20,7 @@ require_relative 'licensee/matchers/dice_matcher'
20
20
  require_relative 'licensee/matchers/package_matcher'
21
21
  require_relative 'licensee/matchers/gemspec_matcher'
22
22
  require_relative 'licensee/matchers/npm_bower_matcher'
23
+ require_relative 'licensee/matchers/cran_matcher'
23
24
 
24
25
  module Licensee
25
26
  # Over which percent is a match considered a match by default
@@ -131,12 +131,16 @@ module Licensee
131
131
  !other.nil? && key == other.key
132
132
  end
133
133
 
134
- private
135
-
136
134
  def pseudo_license?
137
135
  PSEUDO_LICENSES.include?(key)
138
136
  end
139
137
 
138
+ def inspect
139
+ "#<Licensee::License key=#{key}>"
140
+ end
141
+
142
+ private
143
+
140
144
  # Raw content of license file, including YAML front matter
141
145
  def raw_content
142
146
  return if pseudo_license?
@@ -2,6 +2,8 @@
2
2
  module Licensee
3
3
  module Matchers
4
4
  class Copyright
5
+ attr_reader :file
6
+
5
7
  # rubocop:disable Metrics/LineLength
6
8
  REGEX = /\s*(Copyright|\(c\)) (©|\(c\)|\xC2\xA9)? ?(\d{4}|\[year\])(.*)?\s*/i
7
9
 
@@ -0,0 +1,20 @@
1
+ module Licensee
2
+ module Matchers
3
+ class Cran < Package
4
+ attr_reader :file
5
+
6
+ # While we could parse the package.json or bower.json file, prefer
7
+ # a lenient regex for speed and security. Moar parsing moar problems.
8
+ LICENSE_REGEX = /
9
+ ^license:\s*([a-z\-0-9\.]+)
10
+ /ix
11
+
12
+ private
13
+
14
+ def license_property
15
+ match = @file.content.match LICENSE_REGEX
16
+ match[1].downcase if match && match[1]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,6 +1,8 @@
1
1
  module Licensee
2
2
  module Matchers
3
3
  class Exact
4
+ attr_reader :file
5
+
4
6
  def initialize(file)
5
7
  @file = file
6
8
  end
@@ -36,7 +36,7 @@ module Licensee
36
36
  end
37
37
  end
38
38
 
39
- def readme
39
+ def readme_file
40
40
  return unless detect_readme?
41
41
  return @readme if defined? @readme
42
42
  @readme = begin
@@ -45,6 +45,7 @@ module Licensee
45
45
  Readme.new(content, name) if content && name
46
46
  end
47
47
  end
48
+ alias readme readme_file
48
49
 
49
50
  def package_file
50
51
  return unless detect_packages?
@@ -3,10 +3,16 @@ module Licensee
3
3
  class File
4
4
  attr_reader :content, :filename
5
5
 
6
+ ENCODING = Encoding::UTF_8
7
+ ENCODING_OPTIONS = {
8
+ invalid: :replace,
9
+ undef: :replace,
10
+ replace: ''
11
+ }.freeze
12
+
6
13
  def initialize(content, filename = nil)
7
14
  @content = content
8
- options = { invalid: :replace, undef: :replace, replace: '' }
9
- @content.encode!(Encoding::UTF_8, options)
15
+ @content.encode!(ENCODING, ENCODING_OPTIONS)
10
16
  @filename = filename
11
17
  end
12
18
 
@@ -3,6 +3,32 @@ module Licensee
3
3
  class LicenseFile < Licensee::Project::File
4
4
  include Licensee::ContentHelper
5
5
 
6
+ # List of extensions to give preference to
7
+ PREFERRED_EXT = %w(md markdown txt).freeze
8
+ PREFERRED_EXT_REGEX = /\.#{Regexp.union(PREFERRED_EXT)}\z/
9
+
10
+ # Regex to match any extension
11
+ ANY_EXT_REGEX = %r{\.[^./]+\z}
12
+
13
+ # Regex to match, LICENSE, LICENCE, unlicense, etc.
14
+ LICENSE_REGEX = /(un)?licen[sc]e/i
15
+
16
+ # Regex to match COPYING, COPYRIGHT, etc.
17
+ COPYING_REGEX = /copy(ing|right)/i
18
+
19
+ # Hash of Regex => score with which to score potential license files
20
+ FILENAME_REGEXES = {
21
+ /\A#{LICENSE_REGEX}\z/ => 1.0, # LICENSE
22
+ /\A#{LICENSE_REGEX}#{PREFERRED_EXT_REGEX}\z/ => 0.9, # LICENSE.md
23
+ /\A#{COPYING_REGEX}\z/ => 0.8, # COPYING
24
+ /\A#{COPYING_REGEX}#{PREFERRED_EXT_REGEX}\z/ => 0.7, # COPYING.md
25
+ /\A#{LICENSE_REGEX}#{ANY_EXT_REGEX}\z/ => 0.6, # LICENSE.textile
26
+ /\A#{COPYING_REGEX}#{ANY_EXT_REGEX}\z/ => 0.5, # COPYING.textile
27
+ /#{LICENSE_REGEX}/ => 0.4, # LICENSE-MIT
28
+ /#{COPYING_REGEX}/ => 0.3, # COPYING-MIT
29
+ // => 0.0 # Catch all
30
+ }.freeze
31
+
6
32
  def possible_matchers
7
33
  [Matchers::Copyright, Matchers::Exact, Matchers::Dice]
8
34
  end
@@ -13,12 +39,7 @@ module Licensee
13
39
  end
14
40
 
15
41
  def self.name_score(filename)
16
- return 1.0 if filename =~ /\A(un)?licen[sc]e\z/i
17
- return 0.9 if filename =~ /\A(un)?licen[sc]e\.(md|markdown|txt)\z/i
18
- return 0.8 if filename =~ /\Acopy(ing|right)(\.[^.]+)?\z/i
19
- return 0.7 if filename =~ /\A(un)?licen[sc]e\.[^.]+\z/i
20
- return 0.5 if filename =~ /licen[sc]e/i
21
- 0.0
42
+ FILENAME_REGEXES.find { |regex, _| filename =~ regex }[1]
22
43
  end
23
44
 
24
45
  # case-insensitive block to determine if the given file is LICENSE.lesser
@@ -8,13 +8,18 @@ module Licensee
8
8
  when '.json'
9
9
  [Matchers::NpmBower]
10
10
  else
11
- []
11
+ if filename == 'DESCRIPTION' && content.start_with?('Package:')
12
+ [Matchers::Cran]
13
+ else
14
+ []
15
+ end
12
16
  end
13
17
  end
14
18
 
15
19
  def self.name_score(filename)
16
20
  return 1.0 if ::File.extname(filename) == '.gemspec'
17
21
  return 1.0 if filename == 'package.json'
22
+ return 0.9 if filename == 'DESCRIPTION'
18
23
  return 0.75 if filename == 'bower.json'
19
24
  0.0
20
25
  end
@@ -2,8 +2,8 @@ module Licensee
2
2
  class Project
3
3
  class Readme < LicenseFile
4
4
  SCORES = {
5
- /\AREADME\z/i => 1.0,
6
- /\AREADME\.(md|markdown|txt)\z/i => 0.9
5
+ /\AREADME\z/i => 1.0,
6
+ /\AREADME\.(md|markdown|mdown|txt)\z/i => 0.9
7
7
  }.freeze
8
8
 
9
9
  CONTENT_REGEX = /^#+ Licen[sc]e$(.*?)(?=#+|\z)/im
@@ -35,7 +35,6 @@ module Licensee
35
35
  # Retrieve a file's content from disk
36
36
  #
37
37
  # file - the file hash, with the :name key as the file's relative path
38
- # path - the base path to the project
39
38
  #
40
39
  # Returns the fiel contents as a string
41
40
  def load_file(file)
@@ -1,3 +1,3 @@
1
1
  module Licensee
2
- VERSION = '8.5.0'.freeze
2
+ VERSION = '8.6.0'.freeze
3
3
  end
@@ -0,0 +1,56 @@
1
+ RSpec.describe 'command line invocation' do
2
+ let(:command) { ['ruby', 'bin/licensee'] }
3
+ let(:output) do
4
+ Dir.chdir project_root do
5
+ Open3.capture3(*[command, arguments].flatten)
6
+ end
7
+ end
8
+ let(:stdout) { output[0] }
9
+ let(:stderr) { output[1] }
10
+ let(:status) { output[2] }
11
+
12
+ context 'without any arguments' do
13
+ let(:arguments) { [] }
14
+
15
+ it 'Returns a zero exit code' do
16
+ expect(status.exitstatus).to eql(0)
17
+ end
18
+
19
+ it "detects the folder's license" do
20
+ expect(stdout).to match('License: MIT License')
21
+ end
22
+
23
+ it 'outputs the hash' do
24
+ expect(stdout).to match('750260c322080bab4c19fd55eb78bc73e1ae8f11')
25
+ end
26
+
27
+ it 'outputs the attribution' do
28
+ expect(stdout).to match('2014-2016 Ben Balter')
29
+ end
30
+
31
+ it 'outputs the confidence' do
32
+ expect(stdout).to match('Confidence: 100.00%')
33
+ end
34
+
35
+ it 'outputs the method' do
36
+ expect(stdout).to match('Method: Licensee::Matchers::Exact')
37
+ end
38
+ end
39
+
40
+ context 'when given a folder path' do
41
+ let(:arguments) { [project_root] }
42
+
43
+ it "detects the folder's license" do
44
+ expect(stdout).to match('License: MIT License')
45
+ end
46
+ end
47
+
48
+ context 'when given a license path' do
49
+ let(:license_path) { File.expand_path 'LICENSE.md', project_root }
50
+ let(:arguments) { [license_path] }
51
+
52
+ it "detects the file's license" do
53
+ expect(stdout).to match('License: MIT License')
54
+ end
55
+ end
56
+ end