papers 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04a56da48ddc413020f2fcd656e2db6e0e3b0ba8
4
- data.tar.gz: 94f31684ae3f21f18b919cefbb167f024045f5ad
3
+ metadata.gz: a501ec1855e2771a832413f8c6f7e64ef0914be5
4
+ data.tar.gz: edf999ee812b0b0991628f0a0136f500a22f424d
5
5
  SHA512:
6
- metadata.gz: e70b63d4c27b79bbc19a4144664738a933fbe31301d3a3c335bf5aae3e0bdae5ae6227034a41203b4cbb9772959b9977b66e3f31d71748966d15203c78520009
7
- data.tar.gz: 5a3a99002c51bc3f0529d6593e5193dd005d495e6afa4cf1e5f99dc00eee7f569f70622bc52de5be032d087d08a2b90c01ff1d0086580fddbf5493bdfd20cc5a
6
+ metadata.gz: dd676cdb983c3ca29c5709c7ae375440dffc8842f2f2d6aa5352083e4b9045eaeb9f574d9f7612981ff7e2a97a8a5a4d2daa2c89ee516ed8dc3b8ff97fe78665
7
+ data.tar.gz: 275ac6f253cf2cb95b6cbad2c33550318b88439080c654815f62b117932861ce38d4ed1a9f1c2933810c8ab3de495837da425b4afc80e90b2486604ff0e0bfd0
data/.travis.yml CHANGED
@@ -1,8 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
4
3
  - 2.0.0
5
- - 2.1.0
4
+ - 2.1.10
5
+ - 2.2.5
6
+ - 2.3.1
6
7
  script: bundle exec rspec
7
8
  notifications:
8
9
  email:
data/lib/papers.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'papers/configuration'
2
2
  require 'papers/license_validator'
3
+ require 'papers/manifest_command'
3
4
  require 'papers/manifest_generator'
5
+ require 'papers/manifest_updater'
4
6
  require 'papers/cli'
5
7
  require 'papers/version'
6
8
 
@@ -22,4 +24,4 @@ module Papers
22
24
  configuration
23
25
  end
24
26
 
25
- end
27
+ end
data/lib/papers/cli.rb CHANGED
@@ -5,18 +5,25 @@ module Papers
5
5
  class CLI
6
6
 
7
7
  def run
8
- if parse_options[:generate]
8
+ if options[:generate]
9
9
  begin
10
- generator = Papers::ManifestGenerator.new
11
- generator.generate!
10
+ Papers::ManifestGenerator.new.generate!
12
11
  rescue Papers::FileExistsError => e
13
12
  warn "Error: 'papers_manifest.yml' already exists at '#{e.message}'. Aborting..."
14
13
  end
15
14
  end
15
+
16
+ if options[:update]
17
+ Papers::ManifestUpdater.new.update!
18
+ end
16
19
  end
17
20
 
18
21
  private
19
22
 
23
+ def options
24
+ @options ||= parse_options
25
+ end
26
+
20
27
  def parse_options
21
28
  options = {}
22
29
  OptionParser.new do |opts|
@@ -26,6 +33,10 @@ module Papers
26
33
  options[:generate] = v
27
34
  end
28
35
 
36
+ opts.on("-u", "--update", "Update papers_manifest.yml for Rubygems") do |v|
37
+ options[:update] = v
38
+ end
39
+
29
40
  opts.on_tail( '-h', '--help', 'Display this screen' ) do |v|
30
41
  p opts
31
42
  exit
@@ -38,4 +49,4 @@ module Papers
38
49
  return options
39
50
  end
40
51
  end
