Skip to content

Commit

Permalink
Refactoring for application install file path handling
Browse files Browse the repository at this point in the history
- Removed all global constant filepaths
- Centralized all application paths into CeedlingApplicationConfig object that can be updated from :which_ceedling settings
- Streamlined and centralized which Ceedling handling
- Added WHICH_CEEDLING environment variable to support developer needs or unusual build scenarios and match the basic flow of processing project file configuration handling options
  • Loading branch information
mkarlesky committed Apr 19, 2024
1 parent 579dd44 commit 3e34262
Show file tree
Hide file tree
Showing 16 changed files with 287 additions and 184 deletions.
2 changes: 1 addition & 1 deletion bin/actions_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ActionsWrapper
include Thor::Base
include Thor::Actions

source_root( CEEDLING_ROOT )
# Most important mixin method is Thor::Actions class method `source_root()` we call externally

def _directory(src, *args)
directory( src, *args )
Expand Down
105 changes: 82 additions & 23 deletions bin/app_cfg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,97 @@
# SPDX-License-Identifier: MIT
# =========================================================================

require "io/console"

# Create our global application configuration option set
# This approach bridges clean Ruby and Rake
def get_app_cfg()
require "io/console"

app_cfg = {
# Blank initial value for completeness
:project_config => {},
class CeedlingAppConfig

def initialize()
# Installation location determined from the location of this file
ceedling_root_path = File.expand_path( File.join( File.dirname( __FILE__ ), '..' ) )

# Create internal hash of needed values
@app_cfg = {
# Base path of any Ceedling installation
:ceedling_root_path => '',

# Ceedling installation base path + /lib
:ceedling_lib_base_path => '',

# Ceedling installation base path + /lib/ceedling
:ceedling_lib_path => '',

# Ceedling installation base path + /vendor
:ceedling_vendor_path => '',

# Ceedling installation base path + /examples
:ceedling_examples_path => '',

# Blank initial value for completeness
:project_config => {},

# Default, blank value
:log_filepath => '',

# Only specified in project config (no command line or environment variable)
:default_tasks => ['test:all'],

# Default, blank test case filters
:include_test_case => '',
:exclude_test_case => '',

# Default to no duration logging for setup & build ops in Rake context
:stopwatch => false,

# Default to `exit(1)` upon failing test cases
:tests_graceful_fail => false,

# Get terminal width in columns
:terminal_width => (IO.console.winsize)[1],
}

set_paths( ceedling_root_path )
end

def set_project_config(config)
@app_cfg[:project_config] = config
end

def set_log_filepath(filepath)
@app_cfg[:log_filepath] = filepath
end

# Default, blank value
:log_filepath => '',
def set_include_test_case(matcher)
@app_cfg[:include_test_case] = matcher
end

# Only specified in project config (no command line or environment variable)
:default_tasks => ['test:all'],
def set_exclude_test_case(matcher)
@app_cfg[:exclude_test_case] = matcher
end

# Basic check from working directory
# If vendor/ceedling exists, default to running vendored Ceedling
:which_ceedling => (Dir.exist?( 'vendor/ceedling' ) ? 'vendor/ceedling' : 'gem'),
def set_stopwatch(enable)
@app_cfg[:stopwatch] = enable
end

# Default, blank test case filters
:include_test_case => '',
:exclude_test_case => '',
def set_tests_graceful_fail(enable)
@app_cfg[:tests_graceful_fail] = enable
end

# Default to no duration logging for setup & build ops in Rake context
:stopwatch => false,
def set_paths(root_path)
lib_base_path = File.join( root_path, 'lib' )

# Default to `exit(1)` upon failing test cases
:tests_graceful_fail => false,
@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' )
end

# Get terminal width in columns
:terminal_width => (IO.console.winsize)[1],
}
# External accessor to preserve hash-like read accesses
def [](key)
return @app_cfg[key]
end

return app_cfg
end
41 changes: 25 additions & 16 deletions bin/ceedling
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,47 @@

require 'rubygems'

