license_finder 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +0 -1
  3. data/bin/license_finder +21 -1
  4. data/features/approve_dependencies.feature +10 -0
  5. data/features/license_finder.feature +13 -3
  6. data/features/license_finder_rake_task.feature +3 -3
  7. data/features/set_license.feature +14 -0
  8. data/features/step_definitions/steps.rb +5 -0
  9. data/lib/license_finder.rb +13 -2
  10. data/lib/license_finder/bundle.rb +25 -3
  11. data/lib/license_finder/bundle_syncer.rb +12 -0
  12. data/lib/license_finder/bundled_gem.rb +12 -1
  13. data/lib/license_finder/cli.rb +42 -3
  14. data/lib/license_finder/configuration.rb +1 -31
  15. data/lib/license_finder/dependency.rb +30 -94
  16. data/lib/license_finder/dependency_report.rb +30 -0
  17. data/lib/license_finder/html_report.rb +14 -0
  18. data/lib/license_finder/persistence.rb +1 -0
  19. data/lib/license_finder/persistence/yaml.rb +7 -0
  20. data/lib/license_finder/persistence/yaml/configuration.rb +34 -0
  21. data/lib/license_finder/persistence/yaml/dependency.rb +127 -0
  22. data/lib/license_finder/reporter.rb +7 -38
  23. data/lib/license_finder/source_syncer.rb +40 -0
  24. data/lib/license_finder/text_report.rb +9 -0
  25. data/lib/templates/dependency.html.erb +2 -2
  26. data/lib/templates/html_report.erb +93 -0
  27. data/lib/templates/text_report.erb +2 -0
  28. data/license_finder.gemspec +2 -2
  29. data/{README.markdown → readme.md} +22 -11
  30. data/spec/lib/license_finder/bundle_spec.rb +58 -0
  31. data/spec/lib/license_finder/bundle_syncer_spec.rb +22 -0
  32. data/spec/lib/license_finder/bundled_gem_spec.rb +17 -14
  33. data/spec/lib/license_finder/cli_spec.rb +38 -0
  34. data/spec/lib/license_finder/dependency_spec.rb +130 -223
  35. data/spec/lib/license_finder/html_report_spec.rb +67 -0
  36. data/spec/lib/license_finder/persistence/yaml/configuration_spec.rb +5 -0
  37. data/spec/lib/license_finder/persistence/yaml/dependency_spec.rb +5 -0
  38. data/spec/lib/license_finder/possible_license_file_spec.rb +4 -9
  39. data/spec/lib/license_finder/reporter_spec.rb +0 -1
  40. data/spec/lib/license_finder/source_syncer_spec.rb +37 -0
  41. data/spec/lib/license_finder/text_report_spec.rb +29 -0
  42. data/spec/lib/license_finder_spec.rb +9 -11
  43. data/spec/spec_helper.rb +1 -1
  44. data/spec/support/license_examples.rb +1 -1
  45. data/spec/support/shared_examples/persistence/configuration.rb +34 -0
  46. data/spec/support/shared_examples/persistence/dependency.rb +139 -0
  47. metadata +38 -26
  48. data/lib/license_finder/dependency_list.rb +0 -80
  49. data/lib/license_finder/viewable.rb +0 -31
  50. data/lib/templates/dependency_list.html.erb +0 -38
  51. data/spec/lib/license_finder/dependency_list_spec.rb +0 -243
