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
@@ -7,11 +7,13 @@
7
7
 
8
8
  require 'rubygems'
9
9
  require 'rake' # for ext() method
10
- require 'ceedling/file_path_utils' # for class methods
10
+ require 'ceedling/filesystem/file_path_utils' # for class methods
11
+ require 'ceedling/filesystem/project_paths'
11
12
  require 'ceedling/defaults'
12
13
  require 'ceedling/constants' # for Verbosity constants class & base file paths
13
14
  require 'ceedling/filename_extension'
14
15
  require 'ceedling/rake_app/rakefile_component_resolver'
16
+ require 'ceedling/config/build_root_policy'
15
17
 
16
18
  class ConfiguratorBuilder
17
19
 
@@ -130,17 +132,18 @@ class ConfiguratorBuilder
130
132
 
131
133
 
132
134
  # A release is named by :release_build ↳ :output, or by default and the executable
133
- # extension. Its map file shares its name.
135
+ # extension. Its map file shares its name. A relative name is below the release build root,
136
+ # and an absolute one names the release itself.
134
137
  def set_release_target(in_hash)
135
138
  return {} if (not in_hash[:project_release_build])
136
139
 
137
- output = in_hash[:release_build_output]
140
+ output = in_hash[:release_build_output]&.then { |name| ProjectPaths.standardize( name ) }
138
141
  target = output || DEFAULT_RELEASE_TARGET_NAME.ext( in_hash[:extension_executable].primary )
139
142
  map = (output || DEFAULT_RELEASE_TARGET_NAME).ext( in_hash[:extension_map].primary )
140
143
 
141
144
  # tempted to make a helper method in file_path_utils? stop right there, pal. you'll introduce a cyclical dependency
142
145
  root = in_hash[:project_build_release_root]
143
- return { project_release_build_target: File.join( root, target ), project_release_build_map: File.join( root, map ) }
146
+ return { project_release_build_target: release_place( root, target ), project_release_build_map: release_place( root, map ) }
144
147
  end
145
148
 
146
149
 
@@ -163,14 +166,28 @@ class ConfiguratorBuilder
163
166
  end
164
167
 
165
168
 
166
- # Every :paths entry becomes a collection of the directories its globs name
169
+ # Every :paths entry becomes a collection of the directories its globs name, leaving out
170
+ # the build root, which a root above it (`../**`, `./**`) would otherwise sweep in, and
171
+ # the directories Ceedling creates
167
172
  def expand_all_path_globs(in_hash)
168
173
  path_keys = in_hash.keys.select { |key| key.to_s.start_with?( 'paths' ) }
169
174
 
170
- return path_keys.to_h { |key| [:"collection_#{key}", @file_path_collection_utils.collect_paths( in_hash[key] )] }
175
+ return path_keys.to_h { |key| [:"collection_#{key}", @file_path_collection_utils.collect_paths( in_hash[key], **build_exclusions( in_hash ) )] }
171
176
  end
172
177
 
173
178
 
179
+ # The roots build files mirror below, each spelled canonically: those of :paths ↳ :include,
180
+ # for a header's source by convention, and those every header is collected from
181
+ def collect_mirror_roots(in_hash)
182
+ include = Array( in_hash[:paths_include] )
183
+ headers = Array( in_hash[:paths_test] ) + Array( in_hash[:paths_support] ) + include
184
+
185
+ return {
186
+ :collection_mirror_roots_include => @file_path_collection_utils.collect_mirror_roots( include ),
187
+ :collection_mirror_roots_headers => @file_path_collection_utils.collect_mirror_roots( headers )
188
+ }
189
+ end
190
+
174
191
  def collect_source_and_include_paths(in_hash)
