spandx 0.14.0 → 0.17.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
  SHA256:
3
- metadata.gz: 7e01f7023f4a164fb867c7d457769d1c9dd2eb2b480cee88c5d4d682c2d6dc4e
4
- data.tar.gz: f202f85c254d11041b79e1305d12641eb66ea66cec9afea25a38e9724a5636d6
3
+ metadata.gz: d884c729b0d1cb14391435f68b78a77cfb2a73860b8757d4421bda9ff06276bd
4
+ data.tar.gz: 2fe44244d7285b7fc5bd9ddf8660b2bd4b435d8908b6c5e67d305181e6356658
5
5
  SHA512:
6
- metadata.gz: 926df592dfc76466a7e26bcdfd9fc581957b2c748c9272e30a22180a61f4d6498ebb14e04e8acbbccc813f4aae929ecb8ba82ee54064d642990e5874b05bb0b1
7
- data.tar.gz: 5dede807761bf9d4fa91f6a0ea9df1bec9531d0a397fedea5c687b7c12860216e41df47c09fc7e94c8951e7dc0f88c99fc74395913002890b199409b700830f0
6
+ metadata.gz: a6f25542efd0f506dbe65f5dbd179d562fbb37fd9498cffc1cee2ac8a0bfdfabab614269920aa2799736a198529408300277c2d87c7303f3463bd37e0ff67ee8
7
+ data.tar.gz: ebe7266727203ec7a84e741e2dfa5fa76db8a9da30dbfbb258618adbda6e7463a04174fd0c706c23c65068857f06584eef2fcdd25e05fe1ad0ebf5dbd9489c06
@@ -1,4 +1,4 @@
1
- Version 0.14.0
1
+ Version 0.17.0
2
2
 
3
3
  # Changelog
4
4
 
@@ -8,6 +8,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
10
  ## [Unreleased]
11
+ ## [0.17.0] - 2020-12-28
12
+ ### Added
13
+ - Allow indexing gems from index.rubygems.org.
14
+
15
+ ## [0.16.1] - 2020-11-19
16
+ ### Fixed
17
+ - Start spinner for table printer only
18
+
19
+ ## [0.16.0] - 2020-11-19
20
+ ### Changed
21
+ - Pull smaller license cache.
22
+ - Print index files after building them.
23
+
24
+ ## [0.15.1] - 2020-11-18
25
+ ### Fixed
26
+ - Rebuild index after pulling latest cache.
27
+
28
+ ## [0.15.0] - 2020-11-18
29
+ ### Added
30
+ - Parse `/var/lib/dpkg/status` file.
11
31
 
12
32
  ## [0.14.0] - 2020-11-14
13
33
  ### Added
@@ -203,7 +223,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
203
223
  ### Added
204
224
  - Provide ruby API to the latest SPDX catalogue.
205
225
 
206
- [Unreleased]: https://github.com/spandx/spandx/compare/v0.14.0...HEAD
226
+ [Unreleased]: https://github.com/spandx/spandx/compare/v0.17.0...HEAD
227
+ [0.17.0]: https://github.com/spandx/spandx/compare/v0.16.1...v0.17.0
228
+ [0.16.1]: https://github.com/spandx/spandx/compare/v0.16.0...v0.16.1
229
+ [0.16.0]: https://github.com/spandx/spandx/compare/v0.15.1...v0.16.0
230
+ [0.15.1]: https://github.com/spandx/spandx/compare/v0.15.0...v0.15.1
231
+ [0.15.0]: https://github.com/spandx/spandx/compare/v0.14.0...v0.15.0
207
232
  [0.14.0]: https://github.com/spandx/spandx/compare/v0.13.5...v0.14.0
208
233
  [0.13.5]: https://github.com/spandx/spandx/compare/v0.13.4...v0.13.5
209
234
  [0.13.4]: https://github.com/spandx/spandx/compare/v0.13.3...v0.13.4
