papers 2.3.0 → 2.4.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.
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