license_finder 0.6.0 → 0.7.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 (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 %>