ceedling 1.2.1 → 1.2.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 (276) hide show
  1. checksums.yaml +4 -4
  2. data/GIT_COMMIT_SHA +1 -1
  3. data/README.md +11 -9
  4. data/Rakefile +2 -1
  5. data/assets/features/ceedling +1 -1
  6. data/assets/fixtures/test_source_file_duplicate_basenames/test_calc_typo.c +14 -0
  7. data/assets/fixtures/tests_with_duplicate_test_names/test_foo.c +21 -0
  8. data/bin/actionator.rb +6 -12
  9. data/bin/app_cfg.rb +14 -1
  10. data/bin/ceedling +13 -3
  11. data/bin/cli.rb +25 -6
  12. data/bin/cli_handler.rb +113 -73
  13. data/bin/cli_helper.rb +51 -78
  14. data/bin/installation_selector.rb +81 -0
  15. data/bin/launchinator.rb +69 -0
  16. data/bin/mixin_resolvinator.rb +26 -36
  17. data/bin/objects.yml +13 -0
  18. data/bin/path_validator.rb +25 -29
  19. data/bin/versionator.rb +47 -48
  20. data/ceedling.gemspec +19 -15
  21. data/docs/BreakingChanges.md +70 -1
  22. data/docs/Changelog.md +74 -3
  23. data/docs/KnownIssues.md +90 -4
  24. data/docs/ReleaseNotes.md +13 -0
  25. data/lib/ceedling/build_log_writer.rb +33 -0
  26. data/lib/ceedling/config/build_root_policy.rb +70 -0
  27. data/lib/ceedling/config/configurator.rb +14 -16
  28. data/lib/ceedling/config/configurator_builder.rb +58 -28
  29. data/lib/ceedling/config/configurator_paths_validator.rb +179 -0
  30. data/lib/ceedling/config/configurator_plugins.rb +1 -1
  31. data/lib/ceedling/config/configurator_setup.rb +15 -28
  32. data/lib/ceedling/config/configurator_validator.rb +1 -110
  33. data/lib/ceedling/defaults.rb +4 -4
  34. data/lib/ceedling/dependencies/README.md +18 -16
  35. data/lib/ceedling/dependencies/dependency_cache_store.rb +20 -3
  36. data/lib/ceedling/dependencies/dependency_hasher.rb +35 -1
  37. data/lib/ceedling/filename_extension.rb +7 -1
  38. data/lib/ceedling/filesystem/FILE_TREE.md +253 -0
  39. data/lib/ceedling/filesystem/PATH_HANDLING.md +304 -0
  40. data/lib/ceedling/filesystem/README.md +41 -0
  41. data/lib/ceedling/filesystem/build_subpath.rb +102 -0
  42. data/lib/ceedling/filesystem/destination_collision.rb +25 -0
  43. data/lib/ceedling/{file_finder.rb → filesystem/file_finder.rb} +159 -104
  44. data/lib/ceedling/{file_finder_helper.rb → filesystem/file_finder_helper.rb} +36 -31
  45. data/lib/ceedling/filesystem/file_path_collection_utils.rb +183 -0
  46. data/lib/ceedling/{file_path_utils.rb → filesystem/file_path_utils.rb} +108 -97
  47. data/lib/ceedling/{file_system_wrapper.rb → filesystem/file_system_wrapper.rb} +6 -5
  48. data/lib/ceedling/filesystem/file_tree.rb +241 -0
  49. data/lib/ceedling/{file_wrapper.rb → filesystem/file_wrapper.rb} +45 -38
  50. data/lib/ceedling/filesystem/path_exclusions.rb +30 -0
  51. data/lib/ceedling/{path_matcher.rb → filesystem/path_matcher.rb} +27 -23
  52. data/lib/ceedling/{path_mirror.rb → filesystem/path_mirror.rb} +19 -18
  53. data/lib/ceedling/filesystem/path_spellings.rb +55 -0
  54. data/lib/ceedling/filesystem/project_paths.rb +184 -0
  55. data/lib/ceedling/filesystem/working_dir.rb +40 -0
  56. data/lib/ceedling/generators/generator.rb +5 -6
  57. data/lib/ceedling/generators/generator_partials.rb +1 -1
  58. data/lib/ceedling/generators/generator_test_results_backtrace.rb +7 -7
  59. data/lib/ceedling/handoff.rb +121 -0
  60. data/lib/ceedling/includes/include_factory.rb +3 -3
  61. data/lib/ceedling/includes/include_pathinator.rb +67 -10
  62. data/lib/ceedling/includes/includes.rb +1 -1
  63. data/lib/ceedling/installation.rb +92 -0
  64. data/lib/ceedling/library_resolver.rb +99 -0
  65. data/lib/ceedling/objects.yml +23 -2
  66. data/lib/ceedling/partials/partializer.rb +4 -4
  67. data/lib/ceedling/partials/partializer_config.rb +3 -1
  68. data/lib/ceedling/plugins/report_log_writer_plugin.rb +3 -5
  69. data/lib/ceedling/preprocess/preprocessinator_file_assembler.rb +1 -1
  70. data/lib/ceedling/preprocess/preprocessinator_includes_handler.rb +1 -1
  71. data/lib/ceedling/preprocess/preprocessinator_line_marker_includes_extractor.rb +1 -1
  72. data/lib/ceedling/rake_app/rakefile_component_resolver.rb +10 -17
  73. data/lib/ceedling/rakefile.rb +15 -1
  74. data/lib/ceedling/rakefiles/base/tasks_base.rake +1 -1
  75. data/lib/ceedling/rakefiles/release/rules_release.rake +4 -7
  76. data/lib/ceedling/release_invoker/release_build_executor.rb +33 -44
  77. data/lib/ceedling/release_invoker/release_build_planner.rb +14 -6
  78. data/lib/ceedling/reportinator.rb +3 -4
  79. data/lib/ceedling/setupinator.rb +94 -90
  80. data/lib/ceedling/test_context_extractor.rb +5 -1
  81. data/lib/ceedling/test_invoker/PIPELINE.md +9 -7
  82. data/lib/ceedling/test_invoker/mock_locator.rb +60 -2
  83. data/lib/ceedling/test_invoker/partials_manager.rb +12 -0
  84. data/lib/ceedling/test_invoker/standin_headerinator.rb +22 -13
  85. data/lib/ceedling/test_invoker/test_build_executor.rb +24 -40
  86. data/lib/ceedling/test_invoker/test_build_planner.rb +37 -18
  87. data/lib/ceedling/test_invoker/test_build_setup.rb +17 -12
  88. data/lib/ceedling/test_invoker/test_build_validations.rb +16 -31
  89. data/lib/ceedling/test_invoker/test_file_preprocessinator.rb +1 -1
  90. data/lib/ceedling/test_invoker/test_invoker.rb +6 -1
  91. data/lib/ceedling/test_invoker/test_pipeline_helpers.rb +1 -1
  92. data/lib/ceedling/test_invoker/test_source_file_directive_resolver.rb +40 -20
  93. data/lib/ceedling/tool_executor.rb +9 -3
  94. data/lib/ceedling/yaml_wrapper.rb +3 -2
  95. data/lib/version.rb +1 -1
  96. data/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  97. data/plugins/bullseye/lib/bullseye.rb +9 -7
  98. data/plugins/cppcheck/config/defaults_cppcheck.rb +1 -1
  99. data/plugins/dependencies/config/defaults.yml +6 -6
  100. data/plugins/dependencies/dependencies.rake +4 -1
  101. data/plugins/dependencies/lib/dependencies.rb +18 -8
  102. data/plugins/dependencies/lib/dependency_spec.rb +17 -5
  103. data/plugins/fff/lib/fff.rb +45 -39
  104. data/plugins/fff/spec/fff_cmock_wrapper_spec.rb +128 -0
  105. data/plugins/gcov/config/defaults_gcov.rb +1 -1
  106. data/plugins/gcov/lib/console_reportinator.rb +4 -18
  107. data/plugins/gcov/lib/gcov.rb +9 -2
  108. data/plugins/gcov/lib/gcovr_reportinator.rb +8 -40
  109. data/plugins/gcov/lib/gcovr_thresholds.rb +74 -0
  110. data/plugins/gcov/lib/reportgenerator_reportinator.rb +1 -1
  111. data/plugins/module_generator/lib/module_generator.rb +3 -3
  112. data/plugins/report_tests_teamcity_stdout/lib/report_tests_teamcity_stdout.rb +53 -80
  113. data/plugins/sanitize/lib/sanitize_records.rb +3 -6
  114. data/plugins/valgrind/lib/valgrind.rb +14 -7
  115. data/site-local/configuration/reference/cmock.html +2 -1
  116. data/site-local/configuration/reference/files.html +9 -3
  117. data/site-local/configuration/reference/libraries.html +21 -3
  118. data/site-local/configuration/reference/paths.html +29 -6
  119. data/site-local/configuration/reference/project.html +17 -7
  120. data/site-local/configuration/reference/release-build.html +2 -0
  121. data/site-local/configuration/reference/tools.html +9 -0
  122. data/site-local/configuration/which-ceedling.html +377 -17
  123. data/site-local/development/releases.html +5 -1
  124. data/site-local/development/workflow.html +48 -43
  125. data/site-local/getting-started/builds.html +2 -0
  126. data/site-local/getting-started/command-line.html +56 -4
  127. data/site-local/plugins/dependencies.html +6 -3
  128. data/site-local/plugins/fff.html +42 -11
  129. data/site-local/plugins/gcov/gcovr.html +15 -12
  130. data/site-local/plugins/gcov/setup.html +2 -1
  131. data/site-local/plugins/report-tests-raw-output-log.html +3 -1
  132. data/site-local/plugins/report-tests-teamcity-stdout.html +6 -3
  133. data/site-local/plugins/sanitize.html +7 -6
  134. data/site-local/plugins/valgrind.html +8 -7
  135. data/site-local/project/upgrade.html +3 -0
  136. data/site-local/reference/command-line.html +9 -2
  137. data/site-local/sitemap.xml.gz +0 -0
  138. data/site-local/snapshot/plugins/bullseye/config/defaults_bullseye.rb +1 -1
  139. data/site-local/snapshot/plugins/gcov/config/defaults_gcov.rb +1 -1
  140. data/site-local/testing-guide/conventions.html +53 -0
  141. data/spec/integration/actionator_file_operations_spec.rb +91 -1
  142. data/spec/integration/compile_commands_json_db_spec.rb +1 -1
  143. data/spec/integration/configurator_validation_spec.rb +1 -1
  144. data/spec/integration/dependencies/dependency_tracker_cache_hardening_spec.rb +26 -0
  145. data/spec/integration/dependencies/dependency_tracker_core_spec.rb +22 -0
  146. data/spec/integration/launcher_handoff_spec.rb +297 -0
  147. data/spec/integration/mixin_loading_spec.rb +1 -1
  148. data/spec/integration/module_generator_spec.rb +3 -3
  149. data/spec/integration/nested_test_artifacts_spec.rb +99 -0
  150. data/spec/integration/partials_module_resolution_spec.rb +7 -4
  151. data/spec/integration/path_intake_scenarios_spec.rb +101 -0
  152. data/spec/integration/path_scenarios_spec.rb +322 -0
  153. data/spec/integration/quote_include_isolator_spec.rb +1 -1
  154. data/spec/integration/report_build_warnings_log_spec.rb +1 -1
  155. data/spec/integration/report_tests_log_factory_spec.rb +1 -1
  156. data/spec/integration/test_executable_manifest_spec.rb +1 -1
  157. data/spec/integration/test_includes_extractinator_spec.rb +2 -1
  158. data/spec/integration/test_naming_spec.rb +198 -0
  159. data/spec/integration/test_source_file_checks_spec.rb +166 -0
  160. data/spec/integration/tool_validator_spec.rb +1 -1
  161. data/spec/integration/upgrade_docs_spec.rb +84 -0
  162. data/spec/integration/vendor_copy_transient_io_retry_spec.rb +74 -5
  163. data/spec/support/file_tree_helper.rb +88 -0
  164. data/spec/support/integration/configurator_integration_helper.rb +6 -6
  165. data/spec/support/integration/dependency_tracker_integration_helper.rb +1 -1
  166. data/spec/support/integration/partials_generation_integration_helper.rb +2 -2
  167. data/spec/support/integration/path_scenario_harness.rb +173 -0
  168. data/spec/support/integration/spec_integration_helper.rb +1 -1
  169. data/spec/support/integration/test_includes_harness.rb +13 -2
  170. data/spec/support/spec_helper.rb +2 -0
  171. data/spec/support/system/spec_system_helper.rb +7 -6
  172. data/spec/support/system/system_context.rb +21 -3
  173. data/spec/support/working_dir_tracking.rb +49 -0
  174. data/spec/system/build_output_mirroring_spec.rb +2 -2
  175. data/spec/system/conditional_mock_includes_spec.rb +1 -1
  176. data/spec/system/delta_builds_spec.rb +137 -11
  177. data/spec/system/gcov_deployment_spec.rb +1 -0
  178. data/spec/system/header_include_path_validation_spec.rb +4 -4
  179. data/spec/system/launcher_handoff_spec.rb +82 -0
  180. data/spec/system/mock_include_folders_spec.rb +91 -0
  181. data/spec/system/parent_directory_reference_spec.rb +5 -3
  182. data/spec/system/path_handling_probes_spec.rb +192 -0
  183. data/spec/system/preprocessing_parameterized_tests_spec.rb +1 -1
  184. data/spec/system/rake_release_task_path_disambiguation_spec.rb +6 -6
  185. data/spec/system/rake_test_task_path_disambiguation_spec.rb +85 -0
  186. data/spec/system/special_path_characters_spec.rb +86 -0
  187. data/spec/system/support/common_test_cases.rb +23 -21
  188. data/spec/system/support/gcov_common_test_cases.rb +37 -9
  189. data/spec/system/support/sanitize_common_test_cases.rb +2 -2
  190. data/spec/system/support/valgrind_common_test_cases.rb +12 -12
  191. data/spec/system/test_pipeline_stop_points_spec.rb +4 -4
  192. data/spec/system/test_runner_system_include_spec.rb +1 -1
  193. data/spec/system/test_source_file_directive_spec.rb +34 -5
  194. data/spec/units/bin/actionator_spec.rb +14 -17
  195. data/spec/units/bin/app_cfg_spec.rb +37 -0
  196. data/spec/units/bin/cli_handler_spec.rb +282 -6
  197. data/spec/units/bin/cli_helper_spec.rb +116 -45
  198. data/spec/units/bin/installation_selector_spec.rb +114 -0
  199. data/spec/units/bin/launchinator_spec.rb +171 -0
  200. data/spec/units/bin/path_validator_spec.rb +10 -0
  201. data/spec/units/bin/versionator_spec.rb +38 -6
  202. data/spec/units/build_log_writer_spec.rb +57 -0
  203. data/spec/units/config/build_root_policy_spec.rb +61 -0
  204. data/spec/units/config/configurator_builder_spec.rb +37 -6
  205. data/spec/units/config/configurator_paths_validator_spec.rb +292 -0
  206. data/spec/units/config/configurator_setup_spec.rb +9 -65
  207. data/spec/units/config/configurator_spec.rb +27 -5
  208. data/spec/units/config/configurator_validator_spec.rb +1 -172
  209. data/spec/units/default_tools_quoting_spec.rb +83 -0
  210. data/spec/units/dependencies/dependency_cache_store_spec.rb +33 -2
  211. data/spec/units/dependencies/dependency_debug_tree_spec.rb +1 -1
  212. data/spec/units/dependencies/dependency_hasher_spec.rb +42 -1
  213. data/spec/units/dependencies/dependency_path_normalizer_spec.rb +1 -1
  214. data/spec/units/dependencies/dependency_tracker_spec.rb +3 -1
  215. data/spec/units/filename_extension_spec.rb +11 -0
  216. data/spec/units/filesystem/build_subpath_spec.rb +122 -0
  217. data/spec/units/filesystem/destination_collision_spec.rb +30 -0
  218. data/spec/units/{file_finder_helper_spec.rb → filesystem/file_finder_helper_spec.rb} +46 -1
  219. data/spec/units/{file_finder_spec.rb → filesystem/file_finder_spec.rb} +188 -22
  220. data/spec/units/{file_path_collection_utils_spec.rb → filesystem/file_path_collection_utils_spec.rb} +181 -1
  221. data/spec/units/{file_path_utils_spec.rb → filesystem/file_path_utils_spec.rb} +204 -87
  222. data/spec/units/filesystem/file_system_wrapper_spec.rb +33 -0
  223. data/spec/units/filesystem/file_tree_spec.rb +511 -0
  224. data/spec/units/filesystem/file_tree_windows_spec.rb +78 -0
  225. data/spec/units/{file_wrapper_spec.rb → filesystem/file_wrapper_spec.rb} +95 -12
  226. data/spec/units/{path_matcher_spec.rb → filesystem/path_matcher_spec.rb} +12 -1
  227. data/spec/units/{path_mirror_spec.rb → filesystem/path_mirror_spec.rb} +32 -4
  228. data/spec/units/filesystem/project_paths_spec.rb +147 -0
  229. data/spec/units/filesystem/working_dir_spec.rb +71 -0
  230. data/spec/units/generators/generator_spec.rb +12 -6
  231. data/spec/units/generators/generator_test_results_backtrace_spec.rb +50 -46
  232. data/spec/units/generators/generator_test_results_spec.rb +1 -1
  233. data/spec/units/handoff_spec.rb +205 -0
  234. data/spec/units/includes/include_factory_spec.rb +3 -3
  235. data/spec/units/includes/include_pathinator_spec.rb +46 -0
  236. data/spec/units/installation_spec.rb +228 -0
  237. data/spec/units/library_resolver_spec.rb +157 -0
  238. data/spec/units/mock_locator_spec.rb +76 -1
  239. data/spec/units/partials/partializer_config_spec.rb +7 -0
  240. data/spec/units/partials/partializer_spec.rb +1 -0
  241. data/spec/units/partials_manager_spec.rb +17 -0
  242. data/spec/units/plugins/bullseye_spec.rb +15 -2
  243. data/spec/units/plugins/console_reportinator_spec.rb +18 -20
  244. data/spec/units/plugins/dependencies_spec.rb +33 -7
  245. data/spec/units/plugins/dependency_spec_spec.rb +17 -0
  246. data/spec/units/plugins/gcov_spec.rb +28 -3
  247. data/spec/units/plugins/gcovr_reportinator_spec.rb +19 -47
  248. data/spec/units/plugins/gcovr_thresholds_spec.rb +95 -0
  249. data/spec/units/plugins/module_generator_spec.rb +5 -5
  250. data/spec/units/plugins/report_build_warnings_log_spec.rb +3 -3
  251. data/spec/units/plugins/report_log_writer_plugin_spec.rb +10 -1
  252. data/spec/units/plugins/report_tests_raw_output_log_spec.rb +13 -2
  253. data/spec/units/plugins/report_tests_teamcity_stdout_spec.rb +77 -3
  254. data/spec/units/plugins/reportgenerator_reportinator_spec.rb +1 -1
  255. data/spec/units/plugins/sanitize_records_spec.rb +3 -1
  256. data/spec/units/plugins/sanitize_spec.rb +1 -1
  257. data/spec/units/plugins/valgrind_spec.rb +23 -8
  258. data/spec/units/preprocess/preprocessinator_comment_stripper_spec.rb +1 -1
  259. data/spec/units/rake_app/rakefile_component_resolver_spec.rb +21 -0
  260. data/spec/units/release_build_executor_spec.rb +53 -14
  261. data/spec/units/release_build_planner_spec.rb +15 -3
  262. data/spec/units/reportinator_spec.rb +5 -5
  263. data/spec/units/standin_headerinator_spec.rb +31 -1
  264. data/spec/units/test_build_executor_spec.rb +65 -3
  265. data/spec/units/test_build_planner_spec.rb +104 -2
  266. data/spec/units/test_build_setup_spec.rb +96 -12
  267. data/spec/units/test_context_extractor_spec.rb +25 -0
  268. data/spec/units/test_file_preprocessinator_spec.rb +17 -1
  269. data/spec/units/test_includes_extractinator_spec.rb +5 -1
  270. data/spec/units/test_invoker/objects_wiring_spec.rb +6 -3
  271. data/spec/units/test_invoker_spec.rb +14 -1
  272. data/spec/units/test_source_file_directive_resolver_spec.rb +38 -7
  273. data/spec/units/tool_executor_spec.rb +26 -0
  274. data/spec/units/yaml_wrapper_spec.rb +11 -0
  275. metadata +109 -25
  276. data/lib/ceedling/file_path_collection_utils.rb +0 -164
