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