r10k 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (358) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/pull_request_template.md +1 -0
  4. data/.github/workflows/docker.yml +56 -0
  5. data/.github/workflows/release.yml +36 -0
  6. data/.gitignore +9 -0
  7. data/.travis.yml +45 -0
  8. data/CHANGELOG.mkd +1759 -0
  9. data/CODEOWNERS +2 -0
  10. data/CONTRIBUTING.mkd +105 -0
  11. data/Gemfile +15 -0
  12. data/LICENSE +14 -0
  13. data/README.mkd +118 -0
  14. data/Rakefile +3 -0
  15. data/azure-pipelines.yml +86 -0
  16. data/bin/r10k +17 -0
  17. data/doc/common-patterns.mkd +44 -0
  18. data/doc/dynamic-environments.mkd +31 -0
  19. data/doc/dynamic-environments/configuration.mkd +669 -0
  20. data/doc/dynamic-environments/git-environments.mkd +75 -0
  21. data/doc/dynamic-environments/introduction.mkd +69 -0
  22. data/doc/dynamic-environments/master-configuration.mkd +40 -0
  23. data/doc/dynamic-environments/quickstart.mkd +201 -0
  24. data/doc/dynamic-environments/svn-environments.mkd +45 -0
  25. data/doc/dynamic-environments/usage.mkd +132 -0
  26. data/doc/dynamic-environments/workflow-guide.mkd +247 -0
  27. data/doc/faq.mkd +164 -0
  28. data/doc/git/cloning-and-mirroring.mkd +60 -0
  29. data/doc/git/providers.mkd +111 -0
  30. data/doc/puppetfile.mkd +309 -0
  31. data/doc/updating-your-puppetfile.mkd +38 -0
  32. data/docker/.gitignore +1 -0
  33. data/docker/.rspec +4 -0
  34. data/docker/Gemfile +11 -0
  35. data/docker/Makefile +89 -0
  36. data/docker/README.md +28 -0
  37. data/docker/r10k/Dockerfile +67 -0
  38. data/docker/r10k/adduser.sh +13 -0
  39. data/docker/r10k/docker-entrypoint.d/10-analytics.sh +30 -0
  40. data/docker/r10k/docker-entrypoint.sh +11 -0
  41. data/docker/r10k/release.Dockerfile +54 -0
  42. data/docker/spec/dockerfile_spec.rb +43 -0
  43. data/docker/spec/fixtures/Puppetfile +2 -0
  44. data/integration/Gemfile +19 -0
  45. data/integration/README.mkd +29 -0
  46. data/integration/Rakefile +77 -0
  47. data/integration/component/pre-suite/05_install_dev_r10k.rb +12 -0
  48. data/integration/files/README.mkd +4 -0
  49. data/integration/files/hiera.yaml +8 -0
  50. data/integration/files/modules/helloworld/manifests/init.pp +3 -0
  51. data/integration/files/modules/hieratest/manifests/init.pp +3 -0
  52. data/integration/files/modules/unicode/files/pretend_unicode +1 -0
  53. data/integration/files/modules/unicode/manifests/init.pp +6 -0
  54. data/integration/files/pre-suite/git_config.pp.erb +19 -0
  55. data/integration/files/pre-suite/prod_env.config +3 -0
  56. data/integration/files/r10k_conf.yaml.erb +9 -0
  57. data/integration/lib/README.mkd +4 -0
  58. data/integration/lib/git_utils.rb +205 -0
  59. data/integration/lib/master_manipulator.rb +205 -0
  60. data/integration/lib/r10k_utils.rb +222 -0
  61. data/integration/manifests/README.mkd +4 -0
  62. data/integration/pre-suite/00_pe_install.rb +6 -0
  63. data/integration/pre-suite/10_git_config.rb +48 -0
  64. data/integration/pre-suite/20_pe_r10k.rb +55 -0
  65. data/integration/pre-suite/README.mkd +5 -0
  66. data/integration/tests/Puppetfile/HTTP_PROXY_affects_forge_source.rb +72 -0
  67. data/integration/tests/Puppetfile/HTTP_PROXY_affects_git_source.rb +70 -0
  68. data/integration/tests/README.mkd +4 -0
  69. data/integration/tests/basic_functionality/install_pe_only_module_with_puppetfile.rb +83 -0
  70. data/integration/tests/basic_functionality/negative/neg_deploy_with_invalid_r10k_yaml.rb +51 -0
  71. data/integration/tests/basic_functionality/negative/neg_deploy_with_missing_r10k_yaml.rb +28 -0
  72. data/integration/tests/basic_functionality/negative/neg_invalid_git_provider.rb +45 -0
  73. data/integration/tests/basic_functionality/negative/negative_bad_proxy.rb +34 -0
  74. data/integration/tests/basic_functionality/proxy_specified_in_configuration.rb +103 -0
  75. data/integration/tests/basic_functionality/proxy_with_pe_only_module.rb +128 -0
  76. data/integration/tests/basic_functionality/proxy_with_puppetfile.rb +61 -0
  77. data/integration/tests/basic_functionality/rugged_git_provider_with_ssh.rb +109 -0
  78. data/integration/tests/basic_functionality/rugged_git_provider_without_ssh.rb +108 -0
  79. data/integration/tests/command_line/deploy_env_without_mod_update.rb +76 -0
  80. data/integration/tests/command_line/negative/neg_deploy_env_with_module_update.rb +77 -0
  81. data/integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb +23 -0
  82. data/integration/tests/git_source/HTTP_proxy_and_git_source.rb +70 -0
  83. data/integration/tests/git_source/git_source_git.rb +128 -0
  84. data/integration/tests/git_source/git_source_ssh.rb +87 -0
  85. data/integration/tests/git_source/git_source_submodule.rb +70 -0
  86. data/integration/tests/git_source/negative/neg_git_broken_remote.rb +38 -0
  87. data/integration/tests/git_source/negative/neg_git_unauthorized_https.rb +46 -0
  88. data/integration/tests/git_source/negative/neg_git_unauthorized_ssh.rb +73 -0
  89. data/integration/tests/git_source/negative/neg_git_unicode_branch.rb +35 -0
  90. data/integration/tests/i18n/deploy_module_with_unicode_in_file_name.rb +64 -0
  91. data/integration/tests/purging/content_not_purged_at_root.rb +89 -0
  92. data/integration/tests/purging/default_purging.rb +125 -0
  93. data/integration/tests/purging/does_not_purge_files_on_white_list.rb +93 -0
  94. data/integration/tests/purging/invalid_whitelist_types.rb +63 -0
  95. data/integration/tests/user_scenario/basic_workflow/multi_env_1000_branches.rb +66 -0
  96. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +111 -0
  97. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +117 -0
  98. data/integration/tests/user_scenario/basic_workflow/multi_env_hiera.rb +100 -0
  99. data/integration/tests/user_scenario/basic_workflow/multi_env_multi_source.rb +133 -0
  100. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +161 -0
  101. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_basedir.rb +46 -0
  102. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_forge_module.rb +48 -0
  103. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module.rb +45 -0
  104. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +43 -0
  105. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_remote.rb +45 -0
  106. data/integration/tests/user_scenario/basic_workflow/negative/neg_branch_name_collision.rb +64 -0
  107. data/integration/tests/user_scenario/basic_workflow/negative/neg_disk_full.rb +75 -0
  108. data/integration/tests/user_scenario/basic_workflow/negative/neg_duplicate_module_names.rb +44 -0
  109. data/integration/tests/user_scenario/basic_workflow/negative/neg_inaccessible_forge.rb +58 -0
  110. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_env_name.rb +34 -0
  111. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_puppet_file.rb +36 -0
  112. data/integration/tests/user_scenario/basic_workflow/negative/neg_module_specified_at_deleted_release.rb +49 -0
  113. data/integration/tests/user_scenario/basic_workflow/negative/neg_read_only.rb +58 -0
  114. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +51 -0
  115. data/integration/tests/user_scenario/basic_workflow/single_env_10000_files.rb +75 -0
  116. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +104 -0
  117. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_module.rb +81 -0
  118. data/integration/tests/user_scenario/basic_workflow/single_env_custom_module.rb +49 -0
  119. data/integration/tests/user_scenario/basic_workflow/single_env_large_files.rb +75 -0
  120. data/integration/tests/user_scenario/basic_workflow/single_env_module_already_installed.rb +82 -0
  121. data/integration/tests/user_scenario/basic_workflow/single_env_module_last_release_deleted.rb +68 -0
  122. data/integration/tests/user_scenario/basic_workflow/single_env_non-existent_base_dir.rb +94 -0
  123. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +93 -0
  124. data/integration/tests/user_scenario/basic_workflow/single_env_switch_forge_git_module.rb +117 -0
  125. data/integration/tests/user_scenario/basic_workflow/single_env_unicode_paths.rb +60 -0
  126. data/integration/tests/user_scenario/basic_workflow/single_env_upgrade_forge_mod_revert_change.rb +166 -0
  127. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +163 -0
  128. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +111 -0
  129. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +78 -0
  130. data/integration/tests/user_scenario/complex_workflow/single_env_git_module_update.rb +100 -0
  131. data/lib/r10k.rb +11 -0
  132. data/lib/r10k/action/base.rb +31 -0
  133. data/lib/r10k/action/cri_runner.rb +72 -0
  134. data/lib/r10k/action/deploy.rb +9 -0
  135. data/lib/r10k/action/deploy/deploy_helpers.rb +34 -0
  136. data/lib/r10k/action/deploy/display.rb +89 -0
  137. data/lib/r10k/action/deploy/environment.rb +196 -0
  138. data/lib/r10k/action/deploy/module.rb +84 -0
  139. data/lib/r10k/action/puppetfile.rb +10 -0
  140. data/lib/r10k/action/puppetfile/check.rb +31 -0
  141. data/lib/r10k/action/puppetfile/cri_runner.rb +26 -0
  142. data/lib/r10k/action/puppetfile/install.rb +45 -0
  143. data/lib/r10k/action/puppetfile/purge.rb +28 -0
  144. data/lib/r10k/action/runner.rb +96 -0
  145. data/lib/r10k/action/visitor.rb +31 -0
  146. data/lib/r10k/cli.rb +51 -0
  147. data/lib/r10k/cli/deploy.rb +114 -0
  148. data/lib/r10k/cli/ext/logging.rb +15 -0
  149. data/lib/r10k/cli/help.rb +7 -0
  150. data/lib/r10k/cli/puppetfile.rb +74 -0
  151. data/lib/r10k/cli/version.rb +31 -0
  152. data/lib/r10k/deployment.rb +132 -0
  153. data/lib/r10k/deployment/config.rb +56 -0
  154. data/lib/r10k/environment.rb +37 -0
  155. data/lib/r10k/environment/bare.rb +16 -0
  156. data/lib/r10k/environment/base.rb +150 -0
  157. data/lib/r10k/environment/git.rb +81 -0
  158. data/lib/r10k/environment/name.rb +86 -0
  159. data/lib/r10k/environment/svn.rb +91 -0
  160. data/lib/r10k/environment/with_modules.rb +139 -0
  161. data/lib/r10k/errors.rb +61 -0
  162. data/lib/r10k/errors/formatting.rb +28 -0
  163. data/lib/r10k/feature.rb +56 -0
  164. data/lib/r10k/feature/collection.rb +23 -0
  165. data/lib/r10k/features.rb +20 -0
  166. data/lib/r10k/forge/module_release.rb +228 -0
  167. data/lib/r10k/git.rb +196 -0
  168. data/lib/r10k/git/alternates.rb +63 -0
  169. data/lib/r10k/git/cache.rb +108 -0
  170. data/lib/r10k/git/errors.rb +34 -0
  171. data/lib/r10k/git/rugged.rb +17 -0
  172. data/lib/r10k/git/rugged/bare_repository.rb +85 -0
  173. data/lib/r10k/git/rugged/base_repository.rb +93 -0
  174. data/lib/r10k/git/rugged/cache.rb +11 -0
  175. data/lib/r10k/git/rugged/credentials.rb +91 -0
  176. data/lib/r10k/git/rugged/thin_repository.rb +89 -0
  177. data/lib/r10k/git/rugged/working_repository.rb +145 -0
  178. data/lib/r10k/git/shellgit.rb +9 -0
  179. data/lib/r10k/git/shellgit/bare_repository.rb +43 -0
  180. data/lib/r10k/git/shellgit/base_repository.rb +137 -0
  181. data/lib/r10k/git/shellgit/cache.rb +11 -0
  182. data/lib/r10k/git/shellgit/thin_repository.rb +69 -0
  183. data/lib/r10k/git/shellgit/working_repository.rb +111 -0
  184. data/lib/r10k/git/stateful_repository.rb +95 -0
  185. data/lib/r10k/initializers.rb +67 -0
  186. data/lib/r10k/instance_cache.rb +32 -0
  187. data/lib/r10k/keyed_factory.rb +39 -0
  188. data/lib/r10k/logging.rb +109 -0
  189. data/lib/r10k/logging/terminaloutputter.rb +36 -0
  190. data/lib/r10k/module.rb +38 -0
  191. data/lib/r10k/module/base.rb +113 -0
  192. data/lib/r10k/module/forge.rb +177 -0
  193. data/lib/r10k/module/git.rb +109 -0
  194. data/lib/r10k/module/local.rb +36 -0
  195. data/lib/r10k/module/metadata_file.rb +31 -0
  196. data/lib/r10k/module/svn.rb +112 -0
  197. data/lib/r10k/puppetfile.rb +286 -0
  198. data/lib/r10k/settings.rb +194 -0
  199. data/lib/r10k/settings/collection.rb +123 -0
  200. data/lib/r10k/settings/container.rb +97 -0
  201. data/lib/r10k/settings/definition.rb +124 -0
  202. data/lib/r10k/settings/enum_definition.rb +30 -0
  203. data/lib/r10k/settings/helpers.rb +38 -0
  204. data/lib/r10k/settings/list.rb +107 -0
  205. data/lib/r10k/settings/loader.rb +99 -0
  206. data/lib/r10k/settings/mixin.rb +54 -0
  207. data/lib/r10k/settings/uri_definition.rb +19 -0
  208. data/lib/r10k/source.rb +42 -0
  209. data/lib/r10k/source/base.rb +74 -0
  210. data/lib/r10k/source/exec.rb +51 -0
  211. data/lib/r10k/source/git.rb +142 -0
  212. data/lib/r10k/source/hash.rb +182 -0
  213. data/lib/r10k/source/svn.rb +136 -0
  214. data/lib/r10k/source/yaml.rb +20 -0
  215. data/lib/r10k/source/yamldir.rb +32 -0
  216. data/lib/r10k/svn.rb +6 -0
  217. data/lib/r10k/svn/remote.rb +68 -0
  218. data/lib/r10k/svn/working_dir.rb +125 -0
  219. data/lib/r10k/util/attempt.rb +84 -0
  220. data/lib/r10k/util/basedir.rb +65 -0
  221. data/lib/r10k/util/commands.rb +31 -0
  222. data/lib/r10k/util/exec_env.rb +36 -0
  223. data/lib/r10k/util/license.rb +24 -0
  224. data/lib/r10k/util/platform.rb +42 -0
  225. data/lib/r10k/util/purgeable.rb +88 -0
  226. data/lib/r10k/util/setopts.rb +55 -0
  227. data/lib/r10k/util/subprocess.rb +84 -0
  228. data/lib/r10k/util/subprocess/result.rb +56 -0
  229. data/lib/r10k/util/subprocess/runner.rb +26 -0
  230. data/lib/r10k/util/subprocess/runner/jruby.rb +23 -0
  231. data/lib/r10k/util/subprocess/runner/posix.rb +103 -0
  232. data/lib/r10k/util/subprocess/runner/pump.rb +59 -0
  233. data/lib/r10k/util/subprocess/runner/windows.rb +23 -0
  234. data/lib/r10k/util/subprocess/subprocess_error.rb +24 -0
  235. data/lib/r10k/util/symbolize_keys.rb +35 -0
  236. data/lib/r10k/version.rb +6 -0
  237. data/locales/config.yaml +21 -0
  238. data/locales/r10k.pot +545 -0
  239. data/r10k.gemspec +50 -0
  240. data/r10k.yaml.example +112 -0
  241. data/spec/fixtures/empty/.empty +0 -0
  242. data/spec/fixtures/integration/git/puppet-boolean-bare.tar +0 -0
  243. data/spec/fixtures/module/forge/bad_module/metadata.json +1 -0
  244. data/spec/fixtures/module/forge/eight_hundred/Modulefile +8 -0
  245. data/spec/fixtures/module/forge/eight_hundred/metadata.json +19 -0
  246. data/spec/fixtures/unit/action/r10k.yaml +5 -0
  247. data/spec/fixtures/unit/action/r10k_cachedir.yaml +2 -0
  248. data/spec/fixtures/unit/action/r10k_generate_types.yaml +3 -0
  249. data/spec/fixtures/unit/action/r10k_puppet_path.yaml +3 -0
  250. data/spec/fixtures/unit/puppetfile/argument-error/Puppetfile +1 -0
  251. data/spec/fixtures/unit/puppetfile/default-branch-override/Puppetfile +5 -0
  252. data/spec/fixtures/unit/puppetfile/duplicate-module-error/Puppetfile +10 -0
  253. data/spec/fixtures/unit/puppetfile/invalid-syntax/Puppetfile +1 -0
  254. data/spec/fixtures/unit/puppetfile/load-error/Puppetfile +1 -0
  255. data/spec/fixtures/unit/puppetfile/name-error/Puppetfile +1 -0
  256. data/spec/fixtures/unit/puppetfile/valid-forge-with-version/Puppetfile +1 -0
  257. data/spec/fixtures/unit/puppetfile/valid-forge-without-version/Puppetfile +1 -0
  258. data/spec/fixtures/unit/util/purgeable/managed_one/expected_1 +0 -0
  259. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_expected_1 +0 -0
  260. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_unmanaged_1 +0 -0
  261. data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_1 +0 -0
  262. data/spec/fixtures/unit/util/purgeable/managed_two/expected_2 +0 -0
  263. data/spec/fixtures/unit/util/purgeable/managed_two/unmanaged_2 +0 -0
  264. data/spec/fixtures/unit/util/subprocess/runner/no-execute.sh +3 -0
  265. data/spec/integration/git/rugged/bare_repository_spec.rb +13 -0
  266. data/spec/integration/git/rugged/thin_repository_spec.rb +14 -0
  267. data/spec/integration/git/rugged/working_repository_spec.rb +48 -0
  268. data/spec/integration/git/shellgit/bare_repository_spec.rb +13 -0
  269. data/spec/integration/git/shellgit/thin_repository_spec.rb +14 -0
  270. data/spec/integration/git/shellgit/working_repository_spec.rb +13 -0
  271. data/spec/integration/git/stateful_repository_spec.rb +159 -0
  272. data/spec/matchers/exit_with.rb +28 -0
  273. data/spec/matchers/match_realpath.rb +18 -0
  274. data/spec/r10k-mocks.rb +3 -0
  275. data/spec/r10k-mocks/mock_config.rb +33 -0
  276. data/spec/r10k-mocks/mock_env.rb +15 -0
  277. data/spec/r10k-mocks/mock_source.rb +13 -0
  278. data/spec/shared-contexts/git-fixtures.rb +55 -0
  279. data/spec/shared-examples/deploy-actions.rb +69 -0
  280. data/spec/shared-examples/git-repository.rb +38 -0
  281. data/spec/shared-examples/git/bare_repository.rb +132 -0
  282. data/spec/shared-examples/git/thin_repository.rb +26 -0
  283. data/spec/shared-examples/git/working_repository.rb +207 -0
  284. data/spec/shared-examples/puppetfile-action.rb +39 -0
  285. data/spec/shared-examples/settings/ancestry.rb +44 -0
  286. data/spec/shared-examples/subprocess-runner.rb +83 -0
  287. data/spec/spec_helper.rb +40 -0
  288. data/spec/unit/action/cri_runner_spec.rb +72 -0
  289. data/spec/unit/action/deploy/deploy_helpers_spec.rb +38 -0
  290. data/spec/unit/action/deploy/display_spec.rb +31 -0
  291. data/spec/unit/action/deploy/environment_spec.rb +395 -0
  292. data/spec/unit/action/deploy/module_spec.rb +139 -0
  293. data/spec/unit/action/puppetfile/check_spec.rb +41 -0
  294. data/spec/unit/action/puppetfile/cri_runner_spec.rb +47 -0
  295. data/spec/unit/action/puppetfile/install_spec.rb +84 -0
  296. data/spec/unit/action/puppetfile/purge_spec.rb +42 -0
  297. data/spec/unit/action/runner_spec.rb +213 -0
  298. data/spec/unit/action/visitor_spec.rb +39 -0
  299. data/spec/unit/cli_spec.rb +9 -0
  300. data/spec/unit/deployment/config_spec.rb +33 -0
  301. data/spec/unit/deployment_spec.rb +162 -0
  302. data/spec/unit/environment/base_spec.rb +109 -0
  303. data/spec/unit/environment/git_spec.rb +97 -0
  304. data/spec/unit/environment/name_spec.rb +135 -0
  305. data/spec/unit/environment/svn_spec.rb +133 -0
  306. data/spec/unit/errors/formatting_spec.rb +84 -0
  307. data/spec/unit/feature_spec.rb +50 -0
  308. data/spec/unit/forge/module_release_spec.rb +213 -0
  309. data/spec/unit/git/alternates_spec.rb +116 -0
  310. data/spec/unit/git/cache_spec.rb +55 -0
  311. data/spec/unit/git/rugged/cache_spec.rb +29 -0
  312. data/spec/unit/git/rugged/credentials_spec.rb +109 -0
  313. data/spec/unit/git/shellgit/cache_spec.rb +27 -0
  314. data/spec/unit/git/stateful_repository_spec.rb +40 -0
  315. data/spec/unit/git_spec.rb +102 -0
  316. data/spec/unit/initializers_spec.rb +68 -0
  317. data/spec/unit/instance_cache_spec.rb +78 -0
  318. data/spec/unit/keyed_factory_spec.rb +51 -0
  319. data/spec/unit/logging/terminaloutputter_spec.rb +53 -0
  320. data/spec/unit/logging_spec.rb +68 -0
  321. data/spec/unit/module/base_spec.rb +72 -0
  322. data/spec/unit/module/forge_spec.rb +207 -0
  323. data/spec/unit/module/git_spec.rb +274 -0
  324. data/spec/unit/module/metadata_file_spec.rb +68 -0
  325. data/spec/unit/module/svn_spec.rb +178 -0
  326. data/spec/unit/module_spec.rb +29 -0
  327. data/spec/unit/puppetfile_spec.rb +300 -0
  328. data/spec/unit/settings/collection_spec.rb +123 -0
  329. data/spec/unit/settings/container_spec.rb +92 -0
  330. data/spec/unit/settings/definition_spec.rb +79 -0
  331. data/spec/unit/settings/enum_definition_spec.rb +20 -0
  332. data/spec/unit/settings/inheritance_spec.rb +38 -0
  333. data/spec/unit/settings/list_spec.rb +88 -0
  334. data/spec/unit/settings/loader_spec.rb +110 -0
  335. data/spec/unit/settings/uri_definition_spec.rb +23 -0
  336. data/spec/unit/settings_spec.rb +246 -0
  337. data/spec/unit/source/base_spec.rb +31 -0
  338. data/spec/unit/source/exec_spec.rb +81 -0
  339. data/spec/unit/source/git_spec.rb +185 -0
  340. data/spec/unit/source/hash_spec.rb +54 -0
  341. data/spec/unit/source/svn_spec.rb +196 -0
  342. data/spec/unit/source/yaml_spec.rb +42 -0
  343. data/spec/unit/source_spec.rb +10 -0
  344. data/spec/unit/svn/remote_spec.rb +21 -0
  345. data/spec/unit/svn/working_dir_spec.rb +56 -0
  346. data/spec/unit/util/attempt_spec.rb +82 -0
  347. data/spec/unit/util/commands_spec.rb +61 -0
  348. data/spec/unit/util/exec_env_spec.rb +56 -0
  349. data/spec/unit/util/purgeable_spec.rb +230 -0
  350. data/spec/unit/util/setopts_spec.rb +59 -0
  351. data/spec/unit/util/subprocess/result_spec.rb +36 -0
  352. data/spec/unit/util/subprocess/runner/posix_spec.rb +7 -0
  353. data/spec/unit/util/subprocess/runner/pump_spec.rb +79 -0
  354. data/spec/unit/util/subprocess/runner/windows_spec.rb +7 -0
  355. data/spec/unit/util/subprocess/subprocess_error_spec.rb +26 -0
  356. data/spec/unit/util/subprocess_spec.rb +65 -0
  357. data/spec/unit/util/symbolize_keys_spec.rb +67 -0
  358. metadata +582 -0
