spandx 0.12.3 → 0.13.4
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 +4 -4
- data/CHANGELOG.md +74 -25
- data/README.md +11 -7
- data/exe/spandx +1 -2
- data/ext/spandx/extconf.rb +5 -0
- data/ext/spandx/spandx.c +55 -0
- data/ext/spandx/spandx.h +6 -0
- data/lib/spandx.rb +6 -3
- data/lib/spandx/cli.rb +2 -0
- data/lib/spandx/cli/commands/build.rb +13 -2
- data/lib/spandx/cli/commands/scan.rb +11 -20
- data/lib/spandx/cli/main.rb +3 -2
- data/lib/spandx/core/cache.rb +38 -51
- data/lib/spandx/core/content.rb +5 -23
- data/lib/spandx/core/data_file.rb +66 -0
- data/lib/spandx/core/dependency.rb +47 -13
- data/lib/spandx/core/git.rb +8 -32
- data/lib/spandx/core/guess.rb +48 -40
- data/lib/spandx/core/http.rb +7 -2
- data/lib/spandx/core/index_file.rb +103 -0
- data/lib/spandx/core/license_plugin.rb +15 -4
- data/lib/spandx/core/parser.rb +10 -3
- data/lib/spandx/core/path_traversal.rb +35 -0
- data/lib/spandx/core/relation.rb +38 -0
- data/lib/spandx/core/report.rb +6 -12
- data/lib/spandx/core/spinner.rb +51 -0
- data/lib/spandx/dotnet/index.rb +21 -79
- data/lib/spandx/dotnet/parsers/csproj.rb +7 -7
- data/lib/spandx/dotnet/parsers/packages_config.rb +7 -7
- data/lib/spandx/dotnet/parsers/sln.rb +10 -13
- data/lib/spandx/dotnet/project_file.rb +3 -3
- data/lib/spandx/java/index.rb +5 -2
- data/lib/spandx/java/parsers/maven.rb +7 -7
- data/lib/spandx/js/parsers/npm.rb +6 -6
- data/lib/spandx/js/parsers/yarn.rb +7 -7
- data/lib/spandx/php/parsers/composer.rb +7 -7
- data/lib/spandx/python/index.rb +4 -33
- data/lib/spandx/python/parsers/pipfile_lock.rb +4 -4
- data/lib/spandx/python/pypi.rb +0 -2
- data/lib/spandx/python/source.rb +12 -0
- data/lib/spandx/ruby/parsers/gemfile_lock.rb +10 -9
- data/lib/spandx/spdx/catalogue.rb +5 -1
- data/lib/spandx/spdx/composite_license.rb +60 -0
- data/lib/spandx/spdx/expression.rb +114 -0
- data/lib/spandx/spdx/license.rb +4 -14
- data/lib/spandx/version.rb +1 -1
- data/spandx.gemspec +16 -10
- metadata +100 -30
- data/lib/spandx/core/null_gateway.rb +0 -11
- data/lib/spandx/core/table.rb +0 -29
- data/lib/spandx/core/thread_pool.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef9e117562bb153d2bf7a7aa8561244f50f7dcbca8a81300e10279efec45c674
|
4
|
+
data.tar.gz: '069f96ae764417f3b005ebd8e7fee919c66eee38a63649918f7dea3209a9bc34'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67ec66d00236b0c4a98bc770e0b33698ecabb6e868b4e1b309c735a0d3cf5288a49393280f0cff2829d8ab5d1005920b16a877bdabdb2a0b63c88ac9f7af7df9
|
7
|
+
data.tar.gz: 9260aeb08a495fb4f8bd1ba4c2b17fed8e34c2e60e96d5c826c79f7c51d83a8686b4194e060fa77e3b898f1beb17404006dd5370b727d2a7ce98d87ddce41507
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Version 0.
|
1
|
+
Version 0.13.4
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
@@ -9,6 +9,51 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
9
9
|
|
10
10
|
## [Unreleased]
|
11
11
|
|
12
|
+
## [0.13.4] - 2020-05-26
|
13
|
+
### Added
|
14
|
+
- Add detected file path to report output.
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- Use `Pathname` instead of `String` to represent file paths.
|
18
|
+
- Scan current directory when a path is not specified.
|
19
|
+
|
20
|
+
## [0.13.3] - 2020-05-19
|
21
|
+
### Fixed
|
22
|
+
- Ignore invalid URLs during scan.
|
23
|
+
|
24
|
+
## [0.13.2] - 2020-05-17
|
25
|
+
### Fixed
|
26
|
+
- Detect licenses when provided as an array.
|
27
|
+
- Skip empty lockfiles.
|
28
|
+
|
29
|
+
## [0.13.1] - 2020-05-16
|
30
|
+
### Fixed
|
31
|
+
- Add `ext/**/*.c` and `ext/**/*.h` to list of files.
|
32
|
+
|
33
|
+
## [0.13.0] - 2020-05-12
|
34
|
+
### Added
|
35
|
+
- Add progress bar
|
36
|
+
- Add SPDX expression parser.
|
37
|
+
- Add index for each cache.
|
38
|
+
- Update cache paths to point to Spandx organization.
|
39
|
+
- Add optimized CSV parser.
|
40
|
+
- Fetch dependency data concurrently.
|
41
|
+
- Add profiling and benchmarking tools.
|
42
|
+
|
43
|
+
### Changed
|
44
|
+
- Update git pull command to fetch master branch with a depth of 1.
|
45
|
+
- Update Nuget and PyPI cache builders to use same API for writing to cache.
|
46
|
+
- Update license lookup to parse SPDX expressions.
|
47
|
+
|
48
|
+
### Removed
|
49
|
+
- Drop Ruby 2.4 support.
|
50
|
+
- Drop Jaro Winkler algorithm.
|
51
|
+
- Drop Levenshtein algorithm.
|
52
|
+
|
53
|
+
### Fixed
|
54
|
+
- Fix bug in spawning worker threads in thread pool.
|
55
|
+
- Reset `http` global before each test to remove leakage between tests.
|
56
|
+
|
12
57
|
## [0.12.3] - 2020-04-19
|
13
58
|
### Fixed
|
14
59
|
- Ignore nuget entries with missing `items`.
|
@@ -144,27 +189,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
144
189
|
### Added
|
145
190
|
- Provide ruby API to the latest SPDX catalogue.
|
146
191
|
|
147
|
-
[Unreleased]: https://github.com/
|
148
|
-
[0.
|
149
|
-
[0.
|
150
|
-
[0.
|
151
|
-
[0.
|
152
|
-
[0.
|
153
|
-
[0.
|
154
|
-
[0.
|
155
|
-
[0.
|
156
|
-
[0.
|
157
|
-
[0.
|
158
|
-
[0.
|
159
|
-
[0.
|
160
|
-
[0.
|
161
|
-
[0.
|
162
|
-
[0.
|
163
|
-
[0.
|
164
|
-
[0.1
|
165
|
-
[0.
|
166
|
-
[0.
|
167
|
-
[0.
|
168
|
-
[0.1.
|
169
|
-
[0.1.
|
170
|
-
[0.1.
|
192
|
+
[Unreleased]: https://github.com/spandx/spandx/compare/v0.13.3...HEAD
|
193
|
+
[0.13.3]: https://github.com/spandx/spandx/compare/v0.13.2...v0.13.3
|
194
|
+
[0.13.2]: https://github.com/spandx/spandx/compare/v0.13.1...v0.13.2
|
195
|
+
[0.13.1]: https://github.com/spandx/spandx/compare/v0.13.0...v0.13.1
|
196
|
+
[0.13.0]: https://github.com/spandx/spandx/compare/v0.12.3...v0.13.0
|
197
|
+
[0.12.3]: https://github.com/spandx/spandx/compare/v0.12.2...v0.12.3
|
198
|
+
[0.12.2]: https://github.com/spandx/spandx/compare/v0.12.1...v0.12.2
|
199
|
+
[0.12.1]: https://github.com/spandx/spandx/compare/v0.12.0...v0.12.1
|
200
|
+
[0.12.0]: https://github.com/spandx/spandx/compare/v0.11.0...v0.12.0
|
201
|
+
[0.11.0]: https://github.com/spandx/spandx/compare/v0.10.1...v0.11.0
|
202
|
+
[0.10.1]: https://github.com/spandx/spandx/compare/v0.10.0...v0.10.1
|
203
|
+
[0.10.0]: https://github.com/spandx/spandx/compare/v0.9.0...v0.10.0
|
204
|
+
[0.9.0]: https://github.com/spandx/spandx/compare/v0.8.0...v0.9.0
|
205
|
+
[0.8.0]: https://github.com/spandx/spandx/compare/v0.7.0...v0.8.0
|
206
|
+
[0.7.0]: https://github.com/spandx/spandx/compare/v0.6.0...v0.7.0
|
207
|
+
[0.6.0]: https://github.com/spandx/spandx/compare/v0.5.0...v0.6.0
|
208
|
+
[0.5.0]: https://github.com/spandx/spandx/compare/v0.4.1...v0.5.0
|
209
|
+
[0.4.1]: https://github.com/spandx/spandx/compare/v0.4.0...v0.4.1
|
210
|
+
[0.4.0]: https://github.com/spandx/spandx/compare/v0.3.0...v0.4.0
|
211
|
+
[0.3.0]: https://github.com/spandx/spandx/compare/v0.2.0...v0.3.0
|
212
|
+
[0.2.0]: https://github.com/spandx/spandx/compare/v0.1.7...v0.2.0
|
213
|
+
[0.1.7]: https://github.com/spandx/spandx/compare/v0.1.6...v0.1.7
|
214
|
+
[0.1.6]: https://github.com/spandx/spandx/compare/v0.1.5...v0.1.6
|
215
|
+
[0.1.5]: https://github.com/spandx/spandx/compare/v0.1.4...v0.1.5
|
216
|
+
[0.1.4]: https://github.com/spandx/spandx/compare/v0.1.3...v0.1.4
|
217
|
+
[0.1.3]: https://github.com/spandx/spandx/compare/v0.1.2...v0.1.3
|
218
|
+
[0.1.2]: https://github.com/spandx/spandx/compare/v0.1.1...v0.1.2
|
219
|
+
[0.1.1]: https://github.com/spandx/spandx/compare/v0.1.0...v0.1.1
|
data/README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
1
|
+

|
2
|
+
|
3
|
+
*Logo courtesy of [@speasley](https://github.com/speasley)*
|
4
|
+
|
5
|
+
# Spandx 
|
2
6
|
|
3
7
|
A ruby API for interacting with the https://spdx.org software license catalogue.
|
4
8
|
This gem includes a command line interface to scan a software project for the
|
5
9
|
software licenses that are associated with each dependency in the project.
|
6
10
|
`spandx` leverages an offline cache of software licenses for known dependencies.
|
7
|
-
The offline cache allows
|
11
|
+
The offline cache allows Spandx to perform an air gap friendly scan of software
|
8
12
|
projects.
|
9
13
|
|
10
14
|
### Supported project types
|
@@ -42,7 +46,7 @@ Or install it yourself as:
|
|
42
46
|
|
43
47
|
### Command line interface
|
44
48
|
|
45
|
-
The command line interface supports operations to
|
49
|
+
The command line interface supports operations to fetch the latest pre-built cache.
|
46
50
|
See the help for each subcommand for more information on how to use the command.
|
47
51
|
|
48
52
|
```bash
|
@@ -62,19 +66,19 @@ To scan a specific project file use the `scan` command:
|
|
62
66
|
モ spandx scan ruby/Gemfile.lock
|
63
67
|
```
|
64
68
|
|
65
|
-
To activate
|
69
|
+
To activate air gap mode use the `--airgap` option:
|
66
70
|
|
67
71
|
```bash
|
68
72
|
モ spandx scan dotnet/application.sln --airgap
|
69
73
|
モ spandx scan ruby/Gemfile.lock --airgap
|
70
74
|
```
|
71
75
|
|
72
|
-
|
76
|
+
Air gap mode assumes that an offline cache has been placed in `$HOME/.local/share/`.
|
73
77
|
|
74
78
|
To fetch the latest offline cache:
|
75
79
|
|
76
80
|
```bash
|
77
|
-
モ spandx
|
81
|
+
モ spandx pull
|
78
82
|
```
|
79
83
|
|
80
84
|
### Ruby API
|
@@ -106,7 +110,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
106
110
|
|
107
111
|
## Contributing
|
108
112
|
|
109
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
113
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/spandx/spandx.
|
110
114
|
|
111
115
|
## License
|
112
116
|
|
data/exe/spandx
CHANGED
data/ext/spandx/spandx.c
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#include "spandx.h"
|
2
|
+
|
3
|
+
#define NEWLINE 10
|
4
|
+
|
5
|
+
VALUE rb_mSpandx;
|
6
|
+
VALUE rb_mCore;
|
7
|
+
VALUE rb_mCsvParser;
|
8
|
+
|
9
|
+
// "name","version","license"
|
10
|
+
// "name","version","license"\n
|
11
|
+
// "name","version","license"\r
|
12
|
+
// "name","version","license"\r\n
|
13
|
+
// "name","version",""\r\n
|
14
|
+
VALUE parse(VALUE self, VALUE line)
|
15
|
+
{
|
16
|
+
if (NIL_P(line)) return Qnil;
|
17
|
+
|
18
|
+
char *p;
|
19
|
+
|
20
|
+
p = RSTRING_PTR(line);
|
21
|
+
if (*p != '"') return Qnil;
|
22
|
+
|
23
|
+
const VALUE items = rb_ary_new2(3);
|
24
|
+
const char *s, *n;
|
25
|
+
const long len = RSTRING_LEN(line);
|
26
|
+
enum { open, closed } state = closed;
|
27
|
+
|
28
|
+
for (int i = 0; i < len && *p; i++) {
|
29
|
+
if (*p == '"') {
|
30
|
+
n = p;
|
31
|
+
if (i < (len - 1)) *n++;
|
32
|
+
|
33
|
+
if (state == closed) {
|
34
|
+
s = n;
|
35
|
+
state = open;
|
36
|
+
} else if (state == open) {
|
37
|
+
if (!*n || n == p || *n == ',' || *n == NEWLINE) {
|
38
|
+
rb_ary_push(items, rb_str_new(s, p - s));
|
39
|
+
state = closed;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
*(p++);
|
44
|
+
}
|
45
|
+
|
46
|
+
return items;
|
47
|
+
}
|
48
|
+
|
49
|
+
void Init_spandx(void)
|
50
|
+
{
|
51
|
+
rb_mSpandx = rb_define_module("Spandx");
|
52
|
+
rb_mCore = rb_define_module_under(rb_mSpandx, "Core");
|
53
|
+
rb_mCsvParser = rb_define_module_under(rb_mCore, "CsvParser");
|
54
|
+
rb_define_module_function(rb_mCsvParser, "parse", parse, 1);
|
55
|
+
}
|
data/ext/spandx/spandx.h
ADDED
data/lib/spandx.rb
CHANGED
@@ -8,9 +8,12 @@ require 'json'
|
|
8
8
|
require 'logger'
|
9
9
|
require 'net/hippie'
|
10
10
|
require 'nokogiri'
|
11
|
+
require 'parslet'
|
11
12
|
require 'pathname'
|
12
13
|
require 'yaml'
|
13
14
|
require 'zeitwerk'
|
15
|
+
require 'terminal-table'
|
16
|
+
require 'spandx/spandx'
|
14
17
|
|
15
18
|
loader = Zeitwerk::Loader.for_gem
|
16
19
|
loader.setup # ready!
|
@@ -20,7 +23,7 @@ module Spandx
|
|
20
23
|
Rubygems = Ruby
|
21
24
|
|
22
25
|
class << self
|
23
|
-
attr_writer :airgap, :logger
|
26
|
+
attr_writer :airgap, :logger, :http, :git
|
24
27
|
|
25
28
|
def root
|
26
29
|
Pathname.new(File.dirname(__FILE__)).join('../..')
|
@@ -40,8 +43,8 @@ module Spandx
|
|
40
43
|
|
41
44
|
def git
|
42
45
|
@git ||= {
|
43
|
-
cache: ::Spandx::Core::Git.new(url: 'https://github.com/
|
44
|
-
rubygems: ::Spandx::Core::Git.new(url: 'https://github.com/
|
46
|
+
cache: ::Spandx::Core::Git.new(url: 'https://github.com/spandx/cache.git'),
|
47
|
+
rubygems: ::Spandx::Core::Git.new(url: 'https://github.com/spandx/rubygems-cache.git'),
|
45
48
|
spdx: ::Spandx::Core::Git.new(url: 'https://github.com/spdx/license-list-data.git'),
|
46
49
|
}
|
47
50
|
end
|
data/lib/spandx/cli.rb
CHANGED
@@ -17,6 +17,7 @@ module Spandx
|
|
17
17
|
|
18
18
|
def execute(output: $stdout)
|
19
19
|
catalogue = Spandx::Spdx::Catalogue.from_git
|
20
|
+
build_buckets
|
20
21
|
indexes.each do |index|
|
21
22
|
output.puts index.name
|
22
23
|
index.update!(catalogue: catalogue, output: output)
|
@@ -30,9 +31,19 @@ module Spandx
|
|
30
31
|
index = INDEXES[@options[:index]&.to_sym]
|
31
32
|
|
32
33
|
if index.nil?
|
33
|
-
INDEXES.values.uniq.map { |x| x.new(directory:
|
34
|
+
INDEXES.values.uniq.map { |x| x.new(directory: directory) }
|
34
35
|
else
|
35
|
-
[index.new(directory:
|
36
|
+
[index.new(directory: directory)]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def directory
|
41
|
+
@options.fetch(:directory, File.join(Dir.pwd, '.index'))
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_buckets
|
45
|
+
(0x00..0xFF).map { |x| x.to_s(16).rjust(2, '0').downcase }.each do |hex|
|
46
|
+
FileUtils.mkdir_p(File.join(directory, hex))
|
36
47
|
end
|
37
48
|
end
|
38
49
|
end
|
@@ -4,50 +4,41 @@ module Spandx
|
|
4
4
|
module Cli
|
5
5
|
module Commands
|
6
6
|
class Scan
|
7
|
-
attr_reader :scan_path
|
7
|
+
attr_reader :scan_path, :spinner
|
8
8
|
|
9
9
|
def initialize(scan_path, options)
|
10
10
|
@scan_path = ::Pathname.new(scan_path)
|
11
11
|
@options = options
|
12
|
+
@spinner = options[:show_progress] ? ::Spandx::Core::Spinner.new : ::Spandx::Core::Spinner::NULL
|
12
13
|
require(options[:require]) if options[:require]
|
13
14
|
end
|
14
15
|
|
15
16
|
def execute(output: $stdout)
|
16
17
|
report = ::Spandx::Core::Report.new
|
17
|
-
|
18
|
+
each_file do |file|
|
19
|
+
spinner.spin(file)
|
18
20
|
each_dependency_from(file) do |dependency|
|
21
|
+
spinner.spin(file)
|
19
22
|
report.add(dependency)
|
20
23
|
end
|
21
24
|
end
|
25
|
+
spinner.stop
|
22
26
|
output.puts(format(report.to(@options[:format])))
|
23
27
|
end
|
24
28
|
|
25
29
|
private
|
26
30
|
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def each_file_in(dir, &block)
|
32
|
-
files = File.directory?(dir) ? Dir.glob(File.join(dir, '*')) : [dir]
|
33
|
-
files.each do |file|
|
34
|
-
if File.directory?(file)
|
35
|
-
each_file_in(file, &block) if recursive?
|
36
|
-
else
|
37
|
-
Spandx.logger.debug(file)
|
38
|
-
block.call(file)
|
39
|
-
end
|
40
|
-
end
|
31
|
+
def each_file
|
32
|
+
Spandx::Core::PathTraversal
|
33
|
+
.new(scan_path, recursive: @options[:recursive])
|
34
|
+
.each { |file| yield file }
|
41
35
|
end
|
42
36
|
|
43
37
|
def each_dependency_from(file)
|
44
38
|
::Spandx::Core::Parser
|
45
|
-
.for(file)
|
46
39
|
.parse(file)
|
47
|
-
.map { |
|
40
|
+
.map { |x| enhance(x) }
|
48
41
|
.each { |dependency| yield dependency }
|
49
|
-
rescue StandardError => error
|
50
|
-
Spandx.logger.error(error)
|
51
42
|
end
|
52
43
|
|
53
44
|
def format(output)
|
data/lib/spandx/cli/main.rb
CHANGED
@@ -8,10 +8,11 @@ module Spandx
|
|
8
8
|
method_option :recursive, aliases: '-R', type: :boolean, desc: 'Perform recursive scan', default: false
|
9
9
|
method_option :airgap, aliases: '-a', type: :boolean, desc: 'Disable network connections', default: false
|
10
10
|
method_option :logfile, aliases: '-l', type: :string, desc: 'Path to a logfile', default: '/dev/null'
|
11
|
-
method_option :format, aliases: '-f', type: :string, desc: 'Format of report', default: 'table'
|
11
|
+
method_option :format, aliases: '-f', type: :string, desc: 'Format of report. (table, csv, json, hash)', default: 'table'
|
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
|
+
method_option :show_progress, aliases: '-sp', type: :boolean, desc: 'Shows a progress bar', default: true
|
15
|
+
def scan(lockfile = Pathname.pwd)
|
15
16
|
if options[:help]
|
16
17
|
invoke :help, ['scan']
|
17
18
|
else
|
data/lib/spandx/core/cache.rb
CHANGED
@@ -3,83 +3,70 @@
|
|
3
3
|
module Spandx
|
4
4
|
module Core
|
5
5
|
class Cache
|
6
|
-
|
6
|
+
include Enumerable
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
8
|
+
attr_reader :package_manager, :root
|
9
|
+
|
10
|
+
def initialize(package_manager, root:)
|
11
|
+
@package_manager = package_manager.to_s
|
12
|
+
@root = root
|
13
13
|
end
|
14
14
|
|
15
15
|
def licenses_for(name, version)
|
16
|
-
|
17
|
-
|
16
|
+
return [] if name.nil? || name.empty?
|
17
|
+
|
18
|
+
found = datafile_for(name).search(name: name, version: version)
|
19
|
+
Spandx.logger.debug { "Cache miss: #{name}-#{version}" } unless found
|
18
20
|
found ? found[2].split('-|-') : []
|
19
21
|
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def each
|
24
|
+
datafiles.each do |_hex, datafile|
|
25
|
+
datafile.each do |item|
|
26
|
+
yield item
|
27
|
+
end
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
|
-
def
|
28
|
-
|
31
|
+
def insert(name, version, licenses)
|
32
|
+
return if name.nil? || name.empty?
|
33
|
+
|
34
|
+
datafile_for(name).insert(name, version, licenses)
|
29
35
|
end
|
30
36
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
search_for("#{name}-#{version}", io, @lines.fetch(datafile) { |key| @lines[key] = lines_in(io) })
|
35
|
-
end
|
36
|
-
rescue Errno::ENOENT => error
|
37
|
-
Spandx.logger.error(error)
|
38
|
-
nil
|
37
|
+
def insert!(*args)
|
38
|
+
insert(*args)
|
39
|
+
rebuild_index
|
39
40
|
end
|
40
41
|
|
41
42
|
def datafile_for(name)
|
42
|
-
|
43
|
+
datafiles.fetch(key_for(name))
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
until io.eof?
|
49
|
-
lines << io.pos
|
50
|
-
io.gets
|
46
|
+
def rebuild_index
|
47
|
+
datafiles.each do |_hex, datafile|
|
48
|
+
datafile.index.update!
|
51
49
|
end
|
52
|
-
lines
|
53
50
|
end
|
54
51
|
|
55
|
-
|
56
|
-
return if lines.empty?
|
57
|
-
return @cache[term] if @cache.key?(term)
|
58
|
-
|
59
|
-
mid = lines.size == 1 ? 0 : lines.size / 2
|
60
|
-
io.seek(lines[mid])
|
61
|
-
comparison = matches?(term, parse_row(io)) do |row|
|
62
|
-
return row
|
63
|
-
end
|
52
|
+
private
|
64
53
|
|
65
|
-
|
54
|
+
def digest_for(name)
|
55
|
+
Digest::SHA1.hexdigest(name)
|
66
56
|
end
|
67
57
|
|
68
|
-
def
|
69
|
-
(
|
70
|
-
yield row if comparison.zero?
|
71
|
-
end
|
58
|
+
def key_for(name)
|
59
|
+
digest_for(name)[0...2]
|
72
60
|
end
|
73
61
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
62
|
+
def datafiles
|
63
|
+
@datafiles ||= candidate_keys.each_with_object({}) do |key, memo|
|
64
|
+
memo[key] = DataFile.new(File.join(root, key, package_manager))
|
65
|
+
end
|
77
66
|
end
|
78
67
|
|
79
|
-
def
|
80
|
-
|
81
|
-
@cache["#{row[0]}-#{row[1]}"] = row
|
82
|
-
row
|
68
|
+
def candidate_keys
|
69
|
+
(0x00..0xFF).map { |x| x.to_s(16).upcase.rjust(2, '0').downcase }
|
83
70
|
end
|
84
71
|
end
|
85
72
|
end
|