data/bin/cli_handler.rb CHANGED
@@ -10,12 +10,13 @@ require 'mixins' # Built-in Mixins
10
10
  require 'ceedling/constants' # From Ceedling application
11
11
  require 'ceedling/rake_app/rake_task_registry' # From Ceedling application
12
12
  require 'versionator' # Outside DIY context
13
+ require 'ceedling/installation'
13
14
 
14
15
  class CliHandler
15
16
 
16
17
  DOCS_SUBDIR = 'docs'
17
18
 
18
- constructor :composinator, :projectinator, :cli_helper, :path_validator, :rake_task_registry, :actionator, :loginator
19
+ constructor :composinator, :projectinator, :cli_helper, :path_validator, :rake_task_registry, :actionator, :launchinator, :loginator
19
20
 
20
21
  # Override to prevent exception handling from walking & stringifying the object variables.
21
22
  # Object variables are lengthy and produce a flood of output.
@@ -44,6 +45,23 @@ class CliHandler
44
45
  verbosity = @helper.set_verbosity( options[:verbosity] )
45
46
  @helper.set_ruby_replacement( options[:ruby_replacement] )
46
47
 
48
+ # Help comes from the installation the project (if any) selects, so hand off before printing any
49
+ options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
50
+ config, rakefile_path = nil, nil
51
+ if @projectinator.config_available?( filepath:options[:project], env:env )
52
+ begin
53
+ # Silent Ceedling loading unless debug verbosity
54
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:options, silent:!(verbosity == Verbosity::DEBUG) )
55
+ rescue StandardError
56
+ # Help for one command needs no project, so a project that fails to load does not block it
57
+ raise if command.nil?
58
+
59
+ @launchinator.launch( env:env, app_cfg:app_cfg, config:{} )
60
+ end
61
+ else
62
+ @launchinator.launch( env:env, app_cfg:app_cfg, config:{} )
63
+ end
64
+
47
65
  # If help requested for a command, show it and skip listing build tasks
