diff --git a/bin/actions_wrapper.rb b/bin/actions_wrapper.rb old mode 100755 new mode 100644 diff --git a/bin/app_cfg.rb b/bin/app_cfg.rb old mode 100755 new mode 100644 index 96a33d02..e09c33d7 --- a/bin/app_cfg.rb +++ b/bin/app_cfg.rb @@ -13,8 +13,8 @@ class CeedlingAppConfig def initialize() - # Installation location determined from the location of this file - ceedling_root_path = File.expand_path( File.join( File.dirname( __FILE__ ), '..' ) ) + # Default installation location determined from the location of this file + ceedling_root_path = File.join( File.dirname( __FILE__ ), '..' ) # Create internal hash of needed values @app_cfg = { @@ -27,12 +27,18 @@ def initialize() # Ceedling installation base path + /lib/ceedling :ceedling_lib_path => '', + # Ceedling installation base path + /plugins + :ceedling_plugins_path => '', + # Ceedling installation base path + /vendor :ceedling_vendor_path => '', # Ceedling installation base path + /examples :ceedling_examples_path => '', + # Ceedling lib path + lib/ceedling/rakefile.rb + :ceedling_rakefile_filepath => '', + # Blank initial value for completeness :project_config => {}, @@ -62,7 +68,7 @@ def initialize() begin @app_cfg[:terminal_width] = (IO.console.winsize)[1] rescue - # Do nothing; allow default value already set to stand + # Do nothing; allow value already set to stand as default end end @@ -91,13 +97,18 @@ def set_tests_graceful_fail(enable) end def set_paths(root_path) - lib_base_path = File.join( root_path, 'lib' ) + _root_path = File.expand_path( root_path ) + lib_base_path = File.join( _root_path, 'lib' ) + lib_path = File.join( lib_base_path, 'ceedling' ) - @app_cfg[:ceedling_root_path] = root_path + @app_cfg[:ceedling_root_path] = _root_path @app_cfg[:ceedling_lib_base_path] = lib_base_path - @app_cfg[:ceedling_lib_path] = File.join( lib_base_path, 'ceedling' ) - @app_cfg[:ceedling_vendor_path] = File.join( root_path, 'vendor' ) - @app_cfg[:ceedling_examples_path] = File.join( root_path, 'examples' ) + @app_cfg[:ceedling_lib_path] = lib_path + @app_cfg[:ceedling_vendor_path] = File.join( _root_path, 'vendor' ) + @app_cfg[:ceedling_plugins_path] = File.join( _root_path, 'plugins' ) + @app_cfg[:ceedling_examples_path] = File.join( _root_path, 'examples' ) + + @app_cfg[:ceedling_rakefile_filepath] = File.join( lib_path, 'rakefile.rb' ) end # External accessor to preserve hash-like read accesses diff --git a/bin/cli.rb b/bin/cli.rb old mode 100755 new mode 100644 diff --git a/bin/cli_handler.rb b/bin/cli_handler.rb old mode 100755 new mode 100644 index 6cdd3cd9..c5acff2f --- a/bin/cli_handler.rb +++ b/bin/cli_handler.rb @@ -74,9 +74,10 @@ def new_project(env, app_cfg, options, name, dest) raise msg end unless options[:force] - # Update app_cfg paths (ignore return value) + # Update app_cfg paths (ignore return values) @helper.which_ceedling?( env:env, app_cfg:app_cfg ) + # Thor Actions for project tasks use paths in relation to this path ActionsWrapper.source_root( app_cfg[:ceedling_root_path] ) # Blow away any existing directories and contents if --force @@ -94,12 +95,12 @@ def new_project(env, app_cfg, options, name, dest) @helper.copy_docs( app_cfg[:ceedling_root_path], dest ) if options[:docs] # Copy / set up project file - @helper.create_project_file( app_cfg[:ceedling_root_path], dest, options[:local] ) if options[:configs] + @helper.create_project_file( dest, options[:local] ) if options[:configs] # Copy Git Ignore file if options[:gitsupport] @actions._copy_file( - File.join( app_cfg[:ceedling_root_path], 'assets', 'default_gitignore' ), + File.join( 'assets', 'default_gitignore' ), File.join( dest, '.gitignore' ), :force => true ) @@ -111,19 +112,23 @@ def new_project(env, app_cfg, options, name, dest) def upgrade_project(env, app_cfg, options, path) + @helper.set_verbosity( options[:verbosity] ) + @path_validator.standardize_paths( path, options[:project] ) # Check for existing project - if !@helper.project_exists?( path, :&, options[:project], 'vendor/ceedling/lib/ceedling.rb' ) + if !@helper.project_exists?( path, :&, options[:project], 'vendor/ceedling/lib/ceedling/version.rb' ) msg = "Could not find an existing project at #{path}/." raise msg end - if (@helper.which_ceedling?( env:env, app_cfg:app_cfg ) == :gem) - msg = "Project configuration specifies the Ceedling gem, not vendored Ceedling" - raise msg + which, _ = @helper.which_ceedling?( env:env, app_cfg:app_cfg ) + if (which == :gem) + msg = "NOTICE: Project configuration specifies the Ceedling gem, not vendored Ceedling" + @streaminator.stream_puts( msg, Verbosity::NORMAL ) end + # Thor Actions for project tasks use paths in relation to this path ActionsWrapper.source_root( app_cfg[:ceedling_root_path] ) # Recreate vendored tools @@ -191,9 +196,11 @@ def build(env:, app_cfg:, options:{}, tasks:) # Enable setup / operations duration logging in Rake context app_cfg.set_stopwatch( @helper.process_stopwatch( tasks:tasks, default_tasks:default_tasks ) ) + _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ) + @helper.load_ceedling( config: config, - which: @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ), + rakefile_path: path, default_tasks: default_tasks ) @@ -218,9 +225,11 @@ def dumpconfig(env, app_cfg, options, filepath, sections) # Save references app_cfg.set_project_config( config ) + _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ) + config = @helper.load_ceedling( config: config, - which: @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ), + rakefile_path: path, default_tasks: default_tasks ) else @@ -243,9 +252,11 @@ def environment(env, app_cfg, options) # Save references app_cfg.set_project_config( config ) + _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ) + config = @helper.load_ceedling( config: config, - which: @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ) + rakefile_path: path ) env_list = [] @@ -276,7 +287,7 @@ def environment(env, app_cfg, options) def list_examples(env, app_cfg) - # Process which_ceedling for app_cfg but ignore return + # Process which_ceedling for app_cfg modifications but ignore return values @helper.which_ceedling?( env:env, app_cfg:app_cfg ) examples = @helper.lookup_example_projects( app_cfg[:ceedling_examples_path] ) @@ -296,7 +307,7 @@ def create_example(env, app_cfg, options, name, dest) @path_validator.standardize_paths( dest ) - # Process which_ceedling for app_cfg but ignore return + # Process which_ceedling for app_cfg modifications but ignore return values @helper.which_ceedling?( env:env, app_cfg:app_cfg ) examples = @helper.lookup_example_projects( app_cfg[:ceedling_examples_path] ) @@ -313,6 +324,7 @@ def create_example(env, app_cfg, options, name, dest) dest_test = File.join( dest, 'test' ) dest_project = File.join( dest, DEFAULT_PROJECT_FILENAME ) + # Thor Actions for project tasks use paths in relation to this path ActionsWrapper.source_root( app_cfg[:ceedling_root_path] ) @actions._directory( "examples/#{name}/src", dest_src, :force => true ) @@ -356,9 +368,11 @@ def list_rake_tasks(env:, app_cfg:, filepath:nil, mixins:[]) # Save reference to loaded configuration app_cfg.set_project_config( config ) + _, path = @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ) + @helper.load_ceedling( config: config, - which: @helper.which_ceedling?( env:env, config:config, app_cfg:app_cfg ), + rakefile_path: path, default_tasks: app_cfg[:default_tasks] ) diff --git a/bin/cli_helper.rb b/bin/cli_helper.rb old mode 100755 new mode 100644 index d11d7e3c..92f714e9 --- a/bin/cli_helper.rb +++ b/bin/cli_helper.rb @@ -33,14 +33,14 @@ def project_exists?( path, op, *components ) end - def create_project_file(ceedling_root, dest, local) + def create_project_file(dest, local) project_filepath = File.join( dest, DEFAULT_PROJECT_FILENAME ) source_filepath = '' if local - source_filepath = File.join( ceedling_root, 'assets', 'project_with_guts.yml' ) + source_filepath = File.join( 'assets', 'project_with_guts.yml' ) else - source_filepath = File.join( ceedling_root, 'assets', 'project_as_gem.yml' ) + source_filepath = File.join( 'assets', 'project_as_gem.yml' ) end # Clone the project file and update internal version @@ -50,6 +50,7 @@ def create_project_file(ceedling_root, dest, local) end + # Returns two value: (1) symbol :gem or :path and (2) path for Ceedling installation def which_ceedling?(env:, config:{}, app_cfg:) # Determine which Ceedling we're running (in priority) # 1. If there's an environment variable set, validate it, and return :gem or a path @@ -72,8 +73,8 @@ def which_ceedling?(env:, config:{}, app_cfg:) if which_ceedling.nil? walked = @config_walkinator.fetch_value( config, :project, :which_ceedling ) if !walked[:value].nil? - @streaminator.stream_puts( " > Set which Ceedling from config entry :project -> :which_ceedling", Verbosity::OBNOXIOUS ) which_ceedling = walked[:value].strip() + @streaminator.stream_puts( " > Set which Ceedling from config :project -> :which_ceedling => #{which_ceedling}", Verbosity::OBNOXIOUS ) which_ceedling = :gem if (which_ceedling.casecmp( 'gem' ) == 0) end end @@ -92,45 +93,41 @@ def which_ceedling?(env:, config:{}, app_cfg:) @streaminator.stream_puts( " > Defaulting to running Ceedling from Gem", Verbosity::OBNOXIOUS ) end - # Default gem path - ceedling_path = app_cfg[:ceedling_root_path] + # If we're launching from the gem, return :gem and initial Rakefile path + if which_ceedling == :gem + return which_ceedling, app_cfg[:ceedling_rakefile_filepath] + end - if which_ceedling != :gem - ceedling_path = which_ceedling - @path_validator.standardize_paths( ceedling_path ) - if !@file_wrapper.directory?( ceedling_path ) - raise "Configured Ceedling launch path #{ceedling_path}/ does not exist" - end + # Otherwise, handle which_ceedling as a base path + ceedling_path = which_ceedling.dup() + @path_validator.standardize_paths( ceedling_path ) + if !@file_wrapper.directory?( ceedling_path ) + raise "Configured Ceedling launch path #{ceedling_path}/ does not exist" + end - # Update installation paths - app_cfg.set_paths( ceedling_path ) + # Update Ceedling installation paths + app_cfg.set_paths( ceedling_path ) + + # Check updated Ceedling paths + if !@file_wrapper.exist?( app_cfg[:ceedling_rakefile_filepath] ) + raise "Configured Ceedling launch path #{ceedling_path}/ contains no Ceedling installation" end + # Update variable to full application start path + ceedling_path = app_cfg[:ceedling_rakefile_filepath] + @streaminator.stream_puts( " > Launching Ceedling from #{ceedling_path}/", Verbosity::OBNOXIOUS ) - return ceedling_path + return :path, ceedling_path end - def load_ceedling(config:, which:, default_tasks:[]) - # Load Ceedling from the gem - if (which == :gem) - require( 'ceedling' ) - # Load Ceedling from a path - else - ceedling_path = File.join( File.expand_path( which ), 'lib/ceedling.rb' ) - if !@file_wrapper.exist?( ceedling_path ) - raise "Configured Ceedling launch path #{which}/ contains no Ceedling installation" - end - - require( ceedling_path ) - end - + def load_ceedling(config:, rakefile_path:, default_tasks:[]) # Set default tasks Rake::Task.define_task(:default => default_tasks) if !default_tasks.empty? - # Load Ceedling - Ceedling.load_rakefile() + # Load Ceedling application from Rakefile path + require( rakefile_path ) # Loading the Rakefile manipulates the config hash, return it as a convenience return config @@ -358,12 +355,11 @@ def copy_docs(ceedling_root, dest) def vendor_tools(ceedling_root, dest) vendor_path = File.join( dest, 'vendor', 'ceedling' ) - assets_path = File.join( ceedling_root, 'assets' ) # Copy folders from current Ceedling into project %w{plugins lib bin}.each do |folder| @actions._directory( - File.join( ceedling_root, folder ), + folder, File.join( vendor_path, folder ), :force => true ) @@ -385,7 +381,7 @@ def vendor_tools(ceedling_root, dest) # Copy necessary subcomponent dirs into project components.each do |path| - _src = File.join( ceedling_root, path ) + _src = path _dest = File.join( vendor_path, path ) @actions._directory( _src, _dest, :force => true ) end @@ -421,7 +417,7 @@ def vendor_tools(ceedling_root, dest) if windows? # Windows command prompt launch script @actions._copy_file( - File.join( assets_path, 'ceedling.cmd'), + File.join( 'assets', 'ceedling.cmd'), File.join( dest, 'ceedling.cmd'), :force => true ) @@ -429,7 +425,7 @@ def vendor_tools(ceedling_root, dest) # Unix shell launch script launch = File.join( dest, 'ceedling') @actions._copy_file( - File.join( assets_path, 'ceedling'), + File.join( 'assets', 'ceedling'), launch, :force => true ) diff --git a/bin/configinator.rb b/bin/configinator.rb old mode 100755 new mode 100644 diff --git a/bin/mixinator.rb b/bin/mixinator.rb old mode 100755 new mode 100644 diff --git a/bin/objects.yml b/bin/objects.yml old mode 100755 new mode 100644 diff --git a/bin/path_validator.rb b/bin/path_validator.rb old mode 100755 new mode 100644 diff --git a/bin/projectinator.rb b/bin/projectinator.rb old mode 100755 new mode 100644 diff --git a/ceedling.gemspec b/ceedling.gemspec index e6029af3..757e66b8 100644 --- a/ceedling.gemspec +++ b/ceedling.gemspec @@ -54,9 +54,9 @@ Ceedling projects are created with a YAML configuration file. A variety of conve s.files += Dir['vendor/unity/auto/**/*.rb'] s.files += Dir['vendor/unity/src/**/*.[ch]'] - s.files += Dir['**/*'] - s.test_files = Dir['test/**/*', 'spec/**/*', 'features/**/*'] - s.executables = ['ceedling'] # bin/ceedling + s.files += Dir['**/*'] + s.test_files = Dir['test/**/*', 'spec/**/*', 'features/**/*'] + s.executables = ['ceedling'] # bin/ceedling s.require_paths = ["lib", "vendor/cmock/lib"] end diff --git a/lib/ceedling.rb b/lib/ceedling.rb index ef0e568d..28d27198 100644 --- a/lib/ceedling.rb +++ b/lib/ceedling.rb @@ -5,38 +5,10 @@ # SPDX-License-Identifier: MIT # ========================================================================= -## -# This module defines the interface for interacting with and loading a project -# with Ceedling. -module Ceedling - ## - # Returns the location where the gem is installed. - # === Return - # _String_ - The location where the gem lives. - def self.location() - # Ensure parent path traversal is expanded away - File.absolute_path( File.join( File.dirname(__FILE__), '..') ) - end - - ## - # Return the path to the "built-in" plugins. - # === Return - # _String_ - The path where the default plugins live. - def self.plugins_load_path() - File.join( self.location, 'plugins') - end - - ## - # Return the path to the Ceedling Rakefile - # === Return - # _String_ - def self.rakefile() - File.join( self.location, 'lib', 'ceedling', 'rakefile.rb' ) - end - - def self.load_rakefile() - require "#{self.rakefile}" - end - -end +# This file exists solely for `require 'ceedling'` and any backwards compatibility. +# All path loading and related is handled from bin/ceedling. +# There is no shareable, library-worth code in lib/. +module Ceedling + # Emtpy +end \ No newline at end of file diff --git a/lib/ceedling/configurator.rb b/lib/ceedling/configurator.rb index aff78943..d41ce190 100644 --- a/lib/ceedling/configurator.rb +++ b/lib/ceedling/configurator.rb @@ -198,7 +198,7 @@ def tools_supplement_arguments(config) end - def find_and_merge_plugins(config) + def find_and_merge_plugins(plugins_load_path, config) # Plugins must be loaded before generic path evaluation & magic that happen later. # So, perform path magic here as discrete step. config[:plugins][:load_paths].each do |path| @@ -207,7 +207,7 @@ def find_and_merge_plugins(config) end # Add Ceedling's plugins path as load path so built-in plugins can be found - config[:plugins][:load_paths] << FilePathUtils::standardize( Ceedling.plugins_load_path ) + config[:plugins][:load_paths] << plugins_load_path config[:plugins][:load_paths].uniq! paths_hash = @configurator_plugins.process_aux_load_paths(config) diff --git a/lib/ceedling/setupinator.rb b/lib/ceedling/setupinator.rb index 3fc7d4db..aaf02d8f 100644 --- a/lib/ceedling/setupinator.rb +++ b/lib/ceedling/setupinator.rb @@ -42,7 +42,7 @@ def do_setup( app_cfg ) @ceedling[:configurator].eval_environment_variables( config_hash ) @ceedling[:configurator].eval_paths( config_hash ) @ceedling[:configurator].standardize_paths( config_hash ) - @ceedling[:configurator].find_and_merge_plugins( config_hash ) + @ceedling[:configurator].find_and_merge_plugins( app_cfg[:ceedling_plugins_path], config_hash ) @ceedling[:configurator].tools_setup( config_hash ) @ceedling[:configurator].validate_final( config_hash ) # Partially flatten config + build Configurator accessors and globals diff --git a/lib/ceedling/stream_wrapper.rb b/lib/ceedling/stream_wrapper.rb index 556109ce..0dfaec34 100644 --- a/lib/ceedling/stream_wrapper.rb +++ b/lib/ceedling/stream_wrapper.rb @@ -9,12 +9,13 @@ require 'io/nonblock' # If possible, capture standard data streams non-blocking mode at startup (to be restored at shutdown). - # A complex build setup may have intended this change, but it will cause trouble for Ceedling. + # A sophisticated build setup (e.g. CI) may have intended this change on either side of Ceedling, + # but it will cause trouble for Ceedling itself. if STDOUT.respond_to?(:nonblock?) # Non-blocking mode query not implemented on all platforms - STDIN_STARTUP_NONBLOCKING_MODE = (STDIN.nonblock?).freeze - STDOUT_STARTUP_NONBLOCKING_MODE = (STDOUT.nonblock?).freeze - STDERR_STARTUP_NONBLOCKING_MODE = (STDERR.nonblock?).freeze + STDIN_STARTUP_NONBLOCKING_MODE = (STDIN.nonblock?).freeze if !defined?( STDIN_STARTUP_NONBLOCKING_MODE ) + STDOUT_STARTUP_NONBLOCKING_MODE = (STDOUT.nonblock?).freeze if !defined?( STDOUT_STARTUP_NONBLOCKING_MODE ) + STDERR_STARTUP_NONBLOCKING_MODE = (STDERR.nonblock?).freeze if !defined?( STDERR_STARTUP_NONBLOCKING_MODE ) end # Ensure standard data streams are in blocking mode for Ceedling runs @@ -44,7 +45,7 @@ def stderr_puts(string) require 'io/nonblock' # If they were captured, reset standard data streams' non-blocking mode to the setting captured at startup - STDIN.nonblock = STDIN_STARTUP_NONBLOCKING_MODE if defined?(STDIN_STARTUP_NONBLOCKING_MODE) - STDOUT.nonblock = STDOUT_STARTUP_NONBLOCKING_MODE if defined?(STDOUT_STARTUP_NONBLOCKING_MODE) - STDERR.nonblock = STDERR_STARTUP_NONBLOCKING_MODE if defined?(STDERR_STARTUP_NONBLOCKING_MODE) + STDIN.nonblock = STDIN_STARTUP_NONBLOCKING_MODE if defined?( STDIN_STARTUP_NONBLOCKING_MODE ) + STDOUT.nonblock = STDOUT_STARTUP_NONBLOCKING_MODE if defined?( STDOUT_STARTUP_NONBLOCKING_MODE ) + STDERR.nonblock = STDERR_STARTUP_NONBLOCKING_MODE if defined?( STDERR_STARTUP_NONBLOCKING_MODE ) } diff --git a/lib/ceedling/version.rb b/lib/ceedling/version.rb index ec740351..afd7fa34 100644 --- a/lib/ceedling/version.rb +++ b/lib/ceedling/version.rb @@ -7,8 +7,9 @@ # # version.rb is run: -# - As a script to produce a Ceedling version number to $stdout in gem release builds +# - As a script to produce a Ceedling version number used in the release build process # - As a module of version constants consumed by Ceedling's command line version output +# - As a module of version constants consumed by Ceedling’s gem building process module Ceedling module Version @@ -41,7 +42,7 @@ module Version eval("#{name} = '#{a.join(".")}'") end - GEM = "0.3.2" + GEM = "0.32.0" CEEDLING = GEM # If run as a script, end with printing Ceedling’s version to $stdout diff --git a/spec/ceedling_spec.rb b/spec/ceedling_spec.rb deleted file mode 100644 index 8f74ff2f..00000000 --- a/spec/ceedling_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -# ========================================================================= -# Ceedling - Test-Centered Build System for C -# ThrowTheSwitch.org -# Copyright (c) 2010-24 Mike Karlesky, Mark VanderVoord, & Greg Williams -# SPDX-License-Identifier: MIT -# ========================================================================= - -require 'spec_helper' -require 'ceedling' - -describe 'Ceedling' do - context 'location' do - it 'should return the location of the ceedling gem directory' do - # create test state/variables - ceedling_path = File.expand_path( File.join( File.dirname(__FILE__), '..' ).gsub( 'spec','lib' ) ) - # mocks/stubs/expected calls - # execute method - location = Ceedling.location - # validate results - expect(location).to eq(ceedling_path) - end - end - - context 'plugins_load_path' do - it 'should return the location of the plugins directory' do - # create test state/variables - load_path = File.expand_path( File.join( File.dirname(__FILE__), '..' ).gsub( 'spec','lib' ) ) - load_path = File.join( load_path, 'plugins' ) - # mocks/stubs/expected calls - # execute method - location = Ceedling.plugins_load_path - # validate results - expect(location).to eq(load_path) - end - end - - context 'rakefile' do - it 'should return the location of the ceedling rakefile' do - # create test state/variables - rakefile_path = File.expand_path( File.join( File.dirname(__FILE__), '..' ).gsub( 'spec','lib' ) ) - rakefile_path = File.join( rakefile_path, 'lib', 'ceedling', 'rakefile.rb' ) - # mocks/stubs/expected calls - # execute method - location = Ceedling.rakefile - # validate results - expect(location).to eq(rakefile_path) - end - end -end - diff --git a/spec/spec_system_helper.rb b/spec/spec_system_helper.rb index 047153ee..08ccc48c 100644 --- a/spec/spec_system_helper.rb +++ b/spec/spec_system_helper.rb @@ -207,7 +207,7 @@ def can_upgrade_projects end end - def can_upgrade_projects_even_if_test_support_folder_does_not_exists + def can_upgrade_projects_even_if_test_support_folder_does_not_exist @c.with_context do output = `bundle exec ruby -S ceedling upgrade #{@proj_name} 2>&1` FileUtils.rm_rf("#{@proj_name}/test/support") diff --git a/spec/system/deployment_spec.rb b/spec/system/deployment_spec.rb index 471acae0..ba5c246c 100644 --- a/spec/system/deployment_spec.rb +++ b/spec/system/deployment_spec.rb @@ -122,7 +122,7 @@ it { can_test_projects_with_compile_error } it { can_upgrade_projects } - it { can_upgrade_projects_even_if_test_support_folder_does_not_exists } + it { can_upgrade_projects_even_if_test_support_folder_does_not_exist } it { contains_a_vendor_directory } it { does_not_contain_documentation } it { can_fetch_non_project_help }