@@ -0,0 +1,30 @@
1
+ module LicenseFinder
2
+ class DependencyReport
3
+ def self.underscored_name
4
+ @underscored_name ||= begin
5
+ str = name.dup
6
+ str.sub!(/.*::/, '')
7
+ str.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
8
+ str.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
9
+ str.downcase!
10
+ end
11
+ end
12
+
13
+ def initialize(dependencies=[])
14
+ @dependencies = Array dependencies
15
+ end
16
+
17
+ def to_s
18
+ filename = File.join(File.dirname(__FILE__), '..', 'templates', "#{self.class.underscored_name}.erb")
19
+ template = ERB.new(File.read(filename))
20
+ template.result(binding)
21
+ end
22
+
23
+ private
24
+ attr_reader :dependencies
25
+
26
+ def sorted_dependencies
27
+ dependencies.sort_by(&:name)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+
3
+ module LicenseFinder
4
+ class HtmlReport < DependencyReport
5
+ private
6
+ def unapproved_dependencies
7
+ dependencies.reject(&:approved)
8
+ end
9
+
10
+ def grouped_dependencies
11
+ dependencies.group_by(&:license).sort_by { |_, group| group.size }.reverse
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module LicenseFinder
2
+ module Persistence
3
+ autoload :Dependency, 'license_finder/persistence/yaml/dependency'
4
+ autoload :Configuration, 'license_finder/persistence/yaml/configuration'
5
+ end
6
+ end
7
+
@@ -0,0 +1,34 @@
1
+ module LicenseFinder
2
+ module Persistence
3
+ class Configuration
4
+ attr_reader :whitelist, :ignore_groups, :dependencies_dir
5
+
6
+ def initialize(config={})
7
+ if File.exists?(config_file_path)
8
+ yaml = File.read(config_file_path)
9
+ config = YAML.load(yaml).merge config
10
+ end
11
+
12
+ @whitelist = config['whitelist'] || []
13
+ @ignore_groups = (config["ignore_groups"] || []).map(&:to_sym)
14
+ @dependencies_dir = config['dependencies_file_dir'] || '.'
15
+ end
16
+
17
+ def config_file_path
18
+ File.join('.', 'config', 'license_finder.yml')
19
+ end
20
+
21
+ def dependencies_yaml
22
+ File.join(dependencies_dir, "dependencies.yml")
23
+ end
24
+
25
+ def dependencies_text
26
+ File.join(dependencies_dir, "dependencies.txt")
27
+ end
28
+
29
+ def dependencies_html
30
+ File.join(dependencies_dir, "dependencies.html")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,127 @@
1
+ module LicenseFinder
2
+ module Persistence
3
+ class Dependency
4
+ class Database
5
+ def initialize
6
+ @dependency_attributes = YAML.load File.read(LicenseFinder.config.dependencies_yaml) if File.exists?(LicenseFinder.config.dependencies_yaml)
7
+ end
8
+
9
+ def find(&block)
10
+ dependency_attributes.detect &block
11
+ end
12
+
13
+ def update(dependency_hash)
14
+ destroy_by_name_without_saving dependency_hash['name']
15
+ dependency_attributes << dependency_hash
16
+ persist!
17
+ end
18
+
19
+ def delete_all
20
+ File.delete(LicenseFinder.config.dependencies_yaml) if File.exists?(LicenseFinder.config.dependencies_yaml)
21
+ @dependency_attributes = nil
22
+ end
23
+
24
+ def destroy_by_name(name)
25
+ destroy_by_name_without_saving name
26
+ persist!
27
+ end
28
+
29
+ def persist!
30
+ File.open(LicenseFinder.config.dependencies_yaml, 'w+') do |f|
31
+ f.write dependency_attributes.to_yaml
32
+ end
33
+ end
34
+
35
+ def all
36
+ dependency_attributes
37
+ end
38
+
39
+ private
40
+ def destroy_by_name_without_saving(name)
41
+ dependency_attributes.reject! { |a| a['name'] == name }
42
+ end
43
+
44
+ def dependency_attributes
45
+ @dependency_attributes ||= []
46
+ end
47
+ end
48
+
49
+ attr_accessor *LicenseFinder::DEPENDENCY_ATTRIBUTES
50
+
51
+ class << self
52
+ def find_by_name(name)
53
+ attributes = database.find { |a| a['name'] == name }
54
+ new(attributes) if attributes
55
+ end
56
+
57
+ def delete_all
58
+ database.delete_all
59
+ end
60
+
61
+ def all
62
+ database.all.map { |attributes| new(attributes) }
63
+ end
64
+
65
+ def unapproved
66
+ all.select {|d| d.approved == false }
67
+ end
68
+
69
+ def update(attributes)
70
+ database.update attributes
71
+ end
72
+
73
+ def destroy_by_name(name)
74
+ database.destroy_by_name name
75
+ end
76
+
77
+ private
78
+ def database
79
+ @database ||= Database.new
80
+ end
81
+ end
82
+
83
+ def initialize(attributes = {})
84
+ update_attributes_without_saving attributes
85
+ end
86
+
87
+ def config
88
+ LicenseFinder.config
89
+ end
90
+
91
+ def update_attributes new_values
92
+ update_attributes_without_saving(new_values)
93
+ save
94
+ end
95
+
96
+ def approved?
97
+ !!approved
98
+ end
99
+
100
+ def save
101
+ self.class.update(attributes)
102
+ end
103
+
104
+ def destroy
105
+ self.class.destroy_by_name(name)
106
+ end
107
+
108
+ def attributes
109
+ attributes = {}
110
+
111
+ LicenseFinder::DEPENDENCY_ATTRIBUTES.each do |attrib|
112
+ attributes[attrib] = send attrib
113
+ end
114
+
115
+ attributes
116
+ end
117
+
118
+ private
119
+ def update_attributes_without_saving(new_values)
120
+ new_values.each do |key, value|
121
+ send("#{key}=", value)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
@@ -1,51 +1,20 @@
1
1
  module LicenseFinder
