spandx 0.1.1 → 0.1.2

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
  SHA256:
3
- metadata.gz: 79b4eefa834b1649c1cced69cd4666bdabb22f42383cb177545042e3c643eac9
4
- data.tar.gz: e0c3e8836e82c3b34eed0c83d0cdca7212334e87030fb900ae8152e1fa13ffb5
3
+ metadata.gz: a8c7d63af4cdd331e0f9ab51eb895797567278365cc1029dbbe07744158cb5f4
4
+ data.tar.gz: d8cb97dfc05729a577a95c358d2a8397b43bd4628925bf3bcb55b282d6042ee8
5
5
  SHA512:
6
- metadata.gz: 492a1ed30bb41f77c748c6ad70aa258ae16e74d2ee2e8bb437def781d72389403c6a67baf90d728c13971e9a1cf47c5f9535a63f2b754870f936ccb81d73ff3c
7
- data.tar.gz: 6c4281a992017b9dc07e9837426f862a5daa7514f20fa01674896a502b5356c31ab9877ac2e8372fbf39d07f97b21bf1eb3eb50f294dcc88a68ec92e69599e48
6
+ metadata.gz: 252c70cd5862c795eede663242f22b4be188c35a950fa55f41f1b324f9e6ee73b8a1a4bebf3d875fbd68b640359db6e20d5c0bbdd42e90dc640470a5fa91d7ad
7
+ data.tar.gz: 14a5bc5fe4ad89de5288df9ea6425d234d25daced1c6429e17563809ec666109c9b8ba668881cf32b5528c480b44a0fa32b3f57c33bb2608f123c2fd3c62d498
@@ -0,0 +1,13 @@
1
+ name: ci
2
+ on: [push]
3
+ jobs:
4
+ build:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v1
8
+ - name: Set up Ruby 2.6
9
+ uses: actions/setup-ruby@v1
10
+ with:
11
+ ruby-version: 2.6.x
12
+ - name: Run cibuild
13
+ run: bin/cibuild
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ *.log
data/.rubocop.yml CHANGED
@@ -3,46 +3,24 @@ require:
3
3
 
4
4
  AllCops:
5
5
  Exclude:
6
- - 'coverage/**/*'
7
6
  - 'pkg/**/*'
8
7
  - 'spec/fixtures/**/*'
9
- - 'tmp/**/*'
10
- - 'vendor/**/*'
11
8
  TargetRubyVersion: 2.6
12
9
 
13
- Layout/AlignArguments:
10
+ Layout/ArgumentAlignment:
14
11
  EnforcedStyle: with_fixed_indentation
15
12
 
16
- Layout/AlignParameters:
13
+ Layout/ParameterAlignment:
17
14
  Enabled: true
18
15
  EnforcedStyle: with_fixed_indentation
19
16
  IndentationWidth: 2
20
17
 
21
- Layout/ClassStructure:
22
- Enabled: true
23
- Categories:
24
- module_inclusion:
25
- - include
26
- - prepend
27
- - extend
28
- ExpectedOrder:
29
- - module_inclusion
30
- - constants
31
- - public_class_methods
32
- - initializer
33
- - instance_methods
34
- - protected_methods
35
- - private_methods
36
-
37
18
  Layout/EndOfLine:
38
19
  EnforcedStyle: lf
39
20
 
40
- Layout/IndentFirstArrayElement:
21
+ Layout/FirstArrayElementIndentation:
41
22
  EnforcedStyle: consistent
42
23
 
43
- Layout/IndentHeredoc:
44
- EnforcedStyle: active_support
45
-
46
24
  Layout/MultilineMethodCallIndentation:
47
25
  Enabled: true
48
26
  EnforcedStyle: indented
@@ -51,14 +29,8 @@ Lint/AmbiguousBlockAssociation:
51
29
  Exclude:
52
30
  - 'spec/**/*.rb'
53
31
 
54
- Lint/InterpolationCheck:
55
- Exclude:
56
- - 'spec/**/*.rb'
57
-
58
32
  Metrics/BlockLength:
59
33
  Exclude:
60
- - '**/**/*.builder'
61
- - '**/*.rake'
62
34
  - '*.gemspec'
63
35
  - 'Rakefile'
64
36
  - 'spec/**/*.rb'
@@ -69,24 +41,16 @@ Metrics/ModuleLength:
69
41
 
70
42
  Metrics/LineLength:
71
43
  Exclude:
72
- - 'lib/saml/kit/builders/templates/*.builder'
73
44
  - 'spec/**/*.rb'
74
45
  IgnoredPatterns:
75
46
  - '^#*'
76
47
 
77
- Naming/FileName:
78
- Exclude:
79
- - 'lib/saml-kit.rb'
80
-
81
48
  Naming/RescuedExceptionsVariableName:
82
49
  PreferredName: error
83
50
 
84
51
  Style/Documentation:
85
52
  Enabled: false
86
53
 
87
- Style/EachWithObject:
88
- Enabled: false
89
-
90
54
  Style/StringLiterals:
91
55
  EnforcedStyle: 'single_quotes'
92
56
 
@@ -99,14 +63,12 @@ Style/TrailingCommaInHashLiteral:
99
63
  RSpec/ExampleLength:
100
64
  Max: 80
101
65
 
102
- RSpec/MultipleExpectations:
103
- Enabled: false
104
-
105
66
  RSpec/NamedSubject:
106
67
  Enabled: false
107
68
 
108
- RSpec/NestedGroups:
109
- Max: 7
110
-
111
- RSpec/SubjectStub:
69
+ RSpec/FilePath:
112
70
  Enabled: false
71
+
72
+ RSpec/DescribeClass:
73
+ Exclude:
74
+ - 'spec/integration/**/*'
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ Version 0.1.2
2
+
3
+ # Changelog
4
+ All notable changes to this project will be documented in this file.
5
+
6
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
7
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
+
9
+ ## [Unreleased]
10
+ - nil
11
+
12
+ ## [0.1.2] - 2020-01-16
13
+ ### Added
14
+ - Add CLI for `spandx scan <LOCKER>`
15
+ - Parse Gemfile.lock for dependencies.
16
+ - Parse Pipfile.lock for dependencies.
17
+ - Allow lookup for a specific license by id
18
+
19
+ ## [0.1.1] - 2019-10-05
20
+ ### Added
21
+ - Provide ruby API to the latest SPDX catalogue.
22
+
23
+ [Unreleased]: https://github.com/mokhan/spandx/compare/v0.1.2...HEAD
24
+ [0.1.2]: https://github.com/mokhan/spandx/compare/v0.1.1...v0.1.2
25
+ [0.1.1]: https://github.com/mokhan/spandx/compare/v0.1.0...v0.1.1
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spandx (0.1.1)
5
- net-hippie (~> 0.2)
4
+ spandx (0.1.2)
5
+ net-hippie (~> 0.3)
6
+ thor (~> 0.1)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
@@ -17,35 +18,35 @@ GEM
17
18
  safe_yaml (~> 1.0.0)
18
19
  diff-lcs (1.3)
19
20
  hashdiff (1.0.0)
20
- jaro_winkler (1.5.3)
21
- net-hippie (0.2.6)
22
- parallel (1.17.0)
23
- parser (2.6.5.0)
21
+ jaro_winkler (1.5.4)
22
+ net-hippie (0.3.1)
23
+ parallel (1.19.1)
24
+ parser (2.7.0.0)
24
25
  ast (~> 2.4.0)
25
- public_suffix (4.0.1)
26
+ public_suffix (4.0.2)
26
27
  rainbow (3.0.0)