48
66
  if !command.nil?
49
67
  # Block handler
@@ -55,16 +73,8 @@ class CliHandler
55
73
  yield( command ) if block_given?
56
74
 
57
75
  # If project configuration is available, also display Rake tasks
58
- options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
59
- if @projectinator.config_available?( filepath:options[:project], env:env )
60
- list_rake_tasks(
61
- env:env,
62
- app_cfg: app_cfg,
63
- filepath: options[:project],
64
- mixins: options[:mixin],
65
- # Silent Ceedling loading unless debug verbosity
66
- silent: !(verbosity == Verbosity::DEBUG)
67
- )
76
+ if !config.nil?
77
+ list_rake_tasks( app_cfg:app_cfg, config:config, rakefile_path:rakefile_path )
68
78
  else
69
79
  # If no project configuration is available then note why we aren't displaying more
70
80
  msg = "Run help commands in a directory with a project file to list additional options\n\n"
@@ -81,13 +91,18 @@ class CliHandler
81
91
  def rake_help(env:, app_cfg:)
82
92
  @helper.set_verbosity( Verbosity::ERRORS )
83
93
 
84
- list_rake_tasks( env:env, app_cfg:app_cfg )
94
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:{:project => nil, :mixin => []} )
95
+
96
+ list_rake_tasks( app_cfg:app_cfg, config:config, rakefile_path:rakefile_path )
85
97
  end
