pdk 1.9.0 → 3.2.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.
Files changed (163) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +744 -711
  3. data/README.md +23 -21
  4. data/lib/pdk/answer_file.rb +3 -112
  5. data/lib/pdk/bolt.rb +20 -0
  6. data/lib/pdk/cli/build.rb +51 -54
  7. data/lib/pdk/cli/bundle.rb +33 -29
  8. data/lib/pdk/cli/console.rb +148 -0
  9. data/lib/pdk/cli/convert.rb +46 -37
  10. data/lib/pdk/cli/env.rb +51 -0
  11. data/lib/pdk/cli/errors.rb +4 -3
  12. data/lib/pdk/cli/exec/command.rb +285 -0
  13. data/lib/pdk/cli/exec/interactive_command.rb +109 -0
  14. data/lib/pdk/cli/exec.rb +32 -201
  15. data/lib/pdk/cli/exec_group.rb +79 -43
  16. data/lib/pdk/cli/get/config.rb +26 -0
  17. data/lib/pdk/cli/get.rb +22 -0
  18. data/lib/pdk/cli/new/class.rb +20 -22
  19. data/lib/pdk/cli/new/defined_type.rb +21 -21
  20. data/lib/pdk/cli/new/fact.rb +27 -0
  21. data/lib/pdk/cli/new/function.rb +27 -0
  22. data/lib/pdk/cli/new/module.rb +40 -29
  23. data/lib/pdk/cli/new/provider.rb +18 -18
  24. data/lib/pdk/cli/new/task.rb +23 -22
  25. data/lib/pdk/cli/new/test.rb +52 -0
  26. data/lib/pdk/cli/new/transport.rb +27 -0
  27. data/lib/pdk/cli/new.rb +15 -9
  28. data/lib/pdk/cli/release/prep.rb +39 -0
  29. data/lib/pdk/cli/release/publish.rb +46 -0
  30. data/lib/pdk/cli/release.rb +185 -0
  31. data/lib/pdk/cli/remove/config.rb +83 -0
  32. data/lib/pdk/cli/remove.rb +22 -0
  33. data/lib/pdk/cli/set/config.rb +121 -0
  34. data/lib/pdk/cli/set.rb +22 -0
  35. data/lib/pdk/cli/test/unit.rb +71 -69
  36. data/lib/pdk/cli/test.rb +9 -8
  37. data/lib/pdk/cli/update.rb +38 -21
  38. data/lib/pdk/cli/util/command_redirector.rb +13 -3
  39. data/lib/pdk/cli/util/interview.rb +25 -9
  40. data/lib/pdk/cli/util/option_normalizer.rb +6 -6
  41. data/lib/pdk/cli/util/option_validator.rb +19 -9
  42. data/lib/pdk/cli/util/spinner.rb +13 -0
  43. data/lib/pdk/cli/util/update_manager_printer.rb +82 -0
  44. data/lib/pdk/cli/util.rb +105 -48
  45. data/lib/pdk/cli/validate.rb +96 -111
  46. data/lib/pdk/cli.rb +134 -87
  47. data/lib/pdk/config/errors.rb +5 -0
  48. data/lib/pdk/config/ini_file.rb +184 -0
  49. data/lib/pdk/config/ini_file_setting.rb +35 -0
  50. data/lib/pdk/config/json.rb +35 -0
  51. data/lib/pdk/config/json_schema_namespace.rb +137 -0
  52. data/lib/pdk/config/json_schema_setting.rb +51 -0
  53. data/lib/pdk/config/json_with_schema.rb +47 -0
  54. data/lib/pdk/config/namespace.rb +362 -0
  55. data/lib/pdk/config/setting.rb +134 -0
  56. data/lib/pdk/config/task_schema.json +116 -0
  57. data/lib/pdk/config/validator.rb +31 -0
  58. data/lib/pdk/config/yaml.rb +41 -0
  59. data/lib/pdk/config/yaml_with_schema.rb +51 -0
  60. data/lib/pdk/config.rb +304 -0
  61. data/lib/pdk/context/control_repo.rb +61 -0
  62. data/lib/pdk/context/module.rb +28 -0
  63. data/lib/pdk/context/none.rb +22 -0
  64. data/lib/pdk/context.rb +98 -0
  65. data/lib/pdk/control_repo.rb +89 -0
  66. data/lib/pdk/generate/defined_type.rb +27 -33
  67. data/lib/pdk/generate/fact.rb +26 -0
  68. data/lib/pdk/generate/function.rb +49 -0
  69. data/lib/pdk/generate/module.rb +160 -153
  70. data/lib/pdk/generate/provider.rb +16 -69
  71. data/lib/pdk/generate/puppet_class.rb +27 -32
  72. data/lib/pdk/generate/puppet_object.rb +100 -159
  73. data/lib/pdk/generate/task.rb +34 -51
  74. data/lib/pdk/generate/transport.rb +34 -0
  75. data/lib/pdk/generate.rb +21 -8
  76. data/lib/pdk/logger.rb +24 -6
  77. data/lib/pdk/module/build.rb +125 -37
  78. data/lib/pdk/module/convert.rb +146 -65
  79. data/lib/pdk/module/metadata.rb +72 -71
  80. data/lib/pdk/module/release.rb +255 -0
  81. data/lib/pdk/module/update.rb +48 -37
  82. data/lib/pdk/module/update_manager.rb +75 -39
  83. data/lib/pdk/module.rb +10 -2
  84. data/lib/pdk/monkey_patches.rb +268 -0
  85. data/lib/pdk/report/event.rb +36 -48
  86. data/lib/pdk/report.rb +35 -22
  87. data/lib/pdk/template/fetcher/git.rb +84 -0
  88. data/lib/pdk/template/fetcher/local.rb +29 -0
  89. data/lib/pdk/template/fetcher.rb +100 -0
  90. data/lib/pdk/template/renderer/v1/legacy_template_dir.rb +108 -0
  91. data/lib/pdk/template/renderer/v1/renderer.rb +131 -0
  92. data/lib/pdk/template/renderer/v1/template_file.rb +100 -0
  93. data/lib/pdk/template/renderer/v1.rb +25 -0
  94. data/lib/pdk/template/renderer.rb +97 -0
  95. data/lib/pdk/template/template_dir.rb +67 -0
  96. data/lib/pdk/template.rb +52 -0
  97. data/lib/pdk/tests/unit.rb +101 -51
  98. data/lib/pdk/util/bundler.rb +44 -42
  99. data/lib/pdk/util/changelog_generator.rb +138 -0
  100. data/lib/pdk/util/env.rb +48 -0
  101. data/lib/pdk/util/filesystem.rb +139 -2
  102. data/lib/pdk/util/git.rb +108 -8
  103. data/lib/pdk/util/json_finder.rb +86 -0
  104. data/lib/pdk/util/puppet_strings.rb +125 -0
  105. data/lib/pdk/util/puppet_version.rb +71 -87
  106. data/lib/pdk/util/ruby_version.rb +49 -25
  107. data/lib/pdk/util/template_uri.rb +283 -0
  108. data/lib/pdk/util/vendored_file.rb +34 -42
  109. data/lib/pdk/util/version.rb +11 -10
  110. data/lib/pdk/util/windows/api_types.rb +74 -44
  111. data/lib/pdk/util/windows/file.rb +31 -27
  112. data/lib/pdk/util/windows/process.rb +74 -0
  113. data/lib/pdk/util/windows/string.rb +19 -12
  114. data/lib/pdk/util/windows.rb +2 -0
  115. data/lib/pdk/util.rb +111 -124
  116. data/lib/pdk/validate/control_repo/control_repo_validator_group.rb +23 -0
  117. data/lib/pdk/validate/control_repo/environment_conf_validator.rb +98 -0
  118. data/lib/pdk/validate/external_command_validator.rb +213 -0
  119. data/lib/pdk/validate/internal_ruby_validator.rb +101 -0
  120. data/lib/pdk/validate/invokable_validator.rb +238 -0
  121. data/lib/pdk/validate/metadata/metadata_json_lint_validator.rb +84 -0
  122. data/lib/pdk/validate/metadata/metadata_syntax_validator.rb +76 -0
  123. data/lib/pdk/validate/metadata/metadata_validator_group.rb +20 -0
  124. data/lib/pdk/validate/puppet/puppet_epp_validator.rb +131 -0
  125. data/lib/pdk/validate/puppet/puppet_lint_validator.rb +66 -0
  126. data/lib/pdk/validate/puppet/puppet_plan_syntax_validator.rb +38 -0
  127. data/lib/pdk/validate/puppet/puppet_syntax_validator.rb +135 -0
  128. data/lib/pdk/validate/puppet/puppet_validator_group.rb +22 -0
  129. data/lib/pdk/validate/ruby/ruby_rubocop_validator.rb +79 -0
  130. data/lib/pdk/validate/ruby/ruby_validator_group.rb +19 -0
  131. data/lib/pdk/validate/tasks/tasks_metadata_lint_validator.rb +83 -0
  132. data/lib/pdk/validate/tasks/tasks_name_validator.rb +45 -0
  133. data/lib/pdk/validate/tasks/tasks_validator_group.rb +20 -0
  134. data/lib/pdk/validate/validator.rb +120 -0
  135. data/lib/pdk/validate/validator_group.rb +107 -0
  136. data/lib/pdk/validate/yaml/yaml_syntax_validator.rb +86 -0
  137. data/lib/pdk/validate/yaml/yaml_validator_group.rb +19 -0
  138. data/lib/pdk/validate.rb +86 -12
  139. data/lib/pdk/version.rb +2 -2
  140. data/lib/pdk.rb +60 -10
  141. metadata +138 -100
  142. data/lib/pdk/cli/module/build.rb +0 -14
  143. data/lib/pdk/cli/module/generate.rb +0 -45
  144. data/lib/pdk/cli/module.rb +0 -14
  145. data/lib/pdk/i18n.rb +0 -4
  146. data/lib/pdk/module/templatedir.rb +0 -321
  147. data/lib/pdk/template_file.rb +0 -95
  148. data/lib/pdk/validate/base_validator.rb +0 -215
  149. data/lib/pdk/validate/metadata/metadata_json_lint.rb +0 -86
  150. data/lib/pdk/validate/metadata/metadata_syntax.rb +0 -109
  151. data/lib/pdk/validate/metadata_validator.rb +0 -30
  152. data/lib/pdk/validate/puppet/puppet_lint.rb +0 -67
  153. data/lib/pdk/validate/puppet/puppet_syntax.rb +0 -112
  154. data/lib/pdk/validate/puppet_validator.rb +0 -30
  155. data/lib/pdk/validate/ruby/rubocop.rb +0 -77
  156. data/lib/pdk/validate/ruby_validator.rb +0 -29
  157. data/lib/pdk/validate/tasks/metadata_lint.rb +0 -126
  158. data/lib/pdk/validate/tasks/name.rb +0 -88
  159. data/lib/pdk/validate/tasks_validator.rb +0 -33
  160. data/lib/pdk/validate/yaml/syntax.rb +0 -109
  161. data/lib/pdk/validate/yaml_validator.rb +0 -31
  162. data/locales/config.yaml +0 -21
  163. data/locales/pdk.pot +0 -1291