27
- rake (10.5.0)
28
- rspec (3.8.0)
29
- rspec-core (~> 3.8.0)
30
- rspec-expectations (~> 3.8.0)
31
- rspec-mocks (~> 3.8.0)
32
- rspec-core (3.8.2)
33
- rspec-support (~> 3.8.0)
34
- rspec-expectations (3.8.5)
28
+ rake (13.0.1)
29
+ rspec (3.9.0)
30
+ rspec-core (~> 3.9.0)
31
+ rspec-expectations (~> 3.9.0)
32
+ rspec-mocks (~> 3.9.0)
33
+ rspec-core (3.9.0)
34
+ rspec-support (~> 3.9.0)
35
+ rspec-expectations (3.9.0)
35
36
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.8.0)
37
- rspec-mocks (3.8.2)
37
+ rspec-support (~> 3.9.0)
38
+ rspec-mocks (3.9.0)
38
39
  diff-lcs (>= 1.2.0, < 2.0)
39
- rspec-support (~> 3.8.0)
40
- rspec-support (3.8.3)
41
- rubocop (0.75.0)
40
+ rspec-support (~> 3.9.0)
41
+ rspec-support (3.9.0)
42
+ rubocop (0.78.0)
42
43
  jaro_winkler (~> 1.5.1)
43
44
  parallel (~> 1.10)
44
45
  parser (>= 2.6)
45
46
  rainbow (>= 2.2.2, < 4.0)
46
47
  ruby-progressbar (~> 1.7)
47
48
  unicode-display_width (>= 1.4.0, < 1.7)
48
- rubocop-rspec (1.36.0)
49
+ rubocop-rspec (1.37.1)
49
50
  rubocop (>= 0.68.1)
50
51
  ruby-progressbar (1.10.1)
51
52
  safe_yaml (1.0.5)
@@ -62,7 +63,7 @@ PLATFORMS
62
63
  DEPENDENCIES
63
64
  bundler (~> 2.0)
64
65
  bundler-audit (~> 0.6)
65
- rake (~> 10.0)
66
+ rake (~> 13.0)
66
67
  rspec (~> 3.0)
67
68
  rubocop (~> 0.52)
68
69
  rubocop-rspec (~> 1.22)
@@ -70,4 +71,4 @@ DEPENDENCIES
70
71
  webmock (~> 3.7)
71
72
 
72
73
  BUNDLED WITH
73
- 2.0.2
74
+ 2.1.2
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Spandx
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/spandx`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ A ruby API for interacting with the https://spdx.org software license catalogue.
4
4
 
5
+ ![badge](https://github.com/mokhan/spandx/workflows/ci/badge.svg)
5
6
 
6
7
  ## Installation
7
8
 
@@ -21,7 +22,7 @@ Or install it yourself as:
21
22
 
22
23
  ## Usage
23
24
 
24
- TODO: Write usage instructions here
25
+ To fetch the latest version of the catalogue data from [SPDX](https://spdx.org/licenses/licenses.json).
25
26
 
26
27
  ```ruby
27
28
  catalogue = Spandx::Catalogue.latest
@@ -30,6 +31,16 @@ catalogue.each do |license|
30
31
  end
31
32
  ```
32
33
 
34
+ To load an offline copy of the data.
35
+
36
+ ```ruby
37
+ path = File.join(Dir.pwd, 'licenses.json')
38
+ catalogue = Spandx::Catalogue.from_file(path)
39
+ catalogue.each do |license|
40
+ puts license.inspect
41
+ end
42
+ ```
43
+
33
44
  ## Development
34
45
 
35
46
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/cibuild` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -38,7 +49,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
38
49
 
39
50
  ## Contributing
40
51
 
41
- Bug reports and pull requests are welcome on GitLab at https://gitlab.com/xlgmokha/spandx.
52
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mokhan/spandx.
42
53
 
43
54
  ## License
44
55
 
data/exe/spandx CHANGED
@@ -1,4 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'spandx'
4
+ lib_path = File.expand_path('../lib', __dir__)
5
+ $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
6
+ require 'spandx/cli'
7
+
8
+ Signal.trap('INT') do
9
+ warn("\n#{caller.join("\n")}: interrupted")
10
+ exit(1)
11
+ end
12
+
13
+ begin
14
+ Spandx::CLI.start
15
+ rescue Spandx::CLI::Error => error
16
+ puts "ERROR: #{error.message}"
17
+ exit 1
18
+ end
@@ -8,6 +8,10 @@ module Spandx
8
8
  @catalogue = catalogue
