pdk 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +11 -0
- data/lib/pdk/answer_file.rb +1 -1
- data/lib/pdk/cli.rb +16 -6
- data/lib/pdk/cli/bundle.rb +5 -3
- data/lib/pdk/cli/errors.rb +10 -1
- data/lib/pdk/cli/exec.rb +9 -4
- data/lib/pdk/cli/module.rb +14 -0
- data/lib/pdk/cli/module/generate.rb +40 -0
- data/lib/pdk/cli/new.rb +2 -1
- data/lib/pdk/cli/new/class.rb +1 -1
- data/lib/pdk/cli/new/defined_type.rb +27 -0
- data/lib/pdk/cli/new/module.rb +1 -11
- data/lib/pdk/cli/util.rb +3 -3
- data/lib/pdk/cli/util/command_redirector.rb +26 -0
- data/lib/pdk/cli/util/interview.rb +17 -6
- data/lib/pdk/cli/util/option_normalizer.rb +3 -3
- data/lib/pdk/cli/validate.rb +9 -9
- data/lib/pdk/generate.rb +1 -0
- data/lib/pdk/generators/defined_type.rb +49 -0
- data/lib/pdk/generators/module.rb +113 -23
- data/lib/pdk/generators/puppet_class.rb +2 -2
- data/lib/pdk/generators/puppet_object.rb +3 -3
- data/lib/pdk/module/metadata.rb +7 -7
- data/lib/pdk/module/templatedir.rb +3 -3
- data/lib/pdk/report/event.rb +43 -12
- data/lib/pdk/tests/unit.rb +51 -17
- data/lib/pdk/util.rb +3 -3
- data/lib/pdk/util/bundler.rb +5 -5
- data/lib/pdk/util/version.rb +5 -2
- data/lib/pdk/util/windows.rb +6 -0
- data/lib/pdk/validators/base_validator.rb +1 -1
- data/lib/pdk/validators/metadata/metadata_json_lint.rb +2 -2
- data/lib/pdk/validators/metadata/metadata_syntax.rb +2 -2
- data/lib/pdk/validators/puppet/puppet_lint.rb +1 -1
- data/lib/pdk/validators/puppet/puppet_syntax.rb +1 -1
- data/lib/pdk/validators/ruby/rubocop.rb +1 -1
- data/lib/pdk/version.rb +1 -1
- data/lib/puppet/util/windows/api_types.rb +9 -5
- data/locales/pdk.pot +314 -180
- metadata +16 -10
@@ -29,7 +29,7 @@ module PDK
|
|
29
29
|
begin
|
30
30
|
OptionValidator.enum(format, PDK::Report.formats)
|
31
31
|
rescue ArgumentError
|
32
|
-
raise PDK::CLI::
|
32
|
+
raise PDK::CLI::ExitWithError, _("'%{name}' is not a valid report format (%{valid})") % {
|
33
33
|
name: format,
|
34
34
|
valid: PDK::Report.formats.join(', '),
|
35
35
|
}
|
@@ -53,13 +53,13 @@ module PDK
|
|
53
53
|
param_type = 'String' if param_type.nil?
|
54
54
|
|
55
55
|
unless PDK::CLI::Util::OptionValidator.valid_param_name?(param_name)
|
56
|
-
raise PDK::CLI::
|
56
|
+
raise PDK::CLI::ExitWithError, _("'%{name}' is not a valid parameter name") % {
|
57
57
|
name: param_name,
|
58
58
|
}
|
59
59
|
end
|
60
60
|
|
61
61
|
unless PDK::CLI::Util::OptionValidator.valid_data_type?(param_type)
|
62
|
-
raise PDK::CLI::
|
62
|
+
raise PDK::CLI::ExitWithError, _("'%{type}' is not a valid data type") % {
|
63
63
|
type: param_type,
|
64
64
|
}
|
65
65
|
end
|
data/lib/pdk/cli/validate.rb
CHANGED
@@ -6,16 +6,16 @@ module PDK::CLI
|
|
6
6
|
usage _('validate [validators] [options] [targets]')
|
7
7
|
summary _('Run static analysis tests.')
|
8
8
|
description _(
|
9
|
-
"Run metadata,
|
10
|
-
'[validators] is an optional comma
|
11
|
-
"If not specified, all validators
|
12
|
-
'[targets] is an optional space
|
13
|
-
'If not specified,
|
9
|
+
"Run metadata, Puppet, or Ruby validation.\n\n" \
|
10
|
+
'[validators] is an optional comma-separated list of validators to use. ' \
|
11
|
+
"If not specified, all validators are used.\n\n" \
|
12
|
+
'[targets] is an optional space-separated list of files or directories to be validated. ' \
|
13
|
+
'If not specified, validators are run against all applicable files in the module.',
|
14
14
|
)
|
15
15
|
|
16
|
-
flag nil, :list, _('
|
17
|
-
flag :a, 'auto-correct', _('
|
18
|
-
flag nil, :parallel, _('
|
16
|
+
flag nil, :list, _('List all available validators.')
|
17
|
+
flag :a, 'auto-correct', _('Automatically correct problems where possible.')
|
18
|
+
flag nil, :parallel, _('Run validations in parallel.')
|
19
19
|
|
20
20
|
run do |opts, args, _cmd|
|
21
21
|
if args == ['help']
|
@@ -44,7 +44,7 @@ module PDK::CLI
|
|
44
44
|
|
45
45
|
invalid = vals.reject { |v| validator_names.include?(v) }
|
46
46
|
invalid.each do |v|
|
47
|
-
PDK.logger.warn(_("Unknown validator '%{v}'. Available validators: %{validators}") % { v: v, validators: validator_names.join(', ') })
|
47
|
+
PDK.logger.warn(_("Unknown validator '%{v}'. Available validators: %{validators}.") % { v: v, validators: validator_names.join(', ') })
|
48
48
|
end
|
49
49
|
else
|
50
50
|
# This is a single item. Check if it's a known validator, or otherwise treat it as a target.
|
data/lib/pdk/generate.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pdk/generators/puppet_object'
|
2
|
+
|
3
|
+
module PDK
|
4
|
+
module Generate
|
5
|
+
class DefinedType < PuppetObject
|
6
|
+
OBJECT_TYPE = :defined_type
|
7
|
+
|
8
|
+
# Prepares the data needed to render the new defined type template.
|
9
|
+
#
|
10
|
+
# @return [Hash{Symbol => Object}] a hash of information that will be
|
11
|
+
# provided to the defined type and defined type spec templates during
|
12
|
+
# rendering.
|
13
|
+
def template_data
|
14
|
+
data = { name: object_name }
|
15
|
+
|
16
|
+
data
|
17
|
+
end
|
18
|
+
|
19
|
+
# Calculates the path to the .pp file that the new defined type will be
|
20
|
+
# written to.
|
21
|
+
#
|
22
|
+
# @return [String] the path where the new defined type will be written.
|
23
|
+
def target_object_path
|
24
|
+
@target_pp_path ||= begin
|
25
|
+
define_name_parts = object_name.split('::')[1..-1]
|
26
|
+
define_name_parts << 'init' if define_name_parts.empty?
|
27
|
+
|
28
|
+
"#{File.join(module_dir, 'manifests', *define_name_parts)}.pp"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Calculates the path to the file where the tests for the new defined
|
33
|
+
# type will be written.
|
34
|
+
#
|
35
|
+
# @return [String] the path where the tests for the new defined type
|
36
|
+
# will be written.
|
37
|
+
def target_spec_path
|
38
|
+
@target_spec_path ||= begin
|
39
|
+
define_name_parts = object_name.split('::')
|
40
|
+
|
41
|
+
# drop the module name if the object name contains multiple parts
|
42
|
+
define_name_parts.delete_at(0) if define_name_parts.length > 1
|
43
|
+
|
44
|
+
"#{File.join(module_dir, 'spec', 'defines', *define_name_parts)}_spec.rb"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -9,6 +9,7 @@ require 'pdk/module/metadata'
|
|
9
9
|
require 'pdk/module/templatedir'
|
10
10
|
require 'pdk/cli/exec'
|
11
11
|
require 'pdk/cli/util/interview'
|
12
|
+
require 'pdk/cli/util/option_validator'
|
12
13
|
require 'pdk/util'
|
13
14
|
require 'pdk/util/version'
|
14
15
|
|
@@ -18,20 +19,37 @@ module PDK
|
|
18
19
|
def self.default_template_url
|
19
20
|
if !PDK.answers['template-url'].nil?
|
20
21
|
PDK.answers['template-url']
|
21
|
-
|
22
|
+
else
|
23
|
+
puppetlabs_template_url
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.puppetlabs_template_url
|
28
|
+
if PDK::Util.package_install?
|
22
29
|
'file://' + File.join(PDK::Util.package_cachedir, 'pdk-module-template.git')
|
23
30
|
else
|
24
31
|
'https://github.com/puppetlabs/pdk-module-template'
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
28
|
-
def self.
|
35
|
+
def self.validate_options(opts)
|
36
|
+
unless PDK::CLI::Util::OptionValidator.valid_module_name?(opts[:name])
|
37
|
+
error_msg = _(
|
38
|
+
"'%{module_name}' is not a valid module name.\n" \
|
39
|
+
'Module names must begin with a lowercase letter and can only include lowercase letters, digits, and underscores.',
|
40
|
+
) % { module_name: opts[:name] }
|
41
|
+
raise PDK::CLI::ExitWithError, error_msg
|
42
|
+
end
|
43
|
+
|
29
44
|
target_dir = File.expand_path(opts[:target_dir])
|
30
45
|
|
31
|
-
if File.exist?(target_dir)
|
32
|
-
|
33
|
-
|
46
|
+
raise PDK::CLI::ExitWithError, _("The destination directory '%{dir}' already exists") % { dir: target_dir } if File.exist?(target_dir)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.invoke(opts = {})
|
50
|
+
validate_options(opts)
|
34
51
|
|
52
|
+
target_dir = File.expand_path(opts[:target_dir])
|
35
53
|
parent_dir = File.dirname(target_dir)
|
36
54
|
|
37
55
|
begin
|
@@ -68,10 +86,21 @@ module PDK
|
|
68
86
|
end
|
69
87
|
end
|
70
88
|
|
71
|
-
|
89
|
+
if template_url == puppetlabs_template_url
|
90
|
+
# If the user specifies our template via the command line, remove the
|
91
|
+
# saved template-url answer.
|
92
|
+
PDK.answers.update!('template-url' => nil) if opts.key?(:'template-url')
|
93
|
+
else
|
94
|
+
# Save the template-url answer if the module was generated using
|
95
|
+
# a template other than ours.
|
96
|
+
PDK.answers.update!('template-url' => template_url)
|
97
|
+
end
|
72
98
|
|
73
99
|
begin
|
74
|
-
FileUtils.mv(temp_target_dir, target_dir)
|
100
|
+
if FileUtils.mv(temp_target_dir, target_dir)
|
101
|
+
PDK.logger.info(_('Module \'%{name}\' generated at path \'%{path}\'.') % { name: opts[:name], path: target_dir })
|
102
|
+
PDK.logger.info(_('In your module directory, add classes with the \'pdk new class\' command.'))
|
103
|
+
end
|
75
104
|
rescue Errno::EACCES => e
|
76
105
|
raise PDK::CLI::FatalError, _("Failed to move '%{source}' to '%{target}': %{message}") % {
|
77
106
|
source: temp_target_dir,
|
@@ -87,7 +116,7 @@ module PDK
|
|
87
116
|
login_clean = 'username' if login_clean.empty?
|
88
117
|
|
89
118
|
if login_clean != login
|
90
|
-
PDK.logger.warn _('Your username is not a valid Forge username
|
119
|
+
PDK.logger.warn _('Your username is not a valid Forge username. Proceeding with the username %{username}. You can fix this later in metadata.json.') % {
|
91
120
|
username: login_clean,
|
92
121
|
}
|
93
122
|
end
|
@@ -101,9 +130,7 @@ module PDK
|
|
101
130
|
defaults = {
|
102
131
|
'name' => "#{username}-#{opts[:name]}",
|
103
132
|
'version' => '0.1.0',
|
104
|
-
'dependencies' => [
|
105
|
-
{ 'name' => 'puppetlabs-stdlib', 'version_requirement' => '>= 4.13.1 < 5.0.0' },
|
106
|
-
],
|
133
|
+
'dependencies' => [],
|
107
134
|
'requirements' => [
|
108
135
|
{ 'name' => 'puppet', 'version_requirement' => '>= 4.7.0 < 6.0.0' },
|
109
136
|
],
|
@@ -160,7 +187,7 @@ module PDK
|
|
160
187
|
{
|
161
188
|
name: 'author',
|
162
189
|
question: _('Who wrote this module?'),
|
163
|
-
help: _('This
|
190
|
+
help: _('This is used to credit the module\'s author.'),
|
164
191
|
required: true,
|
165
192
|
default: metadata.data['author'],
|
166
193
|
},
|
@@ -171,30 +198,87 @@ module PDK
|
|
171
198
|
required: true,
|
172
199
|
default: metadata.data['license'],
|
173
200
|
},
|
201
|
+
{
|
202
|
+
name: 'operatingsystem_support',
|
203
|
+
question: _('What operating systems does this module support?'),
|
204
|
+
help: _('Use the up and down keys to move between the choices, space to select and enter to continue.'),
|
205
|
+
required: true,
|
206
|
+
choices: {
|
207
|
+
'RedHat based Linux' => [
|
208
|
+
{
|
209
|
+
'operatingsystem' => 'CentOS',
|
210
|
+
'operatingsystemrelease' => ['7'],
|
211
|
+
},
|
212
|
+
{
|
213
|
+
'operatingsystem' => 'OracleLinux',
|
214
|
+
'operatingsystemrelease' => ['7'],
|
215
|
+
},
|
216
|
+
{
|
217
|
+
'operatingsystem' => 'RedHat',
|
218
|
+
'operatingsystemrelease' => ['7'],
|
219
|
+
},
|
220
|
+
{
|
221
|
+
'operatingsystem' => 'Scientific',
|
222
|
+
'operatingsystemrelease' => ['7'],
|
223
|
+
},
|
224
|
+
],
|
225
|
+
'Debian based Linux' => [
|
226
|
+
{
|
227
|
+
'operatingsystem' => 'Debian',
|
228
|
+
'operatingsystemrelease' => ['8'],
|
229
|
+
},
|
230
|
+
{
|
231
|
+
'operatingsystem' => 'Ubuntu',
|
232
|
+
'operatingsystemrelease' => ['16.04'],
|
233
|
+
},
|
234
|
+
],
|
235
|
+
'Fedora' => {
|
236
|
+
'operatingsystem' => 'Fedora',
|
237
|
+
'operatingsystemrelease' => ['25'],
|
238
|
+
},
|
239
|
+
'OSX' => {
|
240
|
+
'operatingsystem' => 'Darwin',
|
241
|
+
'operatingsystemrelease' => ['16'],
|
242
|
+
},
|
243
|
+
'SLES' => {
|
244
|
+
'operatingsystem' => 'SLES',
|
245
|
+
'operatingsystemrelease' => ['12'],
|
246
|
+
},
|
247
|
+
'Solaris' => {
|
248
|
+
'operatingsystem' => 'Solaris',
|
249
|
+
'operatingsystemrelease' => ['11'],
|
250
|
+
},
|
251
|
+
'Windows' => {
|
252
|
+
'operatingsystem' => 'windows',
|
253
|
+
'operatingsystemrelease' => ['2008 R2', '2012 R2', '10'],
|
254
|
+
},
|
255
|
+
},
|
256
|
+
default: [1, 2, 7],
|
257
|
+
},
|
174
258
|
{
|
175
259
|
name: 'summary',
|
176
|
-
question: _('
|
177
|
-
help: _('This
|
260
|
+
question: _('Summarize the purpose of this module in a single sentence.'),
|
261
|
+
help: _('This helps other Puppet users understand what the module does.'),
|
178
262
|
required: true,
|
179
263
|
default: metadata.data['summary'],
|
180
264
|
},
|
181
265
|
{
|
182
266
|
name: 'source',
|
183
267
|
question: _('If there is a source code repository for this module, enter the URL here.'),
|
184
|
-
help: _('Skip this if
|
268
|
+
help: _('Skip this if no repository exists yet. You can update this later in the metadata.json.'),
|
185
269
|
required: true,
|
186
270
|
default: metadata.data['source'],
|
187
271
|
},
|
188
272
|
{
|
189
273
|
name: 'project_page',
|
190
274
|
question: _('If there is a URL where others can learn more about this module, enter it here.'),
|
191
|
-
help: _('Optional.
|
275
|
+
help: _('Optional. You can update this later in the metadata.json.'),
|
192
276
|
default: metadata.data['project_page'],
|
193
277
|
},
|
194
278
|
{
|
195
279
|
name: 'issues_url',
|
196
280
|
question: _('If there is a public issue tracker for this module, enter its URL here.'),
|
197
|
-
help: _('Optional.
|
281
|
+
help: _('Optional. You can update this later in the metadata.json.'),
|
198
282
|
default: metadata.data['issues_url'],
|
199
283
|
},
|
200
284
|
]
|
@@ -208,23 +292,24 @@ module PDK
|
|
208
292
|
interview.add_questions(questions)
|
209
293
|
|
210
294
|
puts _(
|
211
|
-
"\nWe need to create a metadata.json file for this module, so we\'re going to ask you %{count}
|
295
|
+
"\nWe need to create a metadata.json file for this module, so we\'re going to ask you %{count} " \
|
212
296
|
"questions.\n" \
|
213
|
-
'If the question is not applicable to this module,
|
214
|
-
'
|
297
|
+
'If the question is not applicable to this module, accept the default option ' \
|
298
|
+
'shown after each question. You can modify any answers at any time by manually updating ' \
|
215
299
|
"the metadata.json file.\n\n",
|
216
300
|
) % { count: interview.num_questions }
|
217
301
|
|
218
302
|
answers = interview.run
|
219
303
|
|
220
304
|
if answers.nil?
|
221
|
-
PDK.logger.info _('Interview cancelled
|
305
|
+
PDK.logger.info _('Interview cancelled; not generating the module.')
|
222
306
|
exit 0
|
223
307
|
end
|
224
308
|
|
225
309
|
forge_username = answers['name']
|
226
310
|
answers['name'] = "#{answers['name']}-#{opts[:name]}"
|
227
311
|
answers['license'] = opts[:license] if opts.key?(:license)
|
312
|
+
answers['operatingsystem_support'].flatten!
|
228
313
|
metadata.update!(answers)
|
229
314
|
|
230
315
|
puts '-' * 40
|
@@ -234,8 +319,13 @@ module PDK
|
|
234
319
|
puts '-' * 40
|
235
320
|
puts
|
236
321
|
|
237
|
-
|
238
|
-
|
322
|
+
begin
|
323
|
+
continue = prompt.yes?(_('About to generate this module; continue?')) do |q|
|
324
|
+
q.validate(proc { |value| [true, false].include?(value) || value =~ %r{\A(?:yes|y|no|n)\Z}i }, _('Answer "Y" to continue or "n" to cancel.'))
|
325
|
+
end
|
326
|
+
rescue TTY::Prompt::Reader::InputInterrupt
|
327
|
+
PDK.logger.info _('Interview cancelled; not generating the module.')
|
328
|
+
exit 0
|
239
329
|
end
|
240
330
|
|
241
331
|
unless continue
|
@@ -28,8 +28,8 @@ module PDK
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
# Calculates the path to the file
|
32
|
-
# be written
|
31
|
+
# Calculates the path to the file where the tests for the new class will
|
32
|
+
# be written.
|
33
33
|
#
|
34
34
|
# @return [String] the path where the tests for the new class will be
|
35
35
|
# written.
|
@@ -78,14 +78,14 @@ module PDK
|
|
78
78
|
# and create the target files from the template. This is the main entry
|
79
79
|
# point for the class.
|
80
80
|
#
|
81
|
-
# @raise [PDK::CLI::
|
81
|
+
# @raise [PDK::CLI::ExitWithError] if the target files already exist.
|
82
82
|
# @raise [PDK::CLI::FatalError] (see #render_file)
|
83
83
|
#
|
84
84
|
# @api public
|
85
85
|
def run
|
86
86
|
[target_object_path, target_spec_path].each do |target_file|
|
87
87
|
if File.exist?(target_file)
|
88
|
-
raise PDK::CLI::
|
88
|
+
raise PDK::CLI::ExitWithError, _("Unable to generate %{object_type}; '%{file}' already exists.") % { file: target_file, object_type: object_type }
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -165,7 +165,7 @@ module PDK
|
|
165
165
|
# TODO: refactor to a search-and-execute form instead
|
166
166
|
return # work is done # rubocop:disable Lint/NonLocalExitFromIterator
|
167
167
|
elsif template[:allow_fallback]
|
168
|
-
PDK.logger.debug(_('Unable to find a %{type} template in %{url}
|
168
|
+
PDK.logger.debug(_('Unable to find a %{type} template in %{url}; trying next template directory.') % { type: object_type, url: template[:url] })
|
169
169
|
else
|
170
170
|
raise PDK::CLI::FatalError, _('Unable to find the %{type} template in %{url}.') % { type: object_type, url: template[:url] }
|
171
171
|
end
|
data/lib/pdk/module/metadata.rb
CHANGED
@@ -44,11 +44,11 @@ module PDK
|
|
44
44
|
|
45
45
|
def self.from_file(metadata_json_path)
|
46
46
|
unless File.file?(metadata_json_path)
|
47
|
-
raise ArgumentError, _("'%{file}' does not exist or is not a file") % { file: metadata_json_path }
|
47
|
+
raise ArgumentError, _("'%{file}' does not exist or is not a file.") % { file: metadata_json_path }
|
48
48
|
end
|
49
49
|
|
50
50
|
unless File.readable?(metadata_json_path)
|
51
|
-
raise ArgumentError, _("Unable to open '%{file}' for reading") % { file: metadata_json_path }
|
51
|
+
raise ArgumentError, _("Unable to open '%{file}' for reading.") % { file: metadata_json_path }
|
52
52
|
end
|
53
53
|
|
54
54
|
begin
|
@@ -90,16 +90,16 @@ module PDK
|
|
90
90
|
|
91
91
|
err = case modname
|
92
92
|
when nil, '', :namespace_missing
|
93
|
-
'
|
93
|
+
_('Field must be a dash-separated user name and module name.')
|
94
94
|
when %r{[^a-z0-9_]}i
|
95
|
-
'
|
95
|
+
_('Module name must contain only alphanumeric or underscore characters.')
|
96
96
|
when %r{^[^a-z]}i
|
97
|
-
'
|
97
|
+
_('Module name must begin with a letter.')
|
98
98
|
else
|
99
|
-
'
|
99
|
+
_('Namespace must contain only alphanumeric characters.')
|
100
100
|
end
|
101
101
|
|
102
|
-
raise ArgumentError, "Invalid 'name' field in metadata.json:
|
102
|
+
raise ArgumentError, _("Invalid 'name' field in metadata.json: %{err}") % { err: err }
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -52,7 +52,7 @@ module PDK
|
|
52
52
|
unless clone_result[:exit_code].zero?
|
53
53
|
PDK.logger.error clone_result[:stdout]
|
54
54
|
PDK.logger.error clone_result[:stderr]
|
55
|
-
raise PDK::CLI::FatalError, _("Unable to clone git repository '%{repo}' to '%{dest}'") % { repo: path_or_url, dest: temp_dir }
|
55
|
+
raise PDK::CLI::FatalError, _("Unable to clone git repository '%{repo}' to '%{dest}'.") % { repo: path_or_url, dest: temp_dir }
|
56
56
|
end
|
57
57
|
|
58
58
|
@path = PDK::Util.canonical_path(temp_dir)
|
@@ -178,11 +178,11 @@ module PDK
|
|
178
178
|
# @api private
|
179
179
|
def validate_module_template!
|
180
180
|
unless File.directory?(@path)
|
181
|
-
raise ArgumentError, _("The specified template '%{path}' is not a directory") % { path: @path }
|
181
|
+
raise ArgumentError, _("The specified template '%{path}' is not a directory.") % { path: @path }
|
182
182
|
end
|
183
183
|
|
184
184
|
unless File.directory?(@moduleroot_dir) # rubocop:disable Style/GuardClause
|
185
|
-
raise ArgumentError, _("The template at '%{path}' does not contain a 'moduleroot/' directory") % { path: @path }
|
185
|
+
raise ArgumentError, _("The template at '%{path}' does not contain a 'moduleroot/' directory.") % { path: @path }
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|