@@ -52,4 +52,6 @@ void Init_spandx(void)
52
52
  rb_mCore = rb_define_module_under(rb_mSpandx, "Core");
53
53
  rb_mCsvParser = rb_define_module_under(rb_mCore, "CsvParser");
54
54
  rb_define_module_function(rb_mCsvParser, "parse", parse, 1);
55
+
56
+ rb_gc_register_mark_object(rb_mCsvParser);
55
57
  }
@@ -11,6 +11,7 @@ require 'nokogiri'
11
11
  require 'oj'
12
12
  require 'parslet'
13
13
  require 'pathname'
14
+ require 'sorted_set'
14
15
  require 'yaml'
15
16
  require 'zeitwerk'
16
17
  require 'spandx/spandx'
@@ -45,7 +46,7 @@ module Spandx
45
46
  @git ||= {
46
47
  cache: ::Spandx::Core::Git.new(url: 'https://github.com/spandx/cache.git'),
47
48
  rubygems: ::Spandx::Core::Git.new(url: 'https://github.com/spandx/rubygems-cache.git'),
48
- spdx: ::Spandx::Core::Git.new(url: 'https://github.com/spdx/license-list-data.git'),
49
+ spdx: ::Spandx::Core::Git.new(url: 'https://github.com/spdx/license-list-data.git', default_branch: 'master'),
49
50
  }
50
51
  end
51
52
  end
@@ -5,10 +5,11 @@ module Spandx
5
5
  module Commands
6
6
  class Build
7
7
  INDEXES = {
8
+ dotnet: Spandx::Dotnet::Index,
8
9
  maven: Spandx::Java::Index,
9
10
  nuget: Spandx::Dotnet::Index,
10
- dotnet: Spandx::Dotnet::Index,
11
11
  pypi: Spandx::Python::Index,
12
+ rubygems: Spandx::Ruby::Index,
12
13
  }.freeze
13
14
 
14
15
  def initialize(options)
@@ -4,17 +4,56 @@ module Spandx
4
4
  module Cli
5
5
  module Commands
6
6
  class Pull
7
+ attr_reader :cache_dir, :rubygems_cache_dir
8
+
7
9
  def initialize(options)
8
10
  @options = options
11
+ @cache_dir = Spandx.git[:cache].root.join('.index')
12
+ @rubygems_cache_dir = Spandx.git[:rubygems].root.join('.index')
9
13
  end
10
14
 
11
- def execute(output: $stdout)
12
- Spandx.git.each_value do |db|
13
- output.puts "Updating #{db.url}..."
14
- db.update!
15
+ def execute(output: $stderr)
16
+ sync(output)
17
+ build(output, ::Spandx::Core::Dependency::PACKAGE_MANAGERS.values.uniq)
18
+ index_files_in(cache_dir, rubygems_cache_dir).each do |item|
19
+ output.puts item.to_s.gsub(Dir.home, '~')
15
20
  end
16
21
  output.puts 'OK'
17
22
  end
23
+
24
+ private
25
+
26
+ def sync(output)
27
+ Spandx.git.each_value do |db|
28
+ with_spinner("Updating #{db.url}...", output: output) do
29
+ db.update!
30
+ end
31
+ end
32
+ end
33
+
34
+ def build(output, sources)
35
+ with_spinner('Building index...', output: output) do
36
+ sources.each do |source|
37
+ Spandx::Core::Cache.new(source, root: cache_dir).rebuild_index
38
+ end
39
+ Spandx::Core::Cache.new(:rubygems, root: rubygems_cache_dir).rebuild_index
40
+ end
41
+ end
42
+
43
+ def with_spinner(message, output:)
44
+ spinner = TTY::Spinner.new("[:spinner] #{message}", output: output)
45
+ spinner.auto_spin
46
+ yield
47
+ spinner.success('(done)')
48
+ rescue StandardError => error
49
+ spinner.error("(#{error.message})")
50
+ ensure
51
+ spinner.stop
52
+ end
53
+
54
+ def index_files_in(*dirs)
55
+ dirs.map { |x| x.glob('**/*.idx') }.flatten.sort
56
+ end
18
57
  end