86
98
 
87
99
 
88
100
  def new_project(env, app_cfg, ceedling_tag, options, dest)
89
101
  @helper.set_verbosity( options[:verbosity] )
90
102
 
103
+ # The selected installation creates the project with its own code and contents
104
+ @launchinator.launch( env:env, app_cfg:app_cfg )
105
+
91
106
  dest = @path_validator.standardize_paths( dest ).first
92
107
 
93
108
  # If destination is nil, assume it's the working directory
@@ -101,9 +116,6 @@ class CliHandler
101
116
  raise msg
102
117
  end unless options[:force]
103
118
 
104
- # Update app_cfg paths (ignore return values)
105
- @helper.which_ceedling?( env:env, app_cfg:app_cfg )
106
-
107
119
  # Source paths for project tasks resolve in relation to this path
108
120
  @actions.source_root = app_cfg[:ceedling_root_path]
109
121
 
@@ -143,18 +155,21 @@ class CliHandler
143
155
 
144
156
  path, options[:project] = @path_validator.standardize_paths( path, options[:project] )
145
157
 
158
+ # The source is the Ceedling running or WHICH_CEEDLING. A detected vendor/ceedling/ is
159
+ # likely the very copy being replaced. A source that is that copy is refused before any
160
+ # hand-off, since an older copy would delete itself.
161
+ source = @launchinator.resolve( env:env, app_cfg:app_cfg, detect_vendor:false )
162
+ if source == Installation.new( File.join( path, 'vendor', 'ceedling' ) )
163
+ raise CeedlingException.new( "Cannot upgrade #{source.root}/ from itself. Run `upgrade` with the Ceedling to upgrade to, or set WHICH_CEEDLING." )
164
+ end
165
+ @launchinator.proceed( target:source, app_cfg:app_cfg )
166
+
146
167
  # Check for existing project
147
168
  if !@helper.project_exists?( path, :&, options[:project], 'vendor/ceedling/lib/version.rb' )
148
169
  msg = "Could not find an existing project at #{path}/."
149
170
  raise msg
