Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test/0 32/streaminator for all #877

Merged
merged 4 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/project_as_gem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:use_mocks: TRUE
:use_test_preprocessor: TRUE
:use_backtrace: FALSE
:use_decorators: :auto #Decorate Ceedling's output text. Your options are :auto, :all, or :none

# tweak the way ceedling handles automatic tasks
:build_root: build
Expand Down
1 change: 1 addition & 0 deletions assets/project_with_guts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:use_mocks: TRUE
:use_test_preprocessor: TRUE
:use_backtrace: FALSE
:use_decorators: :auto #Decorate Ceedling's output text. Your options are :auto, :all, or :none

# tweak the way ceedling handles automatic tasks
:build_root: build
Expand Down
1 change: 1 addition & 0 deletions assets/project_with_guts_gcov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
:use_mocks: TRUE
:use_test_preprocessor: TRUE
:use_backtrace: FALSE
:use_decorators: :auto #Decorate Ceedling's output text. Your options are :auto, :all, or :none

# tweak the way ceedling handles automatic tasks
:build_root: build
Expand Down
72 changes: 70 additions & 2 deletions bin/ceedling
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,73 @@ CEEDLING_VENDOR = File.join( CEEDLING_ROOT, 'vendor' )
# Add load path for `require 'ceedling/*'` statements and bin/ code
$LOAD_PATH.unshift( CEEDLING_BIN, CEEDLING_LIB_BASE )

# Load "bootloader" / command line handling in bin/
require 'main'
require 'cli' # Located alongside this file in CEEDLING_BIN
require 'constructor' # Assumed installed via Ceedling gem dependencies
require 'app_cfg' # Located alongside this file in CEEDLING_BIN

CEEDLING_APPCFG = get_app_cfg()

# Entry point
begin
# Construct all bootloader objects
# 1. Add full path to $LOAD_PATH to simplify objects.yml
# 2. Add vendored DIY to $LOAD_PATH so we can use it
# 3. Require DIY (used by Ceedling application too)
# 4. Perform object construction + dependency injection from bin/objects.yml
# 5. Remove unneeded / potentially problematic paths from $LOAD_PATH
$LOAD_PATH.unshift( CEEDLING_LIB )
$LOAD_PATH.unshift( File.join(CEEDLING_VENDOR, 'diy/lib') )

require 'diy'
objects = DIY::Context.from_yaml( File.read( File.join( CEEDLING_BIN, 'objects.yml' ) ) )
objects.build_everything()

$LOAD_PATH.delete( CEEDLING_BIN ) # Loaded in top-level `ceedling` script
$LOAD_PATH.delete( CEEDLING_LIB )

# Keep a copy of the command line for edge case CLI hacking (Thor consumes ARGV)
_ARGV = ARGV.clone

#
# NOTE: See comment block in cli.rb to understand CLI handling
# ------------------------------------------------------------
#

# Backwards compatibility command line hack to silently preserve Rake `-T` CLI handling
if (ARGV.size() == 1 and ARGV[0] == '-T')
# Call Rake task listing handler w/ default handling of project file and mixins
objects[:cli_handler].rake_help( env:ENV, app_cfg:CEEDLING_APPCFG )

# Run command line args through Thor (including "naked" Rake tasks)
else
CeedlingTasks::CLI.start( ARGV,
{
:app_cfg => CEEDLING_APPCFG,
:objects => objects,
}
)
end

# Handle case of Thor application CLI failing to handle command line arguments.
rescue Thor::UndefinedCommandError
# Marrying Thor & Rake command line handling creates a gap (see comments in CLI handling).
# If a user enters only Rake build tasks at the command line followed by Thor flags,
# our Thor configuration doesn't see those flags.
# We catch the exception of unrecognized Thor commands here (i.e. any "naked" Rake tasks),
# and try again by forcing the Thor `build` command at the beginning of the command line.
# This way, our Thor handling will process option flags and properly pass the Rake tasks
# along as well.
CeedlingTasks::CLI.start( _ARGV.unshift( 'build' ),
{
:app_cfg => CEEDLING_APPCFG,
:objects => objects,
}
)