41
- end
52
+ end
@@ -0,0 +1,97 @@
1
+ module Papers
2
+ class ManifestCommand
3
+ def initialize(manifest_path = nil)
4
+ @manifest_path = manifest_path || File.join('config', 'papers_manifest.yml')
5
+ end
6
+
7
+ def manifest_exists?
8
+ File.exist?(@manifest_path)
9
+ end
10
+
11
+ def build_header
12
+ [
13
+ "# Dependency Manifest for the Papers gem",
14
+ "# Used to test your gems and javascript against license whitelist",
15
+ "#",
16
+ "# http://github.com/newrelic/papers\n"
17
+ ].join("\n")
18
+ end
19
+
20
+ def get_installed_gems
21
+ gems = {}
22
+ Bundler.load.specs.each do |spec|
23
+ gems[gem_name_and_version(spec)] = gem_entry(spec)
24
+ end
25
+ return gems
26
+ end
27
+
28
+ def get_installed_javascripts
29
+ js = {}
30
+ Javascript.introspected.each do |entry|
31
+ js[entry] = {
32
+ 'license' => 'Unknown',
33
+ 'license_url' => nil,
34
+ 'project_url' => nil
35
+ }
36
+ end
37
+ js.empty? ? nil : js
38
+ end
39
+
40
+ def get_installed_bower_components
41
+ components = {}
42
+ BowerComponent.full_introspected_entries.each do |entry|
43
+ components[entry['name']] = {
44
+ 'license' => 'Unknown',
45
+ 'license_url' => nil,
46
+ 'project_url' => ensure_valid_url(entry['homepage'])
47
+ }
48
+ end
49
+ components.empty? ? nil : components
50
+ end
51
+
52
+ def get_installed_npm_packages
53
+ packages = {}
54
+ NpmPackage.full_introspected_entries.each do |entry|
55
+ packages[entry['name']] = {
56
+ 'license' => 'Unknown',
57
+ 'license_url' => nil,
58
+ 'project_url' => nil
59
+ }
60
+ end
61
+ packages.empty? ? nil : packages
62
+ end
63
+
64
+ def gem_name_and_version(spec)
65
+ if spec.name == 'bundler'
66
+ name_and_version = spec.name
67
+ else
68
+ name_and_version = "#{spec.name}-#{spec.version}"
69
+ end
70
+ end
71
+
72
+ def gem_entry(spec)
73
+ gem_license = blank?(spec.license) ? 'Unknown' : spec.license
74
+ gem_project_url = blank?(spec.homepage) ? nil : spec.homepage
75
+
76
+ {
77
+ 'license' => gem_license,
78
+ 'license_url' => nil,
79
+ 'project_url' => ensure_valid_url(gem_project_url)
80
+ # TODO: add support for multiple licenses? some gemspecs have dual licensing
81
+ }
82
+ end
83
+
84
+ def blank?(str)
85
+ str.to_s.empty?
86
+ end
87
+
88
+ def ensure_valid_url(url_string)
89
+ match_url = URI::regexp.match(url_string)
90
+ if match_url.nil?
91
+ nil
92
+ else
93
+ match_url[0]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -4,7 +4,6 @@ require 'fileutils'
4
4
  require 'uri'
5
5
 
6
6
  module Papers
7
-
8
7
  class FileExistsError < StandardError;
9
8
  attr_reader :manifest_path
10
9
 
@@ -14,11 +13,8 @@ module Papers
14
13
  end
15
14
  end
16
15
 
17
- class ManifestGenerator
18
-
16
+ class ManifestGenerator < ManifestCommand
19
17
  def generate!(args = ARGV)
20
- @manifest_path = File.join('config','papers_manifest.yml')
21
-
22
18
  raise Papers::FileExistsError.new(@manifest_path) if manifest_exists?
23
19
 
24
20
  begin
@@ -46,90 +42,6 @@ module Papers
46
42
  return manifest
47
43
  end
48
44
 
49
- def get_installed_gems
50
- gems = {}
51
- Bundler.load.specs.each do |spec|
52
- if spec.name == 'bundler'
53
- name_and_version = spec.name
54
- else
55
- name_and_version = "#{spec.name}-#{spec.version}"
56
- end
57
-
58
- gem_license = blank?(spec.license) ? 'Unknown' : spec.license
59
- gem_project_url = blank?(spec.homepage) ? nil : spec.homepage
60
-
61
- gems[name_and_version] = {
62
- 'license' => gem_license,
63
- 'license_url' => nil,
64
- 'project_url' => ensure_valid_url(gem_project_url)
65
- # TODO: add support for multiple licenses? some gemspecs have dual licensing
66
- }
67
- end
68
- return gems
69
- end
70
-
71
- def get_installed_javascripts
72
- js = {}
73
- Javascript.introspected.each do |entry|
74
- js[entry] = {
75
- 'license' => 'Unknown',
76
- 'license_url' => nil,
77
- 'project_url' => nil
78
- }
79
- end
80
- js.empty? ? nil : js
81
- end
82
-
83
- def get_installed_bower_components
84
- components = {}
85
- BowerComponent.full_introspected_entries.each do |entry|
86
- components[entry['name']] = {
87
- 'license' => 'Unknown',
88
- 'license_url' => nil,
89
- 'project_url' => ensure_valid_url(entry['homepage'])
90
- }
91
- end
92
- components.empty? ? nil : components
93
- end
94
-
95
- def get_installed_npm_packages
96
- packages = {}
97
- NpmPackage.full_introspected_entries.each do |entry|
98
- packages[entry['name']] = {
99
- 'license' => 'Unknown',
100
- 'license_url' => nil,
101
- 'project_url' => nil
102
- }
103
- end
104
- packages.empty? ? nil : packages
105
- end
106
-
107
- def manifest_exists?
108
- !!File.exist?(@manifest_path)
109
- end
110
-
111
- def build_header
112
- [
113
- "# Dependency Manifest for the Papers gem",
114
- "# Used to test your gems and javascript against license whitelist",
115
- "#",
116
- "# http://github.com/newrelic/papers\n"
117
- ].join("\n")
118
- end
119
-
120
- def ensure_valid_url url_string
121
- match_url = URI::regexp.match(url_string)
122
- if match_url.nil?
123
- nil
124
- else
125
- match_url[0]
126
- end
127
- end
128
-
129
- def blank? str
130
- str.respond_to?(:empty?) ? str.empty? : !str
131
- end
132
-
133
45
  end