175
192
  return {
176
193
  :collection_paths_source_and_include =>
@@ -228,7 +245,7 @@ class ConfiguratorBuilder
228
245
  end
229
246
 
230
247
  # Add / subtract files via :files ↳ :test
231
- tests = file_collection( patterns, in_hash[:files_test] )
248
+ tests = file_collection( in_hash, patterns, in_hash[:files_test] )
232
249
  return { :collection_all_tests => tests }, tests
233
250
  end
234
251
 
@@ -242,19 +259,16 @@ class ConfiguratorBuilder
242
259
  paths = in_hash[:collection_paths_source] + in_hash[:collection_paths_support]
243
260
 
244
261
  # Add / subtract files via :files ↳ :assembly
245
- return { :collection_all_assembly => file_collection( code_patterns( paths, in_hash[:extension_assembly] ), in_hash[:files_assembly] ) }
262
+ return { :collection_all_assembly => file_collection( in_hash, code_patterns( paths, in_hash[:extension_assembly] ), in_hash[:files_assembly] ) }
246
263
  end
247
264
 
248
265
 
249
- # Source files, less any test files that overlapping test and source paths also matched
266
+ # Source files, less any test files that overlapping test and source paths, or :files
267
+ # revisions, also matched
250
268
  def collect_source(in_hash, test_list)
251
- sources = file_list( code_patterns( in_hash[:collection_paths_source], in_hash[:extension_source] ) )
252
-
253
- mixed_in = test_list.select { |test| sources.include?( test ) }
254
- exclude_tests( sources, mixed_in ) unless mixed_in.empty?
255
-
256
269
  # Add / subtract files via :files ↳ :source
257
- return { :collection_all_source => @file_path_collection_utils.revise_filelist( sources, in_hash[:files_source] ) }
270
+ sources = file_collection( in_hash, code_patterns( in_hash[:collection_paths_source], in_hash[:extension_source] ), in_hash[:files_source] )
271
+ return { :collection_all_source => without_tests( sources, test_list ) }
258
272
  end
259
273
 
260
274
 
@@ -262,12 +276,12 @@ class ConfiguratorBuilder
262
276
  paths = in_hash[:collection_paths_test] + in_hash[:collection_paths_support] + in_hash[:collection_paths_include]
263
277
 
264
278
  # Add / subtract files via :files ↳ :include
265
- return { :collection_all_headers => file_collection( code_patterns( paths, in_hash[:extension_header] ), in_hash[:files_include] ) }
279
+ return { :collection_all_headers => file_collection( in_hash, code_patterns( paths, in_hash[:extension_header] ), in_hash[:files_include] ) }
266
280
  end
267
281
 
268
282
 
269
283
  # Source files, plus CException's when exceptions are in use and assembly files when the
270
- # release build assembles
284
+ # release build assembles, less any test file. Source collection already warned of those.
271
285
  def collect_release_build_input(in_hash)
272
286
  assembly = in_hash[:release_build_use_assembly]
273
287
  vendor = in_hash[:project_use_exceptions] ? [in_hash[:project_build_vendor_cexception_path]] : []
@@ -275,7 +289,7 @@ class ConfiguratorBuilder
275
289
 
276
290
  # Add / subtract files via :files ↳ :source & :files ↳ :assembly
277
291
  revisions = in_hash[:files_source] + (assembly ? in_hash[:files_assembly] : [])
278
- return { :collection_release_build_input => file_collection( patterns, revisions ) }
292
+ return { :collection_release_build_input => without_tests( file_collection( in_hash, patterns, revisions ), in_hash[:collection_all_tests], warn: false ) }
279
293
  end
280
294
 
281
295
 
@@ -285,7 +299,7 @@ class ConfiguratorBuilder
285
299
  paths = in_hash[:collection_paths_test] + in_hash[:collection_paths_support] + in_hash[:collection_paths_source]
286
300
  patterns = vendor_patterns( test_vendor_paths( in_hash ) ) + code_patterns( paths, *code_extensions( in_hash, assembly ) )
287
301
 
288
- return { :collection_existing_test_build_input => file_collection( patterns, test_build_revisions( in_hash, assembly ) ) }
302
+ return { :collection_existing_test_build_input => file_collection( in_hash, patterns, test_build_revisions( in_hash, assembly ) ) }
289
303
  end
290
304
 
291
305
 
@@ -306,7 +320,7 @@ class ConfiguratorBuilder
306
320
  patterns = code_patterns( in_hash[:collection_paths_support], *extensions )
307
321
 
308
322
  # Add / subtract files via :files ↳ :support
309
- sources = file_collection( patterns, in_hash[:files_support] ).to_a
323
+ sources = file_collection( in_hash, patterns, in_hash[:files_support] ).to_a
310
324
  objects = sources.map { |file| File.basename( file ).ext( in_hash[:extension_object].primary ) }
311
325
 
312
326
  return { :collection_all_support => sources, :collection_test_fixture_extra_link_objects => objects }
@@ -325,6 +339,11 @@ class ConfiguratorBuilder
325
339
 
326
340
  private
327
341
 
342
+ # A relative release name is below the release build root, and an absolute one names itself
343
+ def release_place(root, name)
344
+ return ProjectPaths.absolute?( name ) ? name : File.join( root, name )
345
+ end
346
+
328
347
  def flatten_section(section, value)
329
348
  case value
330
349
  when nil then {}
@@ -443,8 +462,18 @@ class ConfiguratorBuilder
443
462
  end
444
463
 
445
464
  # Files matching `patterns`, revised by a :files list of additions and removals
446
- def file_collection(patterns, revisions)
447
- return @file_path_collection_utils.revise_filelist( file_list( patterns ), revisions )
465
+ def file_collection(in_hash, patterns, revisions)
466
+ return revised( in_hash, file_list( patterns ), revisions )
467
+ end
468
+
469
+ # A :files glob adds nothing from the build root it is based above, and no :files entry
470
+ # adds anything from the directories Ceedling creates
471
+ def revised(in_hash, list, revisions)
472
+ return @file_path_collection_utils.revise_filelist( list, revisions, **build_exclusions( in_hash ) )
473
+ end
474
+
475
+ def build_exclusions(in_hash)
476
+ return { exclude: [in_hash[:project_build_root]].compact, reserved: BuildRootPolicy.reserved( in_hash ) }
448
477
  end
449
478
 
450
479
  # FileList expands its patterns lazily, so they are expanded here
@@ -454,12 +483,13 @@ class ConfiguratorBuilder
454
483
  return list.resolve()
455
484
  end
456
485
 
457
- def exclude_tests(sources, tests)
458
- sources.exclude( *tests )
459
- @loginator.log(
460
- "Test file paths and source file paths overlap -- test files have been filtered out of the source file collection",
461
- Verbosity::COMPLAIN
462
- )
486
+ # `files` less any of `tests`, compared as collected, warning of any
487
+ def without_tests(files, tests, warn: true)
488
+ mixed_in = files.to_a & tests.to_a
489
+ return files if mixed_in.empty?
490
+
491
+ @loginator.log( 'Test file paths and source file paths overlap -- test files have been filtered out of the source file collection', Verbosity::COMPLAIN ) if warn
492
+ return @file_wrapper.instantiate_file_list_literal( files.to_a - mixed_in ).resolve()
463
493
  end
464
494
 
465
495
  end
@@ -0,0 +1,179 @@
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/filesystem/file_path_utils' # for glob handling class methods
10
+ require 'ceedling/filesystem/project_paths'
11
+ require 'ceedling/config/build_root_policy'
12
+
13
+ # Checks the paths a project file names against the filesystem: each :paths and :files
14
+ # entry, and paths named singly
15
+ class ConfiguratorPathsValidator
16
+
17
+ constructor :config_walkinator, :file_wrapper, :loginator, :reportinator
18
+
19
+ # Walk into config hash. verify existence of path(s) at given key depth.
20
+ # Paths are either full simple paths or a simple portion of a path up to a glob.
21
+ def validate_path_list(config, *keys)
22
+ list, depth = @config_walkinator.fetch_value( *keys, hash:config )
23
+ return false if list.nil?
24
+
25
+ # Trimming add/subtract notation and glob specifiers leaves nothing of a path that
26
+ # begins with a glob, so there is nothing to check
27
+ missing = checked_bases( list ).reject { |path| path.empty? or @file_wrapper.exist?( path ) }
28
+
29
+ walk = @reportinator.generate_config_walk( keys, depth )
30
+ missing.each { |path| log_error( "Config path #{walk} => '#{path}' does not exist in the filesystem." ) }
31
+
32
+ return missing.empty?
33
+ end
34
+
35
+
36
+ # Validate :paths entries, exercising each entry as Ceedling directory glob (variation of Ruby glob)
37
+ def validate_paths_entries(config, key)
38
+ return validate_entries( config, :paths, key ) { |entry, walk, build_root| valid_paths_entry?( entry, walk, build_root ) }
39
+ end
40
+
41
+
42
+ # Validate :files entries, exercising each entry as FileList glob
43
+ def validate_files_entries(config, key)
44
+ return validate_entries( config, :files, key ) { |entry, walk, build_root| valid_files_entry?( entry, walk, build_root ) }
45
+ end
46
+
47
+
48
+ # A build root of its own, warning of each :paths and :files entry within it (BuildRootPolicy)
49
+ def validate_build_root(config)
50
+ root = config[:project][:build_root].to_s
51
+ problem = BuildRootPolicy.problem( root )
52
+ log_error( BuildRootPolicy.message( root, problem ) ) unless problem.nil?
53
+ return false unless problem.nil?
54
+
55
+ BuildRootPolicy.warnings( root, config ) { |keys| @reportinator.generate_config_walk( keys ) }.each { |warning| log_complaint( warning ) }
56
+ return true
57
+ end
58
+
59
+
60
+ # Simple path verification
61
+ def validate_filepath_simple(path, *keys)
62
+ return true if @file_wrapper.exist?( path )
63
+
64
+ walk = @reportinator.generate_config_walk( keys, keys.size )
65
+ log_error( "Config path '#{path}' associated with #{walk} does not exist in the filesystem." )
66
+ return false
67
+ end
68
+
69
+ ### Private ###
70
+
71
+ private
72
+
73
+ # Each entry of one :paths or :files list, usable and passing `check`
74
+ def validate_entries(config, section, key)
75
+ list, _ = @config_walkinator.fetch_value( section, key, hash:config )
76
+ return false if list.nil?
77
+
78
+ walk = @reportinator.generate_config_walk( [section, key] )
79
+ build_root = config.dig( :project, :build_root )
80
+ return list.map { |entry| usable_entry?( entry, walk ) && yield( entry, walk, build_root ) }.all?
81
+ end
82
+
83
+ # Each additive entry's path up to its first glob. An entry YAML read as something other
84
+ # than a string, and a `-:` entry, which may name nothing, are left to the entries validation.
85
+ def checked_bases(list)
86
+ return list.grep( String ).select { |path| FilePathUtils.add_path?( path ) }.map { |path| FilePathUtils::no_decorators( path ) }
87
+ end
88
+
89
+ # A :paths or :files entry that names no path, or wraps its path in quotes, usually
90
+ # quotes only the path after its decoration. YAML keeps those quote marks as part of
91
+ # the value, so the hint points at quoting the whole entry. YAML also reads an unquoted
92
+ # decoration with nothing after it (`- -:`) as a one-key mapping rather than a string.
93
+ ENTRY_QUOTING_HINT = 'Quote the whole entry, decoration included (e.g. "-:path/to/file.c"), ' +
94
+ 'not only the path after its +: or -: decoration.'
95
+
96
+ def usable_entry?(entry, walk)
97
+ path = entry.is_a?( String ) ? FilePathUtils::no_aggregation_decorators( entry ) : ''
98
+
99
+ problem =
100
+ if !entry.nil? and !entry.is_a?( String ) then "is not a path (YAML read it as a #{entry.class})"
101
+ elsif path.empty? then 'names no path'
102
+ elsif path.start_with?( '"', "'" ) then 'wraps its path in quotes'
103
+ end
104
+ return true if problem.nil?
105
+
106
+ log_error( "#{walk} => '#{entry}' #{problem}" )
107
+ log_error( ENTRY_QUOTING_HINT )
108
+ return false
109
+ end
110
+
111
+ # A path naming a file is ignored with a warning. Any other entry must yield directories,
112
+ # except a subdirectories glob of a directory that has none, and a `-:` entry.
113
+ def valid_paths_entry?(entry, walk, build_root)
114
+ path = FilePathUtils::no_aggregation_decorators( entry )
115
+
116
+ if @file_wrapper.exist?( path ) and !@file_wrapper.directory?( path )
117
+ log_complaint( "#{walk} => '#{path}' is a filepath and will be ignored (FYI :paths is directory-oriented while :files is file-oriented)" )
118
+ return true
119
+ end
120
+
121
+ return valid_subtraction?( entry, path, walk, build_root ) unless FilePathUtils.add_path?( entry )
122
+ return true if globbed_directories?( path ) or path =~ /\/\*{1,2}$/
123
+
124
+ log_error( "#{walk} => '#{path}' yielded no directories -- matching glob is malformed or directories do not exist" )
125
+ return false
126
+ end
127
+
128
+ # A `-:` entry leaves out what it names, or warns of naming nothing. A subdirectories glob
129
+ # names its directory too.
130
+ def valid_subtraction?(entry, path, walk, build_root)
131
+ named = path.match?( %r{/\*{1,2}\z} ) ? @file_wrapper.exist?( FilePathUtils.no_decorators( entry ) ) : @file_wrapper.exist?( path )
132
+ return true if named or globbed_directories?( path )
133
+
134
+ return subtracts_nothing( entry, walk, build_root, 'directory' )
135
+ end
136
+
137
+ # A `-:` entry names what a build leaves out, so naming nothing is no error. Below the build
138
+ # root, where nothing exists before a first build, it passes without a word.
139
+ def subtracts_nothing(entry, walk, build_root, kind)
140
+ unless build_root and ProjectPaths.contains?( build_root, FilePathUtils.no_decorators( entry ) )
141
+ log_complaint( "#{walk} => '#{entry.strip}' leaves out nothing; no #{kind} matches it" )
142
+ end
143
+
144
+ return true
145
+ end
146
+
147
+ # #104 -- FilePathUtils.subdirectory_glob escapes literal brackets in the path, so they
148
+ # are matched rather than read as a glob character class
149
+ def globbed_directories?(path)
150
+ return @file_wrapper.directory_listing( FilePathUtils.subdirectory_glob( path ) ).any? { |entry| @file_wrapper.directory?( entry ) }
151
+ end
152
+
153
+ # A path naming a directory is ignored with a warning. Any other entry must yield files,
154
+ # except a `-:` entry.
155
+ def valid_files_entry?(entry, walk, build_root)
156
+ path = FilePathUtils::no_aggregation_decorators( entry )
157
+
158
+ if @file_wrapper.exist?( path ) and @file_wrapper.directory?( path )
159
+ log_complaint( "#{walk} => '#{path}' is a directory path and will be ignored (FYI :files is file-oriented while :paths is directory-oriented)" )
160
+ return true
161
+ end
162
+
163
+ # #104 -- literal brackets are escaped so they are matched rather than read as a glob
164
+ return true unless @file_wrapper.instantiate_file_list( FilePathUtils.escape_glob_brackets( path ) ).size.zero?
165
+ return subtracts_nothing( entry, walk, build_root, 'file' ) unless FilePathUtils.add_path?( entry )
166
+
167
+ log_error( "#{walk} => '#{path}' yielded no files -- matching glob is malformed or files do not exist" )
168
+ return false
169
+ end
170
+
171
+ def log_error(message)
172
+ @loginator.log( message, Verbosity::ERRORS )
173
+ end
174
+
175
+ def log_complaint(message)
176
+ @loginator.log( message, Verbosity::COMPLAIN )
177
+ end
178
+
179
+ end
@@ -6,7 +6,7 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'ceedling/constants'
9
- require 'ceedling/file_path_utils'
9
+ require 'ceedling/filesystem/file_path_utils'
10
10
 
11
11
  class ConfiguratorPlugins
12
12
 
@@ -12,12 +12,13 @@ require 'ceedling/config/line_marker_suppressors'
12
12
 
13
13
  class ConfiguratorSetup
14
14
 
15
- constructor :configurator_builder, :configurator_validator, :loginator, :reportinator, :file_wrapper,
15
+ constructor :configurator_builder, :configurator_validator, :configurator_paths_validator, :loginator, :reportinator, :file_wrapper,
16
16
  :system_wrapper, :tool_executor
17
17
 
18
18
  # Path collections, in order, since each builds on those before it
19
19
  PATH_COLLECTIONS = [
20
20
  :expand_all_path_globs,
21
+ :collect_mirror_roots,
21
22
  :collect_vendor_paths,
22
23
  :collect_source_and_include_paths,
23
24
  :collect_source_include_vendor_paths,
@@ -72,17 +73,6 @@ class ConfiguratorSetup
72
73
  end
73
74
  end
74
75
 
75
- # A vendor destination must be a directory, and the marker file inside it (unity.c,
76
- # cmock.c, CException.c) a plain file. An interrupted run, or a second Ceedling run racing
77
- # this one, can leave either as the wrong type, and the copy would then fail on every
78
- # later build. The whole destination is cleared, so the copy recreates it.
79
- def heal_vendor_path(path, marker_file)
80
- return unless corrupted_vendor_path?( path, marker_file )
81
-
82
- @loginator.log( "Removing corrupted vendor path (unexpected file/directory type): #{path}", Verbosity::COMPLAIN, LogLabels::NOTICE )
83
- @file_wrapper.rm_rf( path )
84
- end
85
-
86
76
  # Brings build/vendor up to date with the frameworks and support files a build needs. Only
87
77
  # a build does this, so a command that only reads the project leaves a concurrent build's
88
78
  # files alone. A file that already matches its source is not written, and one that differs,
@@ -90,8 +80,7 @@ class ConfiguratorSetup
90
80
  #
91
81
  # A release build needs only CException, and that only when exceptions are enabled.
92
82
  def vendor_frameworks_and_support_files(ceedling_lib_path, flattened_config, test_build:, release_build:)
93
- frameworks_for_build( flattened_config, test_build: test_build, release_build: release_build ).each do |source, destination, marker_file|
94
- heal_vendor_path( destination, marker_file )
83
+ frameworks_for_build( flattened_config, test_build: test_build, release_build: release_build ).each do |source, destination|
95
84
  @file_wrapper.sync_tree( source, destination )
96
85
  end
97
86
 
@@ -130,6 +119,11 @@ class ConfiguratorSetup
130
119
  end
131
120
 
132
121
 
122
+ def validate_build_root(config)
123
+ return @configurator_paths_validator.validate_build_root( config )
124
+ end
125
+
126
+
133
127
  # Every check runs, so every problem is reported
134
128
  def validate_paths(config)
135
129
  valid = validate_simple_paths( config[:cmock][:unity_helper_path], :cmock, :unity_helper_path )
@@ -308,23 +302,16 @@ class ConfiguratorSetup
308
302
 
309
303
  private
310
304
 
311
- def corrupted_vendor_path?(path, marker_file)
312
- marker = File.join( path, marker_file )
313
-
314
- return ( @file_wrapper.exist?( path ) && !@file_wrapper.directory?( path ) ) ||
315
- ( @file_wrapper.exist?( marker ) && @file_wrapper.directory?( marker ) )
316
- end
317
-
318
- # Each framework a build uses, as [vendored source, build destination, marker file]
305
+ # Each framework a build uses, as [vendored source, build destination]
319
306
  def vendored_frameworks(config)
320
- frameworks = [ [File.join( config[:unity_vendor_path], UNITY_LIB_PATH ), config[:project_build_vendor_unity_path], UNITY_C_FILE] ]
307
+ frameworks = [ [File.join( config[:unity_vendor_path], UNITY_LIB_PATH ), config[:project_build_vendor_unity_path]] ]
321
308
 
322
309
  if config[:project_use_mocks]
323
- frameworks << [File.join( config[:cmock_vendor_path], CMOCK_LIB_PATH ), config[:project_build_vendor_cmock_path], CMOCK_C_FILE]
310
+ frameworks << [File.join( config[:cmock_vendor_path], CMOCK_LIB_PATH ), config[:project_build_vendor_cmock_path]]
324
311
  end
325
312
 
326
313
  if config[:project_use_exceptions]
327
- frameworks << [File.join( config[:cexception_vendor_path], CEXCEPTION_LIB_PATH ), config[:project_build_vendor_cexception_path], CEXCEPTION_C_FILE]
314
+ frameworks << [File.join( config[:cexception_vendor_path], CEXCEPTION_LIB_PATH ), config[:project_build_vendor_cexception_path]]
328
315
  end
329
316
 
330
317
  return frameworks
@@ -332,7 +319,7 @@ class ConfiguratorSetup
332
319
 
333
320
  def frameworks_for_build(config, test_build:, release_build:)
334
321
  return vendored_frameworks( config ) if test_build
335
- return vendored_frameworks( config ).select { |_, _, marker_file| marker_file == CEXCEPTION_C_FILE } if release_build
322
+ return vendored_frameworks( config ).select { |_, destination| destination == config[:project_build_vendor_cexception_path] } if release_build
336
323
 
337
324
  return []
338
325
  end
@@ -353,13 +340,13 @@ class ConfiguratorSetup
353
340
  end
354
341
 
355
342
  def validate_simple_paths(paths, *keys)
356
- return paths.map { |path| @configurator_validator.validate_filepath_simple( path, *keys ) }.all?
343
+ return paths.map { |path| @configurator_paths_validator.validate_filepath_simple( path, *keys ) }.all?
357
344
  end
358
345
 
359
346
  # Each entry of :paths or :files must exist and yield what its section expects
360
347
  def validate_path_section(config, section, entries_validation)
361
348
  return config[section].keys.sort.map do |key|
362
- @configurator_validator.validate_path_list( config, section, key ) & @configurator_validator.public_send( entries_validation, config, key )
349
+ @configurator_paths_validator.validate_path_list( config, section, key ) & @configurator_paths_validator.public_send( entries_validation, config, key )
363
350
  end.all?
364
351
  end
365
352
 
@@ -6,13 +6,12 @@
6
6
  # =========================================================================
7
7
 
8
8
  require 'ceedling/constants'
9
- require 'ceedling/file_path_utils' # for glob handling class methods
10
9
  require 'ceedling/config/config_matchinator'
11
10
 
12
11
 
13
12
  class ConfiguratorValidator
14
13
 
15
- constructor :config_walkinator, :file_wrapper, :loginator, :reportinator, :tool_validator
14
+ constructor :config_walkinator, :loginator, :reportinator, :tool_validator
16
15
 
17
16
  # Walk into config hash verify existence of data at key depth
18
17
  def exists?(config, *keys)
@@ -23,54 +22,6 @@ class ConfiguratorValidator
23
22
  return false
24
23
  end
25
24
 
26
- # Walk into config hash. verify existence of path(s) at given key depth.
27
- # Paths are either full simple paths or a simple portion of a path up to a glob.
28
- def validate_path_list(config, *keys)
29
- list, depth = @config_walkinator.fetch_value( *keys, hash:config )
30
- return false if list.nil?
31
-
32
- # Trimming add/subtract notation and glob specifiers leaves nothing of a path that
33
- # begins with a glob, so there is nothing to check. An entry YAML read as something
34
- # other than a string is left to the entries validation, which reports it.
35
- paths = list.grep( String ).map { |path| FilePathUtils::no_decorators( path ) }
36
- missing = paths.reject { |path| path.empty? or @file_wrapper.exist?( path ) }
37
-
38
- walk = @reportinator.generate_config_walk( keys, depth )
39
- missing.each { |path| log_error( "Config path #{walk} => '#{path}' does not exist in the filesystem." ) }
40
-
41
- return missing.empty?
42
- end
43
-
44
-
45
- # Validate :paths entries, exercising each entry as Ceedling directory glob (variation of Ruby glob)
46
- def validate_paths_entries(config, key)
47
- list, _ = @config_walkinator.fetch_value( :paths, key, hash:config )
48
- return false if list.nil?
49
-
50
- walk = @reportinator.generate_config_walk( [:paths, key] )
51
- return list.map { |path| usable_entry?( path, walk ) && valid_paths_entry?( FilePathUtils::no_aggregation_decorators( path ), walk ) }.all?
52
- end
53
-
54
-
55
- # Validate :files entries, exercising each entry as FileList glob
56
- def validate_files_entries(config, key)
57
- list, _ = @config_walkinator.fetch_value( :files, key, hash:config )
58
- return false if list.nil?
59
-
60
- walk = @reportinator.generate_config_walk( [:files, key] )
61
- return list.map { |path| usable_entry?( path, walk ) && valid_files_entry?( FilePathUtils::no_aggregation_decorators( path ), walk ) }.all?
62
- end
63
-
64
-
65
- # Simple path verification
66
- def validate_filepath_simple(path, *keys)
67
- return true if @file_wrapper.exist?( path )
68
-
69
- walk = @reportinator.generate_config_walk( keys, keys.size )
70
- log_error( "Config path '#{path}' associated with #{walk} does not exist in the filesystem." )
71
- return false
72
- end
73
-
74
25
  def validate_tool(config:, key:, respect_optional:true)
75
26
  # Get tool
76
27
  walk = [:tools, key]
@@ -102,62 +53,6 @@ class ConfiguratorValidator
102
53
 
103
54
  private
104
55
 
105
- # A :paths or :files entry that names no path, or wraps its path in quotes, usually
106
- # quotes only the path after its decoration. YAML keeps those quote marks as part of
107
- # the value, so the hint points at quoting the whole entry. YAML also reads an unquoted
108
- # decoration with nothing after it (`- -:`) as a one-key mapping rather than a string.
109
- ENTRY_QUOTING_HINT = 'Quote the whole entry, decoration included (e.g. "-:path/to/file.c"), ' +
110
- 'not only the path after its +: or -: decoration.'
111
-
112
- def usable_entry?(entry, walk)
113
- path = entry.is_a?( String ) ? FilePathUtils::no_aggregation_decorators( entry ) : ''
114
-
115
- problem =
116
- if !entry.nil? and !entry.is_a?( String ) then "is not a path (YAML read it as a #{entry.class})"
117
- elsif path.empty? then 'names no path'
118
- elsif path.start_with?( '"', "'" ) then 'wraps its path in quotes'
119
- end
120
- return true if problem.nil?
121
-
122
- log_error( "#{walk} => '#{entry}' #{problem}" )
123
- log_error( ENTRY_QUOTING_HINT )
124
- return false
125
- end
126
-
127
- # A path naming a file is ignored with a warning. Any other entry must yield directories,
128
- # except a subdirectories glob of a directory that has none.
129
- def valid_paths_entry?(path, walk)
130
- if @file_wrapper.exist?( path ) and !@file_wrapper.directory?( path )
131
- log_complaint( "#{walk} => '#{path}' is a filepath and will be ignored (FYI :paths is directory-oriented while :files is file-oriented)" )
132
- return true
133
- end
134
-
135
- return true if globbed_directories?( path ) or path =~ /\/\*{1,2}$/
136
-
137
- log_error( "#{walk} => '#{path}' yielded no directories -- matching glob is malformed or directories do not exist" )
138
- return false
139
- end
140
-
141
- # #104 -- FilePathUtils.subdirectory_glob escapes literal brackets in the path, so they
142
- # are matched rather than read as a glob character class
143
- def globbed_directories?(path)
144
- return @file_wrapper.directory_listing( FilePathUtils.subdirectory_glob( path ) ).any? { |entry| @file_wrapper.directory?( entry ) }
145
- end
146
-
147
- # A path naming a directory is ignored with a warning. Any other entry must yield files.
148
- def valid_files_entry?(path, walk)
149
- if @file_wrapper.exist?( path ) and @file_wrapper.directory?( path )
150
- log_complaint( "#{walk} => '#{path}' is a directory path and will be ignored (FYI :files is file-oriented while :paths is directory-oriented)" )
151
- return true
152
- end
153
-
154
- # #104 -- literal brackets are escaped so they are matched rather than read as a glob
155
- return true unless @file_wrapper.instantiate_file_list( FilePathUtils.escape_glob_brackets( path ) ).size.zero?
156
-
157
- log_error( "#{walk} => '#{path}' yielded no files -- matching glob is malformed or files do not exist" )
158
- return false
159
- end
160
-
161
56
  def validate_regex_matcher(matcher)
162
57
  Regexp.compile( matcher[1..-2] )
163
58
  rescue RegexpError => ex
@@ -168,8 +63,4 @@ class ConfiguratorValidator
168
63
  @loginator.log( message, Verbosity::ERRORS )
169
64
  end
170
65
 
171
- def log_complaint(message)
172
- @loginator.log( message, Verbosity::COMPLAIN )
173
- end
174
-
175
66
  end
@@ -7,7 +7,7 @@
7
7
 
8
8
  require 'ceedling/constants'
9
9
  require 'ceedling/system_wrapper'
10
- require 'ceedling/file_path_utils'
10
+ require 'ceedling/filesystem/file_path_utils'
11
11
 
12
12
  # Assign a default value for system testing where CEEDLING_APPCFG may not be present
13
13
  # TODO: Create code config & test structure that does not internalize a test path like this
@@ -58,14 +58,14 @@ DEFAULT_TEST_LINKER_TOOL = {
58
58
  }
59
59
 
60
60
  DEFAULT_TEST_FIXTURE_TOOL = {
61
- :executable => '${1}'.freeze, # Unity test runner executable
61
+ :executable => '"${1}"'.freeze, # Unity test runner executable, quoted as a path
62
62
  :name => 'default_test_fixture'.freeze,
63
63
  :optional => false.freeze,
64
64
  :arguments => [].freeze
65
65
  }
66
66
 
67
67
  DEFAULT_TEST_FIXTURE_SIMPLE_BACKTRACE_TOOL = {
68
- :executable => '${1}'.freeze, # Unity test runner executable
68
+ :executable => '"${1}"'.freeze, # Unity test runner executable, quoted as a path
69
69
  :name => 'default_test_fixture_simple_backtrace'.freeze,
70
70
  :optional => false.freeze,
71
71
  :arguments => [
@@ -204,7 +204,7 @@ DEFAULT_TEST_BACKTRACE_GDB_TOOL = {
204
204
  '--eval-command run'.freeze,
205
205
  "--command \"${1}\"".freeze, # Debug script file to run
206
206
  '--args'.freeze,
207
- '${2}'.freeze, # Test executable
207
+ '"${2}"'.freeze, # Test executable, quoted as a path
208
208
  # Test case matching flag and (quoted) value, fully composed by the caller as
209
209
  # either `-n "<exact name>"` or `-f "<base name>"` -- see
210
210
  # GeneratorTestResultsBacktrace#unity_filter_arg.