# Bootloader boom handling (ideally this never runs... we failed to build much if we're here)
rescue StandardError => e
$stderr.puts( "\nERROR: #{e.message}" )
$stderr.puts( e.backtrace ) if ( defined?( PROJECT_DEBUG ) and PROJECT_DEBUG )
exit(1)
end

2 changes: 1 addition & 1 deletion bin/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def upgrade(path)
\x5 > ceedling build test:all

TASKS are zero or more build operations created from your project configuration.
If no tasks are provided, the built-in default tasks or your :project
If no tasks are provided, the built-in default tasks or your :project ->
:default_tasks will be executed.

Optional Flags:
Expand Down
48 changes: 28 additions & 20 deletions bin/cli_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class CliHandler

constructor :configinator, :projectinator, :cli_helper, :path_validator, :actions_wrapper, :logger
constructor :configinator, :projectinator, :cli_helper, :path_validator, :actions_wrapper, :streaminator

# Override to prevent exception handling from walking & stringifying the object variables.
# Object variables are lengthy and produce a flood of output.
Expand All @@ -24,13 +24,13 @@ def app_help(env, app_cfg, options, command, &thor_help)
# If help requested for a command, show it and skip listing build tasks
if !command.nil?
# Block handler
@logger._print( '🌱 Application ' )
@streaminator.stream_puts( 'Ceedling Application ' )
thor_help.call( command ) if block_given?
return
end

# Display Thor-generated help listing
@logger._print( '🌱 Application ' )
@streaminator.stream_puts( 'Ceedling Application ' )
thor_help.call( command ) if block_given?

# If it was help for a specific command, we're done
Expand Down Expand Up @@ -90,7 +90,7 @@ def new_project(ceedling_root, options, name, dest)
@actions._touch_file( File.join(dest, 'test/support', '.gitkeep') )
end

@logger.log( "\n🌱 New project '#{name}' created at #{dest}/\n" )
@streaminator.stream_puts( "\nNew project '#{name}' created at #{dest}/\n" )
end


Expand All @@ -104,7 +104,7 @@ def upgrade_project(ceedling_root, options, path)
end

project_filepath = File.join( path, options[:project] )
_, config = @projectinator.load( filepath:project_filepath, silent:true )
_, config = @projectinator.load( filepath:project_filepath )

if (@helper.which_ceedling?( config ) == 'gem')
msg = "Project configuration specifies the Ceedling gem, not vendored Ceedling"
Expand All @@ -124,7 +124,7 @@ def upgrade_project(ceedling_root, options, path)
@helper.copy_docs( ceedling_root, path )
end

@logger.log( "\n🌱 Upgraded project at #{path}/\n" )
@streaminator.stream_puts( "\nUpgraded project at #{path}/\n" )
end


Expand All @@ -146,6 +146,16 @@ def build(env:, app_cfg:, options:{}, tasks:)
)

log_filepath = @helper.process_logging( options[:log], options[:logfile] )
if (config[:project] && config[:project][:use_decorators])
case config[:project][:use_decorators]
when :all
@streaminator.decorate(true)
when :none
@streaminator.decorate(false)
else #includes :auto
#nothing more to do. we've already figured out auto
end
end

# Save references
app_cfg[:project_config] = config
Expand Down Expand Up @@ -200,11 +210,11 @@ def dumpconfig(env, app_cfg, options, filepath, sections)
default_tasks: default_tasks
)
else
@logger.log( " > Skipped loading Ceedling application" )
@streaminator.stream_puts( " > Skipped loading Ceedling application", Verbosity::OBNOXIOUS )
end
ensure
@helper.dump_yaml( config, filepath, sections )
@logger.log( "\n🌱 Dumped project configuration to #{filepath}\n" )
@streaminator.stream_puts( "\nDumped project configuration to #{filepath}\n" )
end
end

