/lib/sdoc_all/base.rb
Ruby | 217 lines | 198 code | 19 blank | 0 comment | 8 complexity | 997eb6bf0ca976eb0f230d051e6303f8 MD5 | raw file
- require 'shellwords'
- class SdocAll
- class Base
- attr_reader :config
- protected
- def raise_unknown_options_if_not_blank!(config)
- unless config.blank?
- raise ConfigError.new("unknown options for \"#{self.class.short_name}\": #{config.inspect}")
- end
- end
- def config_only_option(config)
- if only = config.delete(:only)
- [only].flatten.map(&:to_s).map(&:downcase)
- end
- end
- def config_exclude_option(config)
- if exclude = config.delete(:exclude)
- [exclude].flatten.map(&:to_s).map(&:downcase)
- else
- []
- end
- end
- def sources_path
- self.class.sources_path
- end
- class << self
- BASE_PATH = Pathname.new(Dir.pwd).expand_path
- DOCS_PATH = BASE_PATH + 'docs'
- PUBLIC_PATH = BASE_PATH + 'public'
- def dry_run!
- @@dry_run = true
- end
- def dry_run?
- defined?(@@dry_run) && @@dry_run
- end
- def verbose_level=(val)
- @@verbose_level = val.to_i
- end
- def verbose_level
- defined?(@@verbose_level) ? @@verbose_level : 0
- end
- def base_path
- BASE_PATH
- end
- def docs_path
- DOCS_PATH.tap(&:mkpath)
- end
- def public_path
- PUBLIC_PATH
- end
- def subclasses
- @subclasses ||= {}
- end
- def short_name
- name.demodulize.underscore
- end
- def sources_path
- Pathname.new("sources/#{short_name}").tap do |path|
- path.mkpath
- end
- end
- def used_sources
- @used_sources ||= []
- end
- def inherited(subclass)
- subclasses[subclass.short_name] = subclass
- end
- def entries
- @entries ||= []
- end
- def clear
- entries.clear
- end
- def to_document(type, config)
- type = type.to_s
- config.symbolize_keys! if config.is_a?(Hash)
- subclass = subclasses[type] || subclasses[type.singularize] || subclasses[type.pluralize]
- if subclass
- entries << subclass.new(config)
- else
- raise ConfigError.new("don't know how to build \"#{type}\" => #{config.inspect}")
- end
- end
- def tasks(options = {})
- @@tasks = []
- entries.with_progress('configuring').each do |entry|
- entry.add_tasks(options)
- end
- subclasses.values.each do |subclass|
- unless subclass.used_sources.empty?
- paths = FileList.new
- paths.include(subclass.sources_path + '*')
- subclass.used_sources.each do |path|
- paths.exclude(path)
- end
- paths.resolve.each do |path|
- remove_if_present(path)
- end
- end
- end
- @@tasks
- end
- def add_task(options = {})
- @@tasks << Task.new(options)
- end
- def add_merge_task(options = {})
- @@tasks << MergeTask.new(options)
- end
- def system(*args)
- args = args.map(&:to_s)
- command = args.length == 1 ? args.first : args.shelljoin
- if verbose_level >= 1
- puts [dirs.last && "cd #{dirs.last}", command].compact.join('; ').shrink(250).blue
- end
- unless dry_run?
- if verbose_level >= 2
- Kernel.system(*args)
- else
- rd, wr = IO::pipe
- pid = fork{
- rd.close
- STDOUT.reopen(wr)
- STDERR.reopen(wr)
- wr.close
- exec(*args)
- }
- wr.close
- begin
- true while line = rd.gets
- ensure
- rd.close unless rd.closed?
- Process.wait(pid)
- end
- end
- unless $?.success?
- if $?.signaled?
- raise SignalException.new($?.termsig)
- else
- abort("failed: #{command}")
- end
- end
- end
- end
- def remove_if_present(path)
- path = Pathname(path)
- if path.exist?
- puts "rm -r #{path.to_s.shellescape}".magenta
- FileUtils.remove_entry(path) unless dry_run?
- end
- end
- def dirs
- @@dirs ||= []
- end
- def chdir(path, &block)
- path = Pathname(path)
- dirs.push(path.expand_path)
- Dir.chdir(path, &block)
- ensure
- dirs.pop
- end
- def with_env(key, value)
- old_value, ENV[key] = ENV[key], value
- yield
- ensure
- ENV[key] = old_value
- end
- def output_for_verbose_level(n)
- if verbose_level >= n
- yield
- else
- old_stdout = $stdout
- old_stderr = $stderr
- dev_null = File.open('/dev/null', 'w')
- begin
- $stdout = dev_null
- $stderr = dev_null
- yield
- ensure
- $stdout = old_stdout
- $stderr = old_stderr
- dev_null.close
- end
- end
- end
- end
- end
- end