9
9
  end
10
10
 
11
+ def [](id)
12
+ identity_map[id]
13
+ end
14
+
11
15
  def version
12
16
  catalogue[:licenseListVersion]
13
17
  end
@@ -18,8 +22,18 @@ module Spandx
18
22
  end
19
23
  end
20
24
 
21
- def self.latest
22
- CatalogueGateway.new.fetch
25
+ class << self
26
+ def latest(gateway: ::Spandx::Gateways::Spdx.new)
27
+ gateway.fetch
28
+ end
29
+
30
+ def from_file(path)
31
+ new(JSON.parse(IO.read(path), symbolize_names: true))
32
+ end
33
+
34
+ def empty
35
+ @empty ||= new(licenses: [])
36
+ end
23
37
  end
24
38
 
25
39
  private
@@ -27,7 +41,7 @@ module Spandx
27
41
  attr_reader :catalogue
28
42
 
29
43
  def licenses
30
- @licenses ||= catalogue.fetch(:licenses, []).map { |x| map_from(x) }
44
+ @licenses ||= identity_map.values
31
45
  end
32
46
 
33
47
  def map_from(license_hash)
@@ -37,5 +51,13 @@ module Spandx
37
51
  def present?(item)
38
52
  item && !item.empty?
39
53
  end
54
+
55
+ def identity_map
56
+ @identity_map ||=
57
+ catalogue.fetch(:licenses, []).each_with_object({}) do |hash, memo|
58
+ license = map_from(hash)
59
+ memo[license.id] = license if present?(license.id)
60
+ end
61
+ end
40
62
  end
41
63
  end
