feat: ✨ begin the repo a bit late but better than never
This commit is contained in:
commit
607159334b
22 changed files with 898 additions and 0 deletions
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
/.bundle/
|
||||
/.yardoc
|
||||
/_yardoc/
|
||||
/coverage/
|
||||
/doc/
|
||||
/pkg/
|
||||
/spec/reports/
|
||||
/tmp/
|
13
.rubocop.yml
Normal file
13
.rubocop.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
AllCops:
|
||||
TargetRubyVersion: 2.6
|
||||
|
||||
Style/StringLiterals:
|
||||
Enabled: true
|
||||
EnforcedStyle: double_quotes
|
||||
|
||||
Style/StringLiteralsInInterpolation:
|
||||
Enabled: true
|
||||
EnforcedStyle: double_quotes
|
||||
|
||||
Layout/LineLength:
|
||||
Max: 120
|
14
Gemfile
Normal file
14
Gemfile
Normal file
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
# Specify your gem's dependencies in comfpile.gemspec
|
||||
gemspec
|
||||
|
||||
gem "rake", "~> 13.0"
|
||||
gem "pry"
|
||||
|
||||
gem "minitest", "~> 5.0"
|
||||
gem "debug", "~> 1.0"
|
||||
|
||||
gem "rubocop", "~> 1.21"
|
59
Gemfile.lock
Normal file
59
Gemfile.lock
Normal file
|
@ -0,0 +1,59 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
comfpile (0.1.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ast (2.4.2)
|
||||
coderay (1.1.3)
|
||||
debug (1.6.2)
|
||||
irb (>= 1.3.6)
|
||||
reline (>= 0.3.1)
|
||||
io-console (0.5.11)
|
||||
irb (1.4.1)
|
||||
reline (>= 0.3.0)
|
||||
json (2.6.3)
|
||||
method_source (1.0.0)
|
||||
minitest (5.18.0)
|
||||
parallel (1.22.1)
|
||||
parser (3.2.1.1)
|
||||
ast (~> 2.4.1)
|
||||
pry (0.14.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
regexp_parser (2.7.0)
|
||||
reline (0.3.1)
|
||||
io-console (~> 0.5)
|
||||
rexml (3.2.5)
|
||||
rubocop (1.48.0)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.26.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.27.0)
|
||||
parser (>= 3.2.1.0)
|
||||
ruby-progressbar (1.13.0)
|
||||
unicode-display_width (2.4.2)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
comfpile!
|
||||
debug (~> 1.0)
|
||||
minitest (~> 5.0)
|
||||
pry
|
||||
rake (~> 13.0)
|
||||
rubocop (~> 1.21)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.22
|
29
README.md
Normal file
29
README.md
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Comfpile
|
||||
|
||||
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/comfpile`. To experiment with that code, run `bin/console` for an interactive prompt.
|
||||
|
||||
TODO: Delete this and the text above, and describe your gem
|
||||
|
||||
## Installation
|
||||
|
||||
Install the gem and add to the application's Gemfile by executing:
|
||||
|
||||
$ bundle add comfpile
|
||||
|
||||
If bundler is not being used to manage dependencies, install the gem by executing:
|
||||
|
||||
$ gem install comfpile
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Write usage instructions here
|
||||
|
||||
## Development
|
||||
|
||||
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
||||
|
||||
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
||||
|
||||
## Contributing
|
||||
|
||||
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/comfpile.
|
16
Rakefile
Normal file
16
Rakefile
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "bundler/gem_tasks"
|
||||
require "rake/testtask"
|
||||
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.libs << "test"
|
||||
t.libs << "lib"
|
||||
t.test_files = FileList["test/**/test_*.rb"]
|
||||
end
|
||||
|
||||
require "rubocop/rake_task"
|
||||
|
||||
RuboCop::RakeTask.new
|
||||
|
||||
task default: %i[test rubocop]
|
101
bin/console
Executable file
101
bin/console
Executable file
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "bundler/setup"
|
||||
require "comfpile"
|
||||
|
||||
# You can add fixtures and/or initialization code here to make experimenting
|
||||
# with your gem easier. You can also use a different console, if you like.
|
||||
|
||||
$core = Comfpile::Core.new()
|
||||
|
||||
`mkdir /tmp/test`
|
||||
`touch /tmp/test/main.cpp`
|
||||
|
||||
`mkdir /tmp/test2/`
|
||||
`touch /tmp/test2/main.cpp`
|
||||
|
||||
$core.add_artefact_engine Comfpile::FilesourceEngine, root_path: "/tmp/test2"
|
||||
$core.add_artefact_engine Comfpile::FilesourceEngine, root_path: "/tmp/test"
|
||||
|
||||
|
||||
$core.add_artefact_engine do |engine|
|
||||
engine.add_recipe(:parsed, /^(.+)\.(h|c|cpp)$/) do |match, a|
|
||||
|
||||
a.parent_artefact :sourcefile, a.target
|
||||
|
||||
a.add_step do
|
||||
puts "Parsing file #{@target}..."
|
||||
|
||||
@linked_artefacts = []
|
||||
|
||||
File.readlines(@required_artefacts[:sourcefile][@target][:file]).each do |l|
|
||||
case l
|
||||
when /^#include\s*[<"](.+)[>"]/
|
||||
|
||||
puts "Got include for file #{$1}!"
|
||||
@linked_artefacts << craft_artefact(:parsed, $1)
|
||||
|
||||
when /\/\/+\s*require\s*[<"]((?:.+)\.(?:c|cpp))[>"]/
|
||||
puts "Got require for file #{$1}!"
|
||||
@linked_artefacts << require_artefact(:parsed, $1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
engine.add_recipe(:dependency_list, /^(.+)\.(h|c|cpp)$/) do |match, a|
|
||||
a.parent_artefact :parsed, a.target
|
||||
|
||||
a.add_step do
|
||||
puts "Generating dependency list for #{@target}..."
|
||||
|
||||
parsed_marker = {}
|
||||
parsing_list = [@parent_artefact]
|
||||
|
||||
loop do
|
||||
break if parsing_list.empty?
|
||||
a = parsing_list.pop
|
||||
|
||||
next if a.nil?
|
||||
next unless a.stage == :parsed
|
||||
next unless a.succeeded?
|
||||
|
||||
next if parsed_marker[a.target]
|
||||
parsed_marker[a.target] = true
|
||||
|
||||
parsing_list += a.linked_artefacts
|
||||
end
|
||||
|
||||
@parameters[:dependency_list] = parsed_marker.keys
|
||||
end
|
||||
end
|
||||
|
||||
engine.add_recipe(:x86_debug, /^run (.+)/) do |match, a|
|
||||
|
||||
a.require_artefact :parsed, "#{match[1]}.cpp"
|
||||
end
|
||||
|
||||
engine.add_recipe(:x86_debug, /(.+)\.o$/) do |match, a|
|
||||
a.require_artefact :sourcefile, "#{match[1]}.cpp"
|
||||
|
||||
a.add_step do
|
||||
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
$tst = $core.craft_artefact(:dependency_list, "main.cpp");
|
||||
|
||||
50.times do
|
||||
$core.execute_step
|
||||
end
|
||||
|
||||
puts "Dependency list is: #{$tst[:dependency_list]}"
|
||||
|
||||
# (If you use this, don't forget to add pry to your Gemfile!)
|
||||
require "pry"
|
||||
Pry.start
|
||||
|
8
bin/setup
Executable file
8
bin/setup
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
set -vx
|
||||
|
||||
bundle install
|
||||
|
||||
# Do any other automated setup that you need to do here
|
8
comfpile.code-workspace
Normal file
8
comfpile.code-workspace
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": ".."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
35
comfpile.gemspec
Normal file
35
comfpile.gemspec
Normal file
|
@ -0,0 +1,35 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "lib/comfpile/version"
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "comfpile"
|
||||
spec.version = Comfpile::VERSION
|
||||
spec.authors = ["David Bailey"]
|
||||
spec.email = ["davidbailey.2889@gmail.com"]
|
||||
|
||||
spec.summary = "Comfortably compile source code together"
|
||||
spec.description = "Compile based on simple, understandable source dependencies in-sourcecode, rather than a makefile or whatever other hot mess."
|
||||
spec.homepage = "https://github.com/lucidergs/comfpile"
|
||||
spec.required_ruby_version = ">= 2.6.0"
|
||||
|
||||
spec.metadata["homepage_uri"] = spec.homepage
|
||||
spec.metadata["source_code_uri"] = spec.homepage
|
||||
|
||||
# Specify which files should be added to the gem when it is released.
|
||||
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
||||
spec.files = Dir.chdir(__dir__) do
|
||||
`git ls-files -z`.split("\x0").reject do |f|
|
||||
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
||||
end
|
||||
end
|
||||
spec.bindir = "exe"
|
||||
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
# Uncomment to register a new dependency of your gem
|
||||
# spec.add_dependency "example-gem", "~> 1.0"
|
||||
|
||||
# For more information and examples about making a new gem, check out our
|
||||
# guide at: https://bundler.io/guides/creating_gem.html
|
||||
end
|
12
lib/comfpile.rb
Normal file
12
lib/comfpile.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "comfpile/version"
|
||||
|
||||
require_relative 'comfpile/core.rb'
|
||||
|
||||
require_relative 'comfpile/engines/filesource_engine.rb'
|
||||
|
||||
module Comfpile
|
||||
class Error < StandardError; end
|
||||
# Your code goes here...
|
||||
end
|
216
lib/comfpile/artefact.rb
Normal file
216
lib/comfpile/artefact.rb
Normal file
|
@ -0,0 +1,216 @@
|
|||
|
||||
require 'debug'
|
||||
|
||||
module Comfpile
|
||||
class ArtefactExecSkipError < StandardError
|
||||
end
|
||||
|
||||
class Artefact
|
||||
attr_reader :core, :engine
|
||||
|
||||
attr_reader :exit_state
|
||||
attr_reader :stage, :target
|
||||
|
||||
attr_reader :linked_artefacts
|
||||
|
||||
# ARTEFACT STATES
|
||||
#
|
||||
# The following states are known to the system:
|
||||
# - blocked: The Artefact is blocked and waiting on other artefacts
|
||||
# - waiting: The Artefact is idle and ready to be queued
|
||||
# - running: The Artefact is currently being run
|
||||
# Note that this is not a state, but is determined by the
|
||||
# @running flag
|
||||
# - succeeded: it has finished its work without issue
|
||||
# - skipped: it didn't run/won't run because of failed dependencies
|
||||
# - failed: it has failed due to a requirement not being met
|
||||
#
|
||||
# Meta-States exist:
|
||||
# - in_progress/completed: Anything but/Only succeeded, skipped, failed
|
||||
|
||||
def initialize(core, engine, stage, target)
|
||||
@core = core
|
||||
@engine = engine
|
||||
|
||||
@stage = stage
|
||||
@target = target
|
||||
|
||||
@age = Time.at(0)
|
||||
|
||||
@parent_artefact = nil
|
||||
|
||||
@required_artefacts = nil
|
||||
@linked_artefacts = nil
|
||||
|
||||
@steps = []
|
||||
@step_additions = nil
|
||||
|
||||
@waitlist = []
|
||||
|
||||
@steps_done_ctr = 0
|
||||
|
||||
@parameters = {}
|
||||
|
||||
@exit_state = nil
|
||||
@running = false
|
||||
end
|
||||
|
||||
def [](key)
|
||||
v = @parameters[key]
|
||||
return v unless v.nil?
|
||||
|
||||
if @parent_artefact
|
||||
return @parent_artefact[key]
|
||||
end
|
||||
end
|
||||
def []=(key, value)
|
||||
@parameters[key] = value
|
||||
end
|
||||
|
||||
private def add_step_data(data)
|
||||
@step_additions ||= []
|
||||
|
||||
@step_additions << data
|
||||
end
|
||||
private def process_additional_step_data
|
||||
unless @step_additions.nil?
|
||||
@steps.insert(@steps_done_ctr, @step_additions)
|
||||
@steps.flatten!
|
||||
@step_additions = nil
|
||||
end
|
||||
end
|
||||
|
||||
def add_step(&block)
|
||||
add_step_data({
|
||||
type: :block,
|
||||
executed: false,
|
||||
block: block
|
||||
})
|
||||
end
|
||||
|
||||
def parent_artefact(stage, target)
|
||||
@parent_artefact = require_artefact(stage, target)
|
||||
end
|
||||
|
||||
def require_artefact(stage, target)
|
||||
artefact = @core.craft_artefact(stage, target)
|
||||
|
||||
if(artefact.nil?)
|
||||
fail! "Missing artefact dependency for #{stage} #{target}!"
|
||||
else
|
||||
@waitlist << {
|
||||
artefact: artefact,
|
||||
required: true
|
||||
}
|
||||
end
|
||||
|
||||
@required_artefacts ||= {}
|
||||
@required_artefacts[stage] ||= {}
|
||||
@required_artefacts[stage][target] = artefact
|
||||
|
||||
artefact
|
||||
end
|
||||
|
||||
def craft_artefact(stage, target)
|
||||
artefact = @core.craft_artefact(stage, target)
|
||||
|
||||
artefact
|
||||
end
|
||||
|
||||
def waitlist_empty?
|
||||
return true if completed?
|
||||
|
||||
loop do
|
||||
return true if @waitlist.empty?
|
||||
|
||||
item = @waitlist[-1]
|
||||
|
||||
return false if item[:artefact].in_progress?
|
||||
|
||||
if not item[:required]
|
||||
@waitlist.pop
|
||||
elsif item[:artefact].succeeded?
|
||||
@waitlist.pop
|
||||
else
|
||||
skip! skip! "Failed artefact dependency: #{item[:artefact]}"
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def state
|
||||
return :blocked unless waitlist_empty?
|
||||
return @exit_state unless @exit_state.nil?
|
||||
|
||||
return :running if @running
|
||||
|
||||
return :waiting
|
||||
end
|
||||
|
||||
def completed?
|
||||
not @exit_state.nil?
|
||||
end
|
||||
|
||||
def succeeded?
|
||||
@exit_state == :succeeded
|
||||
end
|
||||
|
||||
def in_progress?
|
||||
not completed?
|
||||
end
|
||||
|
||||
def waiting?
|
||||
self.state == :waiting
|
||||
end
|
||||
|
||||
private def mark_state_change(state, reason, abort: false)
|
||||
puts "#{@stage} #{target}: Reached state #{state}: #{reason}"
|
||||
@exit_state = state
|
||||
@reason = reason
|
||||
|
||||
abort_step! if abort
|
||||
end
|
||||
|
||||
def skip!(reason, **opts)
|
||||
mark_state_change(:skipped, reason, **opts)
|
||||
end
|
||||
def fail!(reason, **opts)
|
||||
mark_state_change(:failed, reason, **opts)
|
||||
end
|
||||
def succeed!(reason, **opts)
|
||||
mark_state_change(:succeeded, reason, **opts)
|
||||
end
|
||||
|
||||
def abort_step!
|
||||
raise ArtefactExecSkipError
|
||||
end
|
||||
|
||||
def execute_step
|
||||
return unless waiting?
|
||||
@running = true
|
||||
|
||||
process_additional_step_data
|
||||
|
||||
next_step = @steps[@steps_done_ctr]
|
||||
succeed! "All done", abort: true if next_step.nil?
|
||||
|
||||
case next_step[:type]
|
||||
when :block
|
||||
instance_exec &next_step[:block]
|
||||
else
|
||||
fail! "Unknown artefact step taken!", abort: true
|
||||
end
|
||||
|
||||
@steps_done_ctr += 1
|
||||
succeed! "All done", abort: true if @steps_done_ctr >= @steps.length
|
||||
|
||||
ensure
|
||||
@running = false
|
||||
end
|
||||
|
||||
def to_s
|
||||
"#<Compfile::Artefact #{@stage} #{@target}>"
|
||||
end
|
||||
end
|
||||
end
|
60
lib/comfpile/artefact_engine.rb
Normal file
60
lib/comfpile/artefact_engine.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
require_relative 'artefact.rb'
|
||||
|
||||
module Comfpile
|
||||
class ArtefactEngine
|
||||
|
||||
attr_accessor :priority, :subpriority
|
||||
|
||||
def initialize(core, **options)
|
||||
@core = core
|
||||
|
||||
@priority = options[:priority] || 0
|
||||
@subpriority = options[:subpriority] || 0
|
||||
|
||||
@recipes = []
|
||||
end
|
||||
|
||||
def craft(stage, target)
|
||||
@recipes.each do |recipe|
|
||||
match = target
|
||||
|
||||
if recipe[:stage]
|
||||
next unless stage == recipe[:stage]
|
||||
end
|
||||
|
||||
if r = recipe[:regex]
|
||||
if r.is_a? String
|
||||
next unless target == r
|
||||
else
|
||||
match = r.match target
|
||||
next if match.nil?
|
||||
end
|
||||
end
|
||||
|
||||
new_artefact = Artefact.new(@core, self, stage, target)
|
||||
|
||||
item = recipe[:block].call(match, new_artefact)
|
||||
|
||||
return new_artefact if item
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
prio = other.priority <=> self.priority
|
||||
return prio unless prio == 0
|
||||
|
||||
other.subpriority <=> self.subpriority
|
||||
end
|
||||
|
||||
def add_recipe(stage = nil, target_regex, &block)
|
||||
@recipes << {
|
||||
regex: target_regex,
|
||||
stage: stage,
|
||||
block: block
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
113
lib/comfpile/core.rb
Normal file
113
lib/comfpile/core.rb
Normal file
|
@ -0,0 +1,113 @@
|
|||
|
||||
require_relative 'artefact_engine.rb'
|
||||
|
||||
module Comfpile
|
||||
class Core
|
||||
attr_reader :processing_stack
|
||||
|
||||
def initialize()
|
||||
@artefact_engines = []
|
||||
@artefact_prio_counter = 0
|
||||
|
||||
# Artefacts are arranged in a double-hash.
|
||||
# First query is stage, second filename.
|
||||
@artefacts = {}
|
||||
|
||||
# Stack-style processing queue for item processing
|
||||
@processing_stack = []
|
||||
end
|
||||
|
||||
def find_artefact(stage, file = :none)
|
||||
@artefacts.dig(stage, file)
|
||||
end
|
||||
|
||||
def craft_artefact(stage, file = :none)
|
||||
artefact = find_artefact(stage, file)
|
||||
|
||||
return artefact unless artefact.nil?
|
||||
|
||||
@artefact_engines.each do |engine|
|
||||
artefact = engine.craft stage, file
|
||||
|
||||
if artefact
|
||||
@artefacts[stage] ||= {}
|
||||
@artefacts[stage][file] = artefact
|
||||
|
||||
@processing_stack.push artefact
|
||||
|
||||
return artefact
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def add_artefact(stage, file = :none, engine: nil, artefact_class: Comfpile::Artefact)
|
||||
return unless find_artefact(stage, file).nil?
|
||||
|
||||
a = Artefact.new(self, engine, stage, file);
|
||||
|
||||
@artefacts[stage] ||= {}
|
||||
@artefacts[stage][file] = a
|
||||
|
||||
yield(a) if block_given?
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def add_artefact_engine(engine_class = Comfpile::ArtefactEngine, **options)
|
||||
new_engine = engine_class.new(self,
|
||||
subpriority: @artefact_prio_counter, **options)
|
||||
@artefact_prio_counter += 1
|
||||
|
||||
yield(new_engine) if block_given?
|
||||
|
||||
@artefact_engines << new_engine
|
||||
@artefact_engines.sort!
|
||||
|
||||
new_engine
|
||||
end
|
||||
|
||||
def processing_stack_prune()
|
||||
loop do
|
||||
return if @processing_stack.empty?
|
||||
|
||||
if @processing_stack[-1].completed?
|
||||
@processing_stack.pop
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def processing_stack_find_next()
|
||||
@processing_stack.reverse_each do |a|
|
||||
return a if a.waiting?
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def execute_step
|
||||
return if @processing_stack.empty?
|
||||
puts "Got #{@processing_stack.length} items..."
|
||||
|
||||
processing_stack_prune
|
||||
|
||||
artefact = processing_stack_find_next
|
||||
|
||||
return nil if artefact.nil?
|
||||
|
||||
puts "Processing artefact #{artefact.stage} #{artefact.target}"
|
||||
|
||||
begin
|
||||
artefact.execute_step
|
||||
rescue ArtefactExecSkipError
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
25
lib/comfpile/engines/filesource_engine.rb
Normal file
25
lib/comfpile/engines/filesource_engine.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
|
||||
module Comfpile
|
||||
class FilesourceEngine < ArtefactEngine
|
||||
def initialize(core, **options)
|
||||
super(core, **options)
|
||||
|
||||
@root_path = options[:root_path]
|
||||
end
|
||||
|
||||
def craft(stage, target)
|
||||
return nil unless stage == :sourcefile
|
||||
|
||||
full_path = File.join(@root_path, target)
|
||||
|
||||
return nil unless File.exists? full_path
|
||||
|
||||
a = Artefact.new(@core, self, stage, target);
|
||||
a[:file] = full_path
|
||||
a[:filepath] = full_path
|
||||
|
||||
a
|
||||
end
|
||||
end
|
||||
end
|
88
lib/comfpile/engines/parser_engine.rb
Normal file
88
lib/comfpile/engines/parser_engine.rb
Normal file
|
@ -0,0 +1,88 @@
|
|||
|
||||
module Compfile
|
||||
class ParserArtefact < Artefact
|
||||
attr_reader :included_files
|
||||
attr_reader :required_files
|
||||
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
|
||||
@included_files = []
|
||||
@required_files = []
|
||||
|
||||
parent_artefact :sourcefile, @target
|
||||
|
||||
add_step do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ParserEngine < ArtefactEngine
|
||||
def initialize(core, **options)
|
||||
super(core, **options)
|
||||
|
||||
@input_file_regex = options[:allowed_files]
|
||||
|
||||
@require_regex = options[:require_reg]
|
||||
@include_regex = options[:include_reg]
|
||||
end
|
||||
|
||||
def generate_parser_artefact(stage, target)
|
||||
match = @input_file_regex.match target
|
||||
return nil if match.nil?
|
||||
|
||||
a = Artefact.new(@core, self, stage, target)
|
||||
|
||||
a.parent_artefact(:sourcefile, target)
|
||||
|
||||
a.add_step do
|
||||
|
||||
@parameters[:included_files] = []
|
||||
@parameters[:required_files] = []
|
||||
|
||||
File.readlines(@parent_artefact[:file]) do |l|
|
||||
case l
|
||||
when @require_regex
|
||||
filename = $~[:file]
|
||||
|
||||
own_dir = File.dirname(@target)
|
||||
relative_file = File.join(own_dir, filename)
|
||||
|
||||
unless craft_artefact(:sourcefile, relative_file).nil?
|
||||
@parameters[:required_files] << require_artefact(:parsed, relative_file)
|
||||
else
|
||||
@parameters[:required_files] << require_artefact(:parsed, filename)
|
||||
end
|
||||
|
||||
when @include_regex
|
||||
filename = $~[:file]
|
||||
|
||||
own_dir = File.dirname(@target)
|
||||
relative_file = File.join(own_dir, filename)
|
||||
|
||||
unless craft_artefact(:sourcefile, relative_file).nil?
|
||||
@parameters[:included_files] << craft_artefact(:parsed, relative_file)
|
||||
else
|
||||
@parameters[:included_files] << craft_artefact(:parsed, filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_dependency_artefact(stage, target)
|
||||
|
||||
end
|
||||
|
||||
def craft(stage, target)
|
||||
case stage
|
||||
when :parsed
|
||||
generate_parser_artefact(stage, target)
|
||||
when :dependency_list
|
||||
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
49
lib/comfpile/resource_location.rb
Normal file
49
lib/comfpile/resource_location.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
require_relative 'sourcefile.rb'
|
||||
|
||||
module Comfpile
|
||||
class ResourceLocation
|
||||
attr_reader :base_path
|
||||
attr_reader :files
|
||||
|
||||
attr_reader :priority, :subpriority
|
||||
|
||||
def initialize(core, base_path, **options)
|
||||
raise ArgumentError, "Resource path must be a string!" unless base_path.is_a? String
|
||||
raise ArgumentError, "Resource path must be a valid file or directory" unless File.exists?(base_path)
|
||||
@base_path = File.expand_path(base_path)
|
||||
|
||||
@name = options[:name] || @location
|
||||
@core = core
|
||||
|
||||
@priority = options[:priority] || 0;
|
||||
@subpriority = options[:subpriority] || 0;
|
||||
|
||||
@settings_map = Hash.new()
|
||||
|
||||
@known_files = Hash.new()
|
||||
end
|
||||
|
||||
def find_sourcefile(item_key)
|
||||
return @known_files[item_key] if @known_files.include? item_key
|
||||
|
||||
item_path = File.join(@base_path, item_key)
|
||||
new_item = nil
|
||||
|
||||
if File.exists? item_path
|
||||
new_item = Sourcefile.new(self, item_path, item_key)
|
||||
|
||||
@known_files[item_key] = new_item
|
||||
end
|
||||
|
||||
new_item
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
prio = other.priority <=> self.priority
|
||||
return prio unless prio == 0
|
||||
|
||||
other.subpriority <=> self.subpriority
|
||||
end
|
||||
end
|
||||
end
|
16
lib/comfpile/sourcefile.rb
Normal file
16
lib/comfpile/sourcefile.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
module Comfpile
|
||||
class Sourcefile
|
||||
attr_reader :full_path, :local_path, :resource_location
|
||||
|
||||
def initialize(resource_location, full_path, local_path)
|
||||
@resource_location = resource_location
|
||||
@full_path = full_path
|
||||
@local_path = local_path
|
||||
end
|
||||
|
||||
def to_s
|
||||
@full_path
|
||||
end
|
||||
end
|
||||
end
|
5
lib/comfpile/version.rb
Normal file
5
lib/comfpile/version.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Comfpile
|
||||
VERSION = "0.1.0"
|
||||
end
|
4
sig/comfpile.rbs
Normal file
4
sig/comfpile.rbs
Normal file
|
@ -0,0 +1,4 @@
|
|||
module Comfpile
|
||||
VERSION: String
|
||||
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
|
||||
end
|
13
test/test_comfpile.rb
Normal file
13
test/test_comfpile.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "test_helper"
|
||||
|
||||
class TestComfpile < Minitest::Test
|
||||
def test_that_it_has_a_version_number
|
||||
refute_nil ::Comfpile::VERSION
|
||||
end
|
||||
|
||||
def test_it_does_something_useful
|
||||
assert false
|
||||
end
|
||||
end
|
6
test/test_helper.rb
Normal file
6
test/test_helper.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
||||
require "comfpile"
|
||||
|
||||
require "minitest/autorun"
|
Loading…
Add table
Add a link
Reference in a new issue