150
171
  end
151
172
 
152
- which, _ = @helper.which_ceedling?( env:env, app_cfg:app_cfg )
153
- if (which == :gem)
154
- msg = "Project configuration specifies the Ceedling gem, not vendored Ceedling"
155
- @loginator.console( msg, LogLabels::NOTICE )
156
- end
157
-
158
173
  # Source paths for project tasks resolve in relation to this path
159
174
  @actions.source_root = app_cfg[:ceedling_root_path]
160
175
 
@@ -163,12 +178,11 @@ class CliHandler
163
178
  @actions.remove_directory( vendor_path )
164
179
  @helper.vendor_tools( app_cfg[:ceedling_root_path], path )
165
180
 
166
- # Recreate documentation if we find docs/ subdirectory
167
- docs_path = File.join( path, 'docs' )
168
- founds_docs = @helper.project_exists?( path, :&, File.join( 'docs', 'CeedlingPacket.md' ) )
169
- if founds_docs
170
- @actions.remove_directory( docs_path )
171
- @helper.copy_docs( app_cfg[:ceedling_root_path], File.join( path, DOCS_SUBDIR ) )
181
+ # Refresh documentation an export wrote, leaving the project's own files in docs/
182
+ docs_path = File.join( path, DOCS_SUBDIR )
183
+ if @helper.exported_docs?( docs_path )
184
+ @helper.remove_exported_docs( docs_path, keep_bundle: !@helper.docs_bundle?( app_cfg[:ceedling_root_path] ) )
185
+ @helper.copy_docs( app_cfg[:ceedling_root_path], docs_path )
172
186
  end
173
187
 
174
188
  @loginator.console( "\nUpgraded project at #{path}/\n", LogLabels::TITLE )
@@ -182,10 +196,9 @@ class CliHandler
182
196
  @helper.set_verbosity( _verbosity, override: false )
183
197
  @helper.set_ruby_replacement( options[:ruby_replacement] )
184
198
 
185
- options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
186
199
  options[:logfile] = @path_validator.standardize_paths( options[:logfile] ).first
187
200
 
188
- _, config = @composinator.loadinate( builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS, filepath:options[:project], mixins:options[:mixin], env:env )
201
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:options )
189
202
 
190
203
  @cli_helper.log_project_name( config )
191
204
 
@@ -245,8 +258,6 @@ class CliHandler
245
258
  app_cfg.set_test_build_tasks( @helper.test_task?( tasks: requested ) )
246
259
  app_cfg.set_release_build_tasks( @helper.release_task?( tasks: requested ) )
247
260
 
248
- _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
249
-
250
261
  # Log Ceedling Application version information
251
262
  _version = Versionator.new(
252
263
  app_cfg[:ceedling_root_path],
@@ -272,7 +283,7 @@ class CliHandler
272
283
 
273
284
  @helper.load_ceedling(
274
285
  config: config,
275
- rakefile_path: path,
286
+ rakefile_path: rakefile_path,
276
287
  default_tasks: default_tasks
277
288
  )
278
289
 
@@ -289,9 +300,9 @@ class CliHandler
289
300
  @helper.set_ruby_replacement( options[:ruby_replacement] )
290
301
 
291
302
  filepath = @path_validator.standardize_paths( filepath ).first
292
- options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
293
303
 
294
- _, config = @composinator.loadinate( builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS, filepath:options[:project], mixins:options[:mixin], env:env )
304
+ # Even without --app, the selected installation merges the configuration by its own rules
305
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:options )
295
306
 
296
307
  # A nil filepath means --stdout was set -- the YAML itself is the only thing
297
308
  # that may reach stdout in that case, for a consuming tool to parse cleanly,
@@ -310,11 +321,9 @@ class CliHandler
310
321
  app_cfg.set_project_config( config )
311
322
  app_cfg.set_logging_path( @helper.process_logging_path( config ) )
312
323
 
313
- _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
314
-
315
324
  config = @helper.load_ceedling(
316
325
  config: config,
317
- rakefile_path: path,
326
+ rakefile_path: rakefile_path,
318
327
  default_tasks: default_tasks
319
328
  )
320
329
  else
@@ -333,9 +342,7 @@ class CliHandler
333
342
  @helper.set_verbosity( options[:verbosity] )
334
343
  @helper.set_ruby_replacement( options[:ruby_replacement] )
335
344
 
336
- options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
337
-
338
- _, config = @composinator.loadinate( builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS, filepath:options[:project], mixins:options[:mixin], env:env )
345
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:options )
339
346
 
340
347
  @cli_helper.log_project_name( config )
341
348
 
@@ -346,12 +353,10 @@ class CliHandler
346
353
  app_cfg.set_logging_path( @helper.process_logging_path( config ) )
347
354
  app_cfg.set_log_filepath( '' )
348
355
 
349
- _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
350
-
351
356
  begin
352
357
  @helper.load_ceedling(
353
358
  config: config,
354
- rakefile_path: path,
359
+ rakefile_path: rakefile_path,
355
360
  default_tasks: default_tasks
356
361
  )
357
362
  ensure
@@ -364,9 +369,7 @@ class CliHandler
364
369
  @helper.set_verbosity( options[:verbosity] )
365
370
  @helper.set_ruby_replacement( options[:ruby_replacement] )
366
371
 
367
- options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
368
-
369
- _, config = @composinator.loadinate( builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS, filepath:options[:project], mixins:options[:mixin], env:env )
372
+ config, rakefile_path = load_project_and_launch( env:env, app_cfg:app_cfg, options:options )
370
373
 
371
374
  @cli_helper.console_project_name( config )
372
375
 
@@ -374,11 +377,9 @@ class CliHandler
374
377
  app_cfg.set_project_config( config )
375
378
  app_cfg.set_logging_path( @helper.process_logging_path( config ) )
376
379
 
377
- _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
378
-
379
380
  config = @helper.load_ceedling(
380
381
  config: config,
381
- rakefile_path: path
382
+ rakefile_path: rakefile_path
382
383
  )
383
384
 
384
385
  env_list = []
@@ -417,8 +418,8 @@ class CliHandler
417
418
  def list_examples(env, app_cfg, options)
418
419
  @helper.set_verbosity( options[:verbosity] )
419
420
 
420
- # Process which_ceedling for app_cfg modifications but ignore return values
421
- @helper.which_ceedling?( env:env, app_cfg:app_cfg )
421
+ # The selected installation lists its own examples
422
+ @launchinator.launch( env:env, app_cfg:app_cfg )
422
423
 
423
424
  examples = @helper.lookup_example_projects( app_cfg[:ceedling_examples_path] )
