pdk 1.9.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
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