dragnet 5.2.1
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 +7 -0
- data/.github/workflows/release.yml +45 -0
- data/.github/workflows/ruby-linters.yml +41 -0
- data/.github/workflows/ruby-tests.yml +38 -0
- data/.github/workflows/sphinx-doc.yml +79 -0
- data/.gitignore +13 -0
- data/.reek.yml +15 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +178 -0
- data/Gemfile +18 -0
- data/README.md +119 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/default.reek +7 -0
- data/dragnet.gemspec +39 -0
- data/exe/dragnet +9 -0
- data/lib/dragnet/base_repository.rb +69 -0
- data/lib/dragnet/cli/base.rb +72 -0
- data/lib/dragnet/cli/logger.rb +72 -0
- data/lib/dragnet/cli/master.rb +173 -0
- data/lib/dragnet/cli.rb +8 -0
- data/lib/dragnet/errors/error.rb +8 -0
- data/lib/dragnet/errors/file_not_found_error.rb +11 -0
- data/lib/dragnet/errors/incompatible_repository_error.rb +10 -0
- data/lib/dragnet/errors/missing_timestamp_attribute_error.rb +11 -0
- data/lib/dragnet/errors/no_mtr_files_found_error.rb +11 -0
- data/lib/dragnet/errors/not_a_repository_error.rb +11 -0
- data/lib/dragnet/errors/repo_path_not_found_error.rb +10 -0
- data/lib/dragnet/errors/unable_to_write_report_error.rb +11 -0
- data/lib/dragnet/errors/unknown_export_format_error.rb +11 -0
- data/lib/dragnet/errors/validation_error.rb +11 -0
- data/lib/dragnet/errors/yaml_format_error.rb +9 -0
- data/lib/dragnet/errors.rb +9 -0
- data/lib/dragnet/explorer.rb +103 -0
- data/lib/dragnet/exporter.rb +130 -0
- data/lib/dragnet/exporters/exporter.rb +29 -0
- data/lib/dragnet/exporters/html_exporter.rb +158 -0
- data/lib/dragnet/exporters/id_generator.rb +35 -0
- data/lib/dragnet/exporters/json_exporter.rb +34 -0
- data/lib/dragnet/exporters/serializers/repo_serializer.rb +40 -0
- data/lib/dragnet/exporters/serializers/test_record_serializer.rb +101 -0
- data/lib/dragnet/exporters/serializers/verification_result_serializer.rb +34 -0
- data/lib/dragnet/exporters/serializers.rb +12 -0
- data/lib/dragnet/exporters/templates/template.html.erb +518 -0
- data/lib/dragnet/exporters.rb +13 -0
- data/lib/dragnet/helpers/repository_helper.rb +27 -0
- data/lib/dragnet/multi_repository.rb +48 -0
- data/lib/dragnet/repo.rb +31 -0
- data/lib/dragnet/repository.rb +77 -0
- data/lib/dragnet/test_record.rb +91 -0
- data/lib/dragnet/validator.rb +79 -0
- data/lib/dragnet/validators/data_validator.rb +75 -0
- data/lib/dragnet/validators/entities/repo_validator.rb +31 -0
- data/lib/dragnet/validators/entities/test_record_validator.rb +93 -0
- data/lib/dragnet/validators/entities.rb +12 -0
- data/lib/dragnet/validators/fields/description_validator.rb +24 -0
- data/lib/dragnet/validators/fields/field_validator.rb +69 -0
- data/lib/dragnet/validators/fields/files_validator.rb +29 -0
- data/lib/dragnet/validators/fields/id_validator.rb +36 -0
- data/lib/dragnet/validators/fields/meta_data_field_validator.rb +36 -0
- data/lib/dragnet/validators/fields/path_validator.rb +22 -0
- data/lib/dragnet/validators/fields/repos_validator.rb +62 -0
- data/lib/dragnet/validators/fields/result_validator.rb +33 -0
- data/lib/dragnet/validators/fields/sha1_validator.rb +42 -0
- data/lib/dragnet/validators/fields.rb +17 -0
- data/lib/dragnet/validators/files_validator.rb +85 -0
- data/lib/dragnet/validators/repos_validator.rb +74 -0
- data/lib/dragnet/validators/validator.rb +20 -0
- data/lib/dragnet/validators.rb +12 -0
- data/lib/dragnet/verification_result.rb +125 -0
- data/lib/dragnet/verifier.rb +64 -0
- data/lib/dragnet/verifiers/changes_verifier.rb +70 -0
- data/lib/dragnet/verifiers/files_verifier.rb +51 -0
- data/lib/dragnet/verifiers/repos_verifier.rb +92 -0
- data/lib/dragnet/verifiers/repository_verifier.rb +27 -0
- data/lib/dragnet/verifiers/result_verifier.rb +32 -0
- data/lib/dragnet/verifiers/test_record_verifier.rb +85 -0
- data/lib/dragnet/verifiers/verifier.rb +37 -0
- data/lib/dragnet/verifiers.rb +8 -0
- data/lib/dragnet/version.rb +5 -0
- data/lib/dragnet.rb +18 -0
- metadata +190 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors/incompatible_repository_error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
# Base class for Dragnet's repository classes.
|
7
|
+
class BaseRepository
|
8
|
+
attr_reader :path
|
9
|
+
|
10
|
+
# @param [Pathname] path The path were the repository is located.
|
11
|
+
def initialize(path:)
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
16
|
+
def git
|
17
|
+
incompatible_repository(__method__)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
21
|
+
def branch
|
22
|
+
incompatible_repository(__method__)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
26
|
+
def branches
|
27
|
+
incompatible_repository(__method__)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
31
|
+
def diff
|
32
|
+
incompatible_repository(__method__)
|
33
|
+
end
|
34
|
+
|
35
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
36
|
+
def head
|
37
|
+
incompatible_repository(__method__)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
41
|
+
def remote_uri_path
|
42
|
+
incompatible_repository(__method__)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
46
|
+
def repositories
|
47
|
+
incompatible_repository(__method__)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
51
|
+
def branches_with(_commit)
|
52
|
+
incompatible_repository(__method__)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
56
|
+
def branches_with_head
|
57
|
+
incompatible_repository(__method__)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# @param [String] message The message for the raised error.
|
63
|
+
# @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised
|
64
|
+
# with the given message.
|
65
|
+
def incompatible_repository(message)
|
66
|
+
raise Dragnet::Errors::IncompatibleRepositoryError, message
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/hash'
|
5
|
+
require 'colorize'
|
6
|
+
require 'thor'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
require_relative 'logger'
|
10
|
+
|
11
|
+
module Dragnet
|
12
|
+
module CLI
|
13
|
+
# Base class for all CLI classes.
|
14
|
+
class Base < Thor
|
15
|
+
include Thor::Actions
|
16
|
+
|
17
|
+
# Exit status codes
|
18
|
+
E_CONFIG_LOAD_ERROR = 1
|
19
|
+
|
20
|
+
attr_reader :configuration, :logger
|
21
|
+
|
22
|
+
class_option :configuration, aliases: :c, desc: 'Configuration file',
|
23
|
+
default: '.dragnet.yaml', required: true
|
24
|
+
|
25
|
+
class_option :quiet, aliases: :q, default: false, type: :boolean,
|
26
|
+
desc: 'Suppresses all terminal output (except for critical errors)'
|
27
|
+
|
28
|
+
# Tells Thor to return an unsuccessful return code (different from 0) if
|
29
|
+
# an error is raised.
|
30
|
+
def self.exit_on_failure?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
# Creates a new instance of the class. Called by Thor when a command is
|
35
|
+
# executed. Creates a logger for the class passing Thor's shell to it
|
36
|
+
# (Thor's shell handles the output to the console)
|
37
|
+
def initialize(*args)
|
38
|
+
super
|
39
|
+
@logger = Dragnet::CLI::Logger.new(shell)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# @return [String] Returns the name of the configuration file (passed via
|
45
|
+
# the -c command line switch).
|
46
|
+
def configuration_file
|
47
|
+
@configuration_file ||= options[:configuration]
|
48
|
+
end
|
49
|
+
|
50
|
+
# Loads the configuration from the given configuration file. (This is a
|
51
|
+
# dumb loader, it basically loads the whole YAML file into a hash, no
|
52
|
+
# parsing, validation or checking takes place)
|
53
|
+
def load_configuration
|
54
|
+
logger.info "Loading configuration file #{configuration_file}..."
|
55
|
+
@configuration = YAML.safe_load(File.read(configuration_file)).deep_symbolize_keys
|
56
|
+
rescue StandardError => e
|
57
|
+
fatal_error("Unable to load the given configuration file: '#{configuration_file}'", e, E_CONFIG_LOAD_ERROR)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Prints the given message alongside the message of the given exception
|
61
|
+
# and then terminates the process with the given exit code.
|
62
|
+
# @param [String] message The error message.
|
63
|
+
# @param [Exception] exception The exception that caused the fatal error.
|
64
|
+
# @param [exit_code] exit_code The exit code.
|
65
|
+
def fatal_error(message, exception, exit_code)
|
66
|
+
puts 'Error: '.colorize(:light_red) + message
|
67
|
+
puts " #{exception.message}"
|
68
|
+
exit(exit_code)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module CLI
|
7
|
+
# A logger for the CLI. It uses the +say+ method in Thor's +Shell+ class to
|
8
|
+
# print the messages to the output, honoring the status of the +quiet+
|
9
|
+
# command line switch.
|
10
|
+
class Logger
|
11
|
+
attr_reader :shell, :log_level
|
12
|
+
|
13
|
+
LEVELS = { debug: 0, info: 1, warn: 2, error: 3 }.freeze
|
14
|
+
DEFAULT_LOG_LEVEL = :info
|
15
|
+
PADDING_STRING = ' '
|
16
|
+
PADDING_WIDTH = 7
|
17
|
+
|
18
|
+
# Creates a new instance of the class.
|
19
|
+
# @param [Thor::Shell::Basic] shell A reference to Thor's +Shell+ this
|
20
|
+
# will be used to send the output to the terminal in which Thor was
|
21
|
+
# started.
|
22
|
+
# @param [Symbol] log_level The log level for the logger. The higher the
|
23
|
+
# level the less output will be printed.
|
24
|
+
# @see LEVELS
|
25
|
+
def initialize(shell, log_level = DEFAULT_LOG_LEVEL)
|
26
|
+
raise ArgumentError, "Unknown logger level: #{log_level}" unless LEVELS.keys.include?(log_level)
|
27
|
+
|
28
|
+
@log_level = LEVELS[log_level]
|
29
|
+
@shell = shell
|
30
|
+
end
|
31
|
+
|
32
|
+
# Prints a message with log level +debug+
|
33
|
+
# @param [String] message The message to print
|
34
|
+
def debug(message)
|
35
|
+
output(:debug, :green, message)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Prints a message with log level +info+
|
39
|
+
# @param [String] message The message to print
|
40
|
+
def info(message)
|
41
|
+
output(:info, :blue, message)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Prints a message with log level +warn+
|
45
|
+
# @param [String] message The message to print
|
46
|
+
def warn(message)
|
47
|
+
output(:warn, :yellow, message)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Prints a message with log level +error+
|
51
|
+
# @param [String] message The message to print
|
52
|
+
def error(message)
|
53
|
+
output(:error, :red, message)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Prints the given message with the given level and text color (only the
|
59
|
+
# name of the level will be colored).
|
60
|
+
# @param [Symbol] level The log level
|
61
|
+
# @param [Symbol] color The color to use. One of the colors available for
|
62
|
+
# the +#colorize+ method.
|
63
|
+
# @param [String] message The message to print.
|
64
|
+
# @see Colorize::InstanceMethods#colorize
|
65
|
+
def output(level, color, message)
|
66
|
+
return unless log_level <= LEVELS[level]
|
67
|
+
|
68
|
+
shell.say "#{level.to_s.capitalize}:".ljust(PADDING_WIDTH, PADDING_STRING).colorize(color) + message
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../explorer'
|
4
|
+
require_relative '../exporter'
|
5
|
+
require_relative '../multi_repository'
|
6
|
+
require_relative '../repository'
|
7
|
+
require_relative '../validator'
|
8
|
+
require_relative '../verifier'
|
9
|
+
require_relative '../version'
|
10
|
+
require_relative 'base'
|
11
|
+
|
12
|
+
module Dragnet
|
13
|
+
module CLI
|
14
|
+
# Entry point class for the Dragnet CLI. Includes all the commands and
|
15
|
+
# sub-commands of the CLI.
|
16
|
+
#
|
17
|
+
# The class should not contain any logic, everything should be delegated to
|
18
|
+
# helper classes as soon as possible. Only exceptions are error handling and
|
19
|
+
# message printing.
|
20
|
+
class Master < Dragnet::CLI::Base
|
21
|
+
E_MISSING_PARAMETER_ERROR = 2
|
22
|
+
E_NO_MTR_FILES_FOUND = 3
|
23
|
+
E_GIT_ERROR = 4
|
24
|
+
E_EXPORT_ERROR = 5
|
25
|
+
E_INCOMPATIBLE_REPOSITORY = 6
|
26
|
+
|
27
|
+
E_ERRORS_DETECTED = 16
|
28
|
+
E_FAILED_TESTS = 32
|
29
|
+
|
30
|
+
map %w[--version -v] => :version
|
31
|
+
|
32
|
+
desc '--version', 'Prints the current version of the Gem'
|
33
|
+
def version
|
34
|
+
say "Dragnet #{Dragnet::VERSION}"
|
35
|
+
say "Copyright (c) #{Time.now.year} ESR Labs GmbH esrlabs.com"
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'check [PATH]', 'Executes the verification procedure. '\
|
39
|
+
'Loads the given configuration file and executes the verify procedure on the given path '\
|
40
|
+
'(defaults to the value of the "path" key in the configuration file or the current '\
|
41
|
+
'working directory if none of them is given)'
|
42
|
+
method_option :export,
|
43
|
+
aliases: 'e', type: :string, repeatable: true,
|
44
|
+
desc: 'If given, the results of the verification procedure will be exported to'\
|
45
|
+
' the given file. The format of the export will be deducted from the given'\
|
46
|
+
" file's name"
|
47
|
+
method_option :'multi-repo',
|
48
|
+
aliases: '-m', type: :boolean, default: false,
|
49
|
+
desc: 'Enables the multi-repo compatibility mode. This prevents Dragnet from assuming'\
|
50
|
+
' that [PATH] refers to a Git repository allowing it to run even if that is not the case.'\
|
51
|
+
" Using this option will cause Dragnet to raise an error if it finds a MTR which doesn't"\
|
52
|
+
" have a 'repos' attribute"
|
53
|
+
def check(path = nil)
|
54
|
+
load_configuration
|
55
|
+
self.path = path
|
56
|
+
|
57
|
+
files = explore
|
58
|
+
test_records, errors = validate(files)
|
59
|
+
verify(test_records)
|
60
|
+
|
61
|
+
export(test_records, errors) if options[:export]
|
62
|
+
|
63
|
+
exit_code = 0
|
64
|
+
exit_code |= E_ERRORS_DETECTED if errors.any?
|
65
|
+
exit_code |= E_FAILED_TESTS unless test_records.all? { |test_record| test_record.verification_result.passed? }
|
66
|
+
|
67
|
+
exit(exit_code) if exit_code.positive? # doing exit(0) will stop RSpec execution.
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# Runs the explorer on the given path.
|
73
|
+
# @return [Array<Pathname>] The array of found MTR files.
|
74
|
+
def explore
|
75
|
+
glob_patterns = configuration[:glob_patterns]
|
76
|
+
|
77
|
+
begin
|
78
|
+
explorer = Dragnet::Explorer.new(path: path, glob_patterns: glob_patterns, logger: logger)
|
79
|
+
explorer.files
|
80
|
+
rescue ArgumentError => e
|
81
|
+
fatal_error('Initialization error. Missing or malformed parameter.', e, E_MISSING_PARAMETER_ERROR)
|
82
|
+
rescue Dragnet::Errors::NoMTRFilesFoundError => e
|
83
|
+
fatal_error('No MTR Files found.', e, E_NO_MTR_FILES_FOUND)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Executes the validator on the given MTR files.
|
88
|
+
# @param [Array<Pathname>] files The files to run the validator on.
|
89
|
+
# @return [Array (Array<Dragnet::TestRecord>, Array<Hash>)] An array.
|
90
|
+
# - The first element is an array of +TestRecord+s with the MTR data.
|
91
|
+
# One for each valid MTR file.
|
92
|
+
# - The second element contains the errors occurred during the
|
93
|
+
# validation process. Can be an empty array.
|
94
|
+
def validate(files)
|
95
|
+
validator = Dragnet::Validator.new(files: files, path: path, logger: logger)
|
96
|
+
[validator.validate, validator.errors]
|
97
|
+
end
|
98
|
+
|
99
|
+
# Executes the verification on the given MTRs
|
100
|
+
# @param [Array<Dragnet::TestRecord>] test_records The array of MTRs on
|
101
|
+
# which the verification should be executed.
|
102
|
+
def verify(test_records)
|
103
|
+
verifier = Dragnet::Verifier.new(test_records: test_records, repository: repository, logger: logger)
|
104
|
+
verifier.verify
|
105
|
+
rescue ArgumentError => e
|
106
|
+
fatal_error("Could not open the specified path: #{path} as a Git Repository", e, E_GIT_ERROR)
|
107
|
+
rescue Dragnet::Errors::IncompatibleRepositoryError => e
|
108
|
+
incompatible_repository_error(e)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Executes the export process.
|
112
|
+
# @param [Array<Dragnet::TestRecord>] test_records The validated and
|
113
|
+
# verified test records.
|
114
|
+
# @param [Array<Hashes>] errors The array of Hashes with the MTR files
|
115
|
+
# that didn't pass the validation process.
|
116
|
+
def export(test_records, errors)
|
117
|
+
exporter = Dragnet::Exporter.new(
|
118
|
+
test_records: test_records, errors: errors, repository: repository, targets: options[:export], logger: logger
|
119
|
+
)
|
120
|
+
|
121
|
+
exporter.export
|
122
|
+
rescue Dragnet::Errors::UnknownExportFormatError, Dragnet::Errors::UnableToWriteReportError => e
|
123
|
+
fatal_error('Export failed', e, E_EXPORT_ERROR)
|
124
|
+
rescue Dragnet::Errors::IncompatibleRepositoryError => e
|
125
|
+
incompatible_repository_error(e)
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [Pathname] The path of the directory where the verification
|
129
|
+
# process should be executed.
|
130
|
+
def path
|
131
|
+
@path || set_fallback_path
|
132
|
+
end
|
133
|
+
|
134
|
+
# @param [Pathname, String] path The path of the directory where the
|
135
|
+
# verification process should be executed.
|
136
|
+
def path=(path)
|
137
|
+
@path = path ? Pathname.new(path) : nil
|
138
|
+
end
|
139
|
+
|
140
|
+
# @raise [ArgumentError] If the given path is not a valid git repository.
|
141
|
+
# @return [Dragnet::Repository, Dragnet::MultiRepository] One of the
|
142
|
+
# possible Repository objects.
|
143
|
+
def repository
|
144
|
+
@repository ||= create_repository
|
145
|
+
end
|
146
|
+
|
147
|
+
# Creates the appropriate Repository object in accordance to the status of
|
148
|
+
# the +multi-repo+ command line option.
|
149
|
+
# @return [Dragnet::MultiRepository] If +multi-repo+ was set to +true+
|
150
|
+
# @return [Dragnet::Repository] If +multi_repo+ was set to +false+
|
151
|
+
def create_repository
|
152
|
+
options[:'multi-repo'] ? Dragnet::MultiRepository.new(path: path) : Dragnet::Repository.new(path: path)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Prints a message and exits with the proper error code when a
|
156
|
+
# +Dragnet::Errors::IncompatibleRepositoryError+ is raised.
|
157
|
+
# @param [Dragnet::Errors::IncompatibleRepositoryError] error The raised
|
158
|
+
# error.
|
159
|
+
def incompatible_repository_error(error)
|
160
|
+
fatal_error('Incompatible git operation:', error, E_INCOMPATIBLE_REPOSITORY)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Called when no path has been given by the user explicitly. The method
|
164
|
+
# uses the configured path or the current working directory as a fallback.
|
165
|
+
# @return [Pathname] The constructed fallback path.
|
166
|
+
def set_fallback_path
|
167
|
+
# The && causes Ruby to return the value of +@path+ AFTER it has been
|
168
|
+
# assigned (converted to a Pathname)
|
169
|
+
(self.path = configuration[:path] || Dir.pwd) && @path
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
data/lib/dragnet/cli.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when one of the files referenced by a MTR File
|
8
|
+
# doesn't exist in the repository.
|
9
|
+
class FileNotFoundError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dragnet
|
4
|
+
module Errors
|
5
|
+
# An error to be raised when an attempt is made to perform an action on a
|
6
|
+
# multi-repo set-up which can only be performed on a single-repo set-up.
|
7
|
+
# For example, trying to perform a +diff+ operation on the multi-repo root.
|
8
|
+
class IncompatibleRepositoryError < Dragnet::Errors::Error; end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when an attempt is made to retrieve the runtime
|
8
|
+
# when one or more timestamp attributes are missing.
|
9
|
+
class MissingTimestampAttributeError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when the +Explorer+ is unable to locate MTR files
|
8
|
+
# with the given glob patterns inside the specified path.
|
9
|
+
class NoMTRFilesFoundError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when the path of a repository entry in a MTR with
|
8
|
+
# multiple repositories doesn't point to an actual git repository.
|
9
|
+
class NotARepositoryError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when Dragnet cannot write to one of the given export
|
8
|
+
# files.
|
9
|
+
class UnableToWriteReportError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
module Errors
|
7
|
+
# An error to be raised when an export target file is given for which the
|
8
|
+
# format is unknown (cannot be deduced from its extension).
|
9
|
+
class UnknownExportFormatError < Dragnet::Errors::Error; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dragnet
|
4
|
+
module Errors
|
5
|
+
# An error to be raised when there is a formatting problem with a YAML file.
|
6
|
+
# For example a missing key. (This error doesn't cover Syntax Errors)
|
7
|
+
class YAMLFormatError < Dragnet::Errors::Error; end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'errors/no_mtr_files_found_error'
|
4
|
+
|
5
|
+
module Dragnet
|
6
|
+
# This class searches for Manual Test Record files inside a given path by
|
7
|
+
# using the given Glob patterns.
|
8
|
+
class Explorer
|
9
|
+
attr_reader :path, :glob_patterns, :logger
|
10
|
+
|
11
|
+
# Creates a new instance of the class.
|
12
|
+
# @param [Pathname] path The path that should be explored.
|
13
|
+
# @param [String, Array<String>] glob_patterns The glob pattern or glob
|
14
|
+
# patterns to use when exploring the specified path.
|
15
|
+
# @param [#info] logger A logger object to use for output.
|
16
|
+
# @raise [ArgumentError] If +path+ or +glob_patterns+ are +nil+ or if they
|
17
|
+
# don't have one of the expected types.
|
18
|
+
def initialize(path:, glob_patterns:, logger:)
|
19
|
+
validate_path(path)
|
20
|
+
validate_patterns(glob_patterns)
|
21
|
+
|
22
|
+
@path = path
|
23
|
+
@glob_patterns = *glob_patterns
|
24
|
+
@logger = logger
|
25
|
+
end
|
26
|
+
|
27
|
+
# Performs the search for MTR files and returns an array with the found
|
28
|
+
# files.
|
29
|
+
# @return [Array<Pathname>] The array of found MTR files.
|
30
|
+
# @raise [Dragnet::Errors::NoMTRFilesFoundError] If no MTR files are found.
|
31
|
+
def files
|
32
|
+
@files ||= find_files
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Raises an +ArgumentError+ with the appropriate message.
|
38
|
+
# @param [String] name The name of the missing parameter.
|
39
|
+
# @raise [ArgumentError] Is always raised with the appropriate message.
|
40
|
+
def missing_parameter(name)
|
41
|
+
raise ArgumentError, "Missing required parameter #{name}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Raises an +ArgumentError+ with the appropriate message.
|
45
|
+
# @param [String] name The name of the parameter with an incompatible type.
|
46
|
+
# @param [String, Class] expected The expected parameter type.
|
47
|
+
# @param [String, Class] given The given parameter type.
|
48
|
+
# @raise [ArgumentError] Is always raised with the appropriate message.
|
49
|
+
def incompatible_parameter(name, expected, given)
|
50
|
+
raise ArgumentError, "Incompatible parameter type #{name}. Expected: #{expected}, given: #{given}"
|
51
|
+
end
|
52
|
+
|
53
|
+
# Validates the given path
|
54
|
+
# @param [Object] path The path to validate
|
55
|
+
# @raise [ArgumentError] If the given path is nil or is not a +Pathname+.
|
56
|
+
def validate_path(path)
|
57
|
+
missing_parameter('path') unless path
|
58
|
+
return if path.is_a?(Pathname)
|
59
|
+
|
60
|
+
incompatible_parameter('path', Pathname, path.class)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Validates the given glob patterns
|
64
|
+
# @param [String, Array<String>] glob_patterns The glob patterns
|
65
|
+
# @raise [ArgumentError] If +glob_patterns+ is +nil+ or it isn't an array
|
66
|
+
# of strings.
|
67
|
+
def validate_patterns(glob_patterns)
|
68
|
+
missing_parameter('glob_patterns') unless glob_patterns
|
69
|
+
|
70
|
+
return if glob_patterns.is_a?(String)
|
71
|
+
return if glob_patterns.is_a?(Array) && glob_patterns.all? { |value| value.is_a?(String) }
|
72
|
+
|
73
|
+
incompatible_parameter('glob_patterns', 'String or Array<String>', glob_patterns.class)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Logs the MTR files that were found.
|
77
|
+
# @param [Array<Pathname>] files The found MTR files.
|
78
|
+
# @return [Array<Pathname>] The same array given in +files+.
|
79
|
+
def log_found_files(files)
|
80
|
+
files.each { |file| logger.info("Found MTR file: #{file}") }
|
81
|
+
end
|
82
|
+
|
83
|
+
# Searches the +path+ for MTR files using the +glob_patterns+
|
84
|
+
# @return [Array<Pathname>] The array of found MTR files.
|
85
|
+
# @raise [Dragnet::Errors::NoMTRFilesFoundError] If no MTR files are found.
|
86
|
+
def find_files
|
87
|
+
logger.info 'Searching for Manual Test Records...'
|
88
|
+
|
89
|
+
files = []
|
90
|
+
|
91
|
+
glob_patterns.each do |glob_pattern|
|
92
|
+
logger.info "Globbing #{path} with #{glob_pattern}..."
|
93
|
+
|
94
|
+
files += log_found_files(path.glob(glob_pattern))
|
95
|
+
end
|
96
|
+
|
97
|
+
return files if files.any?
|
98
|
+
|
99
|
+
raise Dragnet::Errors::NoMTRFilesFoundError,
|
100
|
+
"No MTR Files found in #{path} with the following glob patterns: #{glob_patterns.join(', ')}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|