Expand Down Expand Up @@ -242,13 +252,13 @@ def environment(env, app_cfg, options)
end
end

output = "\n🌱 Environment variables:\n"
output = "\nEnvironment variables:\n"

env_list.sort.each do |line|
output << " • #{line}\n"
end

@logger.log( output + "\n")
@streaminator.stream_puts( output + "\n" )
end


Expand All @@ -257,11 +267,11 @@ def list_examples(examples_path)

raise( "No examples projects found") if examples.empty?

output = "\n🌱 Available example projects:\n"
output = "\nAvailable example projects:\n"

examples.each {|example| output << " • #{example}\n" }

@logger.log( output + "\n" )
@streaminator.stream_puts( output + "\n" )
end


Expand Down Expand Up @@ -294,19 +304,19 @@ def create_example(ceedling_root, examples_path, options, name, dest)
# Copy in documentation
@helper.copy_docs( ceedling_root, dest ) if options[:docs]

@logger.log( "\n🌱 Example project '#{name}' created at #{dest}/\n" )
@streaminator.stream_puts( "\nExample project '#{name}' created at #{dest}/\n" )
end


def version()
require 'ceedling/version'
version = <<~VERSION
🌱 Ceedling => #{Ceedling::Version::CEEDLING}
Ceedling => #{Ceedling::Version::CEEDLING}
CMock => #{Ceedling::Version::CMOCK}
Unity => #{Ceedling::Version::UNITY}
CException => #{Ceedling::Version::CEXCEPTION}
VERSION
@logger.log( version )
@streaminator.stream_puts( version )
end


Expand All @@ -319,21 +329,19 @@ def list_rake_tasks(env:, app_cfg:, filepath:nil, mixins:[])
@configinator.loadinate(
filepath: filepath,
mixins: mixins,
env: env,
silent: true # Suppress project config load logging
env: env
)

# Save reference to loaded configuration
app_cfg[:project_config] = config

@logger.log( "🌱 Build & Plugin Tasks:\n(Parameterized tasks tend to require enclosing quotes and/or escape sequences in most shells)" )
@streaminator.stream_puts( "Ceedling Build & Plugin Tasks:\n(Parameterized tasks tend to require enclosing quotes and/or escape sequences in most shells)" )

@helper.load_ceedling(
project_filepath: project_filepath,
config: config,
which: app_cfg[:which_ceedling],
default_tasks: app_cfg[:default_tasks],
silent: true
default_tasks: app_cfg[:default_tasks]
)

@helper.print_rake_tasks()
Expand Down
27 changes: 16 additions & 11 deletions bin/cli_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

class CliHelper

constructor :file_wrapper, :actions_wrapper, :config_walkinator, :path_validator, :logger
constructor :file_wrapper, :actions_wrapper, :config_walkinator, :path_validator, :streaminator

def setup
#Aliases
@actions = @actions_wrapper

@streaminator.decorate( !windows? )
end


Expand Down Expand Up @@ -47,10 +49,10 @@ def which_ceedling?(config)
end