2
- class Reporter
3
- def self.create_default_configuration
4
- unless File.exists?(LicenseFinder.config.config_file_path)
5
- FileUtils.mkdir_p(File.join('.', 'config'))
6
- FileUtils.cp(
7
- File.join(File.dirname(__FILE__), '..', '..', 'files', 'license_finder.yml'),
8
- LicenseFinder.config.config_file_path
9
- )
10
- end
11
- end
2
+ module Reporter
3
+ extend self
12
4
 
13
- def initialize
14
- self.class.create_default_configuration
15
- @dependency_list = generate_list
16
- save_reports
17
- end
5
+ def write_reports
6
+ dependencies = Dependency.all
18
7
 
19
- def action_items
20
- dependency_list.action_items
8
+ write_file LicenseFinder.config.dependencies_text, TextReport.new(dependencies).to_s
9
+ write_file LicenseFinder.config.dependencies_html, HtmlReport.new(dependencies).to_s
21
10
  end
22
11
 
23
12
  private
24
-
25
- attr_reader :dependency_list
26
-
27
- def save_reports
28
- write_file LicenseFinder.config.dependencies_yaml, dependency_list.to_yaml
29
- write_file LicenseFinder.config.dependencies_text, dependency_list.to_s
30
- write_file LicenseFinder.config.dependencies_html, dependency_list.to_html
31
- end
32
-
33
13
  def write_file(file_path, content)
34
14
  File.open(file_path, 'w+') do |f|
35
15
  f.puts content
36
16
  end
37
17
  end
38
-
39
- def generate_list
40
- bundler_list = DependencyList.from_bundler
41
-
42
- if File.exists?(LicenseFinder.config.dependencies_yaml)
43
- yml = File.open(LicenseFinder.config.dependencies_yaml).readlines.join
44
- existing_list = DependencyList.from_yaml(yml)
45
- existing_list.merge(bundler_list)
46
- else
47
- bundler_list
48
- end
49
- end
50
18
  end
51
19
  end
20
+
@@ -0,0 +1,40 @@
1
+ module LicenseFinder
2
+ class SourceSyncer
3
+ def initialize(source_dependencies, dependencies)
4
+ @source_dependencies = Array source_dependencies
5
+ @dependencies = dependencies
6
+ end
7
+
8
+ def sync!
9
+ destroy_obsolete_dependencies
10
+ update_existing_dependencies
11
+ create_new_dependencies
12
+ dependencies
13
+ end
14
+
15
+ protected
16
+ attr_accessor :dependencies, :source_dependencies
17
+
18
+ def destroy_obsolete_dependencies
19
+ obsolete_dependencies = dependencies.select {|d| !source_dependencies.detect {|s| s.name == d.name }}
20
+ obsolete_dependencies.map &:destroy
21
+
22
+ self.dependencies -= obsolete_dependencies
23
+ end
24
+
25
+ def update_existing_dependencies
26
+ dependencies.each do |d|
27
+ source_dep = source_dependencies.detect { |s| s.name == d.name }
28
+ d.merge(source_dep)
29
+ self.source_dependencies -= [source_dep]
30
+ end
31
+ end
32
+
33
+ def create_new_dependencies
34
+ source_dependencies.each do |d|
35
+ dependencies << d
36
+ d.save
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+
3
+ module LicenseFinder
4
+ class TextReport < DependencyReport
5
+ def to_s
6
+ super.strip
7
+ end
8
+ end
9
+ end
@@ -38,7 +38,7 @@
38
38
  <dl>