424
425
 
@@ -443,10 +444,10 @@ class CliHandler
443
444
  def create_example(env, app_cfg, options, name, dest)
444
445
  @helper.set_verbosity( options[:verbosity] )
445
446
 
446
- dest = @path_validator.standardize_paths( dest ).first
447
+ # The selected installation creates the example with its own code and contents
448
+ @launchinator.launch( env:env, app_cfg:app_cfg )
447
449
 
448
- # Process which_ceedling for app_cfg modifications but ignore return values
449
- @helper.which_ceedling?( env:env, app_cfg:app_cfg )
450
+ dest = @path_validator.standardize_paths( dest ).first
450
451
 
451
452
  examples = @helper.lookup_example_projects( app_cfg[:ceedling_examples_path] )
452
453
 
@@ -491,7 +492,19 @@ class CliHandler
491
492
  end
492
493
 
493
494
 
494
- def docs(app_cfg, dest)
495
+ def docs(env, app_cfg, dest)
496
+ # The selected installation exports its own documentation, if it has any to export
497
+ target = @launchinator.resolve( env:env, app_cfg:app_cfg )
498
+ launcher = Installation.new( app_cfg[:launcher_root_path] )
499
+ if target == launcher or @helper.docs_bundle?( target.root )
500
+ @launchinator.proceed( target:target, app_cfg:app_cfg )
501
+ else
502
+ app_cfg.set_paths( launcher.root )
503
+ msg = "#{target.describe()} holds no documentation bundle to export. " +
504
+ "Exporting the documentation of #{launcher.describe( 'Ceedling launcher' )} instead."
505
+ @loginator.console( msg, LogLabels::NOTICE )
506
+ end
507
+
495
508
  # File operations require an anchored source root
496
509
  @actions.source_root = app_cfg[:ceedling_root_path]
497
510
 
@@ -503,16 +516,17 @@ class CliHandler
503
516
  end
504
517
 
505
518
 
506
- def version(env, app_cfg)
519
+ def version(env, app_cfg, options={})
507
520
  # Versionator is not needed to persist. So, it's not built in the DIY collection.
508
521
 
509
- @helper.set_verbosity( Verbosity::ERRORS )
522
+ @helper.set_verbosity( options[:verbosity] || Verbosity::ERRORS )
510
523
 
511
524
  # Ceedling bootloader
512
- launcher = Versionator.new( app_cfg[:ceedling_root_path] )
525
+ launcher = Versionator.new( app_cfg[:launcher_root_path] )
513
526
 
514
- # This call updates Ceedling paths in app_cfg if which Ceedling has been modified
515
- @helper.which_ceedling?( env:env, app_cfg:app_cfg )
527
+ # This call updates Ceedling paths in app_cfg if the project or environment selects another Ceedling
528
+ config = version_project_config( env, options )
529
+ @launchinator.resolve( env:env, app_cfg:app_cfg, config:config )
516
530
 
517
531
  # Ceedling application
518
532
  application = @helper.manufacture_app_version( app_cfg )
@@ -521,7 +535,7 @@ class CliHandler
521
535
  ceedling = nil
522
536
 
523
537
  # A simple Ceedling version block because launcher and application are the same
524
- if launcher.ceedling_install_path == application.ceedling_install_path
538
+ if Installation.new( launcher.ceedling_install_path ) == Installation.new( application.ceedling_install_path )
525
539
  ceedling = <<~CEEDLING
526
540
  Ceedling => #{application.ceedling_build}
527
541
  ----------------------
@@ -566,6 +580,25 @@ class CliHandler
566
580
 
567
581
  private
568
582
 
583
+ # The project configuration `version` resolves which Ceedling from. A --project or
584
+ # --mixin the user names must load. The default project file is read only when it
585
+ # loads cleanly, so `version` still answers for a broken or absent project.
586
+ def version_project_config(env, options)
587
+ project, mixins = standardize_project_and_mixins( options[:project], options[:mixin] || [] )
588
+ explicit = !project.nil? || !mixins.empty?
589
+
590
+ return {} if !explicit and !@projectinator.config_available?( env:env )
591
+
592
+ begin
593
+ _, config = @composinator.loadinate( builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS, filepath:project, mixins:mixins, env:env, silent:true )
594
+ rescue StandardError
595
+ raise if explicit
596
+ config = {}
597
+ end
598
+
599
+ return config
600
+ end
601
+
569
602
  # Standardizes a project filepath and a mixins list together. PathValidator's
570
603
  # standardize_paths() returns new values rather than updating its arguments in
571
604
  # place, so the mixins list can't just be passed through it directly -- inline
@@ -586,25 +619,32 @@ class CliHandler
586
619
  return _project, _mixins
587
620
  end
588
621
 
589
- def list_rake_tasks(env:, app_cfg:, filepath:nil, mixins:[], silent:false)
590
- _, config =
591
- @composinator.loadinate(
592
- builtin_load_paths:BUILTIN_MIXIN_LOAD_PATHS,
593
- filepath: filepath,
594
- mixins: mixins,
595
- env: env,
596
- silent: silent
597
- )
622
+ # Loads the project configuration, then runs this command in the installation it selects.
623
+ # Returns the configuration and the rakefile to load, unless another installation took over.
624
+ def load_project_and_launch(env:, app_cfg:, options:, silent:false)
625
+ options[:project], options[:mixin] = standardize_project_and_mixins( options[:project], options[:mixin] )
598
626
 
627
+ _, config = @composinator.loadinate(
628
+ builtin_load_paths: BUILTIN_MIXIN_LOAD_PATHS,
629
+ filepath: options[:project],
630
+ mixins: options[:mixin],
631
+ env: env,
632
+ silent: silent
633
+ )
634
+
635
+ rakefile_path = @launchinator.launch( env:env, app_cfg:app_cfg, config:config )
636
+
637
+ return config, rakefile_path
638
+ end
639
+
640
+ def list_rake_tasks(app_cfg:, config:, rakefile_path:)
599
641
  # Save reference to loaded configuration
600
642
  app_cfg.set_project_config( config )
601
643
  app_cfg.set_logging_path( @helper.process_logging_path( config ) )
602
644
 
603
- _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg )
604
-
605
645
  @helper.load_ceedling(
606
646
  config: config,
607
- rakefile_path: path,
647
+ rakefile_path: rakefile_path,
608
648
  default_tasks: app_cfg[:default_tasks]
609
649
  )
610
650
 
data/bin/cli_helper.rb CHANGED
@@ -11,10 +11,24 @@ require 'app_cfg'
11
11
  require 'ceedling/constants'
12
12
  require 'ceedling/exceptions'