CEEDLING_ROOT = File.expand_path( File.join( File.dirname( __FILE__ ), ".." ) )
CEEDLING_BIN = File.join( CEEDLING_ROOT, 'bin' )
CEEDLING_LIB_BASE = File.join( CEEDLING_ROOT, 'lib' )
CEEDLING_LIB = File.join( CEEDLING_LIB_BASE, 'ceedling' )
CEEDLING_VENDOR = File.join( CEEDLING_ROOT, 'vendor' )
# Get the path for our current code directory
ceedling_bin_path = File.expand_path( File.join( File.dirname( __FILE__ ), '..', 'bin' ) )

# Add load path for `require 'ceedling/*'` statements and bin/ code
$LOAD_PATH.unshift( CEEDLING_BIN, CEEDLING_LIB_BASE )
# Add load path so we can `require` files in bin/
$LOAD_PATH.unshift( ceedling_bin_path )

# Pull in our startup configuration code in bin/
require 'app_cfg'
CEEDLING_APPCFG = CeedlingAppConfig.new()

# Add load paths for `require 'ceedling/*'` statements in bin/ code
$LOAD_PATH.unshift( CEEDLING_APPCFG[:ceedling_lib_base_path] )

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
diy_vendor_path = File.join( CEEDLING_APPCFG[:ceedling_vendor_path], 'diy/lib' )

# 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') )
# 5. Remove all paths added to $LOAD_PATH
# (Main application will restore certain paths -- possibly updated by :which_ceedling)
$LOAD_PATH.unshift(
CEEDLING_APPCFG[:ceedling_lib_path],
diy_vendor_path
)

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

$LOAD_PATH.delete( CEEDLING_BIN ) # Loaded in top-level `ceedling` script
$LOAD_PATH.delete( CEEDLING_LIB )
# Remove all load paths we've relied on (main application will set up load paths again)
$LOAD_PATH.delete( ceedling_bin_path )
$LOAD_PATH.delete( CEEDLING_APPCFG[:ceedling_lib_path] )
$LOAD_PATH.delete( diy_vendor_path )

# Keep a copy of the command line for edge case CLI hacking (Thor consumes ARGV)
_ARGV = ARGV.clone
Expand Down
12 changes: 5 additions & 7 deletions bin/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ module CeedlingTasks
YAML file. See documentation for complete details.
\x5> --mixin my_compiler --mixin my/path/mixin.yml"

CEEDLING_EXAMPLES_PATH = File.join( CEEDLING_ROOT, 'examples' )

class CLI < Thor
include Thor::Actions
extend PermissiveCLI
Expand Down Expand Up @@ -185,7 +183,7 @@ def new(name, dest=nil)

_options[:verbosity] = options[:debug] ? VERBOSITY_DEBUG : nil

@handler.new_project( CEEDLING_ROOT, _options, name, _dest )
@handler.new_project( ENV, @app_cfg, _options, name, _dest )
end


Expand All @@ -198,7 +196,7 @@ def new(name, dest=nil)
PATH is required and should be the root of the project to upgrade.
This command only meaningfully operates on projects wth a local vendored copy
of Ceedlng (in <project>/vendor/) and optionally documentation (in
of Ceedling (in <project>/vendor/) and optional documentation (in
<project>/docs/).
Running this command replaces vendored Ceedling with the version running
Expand All @@ -222,7 +220,7 @@ def upgrade(path)

_options[:verbosity] = options[:debug] ? VERBOSITY_DEBUG : nil

@handler.upgrade_project( CEEDLING_ROOT, _options, _path )
@handler.upgrade_project( ENV, @app_cfg, _options, _path )
end


Expand Down Expand Up @@ -336,7 +334,7 @@ def environment()
to extract an example project to your filesystem.
LONGDESC
def examples()
@handler.list_examples( CEEDLING_EXAMPLES_PATH )
@handler.list_examples( ENV, @app_cfg )
end


Expand Down Expand Up @@ -369,7 +367,7 @@ def example(name, dest=nil)

_options[:verbosity] = options[:debug] ? VERBOSITY_DEBUG : nil

@handler.create_example( CEEDLING_ROOT, CEEDLING_EXAMPLES_PATH, _options, name, _dest )
@handler.create_example( ENV, @app_cfg, _options, name, _dest )
end


Expand Down
Loading

0 comments on commit 3e34262

Please sign in to comment.