license_finder 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/.gitignore +4 -3
  2. data/.travis.yml +1 -8
  3. data/bin/license_finder +31 -1
  4. data/db/migrate/201303290935_create_dependencies.rb +14 -0
  5. data/db/migrate/201303291155_create_licenses.rb +13 -0
  6. data/db/migrate/201303291402_create_approvals.rb +13 -0
  7. data/db/migrate/201303291456_create_ancestries.rb +9 -0
  8. data/db/migrate/201303291519_create_bundler_groups.rb +13 -0
  9. data/db/migrate/201303291720_move_manual_from_approvals_to_licenses.rb +11 -0
  10. data/db/migrate/201303291753_allow_null_license_names.rb +7 -0
  11. data/db/migrate/201304011027_allow_null_dependency_version.rb +7 -0
  12. data/db/migrate/201304020947_change_table_name_licenses_to_license_aliases.rb +5 -0
  13. data/features/approve_dependencies.feature +0 -45
  14. data/features/html_report.feature +1 -11
  15. data/features/license_finder.feature +13 -27
  16. data/features/license_finder_rake_task.feature +2 -1
  17. data/features/set_license.feature +2 -4
  18. data/features/step_definitions/license_finder_steps.rb +25 -0
  19. data/features/step_definitions/steps.rb +40 -26
  20. data/features/text_report.feature +2 -2
  21. data/files/license_finder.yml +1 -1
  22. data/lib/license_finder.rb +14 -6
  23. data/lib/license_finder/bundle.rb +4 -17
  24. data/lib/license_finder/bundle_syncer.rb +2 -3
  25. data/lib/license_finder/bundled_gem.rb +4 -47
  26. data/lib/license_finder/cli.rb +9 -16
  27. data/lib/license_finder/configuration.rb +55 -3
  28. data/lib/license_finder/dependency_report.rb +1 -1
  29. data/lib/license_finder/gem_saver.rb +69 -0
  30. data/lib/license_finder/html_report.rb +2 -2
  31. data/lib/license_finder/license.rb +60 -58
  32. data/lib/license_finder/license_files.rb +36 -0
  33. data/lib/license_finder/license_url.rb +8 -6
  34. data/lib/license_finder/platform.rb +32 -0
  35. data/lib/license_finder/possible_license_file.rb +1 -1
  36. data/lib/license_finder/tables.rb +7 -0
  37. data/lib/license_finder/tables/approval.rb +4 -0
  38. data/lib/license_finder/tables/bundler_group.rb +4 -0
  39. data/lib/license_finder/tables/dependency.rb +31 -0
  40. data/lib/license_finder/tables/license_alias.rb +22 -0
  41. data/lib/license_finder/yml_to_sql.rb +127 -0
  42. data/lib/tasks/license_finder.rake +3 -0
  43. data/lib/templates/html_report.erb +50 -32
  44. data/lib/templates/text_report.erb +3 -2
  45. data/license_finder.gemspec +14 -5
  46. data/readme.md +10 -50
  47. data/spec/lib/license_finder/bundle_spec.rb +22 -19
  48. data/spec/lib/license_finder/bundle_syncer_spec.rb +4 -10
  49. data/spec/lib/license_finder/bundled_gem_spec.rb +40 -108
  50. data/spec/lib/license_finder/cli_spec.rb +3 -3
  51. data/spec/lib/license_finder/configuration_spec.rb +53 -21
  52. data/spec/lib/license_finder/gem_saver_spec.rb +155 -0
  53. data/spec/lib/license_finder/html_report_spec.rb +32 -15
  54. data/spec/lib/license_finder/license_files_spec.rb +50 -0
  55. data/spec/lib/license_finder/tables/dependency_spec.rb +102 -0
  56. data/spec/lib/license_finder/tables/license_alias_spec.rb +54 -0
  57. data/spec/lib/license_finder/text_report_spec.rb +6 -4
  58. data/spec/lib/license_finder/yml_to_sql_spec.rb +99 -0
  59. data/spec/lib/license_finder_spec.rb +5 -5
  60. data/spec/spec_helper.rb +17 -1
  61. metadata +79 -32
  62. data/lib/license_finder/dependency.rb +0 -50
  63. data/lib/license_finder/persistence.rb +0 -1
  64. data/lib/license_finder/persistence/yaml.rb +0 -7
  65. data/lib/license_finder/persistence/yaml/configuration.rb +0 -34
  66. data/lib/license_finder/persistence/yaml/dependency.rb +0 -127
  67. data/lib/license_finder/source_syncer.rb +0 -40
  68. data/lib/templates/dependency.html.erb +0 -54
  69. data/spec/lib/license_finder/dependency_spec.rb +0 -188
  70. data/spec/lib/license_finder/persistence/yaml/dependency_spec.rb +0 -5
  71. data/spec/lib/license_finder/source_syncer_spec.rb +0 -37
  72. data/spec/support/shared_examples/persistence/configuration.rb +0 -28
  73. data/spec/support/shared_examples/persistence/dependency.rb +0 -138
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+
3
+ module LicenseFinder
4
+ describe GemSaver do
5
+ let(:gemspec) do
6
+ Gem::Specification.new do |s|
7
+ s.name = 'spec_name'
8
+ s.version = '2.1.3'
9
+ s.summary = 'summary'
10
+ s.description = 'description'
11
+ s.homepage = 'homepage'
12
+
13
+ s.add_dependency 'foo'
14
+ end
15
+ end
16
+
17
+ describe "#save" do
18
+ let(:bundled_gem) { BundledGem.new(gemspec) }
19
+ subject { described_class.find_or_initialize_by_name('spec_name', bundled_gem).save }
20
+
21
+ context "when the dependency is new" do
22
+ it "persists gem data" do
23
+ subject.id.should be
24
+ subject.name.should == "spec_name"
25
+ subject.version.should == "2.1.3"
26
+ subject.summary.should == "summary"
27
+ subject.description.should == "description"
28
+ subject.homepage.should == "homepage"
29
+ end
30
+
31
+ it "associates children" do
32
+ subject.children.map(&:name).should == ['foo']
33
+ end
34
+
35
+ it "marks depenency as unapproved by default" do
36
+ subject.approval.state.should == nil
37
+ end
38
+
39
+ context "with a bundler dependency" do
40
+ let(:bundled_gem) { BundledGem.new(gemspec, stub(:bundler_dependency, groups: %w[1 2 3]))}
41
+
42
+ it "saves the bundler groups" do
43
+ subject.bundler_groups.map(&:name).should =~ %w[1 2 3]
44
+ end
45
+ end
46
+ end
47
+
48
+ context "when the dependency already existed" do
49
+ let!(:old_copy) do
50
+ Dependency.create(
51
+ name: 'spec_name',
52
+ version: '0.1.2',
53
+ summary: 'old summary',
54
+ description: 'old desription',
55
+ homepage: 'old homepage'
56
+ )
57
+ end
58
+
59
+ it "merges in the latest data" do
60
+ subject.id.should == old_copy.id
61
+ subject.name.should == old_copy.name
62
+ subject.version.should == "2.1.3"
63
+ subject.summary.should == "summary"
64
+ subject.description.should == "description"
65
+ subject.homepage.should == "homepage"
66
+ end
67
+
68
+ it "keeps a manually assigned license" do
69
+ old_copy.license = LicenseAlias.create(name: 'foo', manual: true)
70
+ old_copy.save
71
+ subject.license.name.should == 'foo'
72
+ end
73
+
74
+ it "keeps approval" do
75
+ old_copy.approval = Approval.create(state: true)
76
+ old_copy.save
77
+ subject.approval.state.should == true
78
+ end
79
+
80
+ it "ensures correct children are associated" do
81
+ old_copy.add_child Dependency.new(name: 'bob')
82
+ old_copy.add_child Dependency.new(name: 'joe')
83
+ old_copy.children.each(&:save)
84
+ subject.children.map(&:name).should =~ ['foo']
85
+ end
86
+
87
+ context "with a bundler dependency" do
88
+ let(:bundled_gem) { BundledGem.new(gemspec, stub(:bundler_dependency, groups: %w[1 2 3]))}
89
+
90
+ before do
91
+ old_copy.add_bundler_group BundlerGroup.find_or_create(name: 'a')
92
+ old_copy.add_bundler_group BundlerGroup.find_or_create(name: 'b')
93
+ end
94
+
95
+ it "ensures the correct bundler groups are associated" do
96
+ subject.bundler_groups.map(&:name).should =~ %w[1 2 3]
97
+ end
98
+ end
99
+
100
+ context "license changes to something other than 'other'" do
101
+ before do
102
+ old_copy.license = LicenseAlias.create(name: 'other')
103
+ old_copy.save
104
+ gemspec.license = "new license"
105
+ end
106
+
107
+ context "new license is whitelisted" do
108
+ before { LicenseFinder.config.stub(:whitelist).and_return [gemspec.license] }
109
+
110
+ it "should set the approval to true" do
111
+ subject.should be_approved
112
+ end
113
+ end
114
+
115
+ context "new license is not whitelisted" do
116
+ it "should set the approval to false" do
117
+ subject.should_not be_approved
118
+ end
119
+ end
120
+ end
121
+
122
+ context "license changes to unknown (i.e., 'other')" do
123
+ before do
124
+ old_copy.license = LicenseAlias.create(name: 'MIT')
125
+ old_copy.approval = Approval.create(state: false)
126
+ old_copy.save
127
+ gemspec.license = "other"
128
+ end
129
+
130
+ it "should not change the license" do
131
+ subject.license.name.should == 'MIT'
132
+ end
133
+
134
+ it "should not change the approval" do
135
+ subject.should_not be_approved
136
+ end
137
+ end
138
+
139
+ context "license does not change" do
140
+ before do
141
+ old_copy.license = LicenseAlias.create(name: 'MIT')
142
+ old_copy.approval = Approval.create(state: false)
143
+ old_copy.save
144
+ gemspec.license = "MIT"
145
+ end
146
+
147
+ it "should not change the license or approval" do
148
+ subject.should_not be_approved
149
+ subject.license.name.should == "MIT"
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -1,65 +1,82 @@
1
1
  require "spec_helper"