@@ -0,0 +1,135 @@
1
+ require 'spec_helper'
2
+ require 'r10k/environment/name'
3
+
4
+ describe R10K::Environment::Name do
5
+ describe "prefixing" do
6
+ it "uses the branch name as the dirname when prefixing is off" do
7
+ bn = described_class.new('mybranch', :source => 'source', :prefix => false)
8
+ expect(bn.dirname).to eq 'mybranch'
9
+ end
10
+
11
+ it "prepends the source name when prefixing is on" do
12
+ bn = described_class.new('mybranch', :source => 'source', :prefix => true)
13
+ expect(bn.dirname).to eq 'source_mybranch'
14
+ end
15
+
16
+ it "prepends the prefix name when prefixing is overridden" do
17
+ bn = described_class.new('mybranch', {:prefix => "bar", :sourcename => 'foo'})
18
+ expect(bn.dirname).to eq 'bar_mybranch'
19
+ end
20
+
21
+ it "uses the branch name as the dirname when prefixing is nil" do
22
+ bn = described_class.new('mybranch', {:prefix => nil, :sourcename => 'foo'})
23
+ expect(bn.dirname).to eq 'mybranch'
24
+ end
25
+ end
26
+
27
+ describe "determining the validate behavior with :invalid" do
28
+ [
29
+ ['correct_and_warn', {:validate => true, :correct => true}],
30
+ ['correct', {:validate => false, :correct => true}],
31
+ ['error', {:validate => true, :correct => false}],
32
+ ].each do |(setting, outcome)|
33
+ it "treats #{setting} as #{outcome.inspect}" do
34
+ bn = described_class.new('mybranch', :source => 'source', :invalid => setting)
35
+ expect(bn.validate?).to eq outcome[:validate]
36
+ expect(bn.correct?).to eq outcome[:correct]
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "determining if a branch is a valid environment name" do
42
+ invalid_cases = [
43
+ 'hyphenated-branch',
44
+ 'dotted.branch',
45
+ 'slashed/branch',
46
+ 'at@branch',
47
+ 'http://branch'
48
+ ]
49
+
50
+ valid_cases = [
51
+ 'my_branchname',
52
+ 'my_issue_346',
53
+ ]
54
+
55
+ describe "and validate is false" do
56
+ invalid_cases.each do |branch|
57
+ it "is valid if the branch is #{branch}" do
58
+ bn = described_class.new(branch, {:validate => false})
59
+ expect(bn).to be_valid
60
+ end
61
+ end
62
+
63
+ valid_cases.each do |branch|
64
+ it "is valid if the branch is #{branch}" do
65
+ bn = described_class.new(branch, {:validate => false})
66
+ expect(bn).to be_valid
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "and validate is true" do
72
+ invalid_cases.each do |branch|
73
+ it "is invalid if the branch is #{branch}" do
74
+ bn = described_class.new(branch, {:validate => true})
75
+ expect(bn).to_not be_valid
76
+ end
77
+ end
78
+
79
+ valid_cases.each do |branch|
80
+ it "is valid if the branch is #{branch}" do
81
+ bn = described_class.new(branch, {:validate => true})
82
+ expect(bn).to be_valid
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+
89
+ describe "correcting branch names" do
90
+ invalid_cases = [
91
+ 'hyphenated-branch',
92
+ 'dotted.branch',
93
+ 'slashed/branch',
94
+ 'at@branch',
95
+ 'http://branch'
96
+ ]
97
+
98
+ valid_cases = [
99
+ 'my_branchname',
100
+ 'my_issue_346',
101
+ ]
102
+
103
+ describe "and correct is false" do
104
+ invalid_cases.each do |branch|
105
+ it "doesn't modify #{branch}" do
106
+ bn = described_class.new(branch.dup, {:correct => false})
107
+ expect(bn.dirname).to eq branch
108
+ end
109
+ end
110
+
111
+ valid_cases.each do |branch|
112
+ it "doesn't modify #{branch}" do
113
+ bn = described_class.new(branch.dup, {:correct => false})
114
+ expect(bn.dirname).to eq branch
115
+ end
116
+ end
117
+ end
118
+
119
+ describe "and correct is true" do
120
+ invalid_cases.each do |branch|
121
+ it "replaces invalid characters in #{branch} with underscores" do
122
+ bn = described_class.new(branch.dup, {:correct => true})
123
+ expect(bn.dirname).to eq branch.gsub(/\W/, '_')
124
+ end
125
+ end
126
+
127
+ valid_cases.each do |branch|
128
+ it "doesn't modify #{branch}" do
129
+ bn = described_class.new(branch.dup, {:correct => true})
130
+ expect(bn.dirname).to eq branch
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+ require 'r10k/environment'
3
+
4
+ describe R10K::Environment::SVN do
5
+
6
+ subject do
7
+ described_class.new(
8
+ 'myenv',
9
+ '/some/nonexistent/environmentdir',
10
+ 'svn-dirname',
11
+ {
12
+ :remote => 'https://svn-server.site/svn-repo/trunk'
13
+ }
14
+ )
15
+ end
16
+
17
+ let(:working_dir) { subject.working_dir }
18
+
19
+ describe "storing attributes" do
20
+ it "can return the environment name" do
21
+ expect(subject.name).to eq 'myenv'
22
+ end
23
+
24
+ it "can return the environment basedir" do
25
+ expect(subject.basedir).to eq '/some/nonexistent/environmentdir'
26
+ end
27
+
28
+ it "can return the environment dirname" do
29
+ expect(subject.dirname).to eq 'svn-dirname'
30
+ end
31
+
32
+ it "can return the environment remote" do
33
+ expect(subject.remote).to eq 'https://svn-server.site/svn-repo/trunk'
34
+ end
35
+ end
36
+
37
+ describe "synchronizing the environment" do
38
+ it "checks out the working directory when creating a new environment" do
39
+ allow(working_dir).to receive(:is_svn?).and_return(false)
40
+ expect(working_dir).to receive(:checkout)
41
+ subject.sync
42
+ end
43
+
44
+ it "updates the working directory when updating an existing environment" do
45
+ allow(working_dir).to receive(:is_svn?).and_return(true)
46
+ expect(working_dir).to receive(:update)
47
+ subject.sync
48
+ end
49
+ end
50
+
51
+ describe "generating a puppetfile for the environment" do
52
+ let(:puppetfile) { subject.puppetfile }
53
+
54
+ it "creates a puppetfile at the full path to the environment" do
55
+ expect(puppetfile.basedir).to eq '/some/nonexistent/environmentdir/svn-dirname'
56
+ end
57
+
58
+ it "sets the moduledir to 'modules' relative to the environment path" do
59
+ expect(puppetfile.moduledir).to eq '/some/nonexistent/environmentdir/svn-dirname/modules'
60
+ end
61
+
62
+ it "sets the puppetfile path to 'Puppetfile' relative to the environment path" do
63
+ expect(puppetfile.puppetfile_path).to eq '/some/nonexistent/environmentdir/svn-dirname/Puppetfile'
64
+ end
65
+ end
66
+
67
+ describe "enumerating modules" do
68
+ it "loads the Puppetfile and returns modules in that puppetfile" do
69
+ expect(subject.puppetfile).to receive(:load)
70
+ expect(subject.puppetfile).to receive(:modules).and_return [:modules]
71
+ expect(subject.modules).to eq([:modules])
72
+ end
73
+ end
74
+
75
+ describe "determining the status" do
76
+ it "is absent if the working directory is absent" do
77
+ expect(subject.path).to receive(:exist?).and_return(false)
78
+ expect(subject.status).to eq :absent
79
+ end
80
+
81
+ it "is mismatched if the working directory is not an SVN repo" do
82
+ expect(subject.path).to receive(:exist?).and_return(true)
83
+ expect(working_dir).to receive(:is_svn?).and_return(false)
84
+ expect(subject.status).to eq :mismatched
85
+ end
86
+
87
+ it "is mismatched if the working directory remote doesn't match the expected remote" do
88
+ expect(subject.path).to receive(:exist?).and_return(true)
89
+ expect(working_dir).to receive(:is_svn?).and_return(true)
90
+ expect(working_dir).to receive(:url).and_return 'https://svn-server.site/another-svn-repo/trunk'
91
+ expect(subject.status).to eq :mismatched
92
+ end
93
+
94
+ it "is outdated when the the working directory has not synced" do
95
+ expect(subject.path).to receive(:exist?).and_return(true)
96
+ expect(working_dir).to receive(:is_svn?).and_return(true)
97
+ expect(working_dir).to receive(:url).and_return 'https://svn-server.site/svn-repo/trunk'
98
+ expect(subject.status).to eq :outdated
99
+ end
100
+
101
+ it "is insync when the working directory has been synced" do
102
+ expect(subject.path).to receive(:exist?).and_return(true)
103
+ expect(working_dir).to receive(:is_svn?).twice.and_return(true)
104
+ expect(working_dir).to receive(:url).and_return 'https://svn-server.site/svn-repo/trunk'
105
+
106
+ expect(working_dir).to receive(:update)
107
+
108
+ subject.sync
109
+
110
+ expect(subject.status).to eq :insync
111
+ end
112
+ end
113
+
114
+ describe "environment signature" do
115
+ it "returns the svn revision of the branch" do
116
+ expect(working_dir).to receive(:revision).and_return '1337'
117
+ expect(subject.signature).to eq '1337'
118
+ end
119
+ end
120
+
121
+ describe "info hash" do
122
+ let(:info_hash) { subject.info }
123
+
124
+ before(:each) do
125
+ expect(working_dir).to receive(:revision).and_return '1337'
126
+ end
127
+
128
+ it "includes name and signature" do
129
+ expect(info_hash.keys).to include :name, :signature
130
+ expect(info_hash).not_to have_value(nil)
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+ require 'r10k/errors/formatting'
3
+
4
+ describe R10K::Errors::Formatting do
5
+
6
+ describe "without a nested exception" do
7
+ let(:exc) do
8
+ ArgumentError.new("ArgumentError message").tap do |a|
9
+ a.set_backtrace(%w[/backtrace/line:1 /backtrace/line:2])
10
+ end
11
+ end
12
+
13
+ describe "and without a backtrace" do
14
+ subject do
15
+ described_class.format_exception(exc, false)
16
+ end
17
+
18
+ it "formats the exception with the message" do
19
+ expect(subject).to eq("ArgumentError message")
20
+ end
21
+ end
22
+
23
+ describe "and with a backtrace" do
24
+ subject do
25
+ described_class.format_exception(exc, true)
26
+ end
27
+
28
+ it "formats the exception with the message and backtrace" do
29
+ expect(subject).to eq([
30
+ "ArgumentError message",
31
+ "/backtrace/line:1",
32
+ "/backtrace/line:2",
33
+ ].join("\n"))
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "with a nested exception" do
39
+
40
+ let(:nestee) do
41
+ ArgumentError.new("ArgumentError message").tap do |a|
42
+ a.set_backtrace(%w[/backtrace/line:1 /backtrace/line:2])
43
+ end
44
+ end
45
+
46
+ let(:exc) do
47
+ R10K::Error.wrap(nestee, "R10K::Error message").tap do |r|
48
+ r.set_backtrace(%w[/another/backtrace/line:1 /another/backtrace/line:2])
49
+ end
50
+ end
51
+
52
+ describe "and without a backtrace" do
53
+ subject do
54
+ described_class.format_exception(exc, false)
55
+ end
56
+
57
+ it "formats the exception with the message and original message" do
58
+ expect(subject).to eq([
59
+ "R10K::Error message",
60
+ "Original exception:",
61
+ "ArgumentError message"
62
+ ].join("\n"))
63
+ end
64
+ end
65
+
66
+ describe "and with a backtrace" do
67
+ subject do
68
+ described_class.format_exception(exc, true)
69
+ end
70
+
71
+ it "formats the exception with the message, backtrace, original message, and original backtrace" do
72
+ expect(subject).to eq([
73
+ "R10K::Error message",
74
+ "/another/backtrace/line:1",
75
+ "/another/backtrace/line:2",
76
+ "Original exception:",
77
+ "ArgumentError message",
78
+ "/backtrace/line:1",
79
+ "/backtrace/line:2",
80
+ ].join("\n"))
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ require 'r10k/feature'
3
+
4
+ describe R10K::Feature do
5
+ describe "confining a feature to a library" do
6
+ it "is available if the library can be loaded" do
7
+ feature = described_class.new(:r10k, :libraries => 'r10k')
8
+ expect(feature.available?).to be_truthy
9
+ end
10
+
11
+ it "is unavailable if the library cannot be loaded" do
12
+ feature = described_class.new(:squidlibs, :libraries => 'squid/libs')
13
+ expect(feature.available?).to be_falsey
14
+ end
15
+ end
16
+
17
+ describe "confining a feature to a block" do
18
+ it "is available if the block is true" do
19
+ feature = described_class.new(:blockfeature) { true }
20
+ expect(feature.available?).to be_truthy
21
+ end
22
+
23
+ it "is unavailable if the block is false" do
24
+ feature = described_class.new(:blockfeature) { false }
25
+ expect(feature.available?).to be_falsey
26
+ end
27
+ end
28
+
29
+ describe "confining a feature to both a block and libraries" do
30
+ it "is unavailable if the block returns false and libraries are absent" do
31
+ feature = described_class.new(:nope, :libraries => 'nope/nope') { false }
32
+ expect(feature.available?).to be_falsey
33
+ end
34
+
35
+ it "is unavailable if the block returns true and libraries are absent" do
36
+ feature = described_class.new(:nope, :libraries => 'nope/nope') { true }
37
+ expect(feature.available?).to be_falsey
38
+ end
39
+
40
+ it "is unavailable if the block returns false and libraries are present" do
41
+ feature = described_class.new(:nope, :libraries => 'r10k') { false }
42
+ expect(feature.available?).to be_falsey
43
+ end
44
+
45
+ it "is available if the block returns true and libraries are present" do
46
+ feature = described_class.new(:yep, :libraries => 'r10k') { true }
47
+ expect(feature.available?).to be_truthy
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,213 @@
1
+ require 'spec_helper'
2
+ require 'r10k/forge/module_release'
3
+ require 'r10k/util/exec_env'
4
+ require 'puppet_forge'
5
+
6
+ describe R10K::Forge::ModuleRelease do
7
+ subject { described_class.new('branan-eight_hundred', '8.0.0') }
8
+
9
+ let(:forge_release_class) { PuppetForge::V3::Release }
10
+ let(:sha256_digest_class) { Digest::SHA256 }
11
+ let(:md5_digest_class) { Digest::MD5 }
12
+
13
+ let(:download_path) { instance_double('Pathname') }
14
+ let(:tarball_cache_path) { instance_double('Pathname') }
15
+ let(:tarball_cache_root) { instance_double('Pathname') }
16
+ let(:unpack_path) { instance_double('Pathname') }
17
+ let(:target_dir) { instance_double('Pathname') }
18
+ let(:tarball_cache_path) { instance_double('Pathname') }
19
+ let(:md5_file_path) { instance_double('Pathname') }
20
+ let(:sha256_file_path) { instance_double('Pathname') }
21
+
22
+ let(:file_lists) { {:valid=>['valid_ex'], :invalid=>[], :symlinks=>['symlink_ex']} }
23
+
24
+ let(:file_contents) { "skeletor's closet" }
25
+ let(:sha256_digest) { instance_double('Digest::SHA256') }
26
+ let(:sha256_of_tarball) { "sha256_hash" }
27
+ let(:md5_digest) { instance_double('Digest::MD5') }
28
+ let(:md5_of_tarball) { "md5_hash" }
29
+ let(:good_md5) { md5_of_tarball }
30
+ let(:good_sha256) { sha256_of_tarball }
31
+ let(:bad_sha256) { "bad_sha256_hash" }
32
+ let(:bad_md5) { "bad_md5_hash" }
33
+
34
+ before do
35
+ subject.download_path = download_path
36
+ subject.tarball_cache_path = tarball_cache_path
37
+ subject.tarball_cache_root = tarball_cache_root
38
+ subject.unpack_path = unpack_path
39
+ subject.md5_file_path = md5_file_path
40
+ subject.sha256_file_path = sha256_file_path
41
+ end
42
+
43
+ context "no cached tarball" do
44
+ describe '#download' do
45
+ it "downloads the module from the forge into `download_path`" do
46
+ expect(tarball_cache_path).to receive(:exist?).and_return(false)
47
+ expect(subject.forge_release).to receive(:download).with(download_path)
48
+ allow(FileUtils).to receive(:mkdir_p).with(tarball_cache_root)
49
+ expect(FileUtils).to receive(:mv).with(download_path, tarball_cache_path)
50
+ subject.download
51
+ end
52
+ end
53
+ end
54
+
55
+ context "with cached tarball" do
56
+ describe '#download' do
57
+ it "does not download a new tarball" do
58
+ expect(tarball_cache_path).to receive(:exist?).and_return(true)
59
+ expect(subject.forge_release).not_to receive(:download).with(download_path)
60
+ subject.download
61
+ end
62
+ end
63
+ end
64
+
65
+ describe '#verify' do
66
+
67
+ it "verifies using the file SHA256, if that exists" do
68
+ allow(sha256_digest_class).to receive(:file).and_return(sha256_digest)
69
+ allow(sha256_digest).to receive(:hexdigest).and_return(sha256_of_tarball)
70
+ allow(sha256_file_path).to receive(:exist?).and_return(true)
71
+ expect(subject).to receive(:verify_from_file).with(sha256_of_tarball, sha256_file_path)
72
+ subject.verify
73
+ end
74
+
75
+ it "verifies using the forge file_sha256, if no sha256 file exists" do
76
+ allow(sha256_digest_class).to receive(:file).and_return(sha256_digest)
77
+ allow(sha256_digest).to receive(:hexdigest).and_return(sha256_of_tarball)
78
+ allow(sha256_file_path).to receive(:exist?).and_return(false)
79
+ allow(subject.forge_release).to receive(:respond_to?).and_return(true)
80
+ allow(subject.forge_release).to receive(:sha256_file).and_return(sha256_of_tarball)
81
+ expect(subject).to receive(:verify_from_forge)
82
+ subject.verify
83
+ end
84
+
85
+ it "falls back to md5 verification when not in FIPS mode and no sha256 available" do
86
+ expect(R10K::Util::Platform).to receive(:fips?).and_return(false)
87
+ # failed sha256 verification
88
+ allow(sha256_digest_class).to receive(:file).and_return(sha256_digest)
89
+ allow(sha256_digest).to receive(:hexdigest).and_return(sha256_of_tarball)
90
+ allow(sha256_file_path).to receive(:exist?).and_return(false)
91
+ allow(subject.forge_release).to receive(:respond_to?).and_return(false)
92
+ allow(subject).to receive(:verify_from_forge)
93
+ # md5 verification
94
+ allow(md5_digest_class).to receive(:file).and_return(md5_digest)
95
+ allow(md5_digest).to receive(:hexdigest).and_return(md5_of_tarball)
96
+ allow(md5_file_path).to receive(:exist?).and_return(true)
97
+ expect(subject).to receive(:verify_from_file)
98
+ subject.verify
99
+ end
100
+
101
+ it "errors when in FIPS mode and no sha256 is available" do
102
+ expect(R10K::Util::Platform).to receive(:fips?).and_return(true)
103
+ allow(sha256_digest_class).to receive(:file).and_return(sha256_digest)
104
+ allow(sha256_digest).to receive(:hexdigest).and_return(sha256_of_tarball)
105
+ allow(sha256_file_path).to receive(:exist?).and_return(false)
106
+ allow(subject.forge_release).to receive(:respond_to?).and_return(false)
107
+ allow(subject).to receive(:verify_from_forge)
108
+ expect { subject.verify }.to raise_error(R10K::Error)
109
+ end
110
+ end
111
+
112
+ describe '#verify_from_file' do
113
+
114
+ it "does nothing when the checksums match" do
115
+ expect(File).to receive(:read).with(sha256_file_path).and_return(good_sha256)
116
+ expect(subject).not_to receive(:cleanup_cached_tarball_path)
117
+ subject.verify_from_file(sha256_of_tarball, sha256_file_path)
118
+ end
119
+
120
+ it "raises an error and cleans up when the checksums do not match" do
121
+ expect(File).to receive(:read).with(sha256_file_path).and_return(bad_sha256)
122
+ expect(tarball_cache_path).to receive(:delete)
123
+ expect(sha256_file_path).to receive(:delete)
124
+ expect { subject.verify_from_file(sha256_of_tarball, sha256_file_path) }.to raise_error(PuppetForge::V3::Release::ChecksumMismatch)
125
+ end
126
+ end
127
+
128
+ describe '#verify_from_forge' do
129
+ it "write the checksum to file when the checksums match" do
130
+ expect(tarball_cache_path).not_to receive(:delete)
131
+ expect(File).to receive(:write).with(sha256_file_path, good_sha256)
132
+ subject.verify_from_forge(sha256_of_tarball, good_sha256, sha256_file_path)
133
+ end
134
+
135
+ it "raises an error and cleans up when the checksums do not match" do
136
+ expect(tarball_cache_path).to receive(:delete)
137
+ expect { subject.verify_from_forge(sha256_of_tarball, bad_sha256, sha256_file_path) }
138
+ .to raise_error(PuppetForge::V3::Release::ChecksumMismatch)
139
+ end
140
+ end
141
+
142
+ describe '#unpack' do
143
+ it "unpacks the module tarball in `tarball_cache_path` into the provided target path" do
144
+ expect(PuppetForge::Unpacker).to receive(:unpack).with(tarball_cache_path.to_s, target_dir.to_s, unpack_path.to_s).\
145
+ and_return({:valid=>["extractedmodule/metadata.json"], :invalid=>[], :symlinks=>[]})
146
+ subject.unpack(target_dir)
147
+ end
148
+
149
+ it "logs a warning if symlinks are present during the unpacking process" do
150
+ logger_dbl = double(Log4r::Logger, debug1: true, debug2: true)
151
+ allow(subject).to receive(:logger).and_return(logger_dbl)
152
+ allow(PuppetForge::Unpacker).to receive(:unpack).and_return(file_lists)
153
+
154
+ expect(logger_dbl).to receive(:warn).with(/symlinks are unsupported.*#{Regexp.escape(subject.forge_release.slug)}/i)
155
+
156
+ subject.unpack(target_dir)
157
+ end
158
+ end
159
+
160
+ describe "#cleanup" do
161
+ it "cleans up the unpack paths" do
162
+ expect(subject).to receive(:cleanup_unpack_path)
163
+ expect(subject).to receive(:cleanup_download_path)
164
+ subject.cleanup
165
+ end
166
+ end
167
+
168
+ describe "#cleanup_unpack_path" do
169
+ it "ignores the unpack_path if the parent doesn't exist" do
170
+ parent = instance_double('Pathname')
171
+ expect(parent).to receive(:exist?).and_return false
172
+ expect(parent).to_not receive(:rmtree)
173
+ expect(unpack_path).to receive(:parent).and_return(parent)
174
+ subject.cleanup_unpack_path
175
+ end
176
+
177
+ it "removes the containing directory of unpack_path if it exists" do
178
+ parent = instance_double('Pathname')
179
+ expect(parent).to receive(:rmtree)
180
+ expect(parent).to receive(:exist?).and_return true
181
+ expect(unpack_path).to receive(:parent).and_return(parent).exactly(2).times
182
+ subject.cleanup_unpack_path
183
+ end
184
+ end
185
+
186
+ describe "#cleanup_download_path" do
187
+ it "ignores the download_path if the parent doesn't exist" do
188
+ parent = instance_double('Pathname')
189
+ expect(parent).to receive(:exist?).and_return false
190
+ expect(parent).to_not receive(:rmtree)
191
+ expect(download_path).to receive(:parent).and_return(parent)
192
+ subject.cleanup_download_path
193
+ end
194
+
195
+ it "removes the containing directory of download_path if it exists" do
196
+ parent = instance_double('Pathname')
197
+ expect(parent).to receive(:rmtree)
198
+ expect(parent).to receive(:exist?).and_return true
199
+ expect(download_path).to receive(:parent).and_return(parent).exactly(2).times
200
+ subject.cleanup_download_path
201
+ end
202
+ end
203
+
204
+ describe '#install' do
205
+ it "performs all steps needed to install the module" do
206
+ expect(subject).to receive(:download)
207
+ expect(subject).to receive(:verify)
208
+ expect(subject).to receive(:unpack).with(target_dir)
209
+ expect(subject).to receive(:cleanup)
210
+ subject.install(target_dir)
211
+ end
212
+ end
213
+ end