@@ -0,0 +1,283 @@
1
+ require 'pdk'
2
+
3
+ module PDK
4
+ module Util
5
+ class TemplateURI
6
+ SCP_PATTERN = %r{\A(?!\w+://)(?:(?<user>.+?)@)?(?<host>[^:/]+):(?<path>.+)\z}.freeze
7
+
8
+ PACKAGED_TEMPLATE_KEYWORD = 'pdk-default'.freeze
9
+ DEPRECATED_TEMPLATE_URL = 'https://github.com/puppetlabs/pdk-module-template'.freeze
10
+ PDK_TEMPLATE_URL = 'https://github.com/puppetlabs/pdk-templates'.freeze
11
+
12
+ LEGACY_PACKAGED_TEMPLATE_PATHS = {
13
+ 'windows' => 'file:///C:/Program Files/Puppet Labs/DevelopmentKit/share/cache/pdk-templates.git',
14
+ 'macos' => 'file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git',
15
+ 'linux' => 'file:///opt/puppetlabs/pdk/share/cache/pdk-templates.git'
16
+ }.freeze
17
+
18
+ # XXX Previously
19
+ # - template_uri used to get the string form of the uri when generating the module and written to pdk answers and metadata
20
+ # - template_path or deuri_path used for humans to see and commands to run
21
+ # - uri_path used only internally by the template selection code; move out
22
+ # - template_ref used by git checkout
23
+ attr_reader :uri
24
+
25
+ # input/output formats:
26
+ #
27
+ # file:///c:/foo (git clone location)
28
+ # c:/foo (shell paths)
29
+ # file:///c:/foo#main (only for metadata)
30
+ # c:/foo#main (only for metadata)
31
+ #
32
+ # non output formats:
33
+ #
34
+ # /c:/foo (internal use only)
35
+ # /c:/foo#main (internal use only)
36
+ #
37
+ def initialize(opts_or_uri)
38
+ require 'addressable'
39
+ # If a uri string is passed, skip the valid uri finding code.
40
+ @uri = case opts_or_uri
41
+ when self.class
42
+ opts_or_uri.uri
43
+ when String
44
+ begin
45
+ uri, ref = opts_or_uri.split('#', 2)
46
+ if PDK::Util::TemplateURI.packaged_template?(uri)
47
+ PDK::Util::TemplateURI.default_template_addressable_uri.tap { |default| default.fragment = ref unless ref.nil? || ref.empty? }
48
+ else
49
+ Addressable::URI.parse(opts_or_uri)
50
+ end
51
+ rescue Addressable::URI::InvalidURIError
52
+ raise PDK::CLI::FatalError, "PDK::Util::TemplateURI attempted initialization with a non-uri string: #{opts_or_uri}"
53
+ end
54
+ when Addressable::URI
55
+ opts_or_uri.dup
56
+ else
57
+ PDK::Util::TemplateURI.first_valid_uri(PDK::Util::TemplateURI.templates(opts_or_uri))
58
+ end
59
+ end
60
+
61
+ def ==(other)
62
+ @uri == other.uri
63
+ end
64
+
65
+ def bare_uri
66
+ PDK::Util::TemplateURI.bare_uri(@uri)
67
+ end
68
+
69
+ # This is the URI represented in a format suitable for writing to
70
+ # metadata.
71
+ #
72
+ # @returns String
73
+ def metadata_format
74
+ @metadata_format ||= if PDK::Util::TemplateURI.packaged_template?(bare_uri)
75
+ PDK::Util::TemplateURI.human_readable("pdk-default##{uri_fragment}")
76
+ else
77
+ PDK::Util::TemplateURI.human_readable(@uri.to_s)
78
+ end
79
+ end
80
+ alias to_s metadata_format
81
+ alias to_str metadata_format
82
+
83
+ # Returns the fragment of the URI, of the default template's ref if one does not exist
84
+ # @returns String
85
+ # @api private
86
+ def uri_fragment
87
+ @uri.fragment || self.class.default_template_ref(self)
88
+ end
89
+
90
+ def uri_fragment=(fragment)
91
+ @uri.fragment = fragment
92
+ end
93
+
94
+ def default?
95
+ bare_uri == PDK::Util::TemplateURI.bare_uri(PDK::Util::TemplateURI.default_template_addressable_uri)
96
+ end
97
+
98
+ def default_ref?
99
+ uri_fragment == self.class.default_template_ref(self)
100
+ end
101
+
102
+ def puppetlabs_template?
103
+ self.class.packaged_template?(bare_uri) || bare_uri == PDK_TEMPLATE_URL
104
+ end
105
+
106
+ # Class Methods
107
+
108
+ # Remove the fragment off of URI. Useful for removing the branch
109
+ # for Git based URIs
110
+ def self.bare_uri(uri)
111
+ require 'addressable'
112
+
113
+ if uri.is_a?(Addressable::URI) && uri.fragment
114
+ human_readable(uri.to_s.chomp("##{uri.fragment}"))
115
+ else
116
+ human_readable(uri.to_s)
117
+ end
118
+ end
119
+
120
+ # This is the path of the URI, suitable for accessing directly from the shell.
121
+ # @returns String
122
+ def shell_path
123
+ self.class.human_readable(@uri.path)
124
+ end
125
+
126
+ # @returns PDK::Util::TemplateURI
127
+ def self.default_template_uri
128
+ require 'pdk/util'
129
+ require 'addressable'
130
+
131
+ PDK::Util::TemplateURI.new(default_template_addressable_uri)
132
+ end
133
+
134
+ # @returns Addressable::URI
135
+ # @api private
136
+ def self.default_template_addressable_uri
137
+ require 'pdk/util'
138
+ require 'addressable'
139
+
140
+ if PDK::Util.package_install?
141
+ Addressable::URI.new(scheme: 'file', host: '', path: File.join(PDK::Util.package_cachedir, 'pdk-templates.git'))
142
+ else
143
+ Addressable::URI.parse(PDK_TEMPLATE_URL)
144
+ end
145
+ end
146
+
147
+ # `C:...` urls are not URI-safe. They should be of the form `/C:...` to
148
+ # be URI-safe. scp-like urls like `user@host:/path` are not URI-safe
149
+ # either and so are subsequently converted to ssh:// URIs.
150
+ #
151
+ # @returns String
152
+ def self.uri_safe(string)
153
+ url = Gem.win_platform? && string =~ /^[a-zA-Z][|:]/ ? "/#{string}" : string
154
+ parse_scp_url(url)
155
+ end
156
+
157
+ # If the passed value is a URI-safe windows path such as `/C:...` then it
158
+ # should be changed to a human-friendly `C:...` form. Otherwise the
159
+ # passed value is left alone.
160
+ #
161
+ # @returns String
162
+ def self.human_readable(string)
163
+ Gem.win_platform? && string =~ %r{^/[a-zA-Z][|:]} ? string[1..] : string
164
+ end
165
+
166
+ def self.parse_scp_url(url)
167
+ require 'pathname'
168
+ require 'addressable'
169
+
170
+ # Valid URIs to avoid catching:
171
+ # - absolute local paths
172
+ # - have :'s in paths when preceeded by a slash
173
+ # - have only digits following the : and preceeding a / or end-of-string that is 0-65535
174
+ # The last item is ambiguous in the case of scp/git paths vs. URI port
175
+ # numbers, but can be made unambiguous by making the form to
176
+ # ssh://git@github.com/1234/repo.git or
177
+ # ssh://git@github.com:1234/user/repo.git
178
+ scp_url = url.match(SCP_PATTERN)
179
+ return url unless Pathname.new(url).relative? && scp_url
180
+
181
+ uri = Addressable::URI.new(scheme: 'ssh', user: scp_url[:user], host: scp_url[:host], path: scp_url[:path])
182
+ PDK.logger.warn format('%{scp_uri} appears to be an SCP style URL; it will be converted to an RFC compliant URI: %{rfc_uri}', scp_uri: url, rfc_uri: uri.to_s)
183
+
184
+ uri.to_s
185
+ end
186
+
187
+ # @return [Array<Hash{Symbol => Object}>] an array of hashes. Each hash
188
+ # contains 3 keys: :type contains a String that describes the template
189
+ # directory, :url contains a String with the URL to the template
190
+ # directory, and :allow_fallback contains a Boolean that specifies if
191
+ # the lookup process should proceed to the next template directory if
192
+ # the template file is not in this template directory.
193
+ def self.templates(opts)
194
+ require 'pdk/answer_file'
195
+ require 'pdk/util'
196
+ require 'addressable'
197
+
198
+ explicit_url = opts.fetch(:'template-url', nil)
199
+ explicit_ref = opts.fetch(:'template-ref', nil)
200
+
201
+ # 1. Get the CLI, metadata (or answers if no metadata), and default URIs
202
+ # 2. Construct the hash
203
+ if explicit_url
204
+ explicit_uri = Addressable::URI.parse(uri_safe(explicit_url))
205
+ explicit_uri.fragment = explicit_ref || default_template_ref(new(explicit_uri))
206
+ else
207
+ explicit_uri = nil
208
+ end
209
+ metadata_uri = if PDK::Util.module_root && PDK::Util::Filesystem.file?(File.join(PDK::Util.module_root, 'metadata.json')) && PDK::Util.module_metadata['template-url']
210
+ new(uri_safe(PDK::Util.module_metadata['template-url'])).uri
211
+ end
212
+ default_template_url = PDK.config.get_within_scopes('module_defaults.template-url')
213
+ answers_uri = if [PACKAGED_TEMPLATE_KEYWORD, DEPRECATED_TEMPLATE_URL].include?(default_template_url)
214
+ Addressable::URI.parse(default_template_uri)
215
+ elsif default_template_url
216
+ new(uri_safe(default_template_url)).uri
217
+ end
218
+ default_uri = default_template_uri.uri
219
+ default_uri.fragment = default_template_ref(default_template_uri)
220
+
221
+ ary = []
222
+ ary << { type: '--template-url', uri: explicit_uri, allow_fallback: false } if explicit_url
223
+ ary << { type: 'metadata.json', uri: metadata_uri, allow_fallback: true } if metadata_uri
224
+ ary << { type: 'PDK answers', uri: answers_uri, allow_fallback: true } if answers_uri
225
+ ary << { type: 'default', uri: default_uri, allow_fallback: false }
226
+ ary
227
+ end
228
+
229
+ # @returns String
230
+ def self.default_template_ref(uri = nil)
231
+ require 'pdk/util'
232
+ require 'pdk/version'
233
+
234
+ return 'main' if PDK::Util.development_mode?
235
+ return PDK::TEMPLATE_REF if uri.nil?
236
+
237
+ uri = new(uri) unless uri.is_a?(self)
238
+ uri.default? ? PDK::TEMPLATE_REF : 'main'
239
+ end
240
+
241
+ # @returns Addressable::URI
242
+ def self.first_valid_uri(templates_array)
243
+ # 1. Get the four sources of URIs
244
+ # 2. Pick the first non-nil URI
245
+ # 3. Error if the URI is not a valid git repo (missing directory or http 404)
246
+ # 4. Leave updating answers/metadata to other code
247
+ found_template = templates_array.find { |t| valid_template?(t) }
248
+
249
+ raise PDK::CLI::FatalError, 'Unable to find a valid module template to use.' if found_template.nil?
250
+
251
+ found_template[:uri]
252
+ end
253
+
254
+ def self.valid_template?(template, context = PDK.context)
255
+ require 'addressable'
256
+
257
+ return false if template.nil? || !template.is_a?(Hash)
258
+ return false if template[:uri].nil? || !template[:uri].is_a?(Addressable::URI)
259
+
260
+ return true if PDK::Util::Git.repo?(bare_uri(template[:uri]))
261
+
262
+ path = human_readable(template[:uri].path)
263
+ if PDK::Util::Filesystem.directory?(path)
264
+ # We know that it's not a git repository, but it's a valid path on disk
265
+ begin
266
+ renderer = PDK::Template::Renderer.instance(path, template[:uri], context)
267
+ return !renderer.nil?
268
+ rescue StandardError
269
+ nil
270
+ end
271
+ end
272
+
273
+ raise PDK::CLI::FatalError, format('Unable to find a valid template at %{uri}', uri: template[:uri].to_s) unless template[:allow_fallback]
274
+
275
+ false
276
+ end
277
+
278
+ def self.packaged_template?(path)
279
+ path == PACKAGED_TEMPLATE_KEYWORD || LEGACY_PACKAGED_TEMPLATE_PATHS.value?(path)
280
+ end
281
+ end
282
+ end
283
+ end
@@ -1,29 +1,11 @@
1
- require 'pdk/util'
2
- require 'net/https'
3
- require 'openssl'
4
- require 'fileutils'
5
- require 'pdk/util/filesystem'
1
+ require 'pdk'
6
2
 
7
3
  module PDK
8
4
  module Util
9
5
  class VendoredFile
10
6
  class DownloadError < StandardError; end
11
7
 
12
- HTTP_ERRORS = [
13
- EOFError,
14
- Errno::ECONNRESET,
15
- Errno::EINVAL,
16
- Errno::ECONNREFUSED,
17
- Net::HTTPBadResponse,
18
- Net::HTTPHeaderSyntaxError,
19
- Net::ProtocolError,
20
- Timeout::Error,
21
- ].freeze
22
-
23
- attr_reader :file_name
24
- attr_reader :url
25
-
26
- include PDK::Util::Filesystem
8
+ attr_reader :file_name, :url
27
9
 
28
10
  def initialize(file_name, url)
29
11
  @file_name = file_name
@@ -31,56 +13,66 @@ module PDK
31
13
  end
32
14
 
33
15
  def read
34
- return File.read(package_vendored_path) if PDK::Util.package_install?
35
- return File.read(gem_vendored_path) if File.file?(gem_vendored_path)
16
+ require 'pdk/util'
17
+ require 'pdk/util/filesystem'
18
+
19
+ return PDK::Util::Filesystem.read_file(package_vendored_path) if PDK::Util.package_install?
20
+ return PDK::Util::Filesystem.read_file(gem_vendored_path) if PDK::Util::Filesystem.file?(gem_vendored_path)
36
21
 
37
22
  content = download_file
38
23
 
39
24
  # TODO: should only write if it's valid JSON
40
25
  # TODO: need a way to invalidate if out of date
41
- FileUtils.mkdir_p(File.dirname(gem_vendored_path))
42
- write_file(gem_vendored_path, content)
26
+ PDK::Util::Filesystem.mkdir_p(File.dirname(gem_vendored_path))
27
+ PDK::Util::Filesystem.write_file(gem_vendored_path, content)
43
28
  content
44
29
  end
45
30
 
46
31
  private
47
32
 
48
33
  def download_file
49
- PDK.logger.debug _('%{file_name} was not found in the cache, downloading it from %{url}.') % {
50
- file_name: file_name,
51
- url: url,
52
- }
34
+ require 'uri'
35
+ require 'net/https'
36
+ require 'openssl'
37
+
38
+ http_errors = [
39
+ EOFError,
40
+ Errno::ECONNRESET,
41
+ Errno::EINVAL,
42
+ Errno::ECONNREFUSED,
43
+ Net::HTTPBadResponse,
44
+ Net::HTTPHeaderSyntaxError,
45
+ Net::ProtocolError,
46
+ Timeout::Error
47
+ ]
48
+
49
+ PDK.logger.debug format('%{file_name} was not found in the cache, downloading it from %{url}.', file_name: file_name, url: url)
53
50
 
54
51
  uri = URI.parse(url)
55
52
  http = Net::HTTP.new(uri.host, uri.port)
56
53
  http.use_ssl = true
57
- # TODO: Get rid of this, possible workaround:
58
- # https://github.com/glennsarti/dev-tools/blob/master/RubyCerts.ps1
54
+ # TODO: Get rid of this
59
55
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE if Gem.win_platform?
60
56
  request = Net::HTTP::Get.new(uri.request_uri)
61
57
  response = http.request(request)
62
58
 
63
- unless response.code == '200'
64
- raise DownloadError, _('Unable to download %{url}. %{code}: %{message}.') % {
65
- url: url,
66
- code: response.code,
67
- message: response.message,
68
- }
69
- end
59
+ raise DownloadError, format('Unable to download %{url}. %{code}: %{message}.', url: url, code: response.code, message: response.message) unless response.code == '200'
70
60
 
71
61
  response.body
72
- rescue *HTTP_ERRORS => e
73
- raise DownloadError, _('Unable to download %{url}. Check internet connectivity and try again. %{error}') % {
74
- url: url,
75
- error: e,
76
- }
62
+ rescue *http_errors => e
63
+ raise DownloadError, format('Unable to download %{url}. Check internet connectivity and try again. %{error}', url: url, error: e)
77
64
  end
78
65
 
79
66
  def package_vendored_path
67
+ require 'pdk/util'
68
+
80
69
  @package_vendored_path ||= File.join(PDK::Util.package_cachedir, file_name)
81
70
  end
82
71
 
83
72
  def gem_vendored_path
73
+ require 'pdk/util'
74
+ require 'pdk/version'
75
+
84
76
  @gem_vendored_path ||= File.join(PDK::Util.cachedir, PDK::VERSION, file_name)
85
77
  end
86
78
  end
@@ -1,12 +1,11 @@
1
- require 'pdk/version'
2
- require 'pdk/cli/exec'
3
- require 'pdk/util/git'
4
- require 'pdk/logger'
1
+ require 'pdk'
5
2
 
6
3
  module PDK
7
4
  module Util
8
5
  module Version
9
6
  def self.version_string
7
+ require 'pdk/version'
8
+
10
9
  "#{PDK::VERSION} #{pdk_ref}".strip.freeze
11
10
  end
12
11
 
@@ -16,8 +15,8 @@ module PDK
16
15
  end
17
16
 
18
17
  def self.pkg_sha
19
- if version_file && File.exist?(version_file)
20
- ver = File.read(version_file)
18
+ if version_file && PDK::Util::Filesystem.exist?(version_file)
19
+ ver = PDK::Util::Filesystem.read_file(version_file)
21
20
  sha = ver.strip.split('.')[5] unless ver.nil?
22
21
  end
23
22
 
@@ -25,15 +24,17 @@ module PDK
25
24
  end
26
25
 
27
26
  def self.git_ref
28
- source_git_dir = File.join(File.expand_path('../../..', File.dirname(__FILE__)), '.git')
27
+ require 'pdk/util/git'
28
+ source_git_dir = File.join(PDK::Util::Filesystem.expand_path('../../..', File.dirname(__FILE__)), '.git')
29
29
 
30
- return nil unless File.directory?(source_git_dir)
30
+ return unless PDK::Util::Filesystem.directory?(source_git_dir)
31
31
 
32
- ref_result = PDK::Util::Git.git('--git-dir', source_git_dir, 'describe', '--all', '--long')
33
- return ref_result[:stdout].strip if ref_result[:exit_code].zero?
32
+ PDK::Util::Git.describe(source_git_dir)
34
33
  end
35
34
 
36
35
  def self.version_file
36
+ require 'pdk/util'
37
+
37
38
  # FIXME: this gets called a LOT and doesn't currently get cached
38
39
  PDK::Util.find_upwards('PDK_VERSION', File.dirname(__FILE__))
39
40
  end
@@ -1,57 +1,87 @@
1
1
  require 'ffi'
2
2
  require 'pdk/util/windows/string'
3
3
 
4
- module PDK::Util::Windows::APITypes
5
- module ::FFI
6
- WIN32_FALSE = 0
4
+ module PDK
5
+ module Util
6
+ module Windows
7
+ module APITypes
8
+ module ::FFI
9
+ module Library
10
+ def attach_function_private(*args)
11
+ attach_function(*args)
12
+ private args[0]
13
+ end
14
+ end
15
+ end
7
16
 
8
- # standard Win32 error codes
9
- ERROR_SUCCESS = 0
10
- end
17
+ module ::FFI
18
+ class Pointer
19
+ def self.from_string_to_wide_string(str, &_block)
20
+ str = PDK::Util::Windows::String.wide_string(str)
21
+ FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr|
22
+ # uchar here is synonymous with byte
23
+ ptr.put_array_of_uchar(0, str.bytes.to_a)
11
24
 
12
- class ::FFI::Pointer
13
- def self.from_string_to_wide_string(str, &_block)
14
- str = PDK::Util::Windows::String.wide_string(str)
15
- FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr|
16
- # uchar here is synonymous with byte
17
- ptr.put_array_of_uchar(0, str.bytes.to_a)
25
+ yield ptr
26
+ end
18
27
 
19
- yield ptr
20
- end
28
+ # ptr has already had free called, so nothing to return
29
+ nil
30
+ end
21
31
 
22
- # ptr has already had free called, so nothing to return
23
- nil
24
- end
32
+ def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, encode_options = {})
33
+ # char_length is number of wide chars (typically excluding NULLs), *not* bytes
34
+ str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
35
+ str.encode(dst_encoding, str.encoding, **encode_options)
36
+ rescue StandardError => e
37
+ PDK.logger.debug format('Unable to convert value %{string} to encoding %{encoding} due to %{error}', string: str.dump, encoding: dst_encoding, error: e.inspect)
38
+ raise
39
+ end
25
40
 
26
- def read_wide_string(char_length, dst_encoding = Encoding::UTF_8, encode_options = {})
27
- # char_length is number of wide chars (typically excluding NULLs), *not* bytes
28
- str = get_bytes(0, char_length * 2).force_encoding('UTF-16LE')
29
- str.encode(dst_encoding, str.encoding, encode_options)
30
- rescue StandardError => e
31
- PDK.logger.debug _('Unable to convert value %{string} to encoding %{encoding} due to %{error}') % {
32
- string: str.dump,
33
- encoding: dst_encoding,
34
- error: e.inspect,
35
- }
36
- raise
37
- end
38
- end
41
+ def read_arbitrary_wide_string_up_to(max_char_length = 512, null_terminator = :single_null, encode_options = {})
42
+ unless [:single_null, :double_null].include?(null_terminator)
43
+ raise ArgumentError,
44
+ format('Unable to read wide strings with %{null_terminator} terminal nulls', null_terminator: null_terminator)
45
+ end
46
+
47
+ terminator_width = null_terminator == :single_null ? 1 : 2
48
+ reader_method = null_terminator == :single_null ? :get_uint16 : :get_uint32
39
49
 
40
- # FFI Types
41
- # https://github.com/ffi/ffi/wiki/Types
50
+ # Look for the null_terminator; if found, read up to that null
51
+ # (exclusive)
52
+ (0...max_char_length - terminator_width).each do |i|
53
+ return read_wide_string(i, Encoding::UTF_8, encode_options) if send(reader_method, (i * 2)).zero?
54
+ end
42
55
 
43
- # Windows - Common Data Types
44
- # https://msdn.microsoft.com/en-us/library/cc230309.aspx
56
+ # String is longer than the max, read just up to the max
57
+ read_wide_string(max_char_length, Encoding::UTF_8, encode_options)
58
+ end
59
+ end
60
+ end
45
61
 
46
- # Windows Data Types
47
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
62
+ # FFI Types
63
+ # https://github.com/ffi/ffi/wiki/Types
48
64
 
49
- FFI.typedef :uint32, :dword
50
- # buffer_inout is similar to pointer (platform specific), but optimized for buffers
51
- FFI.typedef :buffer_inout, :lpwstr
52
- # buffer_in is similar to pointer (platform specific), but optimized for CONST read only buffers
53
- FFI.typedef :buffer_in, :lpcwstr
54
- # 8 bits per byte
55
- FFI.typedef :uchar, :byte
56
- FFI.typedef :uint16, :wchar
65
+ # Windows - Common Data Types
66
+ # https://msdn.microsoft.com/en-us/library/cc230309.aspx
67
+
68
+ # Windows Data Types
69
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
70
+
71
+ FFI.typedef :uint32, :dword
72
+ # buffer_inout is similar to pointer (platform specific), but optimized for buffers
73
+ FFI.typedef :buffer_inout, :lpwstr
74
+ # buffer_in is similar to pointer (platform specific), but optimized for CONST read only buffers
75
+ FFI.typedef :buffer_in, :lpcwstr
76
+ # 8 bits per byte
77
+ FFI.typedef :uchar, :byte
78
+ FFI.typedef :uint16, :wchar
79
+
80
+ # FFI bool can be only 1 byte at times,
81
+ # Win32 BOOL is a signed int, and is always 4 bytes, even on x64
82
+ # https://blogs.msdn.com/b/oldnewthing/archive/2011/03/28/10146459.aspx
83
+ FFI.typedef :int32, :win32_bool
84
+ end
85
+ end
86
+ end
57
87
  end
@@ -1,36 +1,40 @@
1
1
  require 'pdk/util/windows'
2
2
 
3
- module PDK::Util::Windows::File
4
- require 'ffi'
5
- extend FFI::Library
6
- extend PDK::Util::Windows::String
3
+ module PDK
4
+ module Util
5
+ module Windows
6
+ module File
7
+ require 'ffi'
8
+ extend FFI::Library
9
+ extend PDK::Util::Windows::String
7
10
 
8
- def get_long_pathname(path)
9
- converted = ''
10
- FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
11
- # includes terminating NULL
12
- buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0)
13
- FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
14
- if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE
15
- raise _('Failed to call GetLongPathName')
11
+ def get_long_pathname(path)
12
+ converted = ''
13
+ FFI::Pointer.from_string_to_wide_string(path) do |path_ptr|
14
+ # includes terminating NULL
15
+ buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0)
16
+ FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr|
17
+ raise 'Failed to call GetLongPathName' if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == PDK::Util::Windows::WIN32_FALSE
18
+
19
+ converted = converted_ptr.read_wide_string(buffer_size - 1)
20
+ end
21
+ end
22
+
23
+ converted
16
24
  end
25
+ module_function :get_long_pathname
26
+
27
+ ffi_convention :stdcall
17
28
 
18
- converted = converted_ptr.read_wide_string(buffer_size - 1)
29
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx
30
+ # DWORD WINAPI GetLongPathName(
31
+ # _In_ LPCTSTR lpszShortPath,
32
+ # _Out_ LPTSTR lpszLongPath,
33
+ # _In_ DWORD cchBuffer
34
+ # );
35
+ ffi_lib :kernel32
36
+ attach_function :GetLongPathNameW, [:lpcwstr, :lpwstr, :dword], :dword
19
37
  end
20
38
  end
21
-
22
- converted
23
39
  end
24
- module_function :get_long_pathname
25
-
26
- ffi_convention :stdcall
27
-
28
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa364980(v=vs.85).aspx
29
- # DWORD WINAPI GetLongPathName(
30
- # _In_ LPCTSTR lpszShortPath,
31
- # _Out_ LPTSTR lpszLongPath,
32
- # _In_ DWORD cchBuffer
33
- # );
34
- ffi_lib :kernel32
35
- attach_function :GetLongPathNameW, [:lpcwstr, :lpwstr, :dword], :dword
36
40
  end