19
58
  end
20
59
  end
@@ -12,15 +12,11 @@ module Spandx
12
12
  method_option :pull, aliases: '-p', type: :boolean, desc: 'Pull the latest cache before the scan', default: false
13
13
  method_option :require, aliases: '-r', type: :string, desc: 'Causes spandx to load the library using require.', default: nil
14
14
  def scan(lockfile = Pathname.pwd)
15
- if options[:help]
16
- invoke :help, ['scan']
17
- else
18
- Oj.default_options = { mode: :strict }
19
- Spandx.airgap = options[:airgap]
20
- Spandx.logger = Logger.new(options[:logfile])
21
- pull if options[:pull]
22
- Spandx::Cli::Commands::Scan.new(lockfile, options).execute
23
- end
15
+ return invoke :help, ['scan'] if options[:help]
16
+
17
+ prepare(options)
18
+ pull if options[:pull]
19
+ Spandx::Cli::Commands::Scan.new(lockfile, options).execute
24
20
  end
25
21
 
26
22
  desc 'pull', 'Pull the latest offline cache'
@@ -52,6 +48,14 @@ module Spandx
52
48
  puts "v#{Spandx::VERSION}"
53
49
  end
54
50
  map %w[--version -v] => :version
51
+
52
+ private
53
+
54
+ def prepare(options)
55
+ Oj.default_options = { mode: :strict }
56
+ Spandx.airgap = options[:airgap]
57
+ Spandx.logger = Logger.new(options[:logfile])
58
+ end
55
59
  end
56
60
  end
57
61
  end
@@ -6,8 +6,8 @@ module Spandx
6
6
  class Table < Printer
7
7
  HEADINGS = ['Name', 'Version', 'Licenses', 'Location'].freeze
8
8
 
9
- def initialize
10
- @spinner = TTY::Spinner.new(output: $stderr)
9
+ def initialize(output: $stderr)
10
+ @spinner = TTY::Spinner.new('[:spinner] Scanning...', output: output, clear: true, format: :dots)
11
11
  end
12
12
 
13
13
  def match?(format)
@@ -15,8 +15,8 @@ module Spandx
15
15
  end
16
16
 
17
17
  def print_header(_io)
18
- @dependencies = SortedSet.new
19
18
  @spinner.auto_spin
19
+ @dependencies = SortedSet.new
20
20
  end
21
21
 
22
22
  def print_line(dependency, _io)
@@ -25,6 +25,7 @@ module Spandx
25
25
 
26
26
  def print_footer(io)
27
27
  @spinner.stop
28
+ @spinner.reset
28
29
  io.puts(to_table(@dependencies.map(&:to_a)))
29
30
  end
30
31
 
@@ -56,6 +56,10 @@ module Spandx
56
56
  @index ||= IndexFile.new(self)
57
57
  end
58
58
 
59
+ def to_s
60
+ absolute_path.to_s
61
+ end
62
+
59
63
  private
60
64
 
61
65
  def to_csv(array)
@@ -3,10 +3,11 @@
3
3
  module Spandx
4
4
  module Core
5
5
  class Git
6
- attr_reader :root, :url
6
+ attr_reader :root, :url, :default_branch
7
7
 
8
- def initialize(url:)
8
+ def initialize(url:, default_branch: 'main')
9
9
  @url = url
10
+ @default_branch = default_branch
10
11
  @root = path_for(url)
11
12
  end
12
13
 
@@ -31,14 +32,15 @@ module Spandx
31
32
  root.join('.git').directory?
32
33
  end
33
34
 
34
- def clone!
35
+ def clone!(branch: default_branch)
35
36
  system('rm', '-rf', root.to_s) if root.exist?
36
- system('git', 'clone', '--quiet', '--depth=1', '--single-branch', '--branch', 'master', url, root.to_s)
37
+ system('git', 'clone', '--quiet', '--depth=1', '--single-branch', '--branch', branch, url, root.to_s)
37
38
  end