def load_ceedling(project_filepath:, config:, which:, default_tasks:[], silent:false)
def load_ceedling(project_filepath:, config:, which:, default_tasks:[])
# Determine which Ceedling we're running
# 1. Copy the which value passed in (most likely a default determined in the first moments of startup)
# 2. If a :project :which_ceedling entry exists in the config, use it instead
# 2. If a :project -> :which_ceedling entry exists in the config, use it instead
_which = which.dup()
walked = @config_walkinator.fetch_value( config, :project, :which_ceedling )
_which = walked[:value] if !walked[:value].nil?
Expand All @@ -70,18 +72,18 @@ def load_ceedling(project_filepath:, config:, which:, default_tasks:[], silent:f
ceedling_path = File.expand_path( ceedling_path )

if !@file_wrapper.directory?( ceedling_path )
raise "Configuration value :project :which_ceedling => '#{_which}' points to a path relative to your project file that contains no Ceedling installation"
raise "Configuration value :project -> :which_ceedling => '#{_which}' points to a path relative to your project file that contains no Ceedling installation"
end

# Otherwise, :which_ceedling is an absolute path
else
if !@file_wrapper.exist?( ceedling_path )
raise "Configuration value :project :which_ceedling => '#{_which}' points to a path that contains no Ceedling installation"
raise "Configuration value :project -> :which_ceedling => '#{_which}' points to a path that contains no Ceedling installation"
end
end

require( File.join( ceedling_path, '/lib/ceedling.rb' ) )
@logger.log( " > Running Ceedling from #{ceedling_path}/" ) if !silent
@streaminator.stream_puts( " > Running Ceedling from #{ceedling_path}/", Verbosity::OBNOXIOUS )
end

# Set default tasks
Expand Down Expand Up @@ -189,6 +191,9 @@ def run_rake_tasks(tasks)
def set_verbosity(verbosity=nil)
verbosity = verbosity.nil? ? Verbosity::NORMAL : VERBOSITY_OPTIONS[verbosity.to_sym()]

# If we already set verbosity, there's nothing more to do here
return if Object.const_defined?('PROJECT_VERBOSITY')

# Create global constant PROJECT_VERBOSITY
Object.module_eval("PROJECT_VERBOSITY = verbosity")
PROJECT_VERBOSITY.freeze()
Expand Down Expand Up @@ -216,7 +221,7 @@ def dump_yaml(config, filepath, sections)
if walked[:value].nil?
# Reformat list of symbols to list of :<section>s
_sections.map! {|section| ":#{section.to_s}"}
msg = "Cound not find configuration section #{_sections.join(' ')}"
msg = "Cound not find configuration section #{_sections.join(' -> ')}"
raise(msg)
end

Expand Down Expand Up @@ -396,9 +401,9 @@ def vendor_tools(ceedling_root, dest)

private

def windows?
return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?( RbConfig )
return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false)
end
def windows?
return ((RbConfig::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false) if defined?( RbConfig )
return ((Config::CONFIG['host_os'] =~ /mswin|mingw/) ? true : false)
end

end
8 changes: 4 additions & 4 deletions bin/configinator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ class Configinator

constructor :config_walkinator, :projectinator, :mixinator

def loadinate(filepath:nil, mixins:[], env:{}, silent:false)
def loadinate(filepath:nil, mixins:[], env:{})
# Aliases for clarity
cmdline_filepath = filepath
cmdline_mixins = mixins || []

# Load raw config from command line, environment variable, or default filepath
project_filepath, config = @projectinator.load( filepath:cmdline_filepath, env:env, silent:silent )
project_filepath, config = @projectinator.load( filepath:cmdline_filepath, env:env )

# Extract cfg_enabled_mixins mixins list plus load paths list from config
cfg_enabled_mixins, cfg_load_paths = @projectinator.extract_mixins(
Expand All @@ -36,7 +36,7 @@ def loadinate(filepath:nil, mixins:[], env:{}, silent:false)
if not @projectinator.validate_mixins(
mixins: cfg_enabled_mixins,
load_paths: cfg_load_paths,
source: 'Config :mixins :enabled =>',
source: 'Config :mixins -> :enabled =>',
yaml_extension: yaml_ext
)
raise 'Project configuration file section :mixins failed validation'
Expand Down Expand Up @@ -82,7 +82,7 @@ def loadinate(filepath:nil, mixins:[], env:{}, silent:false)
)

# Merge mixins
@mixinator.merge( config:config, mixins:mixins_assembled, silent:silent )
@mixinator.merge( config:config, mixins:mixins_assembled )

return project_filepath, config
end
Expand Down
Loading
Loading