134
46
 
135
47
  end
@@ -0,0 +1,113 @@
1
+ require 'bundler'
2
+ require 'yaml'
3
+ require 'fileutils'
4
+ require 'uri'
5
+
6
+ module Papers
7
+ class FileMissingError < StandardError
8
+ def initialize(file)
9
+ super("Manifest file #{file} missing, can't update.")
10
+ end
11
+ end
12
+
13
+ class ManifestUpdater < ManifestCommand
14
+ def update!
15
+ updated_content = update
16
+ File.open(@manifest_path, 'w') do |file|
17
+ file.write(updated_content)
18
+ end
19
+
20
+ puts "Updated #{@manifest_path}! Run your tests and check your diffs!"
21
+ end
22
+
23
+ def update
24
+ raise Papers::FileMissingError.new(@manifest_path) unless manifest_exists?
25
+
26
+ original_content = File.read(@manifest_path)
27
+ result = YAML.load(original_content)
28
+
29
+ update_gems(result)
30
+ update_javascript(result, "javascripts", get_installed_javascripts)
31
+ update_javascript(result, "bower_components", get_installed_bower_components)
32
+ update_javascript(result, "npm_packages", get_installed_npm_packages)
33
+
34
+ build_header + YAML.dump(result)
35
+ end
36
+
37
+ def update_gems(result)
38
+ result_gems = result["gems"]
39
+ return unless result_gems
40
+
41
+ manifest_names = manifest_names(result_gems)
42
+ gemspecs.each do |gemspec|
43
+ if manifest_gem_key = manifest_names[gemspec.name]
44
+ update_gem(result_gems, gemspec, manifest_gem_key)
45
+ else
46
+ new_gem(result_gems, gemspec)
47
+ end
48
+ end
49
+
50
+ delete_gems(result_gems, manifest_names)
51
+ end
52
+
53
+ def update_javascript(result, key, installed)
54
+ existing = result[key]
55
+ return unless existing && installed
56
+
57
+ removed = existing.keys - installed.keys
58
+
59
+ # Merge over new results from existing to keep edits
60
+ installed.merge!(existing)
61
+
62
+ # Remove things that aren't installed anymore
63
+ removed.each do |remove|
64
+ installed.delete(remove)
65
+ end
66
+
67
+ result[key] = installed
68
+ end
69
+
70
+ def update_gem(result_gems, gemspec, manifest_gem_key)
71
+ manifest_gem = result_gems.delete(manifest_gem_key)
72
+ if gemspec.license != manifest_gem["license"]
73
+ new_licenses = gemspec.licenses || []
74
+ new_licenses << gemspec.license
75
+ new_licenses.uniq!
76
+
77
+ manifest_gem["license"] = "License Change! Was '#{manifest_gem["license"]}', is now #{new_licenses}"
78
+ end
79
+
80
+ name = gem_name_and_version(gemspec)
81
+ name = gemspec.name if gemspec.name == manifest_gem_key
82
+ result_gems[name] = manifest_gem
83
+ end
84
+
85
+ def new_gem(result_gems, gemspec)
86
+ result_gems[gem_name_and_version(gemspec)] = gem_entry(gemspec)
87
+ end
88
+
89
+ def delete_gems(result_gems, manifest_names)
90
+ # Find removed gems
91
+ manifest_names.each do |(gem_name, gem_key)|
92
+ if gemspecs.none? { |gem| gem.name == gem_name }
93
+ result_gems.delete(gem_key)
94
+ end
95
+ end
96
+ end
97
+
98
+ def name_from_key(key)
99
+ key.include?("-") ? key.rpartition("-").first : key
100
+ end
101
+
102
+ def manifest_names(result_gems)
103
+ result_gems.reduce({}) do |hash, (key, _)|
104
+ hash[name_from_key(key)] = key
105
+ hash
106
+ end
107
+ end
108
+
109
+ def gemspecs
110
+ @gemspecs ||= Bundler.load.specs.dup
111
+ end
112
+ end
113
+ end
@@ -1,7 +1,7 @@
1
1
  module Papers
