PageRenderTime 27ms CodeModel.GetById 5ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/sdoc_all/base.rb

https://github.com/toy/sdoc_all
Ruby | 217 lines | 198 code | 19 blank | 0 comment | 8 complexity | 997eb6bf0ca976eb0f230d051e6303f8 MD5 | raw file
  1. require 'shellwords'
  2. class SdocAll
  3. class Base
  4. attr_reader :config
  5. protected
  6. def raise_unknown_options_if_not_blank!(config)
  7. unless config.blank?
  8. raise ConfigError.new("unknown options for \"#{self.class.short_name}\": #{config.inspect}")
  9. end
  10. end
  11. def config_only_option(config)
  12. if only = config.delete(:only)
  13. [only].flatten.map(&:to_s).map(&:downcase)
  14. end
  15. end
  16. def config_exclude_option(config)
  17. if exclude = config.delete(:exclude)
  18. [exclude].flatten.map(&:to_s).map(&:downcase)
  19. else
  20. []
  21. end
  22. end
  23. def sources_path
  24. self.class.sources_path
  25. end
  26. class << self
  27. BASE_PATH = Pathname.new(Dir.pwd).expand_path
  28. DOCS_PATH = BASE_PATH + 'docs'
  29. PUBLIC_PATH = BASE_PATH + 'public'
  30. def dry_run!
  31. @@dry_run = true
  32. end
  33. def dry_run?
  34. defined?(@@dry_run) && @@dry_run
  35. end
  36. def verbose_level=(val)
  37. @@verbose_level = val.to_i
  38. end
  39. def verbose_level
  40. defined?(@@verbose_level) ? @@verbose_level : 0
  41. end
  42. def base_path
  43. BASE_PATH
  44. end
  45. def docs_path
  46. DOCS_PATH.tap(&:mkpath)
  47. end
  48. def public_path
  49. PUBLIC_PATH
  50. end
  51. def subclasses
  52. @subclasses ||= {}
  53. end
  54. def short_name
  55. name.demodulize.underscore
  56. end
  57. def sources_path
  58. Pathname.new("sources/#{short_name}").tap do |path|
  59. path.mkpath
  60. end
  61. end
  62. def used_sources
  63. @used_sources ||= []
  64. end
  65. def inherited(subclass)
  66. subclasses[subclass.short_name] = subclass
  67. end
  68. def entries
  69. @entries ||= []
  70. end
  71. def clear
  72. entries.clear
  73. end
  74. def to_document(type, config)
  75. type = type.to_s
  76. config.symbolize_keys! if config.is_a?(Hash)
  77. subclass = subclasses[type] || subclasses[type.singularize] || subclasses[type.pluralize]
  78. if subclass
  79. entries << subclass.new(config)
  80. else
  81. raise ConfigError.new("don't know how to build \"#{type}\" => #{config.inspect}")
  82. end
  83. end
  84. def tasks(options = {})
  85. @@tasks = []
  86. entries.with_progress('configuring').each do |entry|
  87. entry.add_tasks(options)
  88. end
  89. subclasses.values.each do |subclass|
  90. unless subclass.used_sources.empty?
  91. paths = FileList.new
  92. paths.include(subclass.sources_path + '*')
  93. subclass.used_sources.each do |path|
  94. paths.exclude(path)
  95. end
  96. paths.resolve.each do |path|
  97. remove_if_present(path)
  98. end
  99. end
  100. end
  101. @@tasks
  102. end
  103. def add_task(options = {})
  104. @@tasks << Task.new(options)
  105. end
  106. def add_merge_task(options = {})
  107. @@tasks << MergeTask.new(options)
  108. end
  109. def system(*args)
  110. args = args.map(&:to_s)
  111. command = args.length == 1 ? args.first : args.shelljoin
  112. if verbose_level >= 1
  113. puts [dirs.last && "cd #{dirs.last}", command].compact.join('; ').shrink(250).blue
  114. end
  115. unless dry_run?
  116. if verbose_level >= 2
  117. Kernel.system(*args)
  118. else
  119. rd, wr = IO::pipe
  120. pid = fork{
  121. rd.close
  122. STDOUT.reopen(wr)
  123. STDERR.reopen(wr)
  124. wr.close
  125. exec(*args)
  126. }
  127. wr.close
  128. begin
  129. true while line = rd.gets
  130. ensure
  131. rd.close unless rd.closed?
  132. Process.wait(pid)
  133. end
  134. end
  135. unless $?.success?
  136. if $?.signaled?
  137. raise SignalException.new($?.termsig)
  138. else
  139. abort("failed: #{command}")
  140. end
  141. end
  142. end
  143. end
  144. def remove_if_present(path)
  145. path = Pathname(path)
  146. if path.exist?
  147. puts "rm -r #{path.to_s.shellescape}".magenta
  148. FileUtils.remove_entry(path) unless dry_run?
  149. end
  150. end
  151. def dirs
  152. @@dirs ||= []
  153. end
  154. def chdir(path, &block)
  155. path = Pathname(path)
  156. dirs.push(path.expand_path)
  157. Dir.chdir(path, &block)
  158. ensure
  159. dirs.pop
  160. end
  161. def with_env(key, value)
  162. old_value, ENV[key] = ENV[key], value
  163. yield
  164. ensure
  165. ENV[key] = old_value
  166. end
  167. def output_for_verbose_level(n)
  168. if verbose_level >= n
  169. yield
  170. else
  171. old_stdout = $stdout
  172. old_stderr = $stderr
  173. dev_null = File.open('/dev/null', 'w')
  174. begin
  175. $stdout = dev_null
  176. $stderr = dev_null
  177. yield
  178. ensure
  179. $stdout = old_stdout
  180. $stderr = old_stderr
  181. dev_null.close
  182. end
  183. end
  184. end
  185. end
  186. end
  187. end