13
13
  require 'ceedling/rake_app/rakefile_component_resolver'
14
+ require 'ceedling/filesystem/project_paths'
15
+ require 'ceedling/config/build_root_policy'
14
16
  require 'versionator' # Outside DIY context
15
17
 
16
18
  class CliHelper
17
19
 
20
+ # Where a documentation export writes the HTML bundle, within a project's docs/
21
+ DOCS_BUNDLE_DIR = 'ceedling'
22
+
23
+ # Directories a documentation export writes into a project's docs/, beside Ceedling's license
24
+ EXPORTED_DOCS_DIRS = [DOCS_BUNDLE_DIR, 'unity', 'cmock', 'c_exception'].freeze
25
+
26
+ # What a 1.0.x export also wrote into docs/: Ceedling's own pages, and its plugins' pages
27
+ LEGACY_EXPORTED_DOCS = %w[
28
+ BreakingChanges.md CODE_OF_CONDUCT.md CONTRIBUTING.md CeedlingPacket.md CeedlingUpgrade.md
29
+ Changelog.md PluginDevelopmentGuide.md ReleaseNotes.md ThrowTheSwitchCodingStandard.md plugins
30
+ ].freeze
31
+
18
32
  constructor :file_wrapper, :actionator, :config_walkinator, :path_validator, :rake_task_registry, :loginator, :reportinator, :system_wrapper, :ruby_expandinator
19
33
 
20
34
  def setup
@@ -106,84 +120,12 @@ class CliHelper
106
120
  end
107
121
 
108
122
 
109
- # Returns two value: (1) symbol :gem or :path and (2) path for Ceedling installation
110
- def which_ceedling?(env:, config:{}, app_cfg:)
111
- # Determine which Ceedling we're running (in priority)
112
- # 1. If there's an environment variable set, validate it, and return :gem or a path
113
- # 2. If :project ↳ :which_ceedling exists in the config, validate it, and return :gem or a path
114
- # 3. If there's a vendor/ceedling/ path in our working directory, return it as a path
115
- # 4. If nothing is set, default to :gem and return it
116
- # 5. Update app_cfg paths if not the gem
117
-
118
- # Nil for prioritized case checking logic blocks that follow
119
- which_ceedling = nil
120
-
121
- # Environment variable
122
- if !env['WHICH_CEEDLING'].nil?
123
- @loginator.console( " > Set which Ceedling using environment variable WHICH_CEEDLING" )
124
- which_ceedling = env['WHICH_CEEDLING'].strip()
125
- which_ceedling = :gem if (which_ceedling.casecmp( 'gem' ) == 0)
126
- end
127
-
128
- # Configuration file
129
- if which_ceedling.nil?
130
- value, _ = @config_walkinator.fetch_value( :project, :which_ceedling, hash:config )
131
- if !value.nil?
132
- which_ceedling = value.strip()
133
- @loginator.lazy( Verbosity::OBNOXIOUS ) { " > Set which Ceedling from config :project ↳ :which_ceedling => #{which_ceedling}" }
134
- which_ceedling = :gem if (which_ceedling.casecmp( 'gem' ) == 0)
135
- end
136
- end
137
-
138
- # Working directory
139
- if which_ceedling.nil?
140
- if @file_wrapper.directory?( 'vendor/ceedling' )
141
- which_ceedling = 'vendor/ceedling'
142
- @loginator.log( " > Set which Ceedling to be vendored installation", Verbosity::OBNOXIOUS )
143
- end
144
- end
145
-
146
- # Default to gem
147
- if which_ceedling.nil?
148
- which_ceedling = :gem
149
- @loginator.log( " > Defaulting to running Ceedling from Gem", Verbosity::OBNOXIOUS )
150
- end
151
-
152
- # If we're launching from the gem, return :gem and initial Rakefile path
153
- if which_ceedling == :gem
154
- @loginator.log( " > Launching Ceedling from #{app_cfg[:ceedling_root_path]}/", Verbosity::OBNOXIOUS )
155
- return which_ceedling, app_cfg[:ceedling_rakefile_filepath]
156
- end
157
-
158
- # Otherwise, handle which_ceedling as a base path
159
- ceedling_path = which_ceedling.dup()
160
- @path_validator.standardize_paths( ceedling_path )
161
- if !@file_wrapper.directory?( ceedling_path )
162
- raise "Configured Ceedling launch path #{ceedling_path}/ does not exist"
163
- end
164
-
165
- # Update Ceedling installation paths
166
- app_cfg.set_paths( ceedling_path )
167
-
168
- # Check updated Ceedling paths
169
- if !@file_wrapper.exist?( app_cfg[:ceedling_rakefile_filepath] )
170
- raise "Configured Ceedling launch path #{ceedling_path}/ contains no Ceedling installation"
171
- end
172
-
173
- # Update variable to full application start path
174
- ceedling_path = app_cfg[:ceedling_rakefile_filepath]
175
-
176
- @loginator.log( " > Launching Ceedling from #{app_cfg[:ceedling_root_path]}/", Verbosity::OBNOXIOUS )
177
-
178
- return :path, ceedling_path
179
- end
180
-
181
-
182
123
  def build_rake_task_registry(config:)
183
124
  paths = RakefileComponentResolver.resolve(
184
125
  config,
185
126
  CEEDLING_APPCFG[:ceedling_lib_path],
186
- CEEDLING_APPCFG[:ceedling_plugins_path]
127
+ CEEDLING_APPCFG[:ceedling_plugins_path],
128
+ expand: ->(path) { @ruby_expandinator.expand( path, source: ":plugins ↳ :load_paths" ) }
187
129
  )
188
130
 
189
131
  @registry.register_test_tasks( paths )
@@ -276,6 +218,11 @@ class CliHelper
276
218
 
277
219
  return '' if build_root.nil?
278
220
 
221
+ # Read as configuration reads it, after inline Ruby string expansion. One that expands to
222
+ # nothing would put the logs at the filesystem root, so it is refused here already.
223
+ build_root = ProjectPaths.standardize( @ruby_expandinator.expand( build_root.to_s, source: ':project ↳ :build_root' ) )
224
+ raise CeedlingException.new( BuildRootPolicy.message( build_root, 'names no directory' ) ) if build_root.empty?
225
+
279
226
  return File.join( build_root, DEFAULT_BUILD_LOGS_PATH )
280
227
  end
281
228
 
@@ -491,7 +438,7 @@ class CliHelper
491
438
 
492
439
 
493
440
  def copy_docs(ceedling_root, dest)
494
- docs_path_ceedling = File.join( dest, 'ceedling' )
441
+ docs_path_ceedling = File.join( dest, DOCS_BUNDLE_DIR )
495
442
 
