spandx 0.11.0 → 0.12.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 +4 -4
- data/CHANGELOG.md +20 -2
- data/README.md +59 -2
- data/exe/spandx +3 -4
- data/lib/spandx.rb +13 -32
- data/lib/spandx/cli.rb +1 -30
- data/lib/spandx/cli/commands/build.rb +41 -0
- data/lib/spandx/cli/commands/pull.rb +21 -0
- data/lib/spandx/cli/commands/scan.rb +17 -2
- data/lib/spandx/cli/main.rb +54 -0
- data/lib/spandx/core/cache.rb +3 -3
- data/lib/spandx/core/circuit.rb +34 -0
- data/lib/spandx/core/dependency.rb +32 -7
- data/lib/spandx/core/gateway.rb +19 -0
- data/lib/spandx/core/{database.rb → git.rb} +7 -2
- data/lib/spandx/core/guess.rb +42 -4
- data/lib/spandx/core/http.rb +30 -5
- data/lib/spandx/core/license_plugin.rb +54 -0
- data/lib/spandx/core/null_gateway.rb +11 -0
- data/lib/spandx/core/parser.rb +8 -25
- data/lib/spandx/core/plugin.rb +15 -0
- data/lib/spandx/core/registerable.rb +27 -0
- data/lib/spandx/core/report.rb +30 -6
- data/lib/spandx/core/table.rb +29 -0
- data/lib/spandx/dotnet/index.rb +10 -5
- data/lib/spandx/dotnet/nuget_gateway.rb +20 -31
- data/lib/spandx/dotnet/parsers/csproj.rb +3 -12
- data/lib/spandx/dotnet/parsers/packages_config.rb +2 -10
- data/lib/spandx/dotnet/parsers/sln.rb +2 -2
- data/lib/spandx/java/gateway.rb +37 -0
- data/lib/spandx/java/index.rb +84 -2
- data/lib/spandx/java/metadata.rb +6 -3
- data/lib/spandx/java/parsers/maven.rb +11 -21
- data/lib/spandx/js/parsers/npm.rb +39 -0
- data/lib/spandx/js/parsers/yarn.rb +30 -0
- data/lib/spandx/js/yarn_lock.rb +67 -0
- data/lib/spandx/js/yarn_pkg.rb +59 -0
- data/lib/spandx/php/packagist_gateway.rb +25 -0
- data/lib/spandx/php/parsers/composer.rb +33 -0
- data/lib/spandx/python/index.rb +78 -0
- data/lib/spandx/python/parsers/pipfile_lock.rb +12 -16
- data/lib/spandx/python/pypi.rb +91 -8
- data/lib/spandx/python/source.rb +5 -1
- data/lib/spandx/{rubygems → ruby}/gateway.rb +8 -9
- data/lib/spandx/{rubygems → ruby}/parsers/gemfile_lock.rb +14 -16
- data/lib/spandx/spdx/catalogue.rb +1 -1
- data/lib/spandx/spdx/license.rb +12 -2
- data/lib/spandx/version.rb +1 -1
- data/spandx.gemspec +4 -1
- metadata +66 -10
- data/lib/spandx/cli/command.rb +0 -65
- data/lib/spandx/cli/commands/index.rb +0 -36
- data/lib/spandx/cli/commands/index/build.rb +0 -32
- data/lib/spandx/cli/commands/index/update.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f54b3c9f0a58ce0038a5ad242c02d7aad3b11090bdecb9d84e67a9f74d5dfd6
|
4
|
+
data.tar.gz: b4ed659d450474bff291b4ee0f723f3342fe9369b690894c1731badb797a4b6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e94f49bff3619f876aa2157f15f8efde4b585720bd95417b1d4c6a48ce24208e18d836597604e4837ea37aee424124404825f8887311ab6697b2efee8474ea42
|
7
|
+
data.tar.gz: cc3553ebc60ff24667c0b182e9beb319bed075e837ef34b348b6b8c15ff16ebccfc56e4cb80c75743baa7862b07e7331e5c924ee2305e6008f5ff1f772e78a71
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Version 0.
|
1
|
+
Version 0.12.0
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
@@ -9,6 +9,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
9
9
|
|
10
10
|
## [Unreleased]
|
11
11
|
|
12
|
+
## [0.12.0] - 2020-04-14
|
13
|
+
### Added
|
14
|
+
- Add `--format csv` option to scan command.
|
15
|
+
- Add `--format table` option to scan command.
|
16
|
+
- Add `--index` option to `build` command.
|
17
|
+
- Add pypi index.
|
18
|
+
- Add maven index.
|
19
|
+
- Add support for parsing `yarn.lock` files.
|
20
|
+
- Add support for parsing `package-lock.json` files.
|
21
|
+
- Add `--pull` option to fetch latest cache before scan.
|
22
|
+
- Add support for parsing `composer.lock` files.
|
23
|
+
- Add support for loading custom plugins via the `--require` option.
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
- Change the default `--format` to `table` for the scan command.
|
27
|
+
|
12
28
|
## [0.11.0] - 2020-03-20
|
13
29
|
### Added
|
14
30
|
- Add `--format` option to scan command.
|
@@ -115,7 +131,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
115
131
|
### Added
|
116
132
|
- Provide ruby API to the latest SPDX catalogue.
|
117
133
|
|
118
|
-
[Unreleased]: https://github.com/mokhan/spandx/compare/v0.
|
134
|
+
[Unreleased]: https://github.com/mokhan/spandx/compare/v0.12.0...HEAD
|
135
|
+
[0.12.0]: https://github.com/mokhan/spandx/compare/v0.11.0...v0.12.0
|
136
|
+
[0.11.0]: https://github.com/mokhan/spandx/compare/v0.10.1...v0.11.0
|
119
137
|
[0.10.1]: https://github.com/mokhan/spandx/compare/v0.10.0...v0.10.1
|
120
138
|
[0.10.0]: https://github.com/mokhan/spandx/compare/v0.9.0...v0.10.0
|
121
139
|
[0.9.0]: https://github.com/mokhan/spandx/compare/v0.8.0...v0.9.0
|
data/README.md
CHANGED
@@ -1,8 +1,26 @@
|
|
1
|
-
# Spandx
|
1
|
+
# Spandx 
|
2
2
|
|
3
3
|
A ruby API for interacting with the https://spdx.org software license catalogue.
|
4
|
+
This gem includes a command line interface to scan a software project for the
|
5
|
+
software licenses that are associated with each dependency in the project.
|
6
|
+
`spandx` leverages an offline cache of software licenses for known dependencies.
|
7
|
+
The offline cache allows spandx to perform a truly airgap friendly scan of software
|
8
|
+
projects.
|
9
|
+
|
10
|
+
### Supported project types
|
11
|
+
|
12
|
+
Spandx can work with following language's package managers. It utilises lock files generated by package managers to find dependencies.
|
13
|
+
|
14
|
+
| Language | Package Manager | Tested in |
|
15
|
+
| ------------ | --------------- | -------: |
|
16
|
+
| Ruby | bundler | 1.17.3 |
|
17
|
+
| Js | Npm | 6.13.4 |
|
18
|
+
| Js | Yarn | 1.19.1 |
|
19
|
+
| Python | Pypi(pipenv) | v2018.11.26 |
|
20
|
+
| C# | nuget | <> |
|
21
|
+
| Java | Maven | 3.6.3 |
|
22
|
+
| Php | Composer | 1.10.5 |
|
4
23
|
|
5
|
-