2
+ require "capybara"
2
3
 
3
4
  module LicenseFinder
4
5
  describe HtmlReport do
5
6
  describe "#to_s" do
6
- let(:dependency) { Dependency.new 'approved' => true }
7
- subject { HtmlReport.new([dependency]).to_s }
7
+ let(:dependency) do
8
+ dep = Dependency.new name: "the-name"
9
+ dep.license = LicenseAlias.create name: 'MIT'
10
+ dep.approval = Approval.create state: true
11
+ dep
12
+ end
13
+
14
+ subject { Capybara.string(HtmlReport.new([dependency]).to_s) }
8
15
 
9
16
  context "when the dependency is approved" do
10
17
  it "should add an approved class to dependency's container" do
11
- should include %{class="approved"}
18
+ should have_selector ".approved"
19
+ end
20
+
21
+ it "does not list the dependency in the action items" do
22
+ should_not have_selector ".action-items"
12
23
  end
13
24
  end
14
25
 
15
26
  context "when the dependency is not approved" do
16
- before { dependency.approved = false }
27
+ before { dependency.approval.state = false }
17
28
 
18
29
  it "should not add an approved class to he dependency's container" do
19
- should include %{class="unapproved"}
30
+ should have_selector ".unapproved"
31
+ end
32
+
33
+ it "lists the dependency in the action items" do
34
+ should have_selector ".action-items li"
20
35
  end
