vagrant-unbundled 2.0.0.1 → 2.0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (351) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -2
  3. data/CHANGELOG.md +34 -0
  4. data/Gemfile.lock +10 -10
  5. data/README.md +2 -2
  6. data/contrib/sudoers/linux-suse +6 -7
  7. data/lib/vagrant/plugin/v2/command.rb +3 -0
  8. data/lib/vagrant/plugin/v2/communicator.rb +1 -1
  9. data/lib/vagrant/registry.rb +1 -1
  10. data/lib/vagrant/util/downloader.rb +1 -2
  11. data/lib/vagrant/util/is_port_open.rb +2 -1
  12. data/lib/vagrant/util/keypair.rb +1 -1
  13. data/lib/vagrant/util/platform.rb +39 -23
  14. data/plugins/commands/destroy/command.rb +31 -10
  15. data/plugins/communicators/ssh/communicator.rb +1 -0
  16. data/plugins/communicators/winrm/helper.rb +6 -1
  17. data/plugins/guests/solaris11/cap/change_host_name.rb +0 -2
  18. data/plugins/guests/solaris11/cap/configure_networks.rb +1 -7
  19. data/plugins/guests/solaris11/plugin.rb +5 -35
  20. data/plugins/guests/windows/cap/public_key.rb +2 -0
  21. data/plugins/guests/windows/guest_network.rb +3 -3
  22. data/plugins/guests/windows/scripts/reboot_detect.ps1 +5 -0
  23. data/plugins/providers/docker/driver.rb +1 -1
  24. data/plugins/providers/docker/executor/local.rb +4 -0
  25. data/plugins/providers/docker/executor/vagrant.rb +4 -0
  26. data/plugins/providers/hyperv/scripts/import_vm_vmcx.ps1 +1 -1
  27. data/plugins/providers/virtualbox/driver/meta.rb +1 -0
  28. data/plugins/providers/virtualbox/driver/version_5_2.rb +16 -0
  29. data/plugins/providers/virtualbox/plugin.rb +1 -0
  30. data/plugins/providers/virtualbox/synced_folder.rb +1 -1
  31. data/plugins/provisioners/chef/provisioner/chef_client.rb +30 -23
  32. data/plugins/provisioners/chef/provisioner/chef_solo.rb +26 -19
  33. data/plugins/provisioners/chef/provisioner/chef_zero.rb +29 -22
  34. data/plugins/provisioners/puppet/provisioner/puppet.rb +23 -4
  35. data/plugins/provisioners/salt/bootstrap-salt.ps1 +15 -3
  36. data/plugins/provisioners/salt/bootstrap-salt.sh +2 -0
  37. data/plugins/provisioners/salt/config.rb +11 -0
  38. data/plugins/provisioners/salt/provisioner.rb +10 -7
  39. data/plugins/provisioners/shell/provisioner.rb +1 -1
  40. data/templates/locales/en.yml +5 -0
  41. data/test/unit/base.rb +2 -0
  42. data/test/unit/plugins/commands/destroy/command_test.rb +155 -0
  43. data/test/unit/plugins/communicators/winrm/helper_test.rb +33 -0
  44. data/test/unit/plugins/guests/solaris11/cap/change_host_name_test.rb +36 -0
  45. data/test/unit/plugins/guests/solaris11/cap/configure_networks_test.rb +56 -0
  46. data/test/unit/plugins/providers/virtualbox/synced_folder_test.rb +26 -0
  47. data/test/unit/plugins/provisioners/salt/config_test.rb +42 -0
  48. data/test/unit/plugins/provisioners/salt/provisioner_test.rb +16 -1
  49. data/test/unit/plugins/provisioners/shell/config_test.rb +3 -3
  50. data/test/unit/plugins/pushes/local-exec/config_test.rb +2 -2
  51. data/test/unit/vagrant/util/downloader_test.rb +28 -0
  52. data/test/unit/vagrant/util/platform_test.rb +58 -0
  53. data/vagrant.gemspec +1 -1
  54. data/vendor/bundle/ruby/2.4.0/bin/rwinrmcp +5 -0
  55. data/vendor/bundle/ruby/2.4.0/bin/vagrant +5 -0
  56. data/vendor/bundle/ruby/2.4.0/bin/vagrant-spec +5 -0
  57. data/vendor/bundle/ruby/2.4.0/bundler/gems/vagrant-spec-af86757912f7/vagrant-spec.gemspec +3 -3
  58. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/CHANGELOG.md +216 -0
  59. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/Gemfile +32 -0
  60. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/LICENSE.txt +202 -0
  61. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/README.md +121 -0
  62. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/Rakefile +32 -0
  63. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/data/unicode.data +0 -0
  64. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna/native.rb +59 -0
  65. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna/pure.rb +677 -0
  66. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/idna.rb +25 -0
  67. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/template.rb +1065 -0
  68. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/uri.rb +2492 -0
  69. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable/version.rb +30 -0
  70. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/lib/addressable.rb +2 -0
  71. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/idna_spec.rb +298 -0
  72. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/net_http_compat_spec.rb +28 -0
  73. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/rack_mount_compat_spec.rb +104 -0
  74. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/security_spec.rb +57 -0
  75. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/template_spec.rb +1419 -0
  76. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/addressable/uri_spec.rb +6468 -0
  77. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/spec/spec_helper.rb +21 -0
  78. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/clobber.rake +2 -0
  79. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/gem.rake +91 -0
  80. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/git.rake +45 -0
  81. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/metrics.rake +22 -0
  82. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/rspec.rake +21 -0
  83. data/vendor/bundle/ruby/2.4.0/gems/addressable-2.5.2/tasks/yard.rake +27 -0
  84. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.gitignore +15 -0
  85. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.rspec +1 -0
  86. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.travis.yml +13 -0
  87. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/.yardopts +1 -0
  88. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/Gemfile +6 -0
  89. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/LICENSE +19 -0
  90. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/README.md +265 -0
  91. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/Rakefile +13 -0
  92. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/changelog.md +72 -0
  93. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/hashdiff.gemspec +25 -0
  94. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/diff.rb +232 -0
  95. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/lcs.rb +69 -0
  96. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/linear_compare_array.rb +155 -0
  97. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/patch.rb +88 -0
  98. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/util.rb +146 -0
  99. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff/version.rb +3 -0
  100. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/lib/hashdiff.rb +6 -0
  101. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/best_diff_spec.rb +74 -0
  102. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/diff_array_spec.rb +60 -0
  103. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/diff_spec.rb +339 -0
  104. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/lcs_spec.rb +75 -0
  105. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/linear_compare_array_spec.rb +48 -0
  106. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/patch_spec.rb +183 -0
  107. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/hashdiff/util_spec.rb +78 -0
  108. data/vendor/bundle/ruby/2.4.0/gems/hashdiff-0.3.7/spec/spec_helper.rb +13 -0
  109. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/CHANGELOG.md +250 -0
  110. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/CONTRIBUTING.md +46 -0
  111. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/LICENSE.md +20 -0
  112. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/README.md +122 -0
  113. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapter.rb +49 -0
  114. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapter_error.rb +15 -0
  115. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/gson.rb +20 -0
  116. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/jr_jackson.rb +25 -0
  117. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_common.rb +23 -0
  118. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_gem.rb +11 -0
  119. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/json_pure.rb +11 -0
  120. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/nsjsonserialization.rb +32 -0
  121. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/oj.rb +25 -0
  122. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/ok_json.rb +23 -0
  123. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/adapters/yajl.rb +19 -0
  124. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/convertible_hash_keys.rb +43 -0
  125. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/options.rb +39 -0
  126. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/options_cache.rb +29 -0
  127. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/parse_error.rb +17 -0
  128. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/vendor/okjson.rb +606 -0
  129. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json/version.rb +17 -0
  130. data/vendor/bundle/ruby/2.4.0/gems/multi_json-1.12.2/lib/multi_json.rb +161 -0
  131. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.gitignore +11 -0
  132. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.rubocop.yml +32 -0
  133. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.rubocop_defaults.yml +177 -0
  134. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.travis.yml +24 -0
  135. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/.yardopts +1 -0
  136. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/2.0-Upgrade.md +52 -0
  137. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/CHANGELOG.md +330 -0
  138. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/Gemfile +10 -0
  139. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/LICENSE.txt +22 -0
  140. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/README.md +202 -0
  141. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/Rakefile +49 -0
  142. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/bin/console +14 -0
  143. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/data/list.txt +12288 -0
  144. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/domain.rb +235 -0
  145. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/errors.rb +39 -0
  146. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/list.rb +243 -0
  147. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/rule.rb +348 -0
  148. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix/version.rb +10 -0
  149. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/lib/public_suffix.rb +175 -0
  150. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/public_suffix.gemspec +25 -0
  151. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/.empty +2 -0
  152. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/acceptance_test.rb +127 -0
  153. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_find.rb +66 -0
  154. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_find_all.rb +102 -0
  155. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_names.rb +91 -0
  156. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_select.rb +26 -0
  157. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_select_incremental.rb +25 -0
  158. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/benchmarks/bm_valid.rb +101 -0
  159. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/domain_profiler.rb +12 -0
  160. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/find_profiler.rb +12 -0
  161. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/find_profiler_jp.rb +12 -0
  162. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/initialization_profiler.rb +11 -0
  163. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/list_profsize.rb +11 -0
  164. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/profilers/object_binsize.rb +57 -0
  165. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/psl_test.rb +49 -0
  166. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/test_helper.rb +13 -0
  167. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/tests.txt +98 -0
  168. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/domain_test.rb +104 -0
  169. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/errors_test.rb +23 -0
  170. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/list_test.rb +239 -0
  171. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/public_suffix_test.rb +186 -0
  172. data/vendor/bundle/ruby/2.4.0/gems/public_suffix-3.0.1/test/unit/rule_test.rb +220 -0
  173. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.gemtest +0 -0
  174. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.gitignore +34 -0
  175. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.rspec-tm +2 -0
  176. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/.travis.yml +24 -0
  177. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/CHANGELOG.md +1460 -0
  178. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/Gemfile +9 -0
  179. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/LICENSE +20 -0
  180. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/README.md +1045 -0
  181. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/Rakefile +30 -0
  182. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/api.rb +97 -0
  183. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/assertion_failure.rb +11 -0
  184. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/callback_registry.rb +35 -0
  185. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/config.rb +18 -0
  186. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/cucumber.rb +10 -0
  187. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/deprecation.rb +9 -0
  188. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/errors.rb +17 -0
  189. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/curb_adapter.rb +337 -0
  190. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +228 -0
  191. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/excon_adapter.rb +162 -0
  192. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_lib_adapter.rb +7 -0
  193. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +19 -0
  194. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/client.rb +14 -0
  195. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/request.rb +10 -0
  196. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/response.rb +43 -0
  197. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/streamer.rb +25 -0
  198. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb/webmock.rb +68 -0
  199. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/http_rb_adapter.rb +37 -0
  200. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/httpclient_adapter.rb +240 -0
  201. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/manticore_adapter.rb +127 -0
  202. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/net_http.rb +362 -0
  203. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/net_http_response.rb +34 -0
  204. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/patron_adapter.rb +130 -0
  205. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +174 -0
  206. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/matchers/hash_including_matcher.rb +36 -0
  207. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/minitest.rb +41 -0
  208. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rack_response.rb +69 -0
  209. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_body_diff.rb +64 -0
  210. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_execution_verifier.rb +78 -0
  211. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_pattern.rb +343 -0
  212. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_registry.rb +35 -0
  213. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_signature.rb +54 -0
  214. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_signature_snippet.rb +61 -0
  215. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/request_stub.rb +100 -0
  216. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/response.rb +153 -0
  217. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/responses_sequence.rb +40 -0
  218. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers/request_pattern_matcher.rb +78 -0
  219. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers/webmock_matcher.rb +52 -0
  220. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec/matchers.rb +27 -0
  221. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/rspec.rb +35 -0
  222. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/stub_registry.rb +67 -0
  223. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/stub_request_snippet.rb +34 -0
  224. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/test_unit.rb +22 -0
  225. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_counter.rb +32 -0
  226. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_keys_stringifier.rb +25 -0
  227. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/hash_validator.rb +17 -0
  228. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/headers.rb +49 -0
  229. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/json.rb +78 -0
  230. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/query_mapper.rb +279 -0
  231. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/uri.rb +111 -0
  232. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/util/version_checker.rb +111 -0
  233. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/version.rb +3 -0
  234. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock/webmock.rb +156 -0
  235. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/lib/webmock.rb +54 -0
  236. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/test_helper.rb +34 -0
  237. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/test_webmock.rb +9 -0
  238. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/minitest/webmock_spec.rb +60 -0
  239. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/curb/curb_spec.rb +466 -0
  240. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/curb/curb_spec_helper.rb +147 -0
  241. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/em_http_request/em_http_request_spec.rb +406 -0
  242. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/em_http_request/em_http_request_spec_helper.rb +77 -0
  243. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/excon/excon_spec.rb +75 -0
  244. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/excon/excon_spec_helper.rb +50 -0
  245. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/http_rb/http_rb_spec.rb +73 -0
  246. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/http_rb/http_rb_spec_helper.rb +51 -0
  247. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/httpclient/httpclient_spec.rb +209 -0
  248. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/httpclient/httpclient_spec_helper.rb +57 -0
  249. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/manticore/manticore_spec.rb +56 -0
  250. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/manticore/manticore_spec_helper.rb +35 -0
  251. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_shared.rb +142 -0
  252. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_spec.rb +317 -0
  253. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/net_http_spec_helper.rb +64 -0
  254. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/net_http/real_net_http_spec.rb +20 -0
  255. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/patron/patron_spec.rb +118 -0
  256. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/patron/patron_spec_helper.rb +54 -0
  257. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/allowing_and_disabling_net_connect.rb +313 -0
  258. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/callbacks.rb +147 -0
  259. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/complex_cross_concern_behaviors.rb +36 -0
  260. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/enabling_and_disabling_webmock.rb +95 -0
  261. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/precedence_of_stubs.rb +15 -0
  262. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/request_expectations.rb +916 -0
  263. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/returning_declared_responses.rb +388 -0
  264. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/shared/stubbing_requests.rb +583 -0
  265. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/typhoeus/typhoeus_hydra_spec.rb +135 -0
  266. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/typhoeus/typhoeus_hydra_spec_helper.rb +60 -0
  267. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/acceptance/webmock_shared.rb +41 -0
  268. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/fixtures/test.txt +1 -0
  269. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/quality_spec.rb +84 -0
  270. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/spec_helper.rb +48 -0
  271. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/example_curl_output.txt +22 -0
  272. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/failures.rb +9 -0
  273. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/my_rack_app.rb +53 -0
  274. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/network_connection.rb +19 -0
  275. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/support/webmock_server.rb +69 -0
  276. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/api_spec.rb +75 -0
  277. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/errors_spec.rb +129 -0
  278. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/http_lib_adapters/http_lib_adapter_registry_spec.rb +17 -0
  279. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/http_lib_adapters/http_lib_adapter_spec.rb +12 -0
  280. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/matchers/hash_including_matcher_spec.rb +87 -0
  281. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/rack_response_spec.rb +112 -0
  282. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_body_diff_spec.rb +90 -0
  283. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_execution_verifier_spec.rb +208 -0
  284. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_pattern_spec.rb +590 -0
  285. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_registry_spec.rb +76 -0
  286. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_signature_snippet_spec.rb +89 -0
  287. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_signature_spec.rb +155 -0
  288. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/request_stub_spec.rb +199 -0
  289. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/response_spec.rb +282 -0
  290. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/stub_registry_spec.rb +103 -0
  291. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/stub_request_snippet_spec.rb +95 -0
  292. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/hash_counter_spec.rb +39 -0
  293. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/hash_keys_stringifier_spec.rb +27 -0
  294. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/headers_spec.rb +28 -0
  295. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/json_spec.rb +33 -0
  296. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/query_mapper_spec.rb +138 -0
  297. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/uri_spec.rb +299 -0
  298. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/util/version_checker_spec.rb +65 -0
  299. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/spec/unit/webmock_spec.rb +11 -0
  300. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/http_request.rb +24 -0
  301. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/shared_test.rb +95 -0
  302. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/test_helper.rb +23 -0
  303. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/test/test_webmock.rb +6 -0
  304. data/vendor/bundle/ruby/2.4.0/gems/webmock-2.3.2/webmock.gemspec +46 -0
  305. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.gitignore +11 -0
  306. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.rspec +3 -0
  307. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.rubocop.yml +9 -0
  308. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/.travis.yml +9 -0
  309. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Gemfile +5 -0
  310. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/LICENSE +202 -0
  311. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/README.md +79 -0
  312. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Rakefile +28 -0
  313. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/VERSION +1 -0
  314. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/Vagrantfile +9 -0
  315. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/appveyor.yml +38 -0
  316. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/bin/rwinrmcp +86 -0
  317. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/changelog.md +60 -0
  318. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/core/file_transporter.rb +527 -0
  319. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/core/tmp_zip.rb +177 -0
  320. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/exceptions.rb +28 -0
  321. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/file_manager.rb +118 -0
  322. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/check_files.ps1.erb +49 -0
  323. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/checksum.ps1.erb +13 -0
  324. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/create_dir.ps1.erb +6 -0
  325. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/delete.ps1.erb +6 -0
  326. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/download.ps1.erb +8 -0
  327. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/exists.ps1.erb +10 -0
  328. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/extract_files.ps1.erb +52 -0
  329. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs/scripts/scripts.rb +31 -0
  330. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/lib/winrm-fs.rb +28 -0
  331. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/config-example.yml +3 -0
  332. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/integration/file_manager_spec.rb +224 -0
  333. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/integration/tmp_zip_spec.rb +26 -0
  334. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/matchers.rb +58 -0
  335. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/spec_helper.rb +71 -0
  336. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/spec/unit/tmp_zip_spec.rb +79 -0
  337. data/vendor/bundle/ruby/2.4.0/gems/winrm-fs-1.1.1/winrm-fs.gemspec +37 -0
  338. data/vendor/bundle/ruby/2.4.0/specifications/addressable-2.5.2.gemspec +39 -0
  339. data/vendor/bundle/ruby/2.4.0/specifications/hashdiff-0.3.7.gemspec +39 -0
  340. data/vendor/bundle/ruby/2.4.0/specifications/multi_json-1.12.2.gemspec +33 -0
  341. data/vendor/bundle/ruby/2.4.0/specifications/public_suffix-3.0.1.gemspec +41 -0
  342. data/vendor/bundle/ruby/2.4.0/specifications/webmock-2.3.2.gemspec +79 -0
  343. data/vendor/bundle/ruby/2.4.0/specifications/winrm-fs-1.1.1.gemspec +57 -0
  344. data/version.txt +1 -1
  345. metadata +295 -11
  346. data/plugins/guests/solaris11/cap/halt.rb +0 -26
  347. data/plugins/guests/solaris11/cap/insert_public_key.rb +0 -21
  348. data/plugins/guests/solaris11/cap/mount_virtualbox_shared_folder.rb +0 -45
  349. data/plugins/guests/solaris11/cap/remove_public_key.rb +0 -21
  350. data/plugins/guests/solaris11/cap/rsync.rb +0 -29
  351. data/test/unit/plugins/guests/solaris11/cap/halt_test.rb +0 -44
