lib/palimpsest/environment.rb in palimpsest-0.0.1 vs lib/palimpsest/environment.rb in palimpsest-0.1.0
- old
+ new
@@ -1,25 +1,46 @@
-require 'grit'
-
module Palimpsest
# An environment is populated with the contents of
# a site's repository at a specified commit.
+ # Alternatively, a single directory can be used to populate the environment.
# The environment's files are rooted in a temporary {#directory}.
# An environment is the primary way to interact with a site's files.
#
# An environment loads a {#config} file from the working {#directory};
# by default, `palimpsest_config.yml`.
#
# Paths are all relative to the working {#directory}.
#
# ````yml
- # palimpsest_config.yml
+ # # example of palimpsest_config.yml
#
+ # # component settings
+ # :components:
+ # # all component paths are relative to the base
+ # :base: _components
+ #
+ # # list of components
+ # :paths:
+ # #- [ components_path, install_path ]
+ # - [ my_app/templates, apps/my_app/templates ]
+ # - [ my_app/extra, apps/my_app ]
+ #
+ # # externals settings
+ # :externals:
+ # # server or local path that repos are under
+ # :server: "https://github.com/razor-x"
+ #
+ # # list of external repos
+ # :repos:
+ # #- [ name, install_path, branch, server (optional) ]
+ # - [ my_app, apps/my_app, master ]
+ # - [ sub_app, apps/my_app/sub_app, my_feature, "https://bitbucket.org/razorx" ]
# # asset settings
# :assets:
- # # all options are passed to `Palimpsest::Assets#options` and will use those defaults if unset
+ # # all options are passed to Assets#options
+ # # options will use defaults set in Palimpsest::Asset::DEFAULT_OPTIONS if unset here
# # unless otherwise mentioned, options can be set or overridden per asset type
# :options:
# # opening and closing brackets for asset source tags
# # global option only: cannot be overridden per asset type
# :src_pre: "[%"
@@ -59,12 +80,14 @@
#
# :paths:
# - assets/stylesheets
# # images can be part of the asset pipeline
# :images:
- # # options can be overridden per type
# :options:
+ # # requires the sprockets-image_compressor gem
+ # :image_compression: true
+ # # options can be overridden per type
# :output: images
# :paths:
# - assets/images
# ````
class Environment
@@ -85,16 +108,13 @@
# @return site to build the environment with
#
# @!attribute treeish
# @return [String] the reference used to pick the commit to build the environment with
#
- # @!attribute [r] directory
- # @return [String] the environment's working directory
- #
# @!attribute [r] populated
# @return [Boolean] true if the site's repo has been extracted
- attr_reader :site, :treeish, :directory, :populated
+ attr_reader :site, :treeish, :populated
def initialize site: nil, treeish: 'master', options: {}
@populated = false
self.options options
self.site = site if site
@@ -107,71 +127,143 @@
def options options={}
@options ||= DEFAULT_OPTIONS
@options = @options.merge options
end
+ # @see Environment#site
def site= site
- raise RuntimeError, "Cannot redefine 'site' once populated" if populated
+ fail RuntimeError, "Cannot redefine 'site' once populated" if populated
@site = site
end
+ # @see Environment#treeish
def treeish= treeish
- raise RuntimeError, "Cannot redefine 'treeish' once populated" if populated
- raise TypeError unless treeish.is_a? String
+ fail RuntimeError, "Cannot redefine 'treeish' once populated" if populated
+ fail TypeError unless treeish.is_a? String
@treeish = treeish
end
+ # @return [String] the environment's working directory
def directory
- raise RuntimeError if site.nil?
if @directory.nil?
- @directory = Palimpsest::Utility.make_random_directory options[:tmp_dir], "#{options[:dir_prefix]}#{site.name}_"
+ name = site.nil? ? '' : site.name
+ @directory = Utility.make_random_directory options[:tmp_dir], "#{options[:dir_prefix]}#{name}_"
else
@directory
end
end
+ # Copy the contents of the working directory.
+ # @param dest [String] path to copy environment's files to
+ # @return [Environment] the current environment instance
+ def copy dest: site.path
+ FileUtils.cp_r Dir["#{directory}/*"], dest, preserve: true
+ self
+ end
+
# Removes the environment's working directory.
+ # @return [Environment] the current environment instance
def cleanup
FileUtils.remove_entry_secure directory if @directory
@directory = nil
+ @assets = []
+ @components = []
@populated = false
- return self
+ self
end
# Extracts the site's files from repository to the working directory.
- def populate from: :repo
+ # @return [Environment] the current environment instance
+ def populate from: :auto
cleanup if populated
- raise RuntimeError, "Cannot populate without 'site'" if site.nil?
+ fail RuntimeError, "Cannot populate without 'site'" if site.nil?
case from
+ when :auto
+ if site.respond_to?(:repo) ? site.repo : nil
+ populate from: :repo
+ else
+ populate from: :source
+ end
when :repo
- raise RuntimeError, "Cannot populate without 'treeish'" if treeish.empty?
- Palimpsest::Utility.extract_repo site.repo, treeish, directory
+ fail RuntimeError, "Cannot populate without 'treeish'" if treeish.empty?
+ Utility.extract_repo site.repo, treeish, directory
+ @populated = true
when :source
- FileUtils.cp_r Dir["#{site.source}/*"], directory
+ FileUtils.cp_r Dir["#{site.source}/*"], directory, preserve: true
+ @populated = true
end
- @populated = true
- return self
+ self
end
# @return [Hash] configuration loaded from {#options}`[:config_file]` under {#directory}
def config
populate unless populated
@config = YAML.load_file "#{directory}/#{options[:config_file]}"
validate_config if @config
end
- # @return [Array<Palimpsest::Assets>] assets with settings and paths loaded from config
+ # @return [Array<Component>] components with paths loaded from config
+ def components
+ return @components if @components
+ return [] if config[:components].nil?
+ return [] if config[:components][:paths].nil?
+
+ @components = []
+
+ base = directory
+ base += config[:components][:base].nil? ? '' : '/' + config[:components][:base]
+
+ config[:components][:paths].each do |paths|
+ @components << Component.new(source_path: "#{base}/#{paths[0]}", install_path: "#{directory}/#{paths[1]}")
+ end
+
+ @components
+ end
+
+ # Install all components.
+ # @return [Environment] the current environment instance
+ def install_components
+ components.each { |c| c.install }
+ self
+ end
+
+ # @return [Array<External>] externals loaded from config
+ def externals
+ return @externals if @externals
+ return [] if config[:externals].nil?
+ return [] if config[:externals][:repos].nil?
+
+ @externals = []
+
+ config[:externals][:repos].each do |repo|
+ source = repo[3].nil? ? config[:externals][:server] : repo[3]
+ @externals << External.new(name: repo[0], source: source, branch: repo[2], install_path: "#{directory}/#{repo[1]}" )
+ end
+
+ @externals
+ end
+
+ # Install all externals.
+ # @return [Environment] the current environment instance
+ def install_externals
+ externals.each { |e| e.install }
+ self
+ end
+
+ # @return [Array<Assets>] assets with settings and paths loaded from config
def assets
+ return @assets if @assets
+
@assets = []
config[:assets].each do |type, opt|
- next if [ :sources ].include? type
+ next if [:sources].include? type
next if opt[:paths].nil?
- assets = Palimpsest::Assets.new directory: directory, paths: opt[:paths]
+ assets = Assets.new directory: directory, paths: opt[:paths]
assets.options config[:assets][:options] unless config[:assets][:options].nil?
assets.options opt[:options] unless opt[:options].nil?
assets.type = type
@assets << assets
end unless config[:assets].nil?
@@ -185,62 +277,84 @@
return [] if config[:assets][:sources].nil?
@sources_with_assets = []
opts = {}
- [ :src_pre, :src_post ].each do |opt|
+ [:src_pre, :src_post].each do |opt|
opts[opt] = config[:assets][:options][opt] unless config[:assets][:options][opt].nil?
end unless config[:assets][:options].nil?
config[:assets][:sources].each do |path|
- @sources_with_assets << Palimpsest::Assets.find_tags("#{directory}/#{path}", nil, opts)
+ @sources_with_assets << Assets.find_tags("#{directory}/#{path}", nil, opts)
end
@sources_with_assets.flatten
end
# Finds all assets in {#sources_with_assets} and
# generates the assets and updates the sources.
+ # @return [Environment] the current environment instance
def compile_assets
sources_with_assets.each do |file|
source = File.read file
assets.each { |a| a.update_source! source }
- Palimpsest::Utility.write source, file
+ Utility.write source, file, preserve: true
end
- return self
+ self
end
private
# Checks the config file for invalid settings.
- #
+ # @todo refactor this
# - Checks that paths are not absolute or use `../` or `~/`.
def validate_config
message = 'bad path in config'
- def safe_path?(path) Palimpsest::Utility.safe_path?(path) end
-
# Checks the option in the asset key.
def validate_asset_options opts
opts.each do |k,v|
- raise RuntimeError, 'bad option in config' if k == :sprockets_options
- raise RuntimeError, message if k == :output && ! safe_path?(v)
+ fail RuntimeError, 'bad option in config' if k == :sprockets_options
+ fail RuntimeError, message if k == :output && ! Utility.safe_path?(v)
end
end
- @config[:assets].each do |k, v|
+ @config[:external].each do |k, v|
+ next if k == :server
+ v.each do |repo|
+ fail RuntimeError, message unless Utility.safe_path? repo[1]
+ end unless v.nil?
+ end unless @config[:external].nil?
+
+ @config[:components].each do |k,v|
+ # process @config[:components][:base] then go to the next option
+ if k == :base
+ fail RuntimeError, message unless Utility.safe_path? v
+ next
+ end unless v.nil?
+
+ # process @config[:components][:paths]
+ if k == :paths
+ v.each do |path|
+ fail RuntimeError, message unless Utility.safe_path? path[0]
+ fail RuntimeError, message unless Utility.safe_path? path[1]
+ end
+ end
+ end unless @config[:components].nil?
+
+ @config[:assets].each do |k, v|
# process @config[:assets][:options] then go to the next option
if k == :options
validate_asset_options v
next
end unless v.nil?
# process @config[:assets][:sources] then go to the next option
if k == :sources
v.each_with_index do |source, i|
- raise RuntimeError, message unless safe_path? source
+ fail RuntimeError, message unless Utility.safe_path? source
end
next
end
# process each asset type in @config[:assets]
@@ -251,13 +365,14 @@
next
end unless asset_value.nil?
# process each asset path
asset_value.each_with_index do |path, i|
- raise RuntimeError, message unless safe_path? path
+ fail RuntimeError, message unless Utility.safe_path? path
end
end
end unless @config[:assets].nil?
+
@config
end
end
end