2
2
  class Version
3
3
  MAJOR = 2
4
- MINOR = 3
4
+ MINOR = 4
5
5
  PATCH = 0
6
6
 
7
7
  def self.to_s
@@ -0,0 +1,163 @@
1
+ require 'spec_helper'
2
+
3
+ describe Papers::ManifestUpdater do
4
+ subject(:updater) { Papers::ManifestUpdater.new(path) }
5
+
6
+ let(:path) { "/config/papers_manifest.yml" }
7
+
8
+ let(:header) { <<EOS
9
+ # Dependency Manifest for the Papers gem
10
+ # Used to test your gems and javascript against license whitelist
11
+ #
12
+ # http://github.com/newrelic/papers
13
+ ---
14
+ EOS
15
+ }
16
+
17
+ before do
18
+ allow(File).to receive(:read).and_call_original
19
+ allow(File).to receive(:read).with(path).and_return(original_content)
20
+
21
+ allow(File).to receive(:exist?).and_call_original
22
+ allow(File).to receive(:exist?).with(path).and_return(true)
23
+ end
24
+
25
+ describe "Ruby" do
26
+ let(:original_content) { <<EOS
27
+ #{header.chomp}
28
+ gems:
29
+ rails-4.2.0:
30
+ license: MIT
31
+ license_url:
32
+ project_url: https://github.com/rails/rails
33
+ newrelic_rpm:
34
+ license: New Relic
35
+ license_url:
36
+ project_url: https://github.com/newrelic/rpm
37
+ EOS
38
+ }
39
+
40
+ let(:shoes_license) { <<EOS
41
+ shoes-4.0.0:
42
+ license: MIT
43
+ license_url:
44
+ project_url: http://shoesrb.com
45
+ EOS
46
+ }
47
+
48
+
49
+ it "avoids unnecessary updates" do
50
+ allow(updater).to receive(:gemspecs).and_return([
51
+ double(name: 'rails', version: '4.2.0', license: "MIT"),
52
+ double(name: 'newrelic_rpm', version: '3.16.2.321', license: "New Relic")
53
+ ])
54
+
55
+ expect(updater.update).to eq(original_content)
56
+ end
57
+
58
+ it "updates version in place" do
59
+ allow(updater).to receive(:gemspecs).and_return([
60
+ double(name: 'rails', version: '4.2.7.1', license: "MIT"),
61
+ double(name: 'newrelic_rpm', version: '3.16.2.321', license: "New Relic")
62
+ ])
63
+
64
+ expected = original_content.gsub(/rails-4.2.0/, "rails-4.2.7.1")
65
+ expect(updater.update).to eq(expected)
66
+ end
67
+
68
+ it "adds new gems" do
69
+ allow(updater).to receive(:gemspecs).and_return([
70
+ double(name: 'rails', version: '4.2.0', license: "MIT"),
71
+ double(name: 'newrelic_rpm', version: '3.16.2.321', license: "New Relic"),
72
+ double(name: 'shoes', version: '4.0.0', license: "MIT", homepage: "http://shoesrb.com")
73
+ ])
74
+
75
+ expected = original_content + shoes_license
76
+ expect(updater.update).to eq(expected)
77
+ end
78
+
79
+ it "deletes removed gems" do
80
+ allow(updater).to receive(:gemspecs).and_return([
81
+ double(name: 'shoes', version: '4.0.0', license: "MIT", homepage: "http://shoesrb.com")
82
+ ])
83
+
84
+ expected = "#{header}gems:\n#{shoes_license}"
85
+ expect(updater.update).to eq(expected)
86
+ end
87
+
88
+ it "warns on change to license" do
89
+ allow(updater).to receive(:gemspecs).and_return([
90
+ double(name: 'rails', version: '5.0.0', license: "NOT-MIT", licenses: ["NOT-MIT"]),
91
+ double(name: 'newrelic_rpm', version: '3.16.2.321', license: "New Relic", licenses: ["New Relic"]),
92
+ ])
93
+
94
+ expected = original_content.gsub(/rails-4.2.0/, "rails-5.0.0").
95
+ sub(/MIT/, "License Change! Was 'MIT', is now [\"NOT-MIT\"]")
96
+ expect(updater.update).to eq(expected)
97
+ end
98
+ end
99
+
100
+ describe "Javascript" do
101
+ let(:original_content) { <<EOS
102
+ #{header.chomp}
103
+ javascripts:
104
+ app/javascripts/instances/index.js:
105
+ license: New Relic
106
+ license_url: http://newrelic.com
107
+ project_url: http://newrelic.com
108
+ app/javascripts/instances/show.js:
109
+ license: Unknown
110
+ license_url:
111
+ project_url:
112
+ bower_components:
113
+ angular:
114
+ license: MIT
115
+ license_url:
116
+ project_url:
117
+ lodash:
118
+ license: Unknown
119
+ license_url:
120
+ project_url:
121
+ npm_packages:
122
+ react:
123
+ license: MIT
124
+ license_url:
125
+ project_url:
126
+ redux:
127
+ license: Unknown
128
+ license_url:
129
+ project_url:
130
+ EOS
131
+ }
132
+
133
+ it "updates javascripts" do
134
+ allow(Papers::Javascript).to receive(:introspected).and_return([
135
+ "app/javascripts/instances/index.js",
136
+ "app/javascripts/instances/delete.js"
137
+ ])
138
+
139
+ expected = original_content.sub(%r{/instances/show.js}, "/instances/delete.js")
140
+ expect(updater.update).to eq(expected)
141
+ end
142
+
143
+ it "updates bower_components" do
144
+ allow(Papers::BowerComponent).to receive(:full_introspected_entries).and_return([
145
+ { "name" => "angular" },
146
+ { "name" => "bower" }
147
+ ])
148
+
149
+ expected = original_content.sub(/lodash/, "bower")
150
+ expect(updater.update).to eq(expected)
151
+ end
152
+
153
+ it "updates npm_packages" do
154
+ allow(Papers::NpmPackage).to receive(:full_introspected_entries).and_return([
155
+ { "name" => "react" },
156
+ { "name" => "flow" }
157
+ ])
158
+
159
+ expected = original_content.sub(/redux/, "flow")
160
+ expect(updater.update).to eq(expected)
161
+ end
162
+ end
163
+ end
@@ -1,5 +1,3 @@
1
- require 'bundler/setup'
2
- require 'rspec'
3
1
  require_relative '../lib/papers'