|
6
24
|
|
7
25
|
## Installation
|
8
26
|
|
@@ -22,6 +40,45 @@ Or install it yourself as:
|
|
22
40
|
|
23
41
|
## Usage
|
24
42
|
|
43
|
+
### Command line interface
|
44
|
+
|
45
|
+
The command line interface supports operations to build and fetch the latest offline index.
|
46
|
+
See the help for each subcommand for more information on how to use the command.
|
47
|
+
|
48
|
+
```bash
|
49
|
+
モ spandx
|
50
|
+
Commands:
|
51
|
+
spandx help [COMMAND] # Describe available commands or one specific command
|
52
|
+
spandx scan LOCKFILE # Scan a lockfile and list dependencies/licenses
|
53
|
+
spandx version # spandx version
|
54
|
+
```
|
55
|
+
|
56
|
+
To scan a specific project file use the `scan` command:
|
57
|
+
|
58
|
+
```bash
|
59
|
+
モ spandx scan dotnet/application.sln
|
60
|
+
モ spandx scan java/pom.xml
|
61
|
+
モ spandx scan python/Pipfile.lock
|
62
|
+
モ spandx scan ruby/Gemfile.lock
|
63
|
+
```
|
64
|
+
|
65
|
+
To activate airgap mode use the `--airgap` option:
|
66
|
+
|
67
|
+
```bash
|
68
|
+
モ spandx scan dotnet/application.sln --airgap
|
69
|
+
モ spandx scan ruby/Gemfile.lock --airgap
|
70
|
+
```
|
71
|
+
|
72
|
+
Airgap mode assumes that an offline cache has been placed in `$HOME/.local/share/`.
|
73
|
+
|
74
|
+
To fetch the latest offline cache:
|
75
|
+
|
76
|
+
```bash
|
77
|
+
モ spandx index update
|
78
|
+
```
|
79
|
+
|
80
|
+
### Ruby API
|
81
|
+
|
25
82
|
To fetch the latest version of the catalogue data from [SPDX](https://spdx.org/licenses/licenses.json).
|
26
83
|
|
27
84
|
```ruby
|
data/exe/spandx
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
lib_path = File.expand_path('../lib', __dir__)
|
5
|
-
|
6
|
-
require 'spandx/cli'
|
5
|
+
require "#{lib_path}/spandx"
|
7
6
|
|
8
7
|
Signal.trap('INT') do
|
9
8
|
warn("\n#{caller.join("\n")}: interrupted")
|
@@ -11,8 +10,8 @@ Signal.trap('INT') do
|
|
11
10
|
end
|
12
11
|
|
13
12
|
begin
|
14
|
-
Spandx::
|
15
|
-
rescue Spandx::
|
13
|
+
Spandx::Cli::Main.start
|
14
|
+
rescue Spandx::Cli::Error => error
|
16
15
|
puts "ERROR: #{error.message}"
|
17
16
|
exit 1
|
18
17
|
end
|
data/lib/spandx.rb
CHANGED
@@ -9,38 +9,15 @@ require 'logger'
|
|
9
9
|
require 'net/hippie'
|
10
10
|
require 'nokogiri'
|
11
11
|
require 'pathname'
|
12
|
+
require 'yaml'
|
13
|
+
require 'zeitwerk'
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
require 'spandx/core/database'
|
16
|
-
require 'spandx/core/dependency'
|
17
|
-
require 'spandx/core/guess'
|
18
|
-
require 'spandx/core/http'
|
19
|
-
require 'spandx/core/parser'
|
20
|
-
require 'spandx/core/report'
|
21
|
-
require 'spandx/core/score'
|
22
|
-
require 'spandx/dotnet/index'
|
23
|
-
require 'spandx/dotnet/nuget_gateway'
|
24
|
-
require 'spandx/dotnet/package_reference'
|
25
|
-
require 'spandx/dotnet/parsers/csproj'
|
26
|
-
require 'spandx/dotnet/parsers/packages_config'
|
27
|
-
require 'spandx/dotnet/parsers/sln'
|
28
|
-
require 'spandx/dotnet/project_file'
|
29
|
-
require 'spandx/java/index'
|
30
|
-
require 'spandx/java/metadata'
|
31
|
-
require 'spandx/java/parsers/maven'
|
32
|
-
require 'spandx/python/parsers/pipfile_lock'
|
33
|
-
require 'spandx/python/pypi'
|
34
|
-
require 'spandx/python/source'
|
35
|
-
require 'spandx/rubygems/gateway'
|
36
|
-
require 'spandx/rubygems/parsers/gemfile_lock'
|
37
|
-
require 'spandx/spdx/catalogue'
|
38
|
-
require 'spandx/spdx/gateway'
|
39
|
-
require 'spandx/spdx/license'
|
40
|
-
require 'spandx/version'
|
15
|
+
loader = Zeitwerk::Loader.for_gem
|
16
|
+
loader.setup # ready!
|
41
17
|
|
42
18
|
module Spandx
|
43
19
|
class Error < StandardError; end
|
20
|
+
Rubygems = Ruby
|
44
21
|
|
45
22
|
class << self
|
46
23
|
attr_writer :airgap, :logger
|
@@ -61,10 +38,14 @@ module Spandx
|
|
61
38
|
@logger ||= Logger.new('/dev/null')
|
62
39
|
end
|
63
40
|
|
64
|
-
def
|
65
|
-
@
|
66
|
-
.new(url: 'https://github.com/
|
67
|
-
.
|
41
|
+
def git
|
42
|
+
@git ||= {
|
43
|
+
cache: ::Spandx::Core::Git.new(url: 'https://github.com/mokhan/spandx-index.git'),
|
44
|
+
rubygems: ::Spandx::Core::Git.new(url: 'https://github.com/mokhan/spandx-rubygems.git'),
|
45
|
+
spdx: ::Spandx::Core::Git.new(url: 'https://github.com/spdx/license-list-data.git'),
|
46
|
+
}
|
68
47
|
end
|
69
48
|
end
|
70
49
|
end
|
50
|
+
|
51
|
+
loader.eager_load
|
data/lib/spandx/cli.rb
CHANGED
@@ -1,38 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thor'
|
4
|
-
require 'spandx'
|
5
|
-
require 'spandx/cli/command'
|
6
|
-
require 'spandx/cli/commands/index'
|
7
|
-
require 'spandx/cli/commands/scan'
|
8
4
|
|
9
5
|
module Spandx
|
10
|
-
|
6
|
+
module Cli
|
11
7
|
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
|
-
register Spandx::Cli::Commands::Index, 'index', 'index [SUBCOMMAND]', 'Command description...'
|
20
|
-
|
21
|
-
desc 'scan LOCKFILE', 'Scan a lockfile and list dependencies/licenses'
|
22
|
-
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
23
|
-
method_option :recursive, aliases: '-r', type: :boolean, desc: 'Perform recursive scan', default: false
|
24
|
-
method_option :airgap, aliases: '-a', type: :boolean, desc: 'Disable network connections', default: false
|
25
|
-
method_option :logfile, aliases: '-l', type: :string, desc: 'Path to a logfile', default: '/dev/null'
|
26
|
-
method_option :format, aliases: '-f', type: :string, desc: 'Format of report', default: 'json'
|
27
|
-
def scan(lockfile)
|
28
|
-
Spandx.airgap = options[:airgap]
|
29
|
-
Spandx.logger = Logger.new(options[:logfile])
|
30
|
-
|
31
|
-
if options[:help]
|
32
|
-
invoke :help, ['scan']
|
33
|
-
else
|
34
|
-
Spandx::Cli::Commands::Scan.new(lockfile, options).execute
|
35
|
-
end
|
36
|
-
end
|
37
8
|
end
|
38
9
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spandx
|
4
|
+
module Cli
|
5
|
+
module Commands
|
6
|
+
class Build
|
7
|
+
INDEXES = {
|
8
|
+
maven: Spandx::Java::Index,
|
9
|
+
nuget: Spandx::Dotnet::Index,
|
10
|
+
dotnet: Spandx::Dotnet::Index,
|
11
|
+
pypi: Spandx::Python::Index,
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def initialize(options)
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(output: $stdout)
|
19
|
+
catalogue = Spandx::Spdx::Catalogue.from_git
|
20
|
+
indexes.each do |index|
|
21
|
+
output.puts index.name
|
22
|
+
index.update!(catalogue: catalogue, output: output)
|
23
|
+
end
|
24
|
+
output.puts 'OK'
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def indexes
|
30
|
+
index = INDEXES[@options[:index]&.to_sym]
|
31
|
+
|
32
|
+
if index.nil?
|
33
|
+
INDEXES.values.uniq.map { |x| x.new(directory: @options[:directory]) }
|
34
|
+
else
|
35
|
+
[index.new(directory: @options[:directory])]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spandx
|
4
|
+
module Cli
|
5
|
+
module Commands
|
6
|
+
class Pull
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(output: $stdout)
|
12
|
+
Spandx.git.each_value do |db|
|
13
|
+
output.puts "Updating #{db.url}..."
|
14
|
+
db.update!
|
15
|
+
end
|
16
|
+
output.puts 'OK'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module Spandx
|
4
4
|
module Cli
|
5
5
|
module Commands
|
6
|
-
class Scan
|
6
|
+
class Scan
|
7
7
|
attr_reader :scan_path
|
8
8
|
|
9
9
|
def initialize(scan_path, options)
|
10
10
|
@scan_path = ::Pathname.new(scan_path)
|
11
11
|
@options = options
|
12
|
+
require(options[:require]) if options[:require]
|
12
13
|
end
|
13
14
|
|
14
15
|
def execute(output: $stdout)
|
@@ -18,7 +19,7 @@ module Spandx
|
|
18
19
|
report.add(dependency)
|
19
20
|
end
|
20
21
|
end
|
21
|
-
output.puts
|
22
|
+
output.puts(format(report.to(@options[:format])))
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
@@ -33,6 +34,7 @@ module Spandx
|
|
33
34
|
if File.directory?(file)
|
34
35
|
each_file_in(file, &block) if recursive?
|
35
36
|
else
|
37
|
+
Spandx.logger.debug(file)
|
36
38
|
block.call(file)
|
37
39
|
end
|
38
40
|
end
|
@@ -42,7 +44,20 @@ module Spandx
|
|
42
44
|
::Spandx::Core::Parser
|
43
45
|
.for(file)
|
44
46
|
.parse(file)
|
47
|
+
.map { |dependency| enhance(dependency) }
|
45
48
|
.each { |dependency| yield dependency }
|
49
|
+
rescue StandardError => error
|
50
|
+
Spandx.logger.error(error)
|
51
|
+
end
|
52
|
+
|
53
|
+
def format(output)
|
54
|
+
Array(output).map(&:to_s)
|
55
|
+
end
|
56
|
+
|
57
|
+
def enhance(dependency)
|
58
|
+
::Spandx::Core::Plugin
|
59
|
+
.all
|
60
|
+
.inject(dependency) { |memo, plugin| plugin.enhance(memo) }
|
46
61
|
end
|
47
62
|
end
|
48
63
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spandx
|
4
|
+
module Cli
|
5
|
+
class Main < Thor
|
6
|
+
desc 'scan LOCKFILE', 'Scan a lockfile and list dependencies/licenses'
|
7
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
8
|
+
method_option :recursive, aliases: '-R', type: :boolean, desc: 'Perform recursive scan', default: false
|
9
|
+
method_option :airgap, aliases: '-a', type: :boolean, desc: 'Disable network connections', default: false
|
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'
|
12
|
+
method_option :pull, aliases: '-p', type: :boolean, desc: 'Pull the latest cache before the scan', default: false
|
13
|
+
method_option :require, aliases: '-r', type: :string, desc: 'Causes spandx to load the library using require.', default: nil
|
14
|
+
def scan(lockfile)
|
15
|
+
if options[:help]
|
16
|
+
invoke :help, ['scan']
|
17
|
+
else
|
18
|
+
Spandx.airgap = options[:airgap]
|
19
|
+
Spandx.logger = Logger.new(options[:logfile])
|
20
|
+
pull if options[:pull]
|
21
|
+
Spandx::Cli::Commands::Scan.new(lockfile, options).execute
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc 'pull', 'Pull the latest offline cache'
|
26
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
27
|
+
def pull(*)
|
28
|
+
if options[:help]
|
29
|
+
invoke :help, ['pull']
|
30
|
+
else
|
31
|
+
Commands::Pull.new(options).execute
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'build', 'Build a package index'
|
36
|
+
method_option :help, aliases: '-h', type: :boolean, desc: 'Display usage information'
|
37
|
+
method_option :directory, aliases: '-d', type: :string, desc: 'Directory to build index in', default: '.index'
|
38
|
+
method_option :index, aliases: '-i', type: :string, desc: 'The specific index to build', default: :all
|
39
|
+
def build(*)
|
40
|
+
if options[:help]
|
41
|
+
invoke :help, ['build']
|
42
|
+
else
|
43
|
+
Commands::Build.new(options).execute
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'version', 'spandx version'
|
48
|
+
def version
|
49
|
+
puts "v#{Spandx::VERSION}"
|
50
|
+
end
|
51
|
+
map %w[--version -v] => :version
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/spandx/core/cache.rb
CHANGED
@@ -5,14 +5,14 @@ module Spandx
|
|
5
5
|
class Cache
|
6
6
|
attr_reader :db, :package_manager
|
7
7
|
|
8
|
-
def initialize(package_manager,
|
8
|
+
def initialize(package_manager, db: Spandx.git[:cache])
|
9
9
|
@package_manager = package_manager
|
10
|
-
@db =
|
10
|
+
@db = db
|
11
11
|
@cache = {}
|
12
12
|
@lines = {}
|
13
13
|
end
|
14
14
|
|
15
|
-
def licenses_for(name
|
15
|
+
def licenses_for(name, version)
|
16
16
|
found = search(name: name, version: version)
|
17
17
|
Spandx.logger.debug("Cache miss: #{name}-#{version}") if found.nil?
|
18
18
|
found ? found[2].split('-|-') : []
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spandx
|
4
|
+
module Core
|
5
|
+
class Circuit
|
6
|
+
attr_reader :state
|
7
|
+
|
8
|
+
def initialize(state: :closed)
|
9
|
+
@state = state
|
10
|
+
end
|
11
|
+
|
12
|
+
def attempt
|
13
|
+
return if open?
|
14
|
+
|
15
|
+
open!
|
16
|
+
result = yield
|
17
|
+
close!
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
def open!
|
22
|
+
@state = :open
|
23
|
+
end
|
24
|
+
|
25
|
+
def close!
|
26
|
+
@state = :closed
|
27
|
+
end
|
28
|
+
|
29
|
+
def open?
|
30
|
+
state == :open
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|