38
39
 
39
- def pull!
40
+ def pull!(remote: 'origin', branch: default_branch)
40
41
  Dir.chdir(root) do
41
- system('git', 'pull', '--no-rebase', '--quiet', 'origin', 'master')
42
+ system('git', 'fetch', '--quiet', '--depth=1', '--prune', '--no-tags', remote)
43
+ system('git', 'checkout', '--quiet', branch)
42
44
  end
43
45
  end
44
46
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Os
5
+ module Parsers
6
+ class Dpkg < ::Spandx::Core::Parser
7
+ class LineReader
8
+ attr_reader :io
9
+
10
+ def initialize(io)
11
+ @io = io
12
+ end
13
+
14
+ def each
15
+ yield read_package(io, Hash.new(''), nil) until io.eof?
16
+ end
17
+
18
+ private
19
+
20
+ def read_package(io, package, prev_key)
21
+ return package if io.eof?
22
+
23
+ line = io.readline.chomp
24
+ return package if line.empty?
25
+
26
+ key, value = split(line, prev_key)
27
+ package[key] += value
28
+ read_package(io, package, key)
29
+ end
30
+
31
+ def split(line, prev_key)
32
+ if prev_key && line.start_with?(' ')
33
+ [prev_key, line]
34
+ else
35
+ key, *rest = line.split(':')
36
+ value = rest&.join(':')&.strip
37
+ [key, value]
38
+ end
39
+ end
40
+ end
41
+
42
+ def match?(path)
43
+ path.basename.fnmatch?('status')
44
+ end
45
+
46
+ def parse(lockfile)
47
+ [].tap do |items|
48
+ lockfile.open(mode: 'r') do |io|
49
+ LineReader.new(io).each do |data|
50
+ items.push(map_from(data, lockfile.to_s))
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def map_from(data, path)
59
+ ::Spandx::Core::Dependency.new(
60
+ path: path,
61
+ name: data['Package'],
62
+ version: data['Version'],
63
+ meta: data
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -8,8 +8,21 @@ module Spandx
8
8
  @http = http
9
9
  end
10
10
 
11
+ def each
12
+ response = http.get('https://index.rubygems.org/versions')
13
+ return unless http.ok?(response)
14
+
15
+ parse_each_from(StringIO.new(response.body)) do |item|
16
+ yield item
17
+ end
18
+ end
19
+
11
20
  def licenses_for(dependency)
12
- details_on(dependency.name, dependency.version)['licenses'] || []
21
+ licenses(dependency.name, dependency.version)
22
+ end
23
+
24
+ def licenses(name, version)
25
+ details_on(name, version)['licenses'] || []
13
26
  end
14
27
 
15
28
  def matches?(dependency)
@@ -20,6 +33,17 @@ module Spandx
20
33
 
21
34
  attr_reader :http
22
35
 
36
+ def parse_each_from(io)
37
+ _created_at = io.readline
38
+ _triple_dash = io.readline
39
+ until io.eof?
40
+ name, versions, _digest = io.readline.split(' ')
41
+ versions.split(',').each do |version|
42
+ yield({ name: name, version: version })
43
+ end
44
+ end
45
+ end
46
+
23
47
  def details_on(name, version)
24
48
  url = "https://rubygems.org/api/v2/rubygems/#{name}/versions/#{version}.json"
25
49
  response = http.get(url, default: {})
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spandx
4
+ module Ruby
5
+ class Index
6
+ include Enumerable
7
+
8
+ attr_reader :directory, :name, :rubygems
9
+
10
+ def initialize(directory:)
11
+ @directory = directory
12
+ @name = 'rubygems'
13
+ @cache = ::Spandx::Core::Cache.new(@name, root: directory)
14
+ @rubygems = ::Spandx::Ruby::Gateway.new
15
+ end
16
+
17
+ def update!(*)
18
+ queue = Queue.new
19
+ [fetch(queue), save(queue)].each(&:join)
20
+ cache.rebuild_index
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :cache
26
+
27
+ def fetch(queue)
28
+ Thread.new do
29
+ rubygems.each do |item|
30
+ queue.enq(
31
+ item.merge(
32
+ licenses: rubygems.licenses(item[:name], item[:version])
33
+ )
34
+ )
35
+ end
36
+ queue.enq(:stop)
37
+ end
38
+ end
39
+
40
+ def save(queue)
41
+ Thread.new do
42
+ loop do
43
+ item = queue.deq
44
+ break if item == :stop
45
+
46
+ cache.insert(item[:name], item[:version], item[:licenses])
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spandx
4
- VERSION = '0.14.0'
4
+ VERSION = '0.17.0'
5
5
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.metadata['homepage_uri'] = spec.homepage
20
20
  spec.metadata['source_code_uri'] = 'https://github.com/spandx/spandx'
21
- spec.metadata['changelog_uri'] = 'https://github.com/spandx/spandx/blob/master/CHANGELOG.md'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/spandx/spandx/blob/main/CHANGELOG.md'
22
22
 
23
23
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
24
  Dir.glob('exe/*') +
@@ -38,6 +38,7 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency 'nokogiri', '~> 1.10'
39
39
  spec.add_dependency 'oj', '~> 3.10'
40
40
  spec.add_dependency 'parslet', '~> 2.0'
41
+ spec.add_dependency 'sorted_set', '~> 1.0'
41
42
  spec.add_dependency 'terminal-table', '~> 1.8'
42
43
  spec.add_dependency 'thor'
43
44
  spec.add_dependency 'tty-spinner', '~> 0.9'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spandx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Can Eldem
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-11-15 00:00:00.000000000 Z
12
+ date: 2020-12-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: addressable
@@ -101,6 +101,20 @@ dependencies:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
103
  version: '2.0'
104
+ - !ruby/object:Gem::Dependency
105
+ name: sorted_set
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
104
118
  - !ruby/object:Gem::Dependency
105
119
  name: terminal-table
106
120
  requirement: !ruby/object:Gem::Requirement
@@ -405,6 +419,7 @@ files:
405
419
  - lib/spandx/js/yarn_lock.rb
406
420
  - lib/spandx/js/yarn_pkg.rb
407
421
  - lib/spandx/os/parsers/apk.rb
422
+ - lib/spandx/os/parsers/dpkg.rb
408
423
  - lib/spandx/php/packagist_gateway.rb
409
424
  - lib/spandx/php/parsers/composer.rb
410
425
  - lib/spandx/python/index.rb
@@ -412,6 +427,7 @@ files:
412
427
  - lib/spandx/python/pypi.rb
413
428
  - lib/spandx/python/source.rb
414
429
  - lib/spandx/ruby/gateway.rb
430
+ - lib/spandx/ruby/index.rb
415
431
  - lib/spandx/ruby/parsers/gemfile_lock.rb
416
432
  - lib/spandx/spdx/catalogue.rb
417
433
  - lib/spandx/spdx/composite_license.rb
@@ -426,7 +442,7 @@ licenses:
426
442
  metadata:
427
443
  homepage_uri: https://spandx.github.io/
428
444
  source_code_uri: https://github.com/spandx/spandx
429
- changelog_uri: https://github.com/spandx/spandx/blob/master/CHANGELOG.md
445
+ changelog_uri: https://github.com/spandx/spandx/blob/main/CHANGELOG.md
430
446
  post_install_message:
431
447
  rdoc_options: []
432
448
  require_paths:
@@ -442,7 +458,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
442
458
  - !ruby/object:Gem::Version
443
459
  version: '0'
444
460
  requirements: []
445
- rubygems_version: 3.1.4
461
+ rubygems_version: 3.2.3
446
462
  signing_key:
447
463
  specification_version: 4
448
464
  summary: A ruby interface to the SPDX catalogue.