21
36
  end
22
37
 
23
38
  context "when the gem has at least one bundler group" do
24
- before { dependency.bundler_groups = ["group"] }
39
+ before { dependency.stub(bundler_groups: [stub(name: "group")]) }
25
40
  it "should show the bundler group(s) in parens" do
26
- should include "(group)"
41
+ should have_text "(group)"
27
42
  end
28
43
  end
29
44
 
30
45
  context "when the gem has no bundler groups" do
31
- before { dependency.bundler_groups = [] }
46
+ before { dependency.stub(bundler_groups: []) }
32
47
 
33
48
  it "should not show any parens or bundler group info" do
34
- should_not include "()"
49
+ should_not have_text "()"
35
50
  end
36
51
 
37
52
  end
38
53
 
39
54
  context "when the gem has at least one parent" do
40
- before { dependency.parents = [OpenStruct.new(:name => "foo parent")] }
55
+ before { dependency.stub(parents: [stub(:name => "foo parent")]) }
41
56
  it "should include a parents section" do
42
- should include "Parents"
57
+ should have_text "Parents"
58
+ should have_text "foo parent"
43
59
  end
44
60
  end
45
61
 
46
62
  context "when the gem has no parents" do
47
63
  it "should not include any parents section in the output" do
48
- should_not include "Parents"
64
+ should_not have_text "Parents"
49
65
  end