data/lib/spandx/cli.rb ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ require 'spandx'
6
+ require 'spandx/command'
7
+ require 'spandx/commands/scan'
8
+
9
+ module Spandx
10
+ class CLI < Thor
11
+ Error = Class.new(StandardError)
12
+
13
+ desc 'version', 'spandx version'
14
+ def version
15
+ puts "v#{Spandx::VERSION}"
16
+ end
17
+ map %w[--version -v] => :version
18
+
19
+ desc 'scan LOCKFILE', 'Command description...'
20
+ method_option :help, aliases: '-h', type: :boolean,
21
+ desc: 'Display usage information'
22
+ def scan(lockfile = nil)
23
+ if options[:help]
24
+ invoke :help, ['scan']
25
+ else
26
+ Spandx::Commands::Scan.new(lockfile, options).execute
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ class Command
5
+ extend Forwardable
6
+
7
+ def_delegators :command, :run
8
+
9
+ # Execute this command
10
+ #
11
+ # @api public
12
+ def execute(*)
13
+ raise(
14
+ NotImplementedError,
15
+ "#{self.class}##{__method__} must be implemented"
16
+ )
17
+ end
18
+
19
+ # The external commands runner
20
+ #
21
+ # @see http://www.rubydoc.info/gems/tty-command
22
+ #
23
+ # @api public
24
+ def command(**options)
25
+ require 'tty-command'
26
+ TTY::Command.new(options)
27
+ end
28
+
29
+ # The cursor movement
30
+ #
31
+ # @see http://www.rubydoc.info/gems/tty-cursor
32
+ #
33
+ # @api public
34
+ def cursor
35
+ require 'tty-cursor'
36
+ TTY::Cursor
37
+ end
38
+
39
+ # Open a file or text in the user's preferred editor
40
+ #
41
+ # @see http://www.rubydoc.info/gems/tty-editor
42
+ #
43
+ # @api public
44
+ def editor
45
+ require 'tty-editor'
46
+ TTY::Editor
47
+ end
48
+
49
+ # File manipulation utility methods
50
+ #
51
+ # @see http://www.rubydoc.info/gems/tty-file
52
+ #
53
+ # @api public
54
+ def generator
55
+ require 'tty-file'
56
+ TTY::File
57
+ end
58
+
59
+ # Terminal output paging
60
+ #
61
+ # @see http://www.rubydoc.info/gems/tty-pager
62
+ #
63
+ # @api public
64
+ def pager(**options)
65
+ require 'tty-pager'
66
+ TTY::Pager.new(options)
67
+ end
68
+
69
+ # Terminal platform and OS properties
70
+ #
71
+ # @see http://www.rubydoc.info/gems/tty-pager
72
+ #
73
+ # @api public
74
+ def platform
75
+ require 'tty-platform'
76
+ TTY::Platform.new
77
+ end
78
+
79
+ # The interactive prompt
80
+ #
81
+ # @see http://www.rubydoc.info/gems/tty-prompt
82
+ #
83
+ # @api public
84
+ def prompt(**options)
85
+ require 'tty-prompt'
86
+ TTY::Prompt.new(options)
87
+ end
88
+
89
+ # Get terminal screen properties
90
+ #
91
+ # @see http://www.rubydoc.info/gems/tty-screen
92
+ #
93
+ # @api public
94
+ def screen
95
+ require 'tty-screen'
96
+ TTY::Screen
97
+ end
98
+
99
+ # The unix which utility
100
+ #
101
+ # @see http://www.rubydoc.info/gems/tty-which
102
+ #
103
+ # @api public
104
+ def which(*args)
105
+ require 'tty-which'
106
+ TTY::Which.which(*args)
107
+ end
108
+
109
+ # Check if executable exists
110
+ #
111
+ # @see http://www.rubydoc.info/gems/tty-which
112
+ #
113
+ # @api public
114
+ def exec_exist?(*args)
115
+ require 'tty-which'
116
+ TTY::Which.exist?(*args)
117
+ end
118
+ end
119
+ end
File without changes
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Commands
5
+ class Scan < Spandx::Command
6
+ attr_reader :lockfile
7
+
8
+ def initialize(lockfile, options)
9
+ @lockfile = lockfile ? Pathname.new(File.expand_path(lockfile)) : nil
10
+ @options = options
11
+ end
12
+
13
+ def execute(output: $stdout)
14
+ if lockfile.nil?
15
+ output.puts 'OK'
16
+ else
17
+ report = Parsers.for(lockfile).parse(lockfile)
18
+ output.puts report.to_json
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Gateways
5
+ class Http
6
+ attr_reader :driver
7
+
8
+ def initialize(driver: Http.default_driver)
9
+ @driver = driver
10
+ end
11
+
12
+ def get(uri, default: nil)
13
+ driver.with_retry do |client|
14
+ client.get(uri)
15
+ end
16
+ rescue *Net::Hippie::CONNECTION_ERRORS
17
+ default
18
+ end
19
+
20
+ def ok?(response)
21
+ response.is_a?(Net::HTTPSuccess)
22
+ end
23
+
24
+ def self.default_driver
25
+ @default_driver ||= Net::Hippie::Client.new.tap do |client|
26
+ client.logger = ::Logger.new('http.log')
27
+ client.follow_redirects = 3
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Gateways
5
+ class PyPI
6
+ class Source
7
+ attr_reader :name, :uri, :verify_ssl
8
+
9
+ def initialize(source)
10
+ @name = source['name']
11
+ @uri = URI.parse(source['url'])
12
+ @verify_ssl = source['verify_ssl']
13
+ end
14
+
15
+ def host
16
+ @uri.host
17
+ end
18
+
19
+ def uri_for(name, version)
20
+ URI.parse("https://#{host}/pypi/#{name}/#{version}/json")
21
+ end
22
+
23
+ def lookup(name, version, http: Spandx.http)
24
+ response = http.get(uri_for(name, version))
25
+ response if http.ok?(response)
26
+ end
27
+
28
+ class << self
29
+ def sources_from(json)
30
+ meta = json['_meta']
31
+ meta['sources'].map do |hash|
32
+ Gateways::PyPI::Source.new(hash)
33
+ end
34
+ end
35
+
36
+ def default
37
+ new(
38
+ 'name' => 'pypi',
39
+ 'url' => 'https://pypi.org/simple',
40
+ 'verify_ssl' => true
41
+ )
42
+ end
43
+ end
44
+ end
45
+
46
+ def initialize(sources: [Source.default])
47
+ @sources = sources
48
+ end
49
+
50
+ def definition_for(name, version)
51
+ @sources.each do |source|
52
+ response = source.lookup(name, version)
53
+ return JSON.parse(response.body).fetch('info', {}) if response
54
+ end
55
+ {}
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Gateways
5
+ class Spdx
6
+ URL = 'https://spdx.org/licenses/licenses.json'
7
+
8
+ def fetch(url: URL, http: Spandx.http, default: Catalogue.empty)
9
+ response = http.get(url, default: default)
10
+ http.ok?(response) ? parse(response.body) : default
11
+ end
12
+
13
+ private
14
+
15
+ def parse(json)
16
+ Catalogue.new(JSON.parse(json, symbolize_names: true))
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Parsers
5
+ class Base
6
+ attr_reader :catalogue
7
+
8
+ def initialize(catalogue:)
9
+ @catalogue = catalogue
10
+ end
11
+
12
+ class << self
13
+ include Enumerable
14
+
15
+ def each(&block)
16
+ registry.each do |x|
17
+ block.call(x)
18
+ end
19
+ end
20
+
21
+ def inherited(subclass)
22
+ registry.push(subclass)
23
+ end
24
+
25
+ def registry
26
+ @registry ||= []
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Parsers
5
+ class GemfileLock < Base
6
+ def self.matches?(filename)
7
+ filename.match?(/Gemfile.*\.lock/)
8
+ end
9
+
10
+ def parse(lockfile)
11
+ report = Report.new
12
+ dependencies_from(lockfile) do |dependency|
13
+ spec = dependency.to_spec
14
+ report.add(
15
+ name: dependency.name,
16
+ version: spec.version.to_s,
17
+ licenses: [catalogue[spec.license]]
18
+ )
19
+ end
20
+ report
21
+ end
22
+
23
+ private
24
+
25
+ def dependencies_from(lockfile)
26
+ ::Bundler::LockfileParser
27
+ .new(IO.read(lockfile))
28
+ .dependencies.each do |_key, dependency|
29
+ yield dependency
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Parsers
5
+ class PipfileLock < Base
6
+ def self.matches?(filename)
7
+ filename.match?(/Pipfile.*\.lock/)
8
+ end
9
+
10
+ def parse(lockfile)
11
+ report = Report.new
12
+ dependencies_from(lockfile) do |x|
13
+ report.add(
14
+ name: x[:name],
15
+ version: x[:version],
16
+ licenses: x[:licenses]
17
+ )
18
+ end
19
+ report
20
+ end
21
+
22
+ private
23
+
24
+ def dependencies_from(lockfile)
25
+ json = JSON.parse(IO.read(lockfile))
26
+ each_dependency(pypi_for(json), json) do |name, version, definition|
27
+ yield({ name: name, version: version, licenses: [catalogue[definition['license']]] })
28
+ end
29
+ end
30
+
31
+ def each_dependency(pypi, json, groups: %w[default develop])
32
+ groups.each do |group|
33
+ json[group].each do |name, value|
34
+ version = canonicalize(value['version'])
35
+ yield name, version, pypi.definition_for(name, version)
36
+ end
37
+ end
38
+ end
39
+
40
+ def canonicalize(version)
41
+ version.gsub(/==/, '')
42
+ end
43
+
44
+ def pypi_for(json)
45
+ Gateways::PyPI.new(
46
+ sources: Gateways::PyPI::Source.sources_from(json)
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spandx/parsers/base'
4
+ require 'spandx/parsers/gemfile_lock'
5
+ require 'spandx/parsers/pipfile_lock'
6
+
7
+ module Spandx
8
+ module Parsers
9
+ class << self
10
+ def for(path, catalogue: Spandx::Catalogue.latest)
11
+ result = ::Spandx::Parsers::Base.find do |x|
12
+ x.matches?(File.basename(path))
13
+ end
14
+
15
+ result&.new(catalogue: catalogue)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ class Report
5
+ def initialize(report: { version: '1.0', packages: [] })
6
+ @report = report
7
+ end
8
+
9
+ def add(name:, version:, licenses: [])
10
+ @report[:packages].push(
11
+ name: name,
12
+ version: version,
13
+ licenses: licenses.map(&:id)
14
+ )
15
+ end
16
+
17
+ def to_h
18
+ @report
19
+ end
20
+
21
+ def to_json(*_args)
22
+ JSON.pretty_generate(to_h)
23
+ end
24
+ end
25
+ end
File without changes
@@ -0,0 +1 @@
1
+ #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spandx
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/spandx.rb CHANGED
@@ -1,11 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+ require 'json'
3
5
  require 'net/hippie'
6
+
4
7
  require 'spandx/catalogue'
5
- require 'spandx/catalogue_gateway'
8
+ require 'spandx/gateways/http'
9
+ require 'spandx/gateways/pypi'
10
+ require 'spandx/gateways/spdx'
6
11
  require 'spandx/license'
12
+ require 'spandx/parsers'
13
+ require 'spandx/report'
7
14
  require 'spandx/version'
8
15
 
9
16
  module Spandx
10
17
  class Error < StandardError; end
18
+
19
+ class << self
20
+ def root
21
+ Pathname.new(File.dirname(__FILE__)).join('../..')
22
+ end
23
+
24
+ def http
25
+ @http ||= Spandx::Gateways::Http.new
26
+ end
27
+ end
11
28
  end
data/spandx.gemspec CHANGED
@@ -12,12 +12,12 @@ Gem::Specification.new do |spec|
12
12
 
13
13
  spec.summary = 'A ruby interface to the SPDX catalogue.'
14
14
  spec.description = 'A ruby interface to the SPDX catalogue.'
15
- spec.homepage = 'https://gitlab.com/xlgmokha/spandx'
15
+ spec.homepage = 'https://github.com/mokhan/spandx'
16
16
  spec.license = 'MIT'
17
17
 
18
18
  spec.metadata['homepage_uri'] = spec.homepage
19
- spec.metadata['source_code_uri'] = 'https://gitlab.com/xlgmokha/spandx'
20
- spec.metadata['changelog_uri'] = 'https://gitlab.com/xlgmokha/spandx/blob/master/CHANGELOG.md'
19
+ spec.metadata['source_code_uri'] = 'https://github.com/mokhan/spandx'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/mokhan/spandx/blob/master/CHANGELOG.md'
21
21
 
22
22
  # Specify which files should be added to the gem when it is released.
23
23
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -28,10 +28,11 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
30
 
31
- spec.add_dependency 'net-hippie', '~> 0.2'
31
+ spec.add_dependency 'net-hippie', '~> 0.3'
32
+ spec.add_dependency 'thor', '~> 0.1'
32
33
  spec.add_development_dependency 'bundler', '~> 2.0'
33
34
  spec.add_development_dependency 'bundler-audit', '~> 0.6'
34
- spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rake', '~> 13.0'
35
36
  spec.add_development_dependency 'rspec', '~> 3.0'
36
37
  spec.add_development_dependency 'rubocop', '~> 0.52'
37
38
  spec.add_development_dependency 'rubocop-rspec', '~> 1.22'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spandx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-05 00:00:00.000000000 Z
11
+ date: 2020-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-hippie
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.2'
19
+ version: '0.3'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.2'
26
+ version: '0.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +72,14 @@ dependencies:
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '10.0'
75
+ version: '13.0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '10.0'
82
+ version: '13.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -130,11 +144,12 @@ executables:
130
144
  extensions: []
131
145
  extra_rdoc_files: []
132
146
  files:
147
+ - ".github/workflows/ci.yml"
133
148
  - ".gitignore"
134
149
  - ".gitlab-ci.yml"
135
150
  - ".rspec"
136
151
  - ".rubocop.yml"
137
- - ".travis.yml"
152
+ - CHANGELOG.md
138
153
  - Gemfile
139
154
  - Gemfile.lock
140
155
  - LICENSE.txt
@@ -149,17 +164,30 @@ files:
149
164
  - exe/spandx
150
165
  - lib/spandx.rb
151
166
  - lib/spandx/catalogue.rb
152
- - lib/spandx/catalogue_gateway.rb
167
+ - lib/spandx/cli.rb
168
+ - lib/spandx/command.rb
169
+ - lib/spandx/commands/.gitkeep
170
+ - lib/spandx/commands/scan.rb
171
+ - lib/spandx/gateways/http.rb
172
+ - lib/spandx/gateways/pypi.rb
173
+ - lib/spandx/gateways/spdx.rb
153
174
  - lib/spandx/license.rb
175
+ - lib/spandx/parsers.rb
176
+ - lib/spandx/parsers/base.rb
177
+ - lib/spandx/parsers/gemfile_lock.rb
178
+ - lib/spandx/parsers/pipfile_lock.rb
179
+ - lib/spandx/report.rb
180
+ - lib/spandx/templates/.gitkeep
181
+ - lib/spandx/templates/scan/.gitkeep
154
182
  - lib/spandx/version.rb
155
183
  - spandx.gemspec
156
- homepage: https://gitlab.com/xlgmokha/spandx
184
+ homepage: https://github.com/mokhan/spandx
157
185
  licenses:
158
186
  - MIT
159
187
  metadata:
160
- homepage_uri: https://gitlab.com/xlgmokha/spandx
161
- source_code_uri: https://gitlab.com/xlgmokha/spandx
162
- changelog_uri: https://gitlab.com/xlgmokha/spandx/blob/master/CHANGELOG.md
188
+ homepage_uri: https://github.com/mokhan/spandx
189
+ source_code_uri: https://github.com/mokhan/spandx
190
+ changelog_uri: https://github.com/mokhan/spandx/blob/master/CHANGELOG.md
163
191
  post_install_message:
164
192
  rdoc_options: []
165
193
  require_paths:
@@ -175,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
175
203
  - !ruby/object:Gem::Version
176
204
  version: '0'
177
205
  requirements: []
178
- rubygems_version: 3.0.3
206
+ rubygems_version: 3.1.2
179
207
  signing_key:
180
208
  specification_version: 4
181
209
  summary: A ruby interface to the SPDX catalogue.
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.4
7
- before_install: gem install bundler -v 2.0.2
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Spandx
4
- class CatalogueGateway
5
- URL = 'https://spdx.org/licenses/licenses.json'
6
-
7
- def initialize(http: default_client)
8
- @http = http
9
- end
10
-
11
- def fetch(url: URL)
12
- response = http.get(url)
13
-
14
- if response.code == '200'
15
- parse(response.body)
16
- else
17
- empty_catalogue
18
- end
19
- rescue *::Net::Hippie::CONNECTION_ERRORS
20
- empty_catalogue
21
- end
22
-
23
- private
24
-
25
- attr_reader :http
26
-
27
- def parse(json)
28
- build_catalogue(JSON.parse(json, symbolize_names: true))
29
- end
30
-
31
- def empty_catalogue
32
- build_catalogue(licenses: [])
33
- end
34
-
35
- def build_catalogue(hash)
36
- Catalogue.new(hash)
37
- end
38
-
39
- def default_client
40
- Net::Hippie::Client.new
41
- end
42
- end
43
- end