39
39
  <dt>Parents</dt>
40
40
  <% parents.each do |parent| %>
41
- <dd><%= parent.name %></dd>
41
+ <dd><%= parent %></dd>
42
42
  <% end %>
43
43
  </dl>
44
44
  <% end %>
@@ -47,7 +47,7 @@
47
47
  <dl>
48
48
  <dt>Children</dt>
49
49
  <% children.each do |child| %>
50
- <dd><%= child.name %></dd>
50
+ <dd><%= child %></dd>
51
51
  <% end %>
52
52
  </dl>
53
53
  <% end %>
@@ -0,0 +1,93 @@
1
+ <html>
2
+ <head>
3
+ <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.1/css/bootstrap.min.css" rel="stylesheet">
4
+ <style type="text/css">
5
+ body {
6
+ margin: 50px;
7
+ }
8
+
9
+ .unapproved h2, .unapproved h2 a {
10
+ color: red;
11
+ }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <div class="container">
16
+ <div class="summary hero-unit">
17
+ <h1>Dependencies</h1>
18
+
19
+ <h4>
20
+ <%= dependencies.size %> total
21
+
22
+ <% if unapproved_dependencies.any? %>
23
+ <span class="badge badge-important"><%= unapproved_dependencies.size %> unapproved</span>
24
+ <% end %>
25
+ </h4>
26
+
27
+ <ul>
28
+ <% grouped_dependencies.each do |license, group| %>
29
+ <li><%= group.size %> <%= license %></li>
30
+ <% end %>
31
+ </ul>
32
+ </div>
33
+ <div class="dependencies">
34
+ <% sorted_dependencies.each do |dependency| %>
35
+ <div id="<%= dependency.name %>" class="<%= dependency.approved ? "approved" : "unapproved" %>">
36
+ <h2>
37
+ <% if dependency.homepage && !dependency.homepage.empty? %>
38
+ <a href="<%= dependency.homepage %>"><%= dependency.name %></a>
39
+ <% else %>
40
+ <%= dependency.name %>
41
+ <% end %>
42
+ v<%= dependency.version %>
43
+ <% if dependency.bundler_groups.any? %>
44
+ (<%= dependency.bundler_groups.join(", ") %>)
45
+ <% end %>
46
+ </h2>
47
+ <table class="table table-striped table-bordered">
48
+ <thead>
49
+ <tr>
50
+ <th>Summary</th>
51
+ <th>Description</th>
52
+ <th>License</th>
53
+ </tr>
54
+ </thead>
55
+ <tbody>
56
+ <tr>
57
+ <td><%= dependency.summary %></td>
58
+ <td><%= dependency.description %></td>
59
+ <td>
60
+ <% if dependency.license_url && !dependency.license_url.empty? %>
61
+ <a href="<%= dependency.license_url %>"><%= dependency.license %></a>
62
+ <% else %>
63
+ <%= dependency.license %>
64
+ <% end %>
65
+ </td>
66
+ </td>
67
+ </tr>
68
+ </tbody>
69
+ </table>
70
+
71
+ <% if dependency.parents.any? %>
72
+ <dl>
73
+ <dt>Parents</dt>
74
+ <% dependency.parents.each do |parent| %>
75
+ <dd><%= parent %></dd>
76
+ <% end %>
77
+ </dl>
78
+ <% end %>
79
+
80
+ <% if dependency.children.any? %>
81
+ <dl>
82
+ <dt>Children</dt>
83
+ <% dependency.children.each do |child| %>
84
+ <dd><%= child %></dd>
85
+ <% end %>
86
+ </dl>
87
+ <% end %>
88
+ </div>
89
+ <% end %>
90
+ </div>
91
+ </div>
92
+ </body>
93
+ </html>
@@ -0,0 +1,2 @@
1
+ <% sorted_dependencies.each do |s| %><%=s.name %>, <%=s.version %>, <%=s.license%>
2
+ <% end %>