@@ -0,0 +1,79 @@
1
+ # File system operations over Windows Remote Management (WinRM) for Ruby
2
+ [![Build Status](https://travis-ci.org/WinRb/winrm-fs.svg?branch=master)](https://travis-ci.org/WinRb/winrm-fs)
3
+ [![Gem Version](https://badge.fury.io/rb/winrm-fs.svg)](http://badge.fury.io/rb/winrm-fs)
4
+ [![Build status](https://ci.appveyor.com/api/projects/status/wm6apa8ojfhfmwsf?svg=true)](https://ci.appveyor.com/project/winrb/winrm-fs)
5
+
6
+ ## Uploading files
7
+ Files may be copied from the local machine to the winrm endpoint. Individual files or directories, as well as arrays of files and directories may be specified:
8
+ ```ruby
9
+ require 'winrm-fs'
10
+
11
+ connection = WinRM::Connection.new(...
12
+ file_manager = WinRM::FS::FileManager.new(connection)
13
+
14
+ # upload file.txt from the current working directory
15
+ file_manager.upload('file.txt', 'c:/file.txt')
16
+
17
+ # upload the my_dir directory to c:/foo/my_dir
18
+ file_manager.upload('/Users/sneal/my_dir', 'c:/foo/my_dir')
19
+
20
+ # upload multiple directories and a file to c:\programData
21
+ file_manager.upload([
22
+ '/Users/sneal/foo1',
23
+ '/Users/sneal/foo2'
24
+ '/Users/sneal/fluffy.txt'
25
+ ], '$env:ProgramData')
26
+ ```
27
+
28
+ ### Optimizing WinRM settings
29
+ Since winrm-fs 1.0/winrm 2.0, files are uploaded using the PSRP protocol and transfer speeds are dramatically improved from previous versions. This is largely due to the fact that the size of chunks that can be transferred at one time are now governed by the `MaxEnvelopeSizekb` winrm configuration setting on the endpoint. This default to 500 on Windows 2012 R2 and 150 on Windows 2008 R2. You may experience much faster transfer rates on 2008 R2 by increasing this setting.
30
+
31
+ ### Handling progress events
32
+ If you want to implement your own custom progress handling, you can pass a code
33
+ block and use the proggress data that `upload` yields to this block:
34
+ ```ruby
35
+ file_manager.upload('c:/dev/my_dir', '$env:AppData') do |bytes_copied, total_bytes, local_path, remote_path|
36
+ puts "#{bytes_copied}bytes of #{total_bytes}bytes copied"
37
+ end
38
+ ```
39
+
40
+ ## Troubleshooting
41
+
42
+ If you're having trouble, first of all its most likely a network or WinRM configuration
43
+ issue. Take a look at the [WinRM gem troubleshooting](https://github.com/WinRb/WinRM#troubleshooting)
44
+ first.
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it.
49
+ 2. Create a branch (git checkout -b my_feature_branch)
50
+ 3. Run the unit and integration tests (bundle exec rake integration)
51
+ 4. Commit your changes (git commit -am "Added a sweet feature")
52
+ 5. Push to the branch (git push origin my_feature_branch)
53
+ 6. Create a pull requst from your branch into master (Please be sure to provide enough detail for us to cipher what this change is doing)
54
+
55
+ ### Running the tests
56
+
57
+ We use Bundler to manage dependencies during development.
58
+
59
+ ```
60
+ $ bundle install
61
+ ```
62
+
63
+ Once you have the dependencies, you can run the unit tests with `rake`:
64
+
65
+ ```
66
+ $ bundle exec rake spec
67
+ ```
68
+
69
+ To run the integration tests you will need a Windows box with the WinRM service properly configured. Its easiest to use the Vagrant Windows box in the Vagrantilfe of this repo.
70
+
71
+ 1. Create a Windows VM with WinRM configured (see above).
72
+ 2. Copy the config-example.yml to config.yml - edit this file with your WinRM connection details.
73
+ 3. Run `bundle exec rake integration`
74
+
75
+ ## WinRM-fs Authors
76
+ * Shawn Neal (https://github.com/sneal)
77
+ * Matt Wrock (https://github.com/mwrock)
78
+
79
+ [Contributors](https://github.com/WinRb/winrm-fs/graphs/contributors)
@@ -0,0 +1,28 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ # Change to the directory of this file.
8
+ Dir.chdir(File.expand_path('../', __FILE__))
9
+
10
+ # For gem creation and bundling
11
+ require 'bundler/gem_tasks'
12
+
13
+ RSpec::Core::RakeTask.new(:spec) do |task|
14
+ task.pattern = 'spec/unit/*_spec.rb'
15
+ task.rspec_opts = ['--color', '-f documentation']
16
+ end
17
+
18
+ # Run the integration test suite
19
+ RSpec::Core::RakeTask.new(:integration) do |task|
20
+ task.pattern = 'spec/integration/*_spec.rb'
21
+ task.rspec_opts = ['--color', '-f documentation']
22
+ end
23
+
24
+ RuboCop::RakeTask.new
25
+
26
+ task default: [:spec, :rubocop]
27
+
28
+ task all: [:default, :integration]
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+ # -*- mode: ruby -*-
3
+ # vi: set ft=ruby :
4
+
5
+ VAGRANTFILE_API_VERSION = '2'
6
+
7
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8
+ config.vm.box = 'mwrock/WindowsNano'
9
+ end
@@ -0,0 +1,38 @@
1
+ version: "master-{build}"
2
+
3
+ os: Windows Server 2012 R2
4
+ platform:
5
+ - x64
6
+
7
+ environment:
8
+ winrm_user: test_user
9
+ winrm_password: Pass@word1
10
+
11
+ matrix:
12
+ - ruby_version: "21"
13
+ winrm_endpoint: http://localhost:5985/wsman
14
+
15
+ clone_folder: c:\projects\winrm-fs
16
+ clone_depth: 1
17
+ branches:
18
+ only:
19
+ - master
20
+
21
+ install:
22
+ - ps: net user /add $env:winrm_user $env:winrm_password
23
+ - ps: net localgroup administrators $env:winrm_user /add
24
+ - ps: winrm set winrm/config/client/auth '@{Basic="true"}'
25
+ - ps: winrm set winrm/config/service/auth '@{Basic="true"}'
26
+ - ps: winrm set winrm/config/service '@{AllowUnencrypted="true"}'
27
+ - ps: $env:PATH="C:\Ruby$env:ruby_version\bin;$env:PATH"
28
+ - ps: Write-Host $env:PATH
29
+ - ps: ruby --version
30
+ - ps: gem --version
31
+ - ps: bundler --version
32
+
33
+ build_script:
34
+ - bundle install || bundle install || bundle install
35
+
36
+ test_script:
37
+ - SET SPEC_OPTS=--format progress
38
+ - bundle exec rake integration
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ #
4
+ # Copyright 2014 Shawn Neal <sneal@sneal.net>
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ # TODO: refactor this
19
+ # rubocop:disable all
20
+
21
+ $LOAD_PATH.push File.expand_path('../../lib', __FILE__)
22
+
23
+ require 'io/console'
24
+ require 'winrm-fs'
25
+
26
+ def help_msg
27
+ puts 'Usage: rwinrmcp sourcefile user@host:directory/targetfile'
28
+ puts ''
29
+ end
30
+
31
+ def parse_options
32
+ options = {}
33
+ fail 'Missing required options' unless ARGV.length == 2
34
+
35
+ options[:source_path] = ARGV[0]
36
+ fail "Cannot find source file: #{options[:source_path]}" unless \
37
+ File.exist?(options[:source_path])
38
+
39
+ m = /^(?<user>[a-z0-9\.\!\$ _-]+)@{1}(?<host>[a-z0-9\.\-]+)(?<port>:[0-9]+)?:{1}(?<file>.+)/i.match(ARGV[1])
40
+ fail "#{ARGV[1]} is an invalid destination" unless m
41
+ options[:user] = m[:user]
42
+ options[:endpoint] = "http://#{m[:host]}#{m[:port] || ':5985'}/wsman"
43
+ options[:dest_path] = m[:file]
44
+
45
+ # Get the password
46
+ print 'Password: '
47
+ options[:pass] = STDIN.noecho(&:gets).chomp
48
+ puts
49
+
50
+ # Set some defaults required by WinRM WS
51
+ options[:auth_type] = :plaintext
52
+ options[:basic_auth_only] = true
53
+
54
+ options
55
+ rescue StandardError => e
56
+ puts e.message
57
+ help_msg
58
+ exit 1
59
+ end
60
+
61
+ def file_manager(options)
62
+ service = WinRM::WinRMWebService.new(
63
+ options[:endpoint],
64
+ options[:auth_type].to_sym,
65
+ options)
66
+ WinRM::FS::FileManager.new(service)
67
+ end
68
+
69
+ def run(options)
70
+ bytes = file_manager(options).upload(options[:source_path], options[:dest_path])
71
+ puts "#{bytes} total bytes transfered"
72
+ exit 0
73
+ rescue Interrupt
74
+ puts 'exiting'
75
+ # ctrl-c
76
+ rescue WinRM::WinRMAuthorizationError
77
+ puts 'Authentication failed, bad user name or password'
78
+ exit 1
79
+ rescue StandardError => e
80
+ puts e.message
81
+ exit 1
82
+ end
83
+
84
+ run(parse_options)
85
+
86
+ # rubocop:enable all
@@ -0,0 +1,60 @@
1
+ # WinRM-fs Gem Changelog
2
+ # 1.1.1
3
+ - Remove empty items from powershell pipeline when extracting zip files
4
+
5
+ # 1.1.0
6
+ - Convert MD5 hashes to SHA1.
7
+
8
+ # 1.0.2
9
+ - Fix `Pathname.glob` expansion of shortnames.
10
+
11
+ # 1.0.1
12
+ - Call ClearScriptBlockCache to prevent OutOfMemoryExceptions ClearScriptBlockCache
13
+
14
+ # 1.0.0
15
+ - Using winrm v2. File uploads just got a whole lot faster!
16
+
17
+ # 0.4.3
18
+ - Fix error handling with wmf5, filtering out progress output from inspected stderr.
19
+
20
+ # 0.4.2
21
+ - Improved Powershell error handling in metadata checking.
22
+
23
+ # 0.4.1
24
+ - Fixes a regression on Windows 2008 R2/Windows 7 and below where the WinRM service corrupts the check files metadata resulting in malformed destination paths.
25
+
26
+ # 0.4.0
27
+ - Correct the destination path of individual files. Always assume it is the full destination path unless it is an existing directory. This may potentialy break some callers expecting the remote path to be a directory that winrm-fs will create if missing as the destination of the local file. A new directory will not be created and the local file will be uploaded directly to the remote path.
28
+
29
+ # 0.3.2
30
+ - Fix re-extraction of cached directories from temp folder when there is more than one "clean" directory deleted from destination
31
+
32
+ # 0.3.1
33
+ - Widen logging version constraints to include 2.0 (matching WinRM core gem)
34
+
35
+ # 0.3.0
36
+ - Jetisons `CommandExecutor` now living in the core WinRM gem and swaps in implementation currently used in the winrm-transport gem. These changes should have little visible effect on current consumers of the `FileManager` class with these exceptions:
37
+ - BREAKING CHANGE: When uploading a directory and the destination directory exists on the endpoint, the source base directory will be created below the destination directory on the endpoint and the source directory contents will be unzipped to that location. Prior to this release, the contents of the source directory would be unzipped to an existing destination directory without creating the source base directory. This new behavior is more consistent with SCP and other well known shell copy commands.
38
+ - `Upload` may now receive an array of source files and directories rather than just a single file or directory path.
39
+
40
+ # 0.2.4
41
+ - Fix issue 21, downloading files is extremely slow.
42
+ - Add zip file creation debug logging.
43
+
44
+ # 0.2.3
45
+ - Fix yielding progress data, issue #23
46
+
47
+ # 0.2.2
48
+ - Fix powershell streams leaking to standard error breaking Windows 10, issue #18
49
+
50
+ # 0.2.1
51
+ - Fixed issue 16 creating zip file on Windows
52
+
53
+ # 0.2.0
54
+ - Redesigned temp zip file creation system
55
+ - Fixed lots of small edge case issues especially with directory uploads
56
+ - Simplified file manager upload method API to take only a single source file or directory
57
+ - Expanded acceptable username and hostnames for rwinrmcp
58
+
59
+ # 0.1.0
60
+ - Initial alpha quality release
@@ -0,0 +1,527 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2015, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'benchmark'
20
+ require 'csv'
21
+ require 'digest'
22
+ require 'securerandom'
23
+ require 'stringio'
24
+
25
+ require 'winrm-fs/core/tmp_zip'
26
+
27
+ module WinRM
28
+ module FS
29
+ module Core
30
+ # Wrapped exception for any internally raised WinRM-related errors.
31
+ #
32
+ # @author Fletcher Nichol <fnichol@nichol.ca>
33
+ class FileTransporterFailed < ::WinRM::WinRMError; end
34
+ # rubocop:disable MethodLength, AbcSize, ClassLength
35
+
36
+ # Object which can upload one or more files or directories to a remote
37
+ # host over WinRM using PowerShell scripts and CMD commands. Note that
38
+ # this form of file transfer is *not* ideal and extremely costly on both
39
+ # the local and remote sides. Great pains are made to minimize round
40
+ # trips to the remote host and to minimize the number of PowerShell
41
+ # sessions being invoked which can be 2 orders of magnitude more
42
+ # expensive than vanilla CMD commands.
43
+ #
44
+ # This object is supported by a `PowerShell` instance as it
45
+ # depends on the `#run` API contract.
46
+ #
47
+ # An optional logger can be supplied, assuming it can respond to the
48
+ # `#debug` and `#debug?` messages.
49
+ #
50
+ # @author Fletcher Nichol <fnichol@nichol.ca>
51
+ # @author Matt Wrock <matt@mattwrock.com>
52
+ class FileTransporter
53
+ # Creates a FileTransporter given a PowerShell object.
54
+ #
55
+ # @param shell [PowerShell] a winrm PowerShell object
56
+ def initialize(shell, opts = {})
57
+ @shell = shell
58
+ @logger = shell.logger
59
+ @id_generator = opts.fetch(:id_generator) { -> { SecureRandom.uuid } }
60
+ end
61
+
62
+ # Uploads a collection of files and/or directories to the remote host.
63
+ #
64
+ # **TODO Notes:**
65
+ # * options could specify zip mode, zip options, etc.
66
+ # * maybe option to set tmpfile base dir to override $env:PATH?
67
+ # * progress yields block like net-scp progress
68
+ # * final API: def upload(locals, remote, _options = {}, &_progress)
69
+ #
70
+ # @param locals [Array<String>,String] one or more local file or
71
+ # directory paths
72
+ # @param remote [String] the base destination path on the remote host
73
+ # @return [Hash] report hash, keyed by the local SHA1 digest
74
+ def upload(locals, remote)
75
+ files = nil
76
+ report = nil
77
+ remote = remote.to_s
78
+
79
+ elapsed1 = Benchmark.measure do
80
+ files = make_files_hash(Array(locals), remote)
81
+ report = check_files(files)
82
+ merge_with_report!(files, report)
83
+ reconcile_destinations!(files)
84
+ end
85
+ total_size = total_base64_transfer_size(files)
86
+
87
+ elapsed2 = Benchmark.measure do
88
+ report = stream_upload_files(files) do |local_path, xfered|
89
+ yield xfered, total_size, local_path, remote if block_given?
90
+ end
91
+ merge_with_report!(files, report)
92
+ end
93
+
94
+ elapsed3 = Benchmark.measure do
95
+ report = extract_files(files)
96
+ merge_with_report!(files, report)
97
+ cleanup(files)
98
+ end
99
+
100
+ logger.debug(
101
+ "Uploaded #{files.keys.size} items " \
102
+ "dirty_check: #{duration(elapsed1.real)} " \
103
+ "stream_files: #{duration(elapsed2.real)} " \
104
+ "extract: #{duration(elapsed3.real)} " \
105
+ )
106
+
107
+ [total_size, files]
108
+ end
109
+
110
+ private
111
+
112
+ # @return [String] the Array pack template for Base64 encoding a stream
113
+ # of data
114
+ # @api private
115
+ BASE64_PACK = 'm0'.freeze
116
+
117
+ # @return [String] the directory where temporary upload artifacts are
118
+ # persisted
119
+ # @api private
120
+ TEMP_UPLOAD_DIRECTORY = '$env:TEMP\\winrm-upload'.freeze
121
+
122
+ # @return [#debug,#debug?] the logger
123
+ # @api private
124
+ attr_reader :logger
125
+
126
+ # @return [Winrm::Shells::Powershell] a WinRM Powershell shell
127
+ # @api private
128
+ attr_reader :shell
129
+
130
+ # @return [Integer] the maximum number of bytes to send per request
131
+ # when streaming a file. This is optimized to send as much data
132
+ # as allowed in a single PSRP fragment
133
+ # @api private
134
+ def max_encoded_write
135
+ @max_encoded_write ||= begin
136
+ empty_command = WinRM::PSRP::MessageFactory.create_pipeline_message(
137
+ '00000000-0000-0000-0000-000000000000',
138
+ '00000000-0000-0000-0000-000000000000',
139
+ stream_command('')
140
+ )
141
+ shell.max_fragment_blob_size - empty_command.bytes.length
142
+ end
143
+ end
144
+
145
+ # Examines the files and corrects the file destination if it is
146
+ # targeting an existing folder. In this case, the destination path
147
+ # will have the base name of the source file appended. This only
148
+ # applies to file uploads and not to folder uploads.
149
+ #
150
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
151
+ # @return [Hash] a report hash, keyed by the local SHA1 digest
152
+ # @api private
153
+ def reconcile_destinations!(files)
154
+ files.each do |_, data|
155
+ if data['target_is_folder'] == 'True'
156
+ data['dst'] = File.join(data['dst'], File.basename(data['src']))
157
+ end
158
+ end
159
+ end
160
+
161
+ # Adds an entry to a files Hash (keyed by local SHA1 digest) for a
162
+ # directory. When a directory is added, a temporary Zip file is created
163
+ # containing the contents of the directory and any file-related data
164
+ # such as SHA1 digest, size, etc. will be referring to the Zip file.
165
+ #
166
+ # @param hash [Hash] hash to be mutated
167
+ # @param dir [String] directory path to be Zipped and added
168
+ # @param remote [String] path to destination on remote host
169
+ # @api private
170
+ def add_directory_hash!(hash, dir, remote)
171
+ logger.debug "creating hash for directory #{remote}"
172
+ zip_io = TmpZip.new(dir, logger)
173
+ zip_sha1 = sha1sum(zip_io.path)
174
+
175
+ hash[zip_sha1] = {
176
+ 'src' => dir,
177
+ 'src_zip' => zip_io.path.to_s,
178
+ 'zip_io' => zip_io,
179
+ 'tmpzip' => "#{TEMP_UPLOAD_DIRECTORY}\\tmpzip-#{zip_sha1}.zip",
180
+ 'dst' => "#{remote}\\#{File.basename(dir)}",
181
+ 'size' => File.size(zip_io.path)
182
+ }
183
+ end
184
+
185
+ # Adds an entry to a files Hash (keyed by local SHA1 digest) for a file.
186
+ #
187
+ # @param hash [Hash] hash to be mutated
188
+ # @param local [String] file path
189
+ # @param remote [String] path to destination on remote host
190
+ # @api private
191
+ def add_file_hash!(hash, local, remote)
192
+ logger.debug "creating hash for file #{remote}"
193
+
194
+ hash[sha1sum(local)] = {
195
+ 'src' => local,
196
+ 'dst' => remote,
197
+ 'size' => File.size(local)
198
+ }
199
+ end
200
+
201
+ # Runs the check_files PowerShell script against a collection of
202
+ # destination path/SHA1 checksum pairs. The PowerShell script returns
203
+ # its results as a CSV-formatted report which is converted into a Ruby
204
+ # Hash.
205
+ #
206
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
207
+ # @return [Hash] a report hash, keyed by the local SHA1 digest
208
+ # @api private
209
+ def check_files(files)
210
+ logger.debug 'Running check_files.ps1'
211
+ hash_file = check_files_ps_hash(files)
212
+ script = WinRM::FS::Scripts.render('check_files', hash_file: hash_file)
213
+ parse_response(shell.run(script))
214
+ end
215
+
216
+ # Constructs a collection of destination path/SHA1 checksum pairs as a
217
+ # String representation of the contents of a PowerShell Hash Table.
218
+ #
219
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
220
+ # @return [String] the inner contents of a PowerShell Hash Table
221
+ # @api private
222
+ def check_files_ps_hash(files)
223
+ hash = files.map do |sha1, data|
224
+ [
225
+ sha1,
226
+ {
227
+ 'target' => data.fetch('tmpzip', data['dst']),
228
+ 'src_basename' => File.basename(data['src']),
229
+ 'dst' => data['dst']
230
+ }
231
+ ]
232
+ end
233
+ ps_hash(Hash[hash])
234
+ end
235
+
236
+ # Performs any final cleanup on the report Hash and removes any
237
+ # temporary files/resources used in the upload task.
238
+ #
239
+ # @param files [Hash] a files hash
240
+ # @api private
241
+ def cleanup(files)
242
+ files.select { |_, data| data.key?('zip_io') }.each do |sha1, data|
243
+ data.fetch('zip_io').unlink
244
+ files.fetch(sha1).delete('zip_io')
245
+ logger.debug "Cleaned up src_zip #{data['src_zip']}"
246
+ end
247
+ end
248
+
249
+ # Runs the extract_files PowerShell script against a collection of
250
+ # temporary file/destination path pairs. The PowerShell script returns
251
+ # its results as a CSV-formatted report which is converted into a Ruby
252
+ # Hash. The script will not be invoked if there are no zip files
253
+ # present in the incoming files Hash.
254
+ #
255
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
256
+ # @return [Hash] a report hash, keyed by the local SHA1 digest
257
+ # @api private
258
+ def extract_files(files)
259
+ extracted_files = extract_files_ps_hash(files)
260
+
261
+ if extracted_files == ps_hash({})
262
+ logger.debug 'No remote files to extract, skipping'
263
+ {}
264
+ else
265
+ logger.debug 'Running extract_files.ps1'
266
+ script = WinRM::FS::Scripts.render('extract_files', hash_file: extracted_files)
267
+
268
+ parse_response(shell.run(script))
269
+ end
270
+ end
271
+
272
+ # Constructs a collection of temporary file/destination path pairs for
273
+ # all zipped folders as a String representation of the contents of a
274
+ # PowerShell Hash Table.
275
+ #
276
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
277
+ # @return [String] the inner contents of a PowerShell Hash Table
278
+ # @api private
279
+ def extract_files_ps_hash(files)
280
+ file_data = files.select { |_, data| data.key?('tmpzip') }
281
+
282
+ result = file_data.map do |sha1, data|
283
+ val = { 'dst' => data['dst'] }
284
+ val['tmpzip'] = data['tmpzip'] if data['tmpzip']
285
+
286
+ [sha1, val]
287
+ end
288
+
289
+ ps_hash(Hash[result])
290
+ end
291
+
292
+ # Returns a formatted string representing a duration in seconds.
293
+ #
294
+ # @param total [Integer] the total number of seconds
295
+ # @return [String] a formatted string of the form (XmYY.00s)
296
+ def duration(total)
297
+ total = 0 if total.nil?
298
+ minutes = (total / 60).to_i
299
+ seconds = (total - (minutes * 60))
300
+ format('(%dm%.2fs)', minutes, seconds)
301
+ end
302
+
303
+ # Contructs a Hash of files or directories, keyed by the local SHA1
304
+ # digest. Each file entry has a source and destination set, at a
305
+ # minimum.
306
+ #
307
+ # @param locals [Array<String>] a collection of local files or
308
+ # directories
309
+ # @param remote [String] the base destination path on the remote host
310
+ # @return [Hash] files hash, keyed by the local SHA1 digest
311
+ # @api private
312
+ def make_files_hash(locals, remote)
313
+ hash = {}
314
+ locals.each do |local|
315
+ local = local.to_s
316
+ expanded = File.expand_path(local)
317
+ expanded += local[-1] if local.end_with?('/', '\\')
318
+
319
+ if File.file?(expanded)
320
+ add_file_hash!(hash, expanded, remote)
321
+ elsif File.directory?(expanded)
322
+ add_directory_hash!(hash, expanded, remote)
323
+ else
324
+ fail Errno::ENOENT, "No such file or directory #{expanded}"
325
+ end
326
+ end
327
+ hash
328
+ end
329
+
330
+ # @return [String] the SHA1 digest of a local file
331
+ # @api private
332
+ def sha1sum(local)
333
+ Digest::SHA1.file(local).hexdigest
334
+ end
335
+
336
+ # Destructively merges a report Hash into an existing files Hash.
337
+ # **Note:** this method mutates the files Hash.
338
+ #
339
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
340
+ # @param report [Hash] report hash, keyed by the local SHA1 digest
341
+ # @api private
342
+ def merge_with_report!(files, report)
343
+ files.merge!(report) { |_, oldval, newval| oldval.merge(newval) }
344
+ end
345
+
346
+ # @param depth [Integer] number of padding characters (default: `0`)
347
+ # @return [String] a whitespace padded string of the given length
348
+ # @api private
349
+ def pad(depth = 0)
350
+ ' ' * depth
351
+ end
352
+
353
+ # Parses response of a PowerShell script or CMD command which contains
354
+ # a CSV-formatted document in the standard output stream.
355
+ #
356
+ # @param output [WinRM::Output] output object with stdout, stderr, and
357
+ # exit code
358
+ # @return [Hash] report hash, keyed by the local SHA1 digest
359
+ # @api private
360
+ def parse_response(output)
361
+ exitcode = output.exitcode
362
+ stderr = output.stderr
363
+
364
+ if exitcode != 0
365
+ fail FileTransporterFailed, "[#{self.class}] Upload failed " \
366
+ "(exitcode: #{exitcode})\n#{stderr}"
367
+ elsif stderr != '\r\n' && stderr != ''
368
+ fail FileTransporterFailed, "[#{self.class}] Upload failed " \
369
+ "(exitcode: 0), but stderr present\n#{stderr}"
370
+ end
371
+
372
+ logger.debug 'Parsing CSV Response'
373
+ logger.debug output.stdout
374
+
375
+ array = CSV.parse(output.stdout, headers: true).map(&:to_hash)
376
+ array.each { |h| h.each { |key, value| h[key] = nil if value == '' } }
377
+ Hash[array.map { |entry| [entry.fetch('src_sha1'), entry] }]
378
+ end
379
+
380
+ # Converts a Ruby hash into a PowerShell hash table, represented in a
381
+ # String.
382
+ #
383
+ # @param obj [Object] source Hash or object when used in recursive
384
+ # calls
385
+ # @param depth [Integer] padding depth, used in recursive calls
386
+ # (default: `0`)
387
+ # @return [String] a PowerShell hash table
388
+ # @api private
389
+ def ps_hash(obj, depth = 0)
390
+ if obj.is_a?(Hash)
391
+ obj.map do |k, v|
392
+ %(#{pad(depth + 2)}#{ps_hash(k)} = #{ps_hash(v, depth + 2)})
393
+ end.join(";\n").insert(0, "@{\n").insert(-1, "\n#{pad(depth)}}")
394
+ else
395
+ %("#{obj}")
396
+ end
397
+ end
398
+
399
+ # Uploads an IO stream to a Base64-encoded destination file.
400
+ #
401
+ # **Implementation Note:** Some of the code in this method may appear
402
+ # slightly too dense and while adding additional variables would help,
403
+ # the code is written very precisely to avoid unwanted allocations
404
+ # which will bloat the Ruby VM's object space (and memory footprint).
405
+ # The goal here is to stream potentially large files to a remote host
406
+ # while not loading the entire file into memory first, then Base64
407
+ # encoding it--duplicating the file in memory again.
408
+ #
409
+ # @param input_io [#read] a readable stream or object to be uploaded
410
+ # @param dest [String] path to the destination file on the remote host
411
+ # @return [Integer,Integer] the number of resulting upload chunks and
412
+ # the number of bytes transferred to the remote host
413
+ # @api private
414
+ def stream_upload(input_io, dest)
415
+ read_size = ((max_encoded_write - dest.length) / 4) * 3
416
+ chunk, bytes = 1, 0
417
+ buffer = ''
418
+ shell.run(<<-EOS
419
+ $to = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath("#{dest}")
420
+ $parent = Split-Path $to
421
+ if(!(Test-path $parent)) { mkdir $parent | Out-Null }
422
+ $fileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @(
423
+ $to,
424
+ [system.io.filemode]::Create,
425
+ [System.io.FileAccess]::Write,
426
+ [System.IO.FileShare]::ReadWrite
427
+ )
428
+
429
+ # Powershell caches ScrpitBlocks in a dictionary
430
+ # keyed on the script block text. Thats just great
431
+ # unless the script is super large and called a gillion
432
+ # times like we might do. In such a case it will saturate the
433
+ # Large Object Heap and lead to Out Of Memory exceptions
434
+ # for large files or folders. So we call the internal method
435
+ # ClearScriptBlockCache to clear it.
436
+ $bindingFlags= [Reflection.BindingFlags] "NonPublic,Static"
437
+ $method = [scriptblock].GetMethod("ClearScriptBlockCache", $bindingFlags)
438
+ EOS
439
+ )
440
+
441
+ while input_io.read(read_size, buffer)
442
+ bytes += (buffer.bytesize / 3 * 4)
443
+ shell.run(stream_command([buffer].pack(BASE64_PACK)))
444
+ logger.debug "Wrote chunk #{chunk} for #{dest}" if chunk % 25 == 0
445
+ chunk += 1
446
+ yield bytes if block_given?
447
+ end
448
+ shell.run('$fileStream.Dispose()')
449
+ buffer = nil # rubocop:disable Lint/UselessAssignment
450
+
451
+ [chunk - 1, bytes]
452
+ end
453
+
454
+ def stream_command(encoded_bytes)
455
+ <<-EOS
456
+ if($method) { $method.Invoke($Null, $Null) }
457
+ $bytes=[Convert]::FromBase64String('#{encoded_bytes}')
458
+ $fileStream.Write($bytes, 0, $bytes.length)
459
+ EOS
460
+ end
461
+
462
+ # Uploads a local file.
463
+ #
464
+ # @param src [String] path to a local file
465
+ # @param dest [String] path to the file on the remote host
466
+ # @return [Integer,Integer] the number of resulting upload chunks and
467
+ # the number of bytes transferred to the remote host
468
+ # @api private
469
+ def stream_upload_file(src, dest, &block)
470
+ logger.debug "Uploading #{src} to #{dest}"
471
+ chunks, bytes = 0, 0
472
+ elapsed = Benchmark.measure do
473
+ File.open(src, 'rb') do |io|
474
+ chunks, bytes = stream_upload(io, dest, &block)
475
+ end
476
+ end
477
+ logger.debug(
478
+ "Finished uploading #{src} to #{dest} " \
479
+ "(#{bytes.to_f / 1000} KB over #{chunks} chunks) " \
480
+ "in #{duration(elapsed.real)}"
481
+ )
482
+
483
+ [chunks, bytes]
484
+ end
485
+
486
+ # Uploads a collection of "dirty" files to the remote host as
487
+ # Base64-encoded temporary files. A "dirty" file is one which has the
488
+ # `"chk_dirty"` option set to `"True"` in the incoming files Hash.
489
+ #
490
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
491
+ # @return [Hash] a report hash, keyed by the local SHA1 digest
492
+ # @api private
493
+ def stream_upload_files(files)
494
+ response = {}
495
+ files.each do |sha1, data|
496
+ src = data.fetch('src_zip', data['src'])
497
+ if data['chk_dirty'] == 'True'
498
+ response[sha1] = { 'dest' => data['tmpzip'] || data['dst'] }
499
+ chunks, bytes = stream_upload_file(src, data['tmpzip'] || data['dst']) do |xfered|
500
+ yield data['src'], xfered
501
+ end
502
+ response[sha1]['chunks'] = chunks
503
+ response[sha1]['xfered'] = bytes
504
+ else
505
+ logger.debug "File #{data['dst']} is up to date, skipping"
506
+ end
507
+ end
508
+ response
509
+ end
510
+
511
+ # Total by byte count to be transferred.
512
+ # Calculates count based on the sum of base64 encoded content size
513
+ # of all files base 64 that are dirty.
514
+ #
515
+ # @param files [Hash] files hash, keyed by the local SHA1 digest
516
+ # @return [Fixnum] total byte size
517
+ # @api private
518
+ def total_base64_transfer_size(files)
519
+ size = 0
520
+ files.values.each { |file| size += file['size'] if file['chk_dirty'] == 'True' }
521
+ size / 3 * 4
522
+ end
523
+ end
524
+ # rubocop:enable MethodLength, AbcSize, ClassLength
525
+ end
526
+ end
527
+ end