Permalink
Browse files

license_finder --approve some_gem

* approves the gem
* updates the database (i.e., the YAML file)
* cleans up notions of persistence

[finishes #36107261]
  • Loading branch information...
1 parent 559ae80 commit 0cccbadb0af17a8f57fcdfdc7ac4e84e9497d820 Matthew Kane Parker and Paul Meskers committed Sep 17, 2012
View
@@ -5,3 +5,6 @@ Gemfile.lock
.rvmrc
.idea/*
tmp/
+dependencies.yml
+dependencies.txt
+config/
View
@@ -65,8 +65,10 @@ and then edited the resulting file).
### Manually approving dependencies
Whenever you have a dependency that falls outside of your whitelist, `license_finder` will tell you.
-If your business decides that this is an acceptable risk, you can manually approve the dependency by finding its
-section in the `dependencies.yml` file and setting its `approved` attribute to true. For example, lets assume you've only
+If your business decides that this is an acceptable risk, you can manually approve the dependency by using the `-a` or
+`--approve` option of the `license_finder` command.
+
+For example, lets assume you've only
whitelisted the "MIT" license in your `config/license_finder.yml`. You then add the 'awesome_gpl_gem' to your Gemfile,
which we'll assume is licensed with the `GPL` license. You then run `license_finder` and see
the gem listed in the output:
@@ -75,14 +77,10 @@ the gem listed in the output:
awesome_gpl_gem, 1.0.0, GPL
```
-Your business tells you that in this case, it's acceptable to use this gem. You should now update your `dependencies.yml`
-file, setting the `approved` attribute to `true` for the `awesome_gpl_gem` section:
+Your business tells you that in this case, it's acceptable to use this gem. You now run:
-```yaml
-- name: awesome_gpl_gem
- version: 1.0.0
- license: GPL
- approved: true
+```sh
+$ bundle exec license_finder -a awesome_gpl_gem
```
If you rerun `license_finder`, you should no longer see `awesome_gpl_gem` in the output.
View
@@ -1,4 +1,16 @@
#!/usr/bin/env ruby
require 'license_finder'
-LicenseFinder::CLI.check_for_action_items
+require 'optparse'
+
+options = {}
+
+OptionParser.new do |opts|
+ opts.banner = "Usage: license_finder [options]"
+
+ opts.on("-a", "--approve [GEM_NAME]", "Approve a gem by name.") do |gem_name|
+ options[:approve] = gem_name
+ end
+end.parse!
+
+LicenseFinder::CLI.execute! options
@@ -3,6 +3,13 @@ Feature: Approving non-whitelisted Dependencies
As an application developer using license finder
I want to be able to manually approve dependencies that have licenses which fall outside of my whitelist
+ Scenario: Approving a non-whitelisted dependency via the `license_finder` command
+ Given I have an app with license finder
+ And my app depends on a gem "gpl_gem" licensed with "GPL"
+ When I run "license_finder"
+ When I run "license_finder -a gpl_gem"
+ Then I should see the "gpl_gem" in the html flagged as "approved"
+
Scenario: Manually approving a non-whitelisted dependency
Given I have an app with license finder
And my app depends on a gem "gpl_gem" licensed with "GPL"
@@ -25,4 +25,5 @@ def self.load_rake_tasks
end
end
+require 'erb'
require 'license_finder/railtie' if defined?(Rails)
@@ -32,7 +32,7 @@ def to_dependency
'summary' => @spec.summary,
'description' => @spec.description,
'homepage' => @spec.homepage,
- 'children' => @spec.dependencies
+ 'children' => @spec.dependencies.collect(&:name)
)
end
@@ -13,5 +13,16 @@ def check_for_action_items
exit 1
end
end
+
+ def execute! options={}
+ if options.has_key?(:approve)
+ dependency = Dependency.find_by_name(options[:approve])
+ dependency.approve!
+ puts "The #{dependency.name} has been approved!\n\n"
+ check_for_action_items
+ else
+ check_for_action_items
+ end
+ end
end
end
@@ -1,37 +1,115 @@
-# encoding: UTF-8
-require "erb"
-
module LicenseFinder
class Dependency
+ class Database
+ def initialize
+ @dependency_attributes = YAML.load File.read(LicenseFinder.config.dependencies_yaml) if File.exists?(LicenseFinder.config.dependencies_yaml)
+ end
+
+ def find(&block)
+ dependency_attributes.detect &block
+ end
+
+ def update(dependency_hash)
+ dependency_attributes.reject! { |a| a['name'] == dependency_hash['name'] }
+ dependency_attributes << dependency_hash
+ persist!
+ end
+
+ def delete_all
+ File.delete(LicenseFinder.config.dependencies_yaml) if File.exists?(LicenseFinder.config.dependencies_yaml)
+ @dependency_attributes = nil
+ end
+
+ def persist!
+ File.write(LicenseFinder.config.dependencies_yaml, dependency_attributes.to_yaml)
+ end
+
+ private
+ def dependency_attributes
+ @dependency_attributes ||= []
+ end
+ end
+
include Viewable
- attr_accessor :name, :version, :license, :approved, :license_url, :notes, :license_files,
- :readme_files, :source, :bundler_groups, :homepage, :children, :parents
+ ATTRIBUTE_NAMES = [
+ "name", "source", "version", "license", "license_url", "approved", "notes",
+ "license_files", "readme_files", "bundler_groups", "summary",
+ "description", "homepage", "children", "parents"
+ ]
+
+
+ attr_accessor *ATTRIBUTE_NAMES
attr_reader :summary, :description
def self.from_hash(attrs)
- attrs['license_files'] = attrs['license_files'].map { |lf| lf['path'] } if attrs['license_files']
- attrs['readme_files'] = attrs['readme_files'].map { |rf| rf['path'] } if attrs['readme_files']
-
new(attrs)
end
+ def self.find_by_name(name)
+ attributes = database.find { |a| a['name'] == name }
+ new(attributes) if attributes
+ end
+
+ def self.database
+ @database ||= Database.new
+ end
+
def initialize(attributes = {})
- @source = attributes['source']
- @name = attributes['name']
- @version = attributes['version']
- @license = attributes['license']
- @approved = attributes['approved'] || LicenseFinder.config.whitelist.include?(attributes['license'])
- @notes = attributes['notes'] || ''
- @license_files = attributes['license_files'] || []
- @readme_files = attributes['readme_files'] || []
- @bundler_groups = attributes['bundler_groups'] || []
- @summary = attributes['summary']
- @description = attributes['description']
- @homepage = attributes['homepage']
- @children = attributes.fetch('children', [])
- @parents = attributes.fetch('parents', [])
+ attributes.each do |key, value|
+ send("#{key}=", value)
+ end
+ end
+
+ def approved
+ return @approved if defined?(@approved)
+
+ @approved = LicenseFinder.config.whitelist.include?(license)
+ end
+
+ def notes
+ @notes ||= ''
+ end
+
+ def license_files
+ @license_files ||= []
+ end
+
+ def readme_files
+ @readme_files ||= []
+ end
+
+ def bundler_groups
+ @bundler_groups ||= []
+ end
+
+ def children
+ @children ||= []
+ end
+
+ def parents
+ @parents ||= []
+ end
+
+ def approve!
+ @approved = true
+ save!
+ end
+
+
+ def save!
+ self.class.database.update(attributes)
+ end
+
+ def attributes
+ attributes = {}
+
+ ATTRIBUTE_NAMES.each do |attrib|
+ attributes[attrib] = send attrib
+ end
+
+ attributes
end
def license_url
@@ -41,21 +119,7 @@ def license_url
def merge(other)
raise "Cannot merge dependencies with different names. Expected #{name}, was #{other.name}." unless other.name == name
- merged = self.class.new(
- 'name' => name,
- 'version' => other.version,
- 'license_files' => other.license_files,
- 'readme_files' => other.readme_files,
- 'license_url' => other.license_url,
- 'notes' => notes,
- 'source' => other.source,
- 'summary' => other.summary,
- 'description' => other.description,
- 'bundler_groups' => other.bundler_groups,
- 'homepage' => other.homepage,
- 'children' => other.children,
- 'parents' => other.parents
- )
+ merged = self.class.new(other.attributes.merge('notes' => notes))
case other.license
when license, 'other'
@@ -70,32 +134,7 @@ def merge(other)
end
def as_yaml
- attrs = {
- 'name' => name,
- 'version' => version,
- 'license' => license,
- 'approved' => approved,
- 'source' => source,
- 'license_url' => license_url,
- 'homepage' => homepage,
- 'notes' => notes,
- 'license_files' => nil,
- 'readme_files' => nil
- }
-
- unless license_files.empty?
- attrs['license_files'] = license_files.map do |file|
- {'path' => file}
- end
- end
-
- unless readme_files.empty?
- attrs['readme_files'] = readme_files.map do |file|
- {'path' => file}
- end
- end
-
- attrs
+ attributes
end
def to_s
@@ -20,21 +20,25 @@ def self.setup_parents_of_dependencies(dep_list)
dep_list.dependencies.each do |dep|
dep.children.each do |child_dep|
- license_finder_dependency = dependency_index[child_dep.name]
- license_finder_dependency.parents << dep if license_finder_dependency
+ license_finder_dependency = dependency_index[child_dep]
+ license_finder_dependency.parents << dep.name if license_finder_dependency
end
end
end
def self.from_yaml(yaml)
deps = YAML.load(yaml)
- new(deps.map { |attrs| Dependency.from_hash(attrs) })
+ new(deps.map { |attrs| Dependency.new(attrs) })
end
def initialize(dependencies)
@dependencies = dependencies
end
+ def save!
+ dependencies.map(&:save!)
+ end
+
def merge(new_list)
deps = new_list.dependencies.map do |new_dep|
old_dep = dependencies.detect { |d| d.name == new_dep.name }
@@ -25,7 +25,7 @@ def action_items
attr_reader :dependency_list
def save_reports
- write_file LicenseFinder.config.dependencies_yaml, dependency_list.to_yaml
+ dependency_list.save!
write_file LicenseFinder.config.dependencies_text, dependency_list.to_s
write_file LicenseFinder.config.dependencies_html, dependency_list.to_html
end
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module LicenseFinder
module Viewable
def self.included(base)
@@ -38,7 +38,7 @@
<dl>
<dt>Parents</dt>
<% parents.each do |parent| %>
- <dd><%= parent.name %></dd>
+ <dd><%= parent %></dd>
<% end %>
</dl>
<% end %>
@@ -47,7 +47,7 @@
<dl>
<dt>Children</dt>
<% children.each do |child| %>
- <dd><%= child.name %></dd>
+ <dd><%= child %></dd>
<% end %>
</dl>
<% end %>
@@ -10,6 +10,8 @@
s.summary = 'summary'
s.description = 'description'
s.homepage = 'homepage'
+
+ s.add_dependency 'foo'
end
end
@@ -118,6 +120,7 @@ def fixture_path(fixture)
its(:source) { should == 'bundle' }
its(:description) { should == 'description' }
its(:homepage) { should == 'homepage' }
+ its(:children) { should == ['foo']}
describe 'with a known license' do
before do
Oops, something went wrong.

0 comments on commit 0cccbad

Please sign in to comment.