4
2
 
5
3
  describe 'NpmPackageSpecification' do
data/spec/papers_spec.rb CHANGED
@@ -1,6 +1,4 @@
1
- require 'bundler/setup'
2
- require 'rspec'
3
- require_relative '../lib/papers'
1
+ require 'spec_helper'
4
2
 
5
3
  describe 'Papers' do
6
4
 
@@ -0,0 +1,3 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+ require_relative '../lib/papers'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papers
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ralph Bodenner
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-10-12 00:00:00.000000000 Z
15
+ date: 2016-10-13 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rake
@@ -69,11 +69,15 @@ files:
69
69
  - lib/papers/dependency_specification/javascript.rb
70
70
  - lib/papers/dependency_specification/npm_package.rb
71
71
  - lib/papers/license_validator.rb
72
+ - lib/papers/manifest_command.rb
72
73
  - lib/papers/manifest_generator.rb
74
+ - lib/papers/manifest_updater.rb
73
75
  - lib/papers/version.rb
74
76
  - papers.gemspec
77
+ - spec/manifest_updater_spec.rb
75
78
  - spec/npm_package_spec.rb
76
79
  - spec/papers_spec.rb
80
+ - spec/spec_helper.rb
77
81
  - spec/support/package.json
78
82
  - spec/support/package_with_error.json
79
83
  homepage: http://github.com/newrelic/papers
@@ -96,12 +100,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
100
  version: '0'
97
101
  requirements: []
98
102
  rubyforge_project:
99
- rubygems_version: 2.4.8
103
+ rubygems_version: 2.6.2
100
104
  signing_key:
101
105
  specification_version: 4
102
106
  summary: Validate the licenses of software dependencies you use
103
107
  test_files:
108
+ - spec/manifest_updater_spec.rb
104
109
  - spec/npm_package_spec.rb
105
110
  - spec/papers_spec.rb
111
+ - spec/spec_helper.rb
106
112
  - spec/support/package.json
107
113
  - spec/support/package_with_error.json