496
443
  # Hash that will hold documentation copy paths
497
444
  # - Key: (modified) destination documentation path
@@ -537,9 +484,8 @@ class CliHelper
537
484
  end
538
485
 
539
486
  # If present copy internl HTML documentation bundle (site-local/) to docs/ceedling/
540
- site_local_path = File.join( ceedling_root, DOCS_SITE_LOCAL_PATH )
541
- if @file_wrapper.directory?( site_local_path )
542
- @actions.copy_directory( site_local_path, docs_path_ceedling, force: true )
487
+ if docs_bundle?( ceedling_root )
488
+ @actions.copy_directory( File.join( ceedling_root, DOCS_SITE_LOCAL_PATH ), docs_path_ceedling, force: true )
543
489
  else
544
490
  @loginator.console( "Internal HTML documentation bundle not found", LogLabels::WARNING )
545
491
  return
@@ -556,6 +502,32 @@ class CliHelper
556
502
  end
557
503
 
558
504
 
505
+ # Whether an installation holds the HTML documentation bundle. A `--local` copy carries none.
506
+ def docs_bundle?(ceedling_root)
507
+ return @file_wrapper.directory?( File.join( ceedling_root, DOCS_SITE_LOCAL_PATH ) )
508
+ end
509
+
510
+
511
+ # Whether a project's docs/ holds documentation an export wrote, in the layout of 1.1.0
512
+ # and later or of 1.0.x
513
+ def exported_docs?(docs_path)
514
+ return (EXPORTED_DOCS_DIRS + ['CeedlingPacket.md']).any? { |entry| @file_wrapper.exist?( File.join( docs_path, entry ) ) }
515
+ end
516
+
517
+
518
+ # Removes what an export wrote into a project's docs/, leaving everything else. An HTML
519
+ # bundle the source cannot replace is kept. The export overwrites its own license, so a
520
+ # license file here, which may be the project's, stays.
521
+ def remove_exported_docs(docs_path, keep_bundle:)
522
+ entries = EXPORTED_DOCS_DIRS + LEGACY_EXPORTED_DOCS
523
+ entries -= [DOCS_BUNDLE_DIR] if keep_bundle
524
+
525
+ entries.map { |entry| File.join( docs_path, entry ) }.each do |path|
526
+ @actions.remove_directory( path ) if @file_wrapper.exist?( path )
527
+ end
528
+ end
529
+
530
+
559
531
  def vendor_tools(ceedling_root, dest)
560
532
  vendor_path = File.join( dest, 'vendor', 'ceedling' )
561
533
 
@@ -580,6 +552,7 @@ class CliHelper
580
552
  'vendor/diy/lib/',
581
553
  'vendor/unity/auto/',
582
554
  'vendor/unity/src/',
555
+ 'vendor/unity/test/targets/', # Built-in mixins, which the vendored launcher validates
583
556
  ]
584
557
 
585
558
  # Copy necessary subcomponent dirs into project
@@ -0,0 +1,81 @@
1
+ # =========================================================================
2
+ # Ceedling - Test-Centered Build System for C
3
+ # ThrowTheSwitch.org
4
+ # Copyright (c) 2010-26 Mike Karlesky, Mark VanderVoord, & Greg Williams
5
+ # SPDX-License-Identifier: MIT
6
+ # =========================================================================
7
+
8
+ require 'ceedling/constants'
9
+ require 'ceedling/installation'
10
+
11
+ # Decides which Ceedling installation runs a command, and points app_cfg's paths at it
12
+ class InstallationSelector
13
+
14
+ VENDOR_PATH = 'vendor/ceedling'
15
+
16
+ constructor :file_wrapper, :config_walkinator, :path_validator, :loginator
17
+
18
+ # Precedence:
19
+ # 1. The WHICH_CEEDLING environment variable
20
+ # 2. :project ↳ :which_ceedling in the configuration
21
+ # 3. A vendor/ceedling/ directory in the working directory, unless detect_vendor is off
22
+ # 4. The launcher's own installation
23
+ # Each is a path to an installation or `gem`, meaning the launcher's own.
24
+ def select(env:, app_cfg:, config: {}, detect_vendor: true)
25
+ which = from_environment( env ) || from_config( config )
26
+ which ||= from_vendor_directory() if detect_vendor
27
+
28
+ if which.nil? or which.casecmp?( 'gem' )
29
+ @loginator.log( " > Defaulting to running Ceedling from Gem", Verbosity::OBNOXIOUS ) if which.nil?
30
+ return use( app_cfg[:launcher_root_path], app_cfg )
31
+ end
32
+
33
+ return use( validate( which ), app_cfg )
34
+ end
35
+
36
+ private
37
+
38
+ def from_environment(env)
39
+ return nil if env['WHICH_CEEDLING'].nil?
40
+
41
+ @loginator.log( " > Set which Ceedling using environment variable WHICH_CEEDLING", Verbosity::OBNOXIOUS )
42
+ return env['WHICH_CEEDLING'].strip()
43
+ end
44
+
45
+ def from_config(config)
46
+ value, _ = @config_walkinator.fetch_value( :project, :which_ceedling, hash:config )
47
+ return nil if value.nil?
48
+
49
+ @loginator.lazy( Verbosity::OBNOXIOUS ) { " > Set which Ceedling from config :project ↳ :which_ceedling => #{value.strip()}" }
50
+ return value.strip()
51
+ end
52
+
53
+ def from_vendor_directory()
54
+ return nil if !@file_wrapper.directory?( VENDOR_PATH )
55
+
56
+ @loginator.log( " > Set which Ceedling to be vendored installation", Verbosity::OBNOXIOUS )
57
+ return VENDOR_PATH
58
+ end
59
+
60
+ # Returns the standardized path of an installation, raising if it holds none
61
+ def validate(which)
62
+ path = @path_validator.standardize_paths( which ).first
63
+ if !@file_wrapper.directory?( path )
64
+ raise "Configured Ceedling launch path #{path}/ does not exist"
65
+ end
66
+
67
+ if !@file_wrapper.exist?( Installation.new( path ).rakefile_path )
68
+ raise "Configured Ceedling launch path #{path}/ contains no Ceedling installation"
69
+ end
70
+
71
+ return path
72
+ end
73
+
74
+ def use(root, app_cfg)
75
+ app_cfg.set_paths( root )
76
+ @loginator.log( " > Launching Ceedling from #{app_cfg[:ceedling_root_path]}/", Verbosity::OBNOXIOUS )
77
+
78
+ return Installation.new( root )
79
+ end
80
+
81
+ end