50
66
  end
51
67
 
52
68
  context "when the gem has at least one child" do
53
- before { dependency.children = [OpenStruct.new(:name => "foo child")] }
69
+ before { dependency.stub(children: [stub(:name => "foo child")]) }
54
70
 
55
71
  it "should include a Children section" do
56
- should include "Children"
72
+ should have_text "Children"
73
+ should have_text "foo child"
57
74
  end
58
75
  end
59
76
 
60
77
  context "when the gem has no children" do
61
78
  it "should not include any Children section in the output" do
62
- should_not include "Children"
79
+ should_not have_text "Children"
63
80
  end
64
81
  end
65
82
  end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ module LicenseFinder
4
+ describe LicenseFiles do
5
+ def fixture_path(fixture)
6
+ Pathname.new(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec', 'fixtures', fixture)).realpath.to_s
7
+ end
8
+
9
+ describe "#files" do
10
+ it "is empty if there aren't any license files" do
11
+ subject = described_class.new('/not/a/dir')
12
+ subject.files.should == []
13
+ end
14
+
15
+ it "includes files with names like LICENSE, License or COPYING" do
16
+ subject = described_class.new(fixture_path('license_names'))
17
+
18
+ subject.files.map(&:file_name).should =~
19
+ %w[COPYING.txt LICENSE Mit-License README.rdoc Licence.rdoc]
20
+ end
21
+
22
+ it "includes files deep in the hierarchy" do
23
+ subject = described_class.new(fixture_path('nested_gem'))
24
+
25
+ subject.files.map { |f| [f.file_name, f.file_path] }.should =~ [
26
+ %w[LICENSE vendor/LICENSE]
27
+ ]
28
+ end
29
+
30
+ it "includes both files nested inside LICENSE directory and top level files" do
31
+ subject = described_class.new(fixture_path('license_directory'))
32
+ found_license_files = subject.files
33
+
34
+ found_license_files.map { |f| [f.file_name, f.file_path] }.should =~ [
35
+ %w[BSD-2-Clause.txt LICENSE/BSD-2-Clause.txt],
36
+ %w[GPL-2.0.txt LICENSE/GPL-2.0.txt],
37
+ %w[MIT.txt LICENSE/MIT.txt],
38
+ %w[RUBY.txt LICENSE/RUBY.txt],
39
+ %w[COPYING COPYING],
40
+ %w[LICENSE LICENSE/LICENSE]
41
+ ]
42
+ end
43
+
44
+ it "handles non UTF8 encodings" do
45
+ subject = described_class.new(fixture_path('utf8_gem'))
46
+ expect { subject.files }.not_to raise_error
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ module LicenseFinder
4
+ describe Dependency do
5
+ let(:attributes) do
6
+ {
7
+ 'name' => "spec_name",
8
+ 'version' => "2.1.3",
9
+ 'license' => "GPLv2",
10
+ 'approved' => false,
11
+ 'notes' => 'some notes',
12
+ 'homepage' => 'homepage',
13
+ 'license_files' => ['/Users/pivotal/foo/lic1', '/Users/pivotal/bar/lic2'],
14
+ 'bundler_groups' => ["test"]
15
+ }
16
+ end
17
+
18
+ let(:config) { Configuration.new }
19
+
20
+ before do
21
+ LicenseFinder.stub(:config).and_return config
22
+ config.whitelist = ["MIT", "other"]
23
+ end
24
+
25
+ describe ".destroy_obsolete" do
26
+ it "destroys every dependency except for the ones provided as 'current'" do
27
+ cur1 = Dependency.create(name: "current dependency 1")
28
+ cur2 = Dependency.create(name: "current dependency 2")
29
+ Dependency.create(name: "old dependency 1")
30
+ Dependency.create(name: "old dependency 2")
31
+
32
+ Dependency.destroy_obsolete([cur1, cur2])
33
+ Dependency.all.should =~ [cur1, cur2]
34
+ end
35
+ end
36
+
37
+ describe '.unapproved' do
38
+ it "should return all unapproved dependencies" do
39
+ dependency = Dependency.create(name: "unapproved dependency", version: '0.0.1')
40
+ dependency.approval = Approval.create(state: false)
41
+ dependency.save
42
+ approved = Dependency.create(name: "approved dependency", version: '0.0.1')
43
+ approved.approval = Approval.create(state: true)
44
+ approved.save
45
+ whitelisted = Dependency.create(name: "approved dependency", version: '0.0.1')
46
+ whitelisted.license = LicenseAlias.create(name: 'MIT')
47
+ whitelisted.approval = Approval.create(state: false)
48
+ whitelisted.save
49
+
50
+ unapproved = Dependency.unapproved
51
+ unapproved.count.should == 1
52
+ unapproved.should_not be_any(&:approved?)
53
+ end
54
+ end
55
+
56
+ describe '#approve!' do
57
+ it "should update the database to show the dependency is approved" do
58
+ dependency = Dependency.create(name: "foo", version: '0.0.1')
59
+ dependency.approval = Approval.create(state: false)
60
+ dependency.save
61
+ dependency.approve!
62
+ dependency.reload.should be_approved
63
+ end
64
+ end
65
+
66
+ describe "#approved?" do
67
+ let(:dependency) { Dependency.create(name: 'some gem') }
68
+
69
+ it "is true if its license is whitelisted" do
70
+ dependency.stub_chain(:license, whitelisted?: true)
71
+ dependency.should be_approved
72
+ end
73
+
74
+ it "is true if it has been approved" do
75
+ dependency.stub_chain(:license, whitelisted?: false)
76
+ dependency.stub_chain(:approval, state: true)
77
+ dependency.should be_approved
78
+ end
79
+
80
+ it "is false otherwise" do
81
+ dependency.stub_chain(:license, whitelisted?: false)
82
+ dependency.stub_chain(:approval, state: false)
83
+ dependency.should_not be_approved
84
+ end
85
+ end
86
+
87
+ describe "#set_license_manually" do
88
+ let(:gem) do
89
+ dependency = Dependency.new(name: "bob", version: '0.0.1')
90
+ dependency.license = LicenseAlias.create(name: 'Original')
91
+ dependency.save
92
+ dependency
93
+ end
94
+
95
+ it "delegates to the license" do
96
+ gem.license.should_receive(:set_manually).with('Updated')
97
+ gem.set_license_manually('Updated')
98
+ end
99
+ end
100
+ end
101
+ end
102
+
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ module LicenseFinder
4
+ describe LicenseAlias do
5
+ describe 'initializes' do
6
+ it "delegates to LicenseUrl.find_by_name for the url" do
7
+ LicenseUrl.stub(:find_by_name).with("MIT").and_return "http://license-url.com"
8
+ license = described_class.new(name: 'MIT')
9
+ license.url.should == "http://license-url.com"
10
+ end
11
+ end
12
+
13
+ describe "#set_manually" do
14
+ subject do
15
+ described_class.create(name: 'Original')
16
+ end
17
+
18
+ it "modifies the license" do
19
+ subject.set_manually('Updated')
20
+ subject.reload.name.should == 'Updated'
21
+ end
22
+
23
+ it "marks the approval as manual" do
24
+ subject.set_manually('Updated')
25
+ subject.reload.manual.should be_true
26
+ end
27
+ end
28
+
29
+ describe "#whitelisted?" do
30
+ let(:config) { Configuration.new }
31
+
32
+ before do
33
+ LicenseFinder.stub(:config).and_return config
34
+ config.whitelist = ["MIT", "other"]
35
+ end
36
+
37
+ it "should return true when the license is whitelisted" do
38
+ described_class.new(name: 'MIT').should be_whitelisted
39
+ end
40
+
41
+ it "should return true when the license is an alternative name of a whitelisted license" do
42
+ described_class.new(name: 'Expat').should be_whitelisted
43
+ end
44
+
45
+ it "should return true when the license has no matching license class, but is whitelisted anyways" do
46
+ described_class.new(name: 'other').should be_whitelisted
47
+ end
48
+
49
+ it "should return false when the license is not whitelisted" do
50
+ described_class.new(name: 'GPL').should_not be_whitelisted
51
+ end
52
+ end
53
+ end
54
+ end