clone command (WIP) + pull command (WIP): site + pages
did
committed Jul 28, 2015
commit 8c9260827d08e89cf833e050ba5516988e189f4d
Showing 25
changed files with
573 additions
and 318 deletions
Gemfile
+1
-1
| @@ | @@ -17,7 +17,7 @@ gem 'therubyracer' |
| # gem 'locomotivecms_coal', github: 'locomotivecms/coal', ref: '32b2844', require: false | |
| # gem 'locomotivecms_common', github: 'locomotivecms/common', ref: '3046b79893', require: false | |
| - | # gem 'locomotivecms_coal', path: '../in_progress/coal', require: false |
| + | gem 'locomotivecms_coal', path: '../in_progress/coal', require: false |
| # gem 'locomotivecms_steam', path: '../in_progress/steam', require: false | |
| # gem 'locomotivecms_common', path: '../in_progress/common', require: false | |
generators/blank/config.ru
+0
-3
| @@ | @@ -1,3 +0,0 @@ |
| - | require 'locomotive/wagon/standalone_server' |
| - | |
| - | run Locomotive::Wagon::StandaloneServer.new(File.expand_path('.')) |
| \ No newline at end of file | |
generators/bootstrap3/config.ru
+0
-3
| @@ | @@ -1,3 +0,0 @@ |
| - | require 'locomotive/wagon/standalone_server' |
| - | |
| - | run Locomotive::Wagon::StandaloneServer.new(File.expand_path('.')) |
| \ No newline at end of file | |
generators/cloned/config.ru
+0
-3
| @@ | @@ -1,3 +0,0 @@ |
| - | require 'locomotive/wagon/standalone_server' |
| - | |
| - | run Locomotive::Wagon::StandaloneServer.new(File.expand_path('.')) |
| \ No newline at end of file | |
generators/cloned/config/deploy.yml.tt
+3
-2
| @@ | @@ -1,8 +1,9 @@ |
| production: | |
| host: <%= config[:host] %> | |
| - | <% if config[:email] -%> |
| + | handle: <%= config[:handle] %> |
| email: <%= config[:email] %> | |
| + | <% if config[:password] -%> |
| password: <%= config[:password] %> | |
| <% elsif config[:api_key] -%> | |
| api_key: <%= config[:api_key] -%> | |
| - | <% end -%> |
| \ No newline at end of file | |
| + | <% end -%> |
generators/foundation5/config.ru
+0
-3
| @@ | @@ -1,3 +0,0 @@ |
| - | require 'locomotive/wagon/standalone_server' |
| - | |
| - | run Locomotive::Wagon::StandaloneServer.new(File.expand_path('.')) |
| \ No newline at end of file | |
generators/line_case/config.ru
+0
-3
| @@ | @@ -1,3 +0,0 @@ |
| - | require 'locomotive/wagon/standalone_server' |
| - | |
| - | run Locomotive::Wagon::StandaloneServer.new(File.expand_path('.')) |
| \ No newline at end of file | |
locomotive/wagon.rb b/lib/locomotive/wagon.rb
+3
-31
| @@ | @@ -80,21 +80,9 @@ module Locomotive |
| # @param [ Hash ] connection_info The information to get connected to the remote site | |
| # @param [ Hash ] options The options passed to the pull process | |
| # | |
| - | def self.pull(path, connection_info, options = {}) |
| - | raise 'TODO' |
| - | # self.require_mounter(path, false, options[:disable_misc]) |
| - | |
| - | # connection_info[:uri] = "#{connection_info.delete(:host)}/locomotive/api" |
| - | |
| - | # _options = { console: true }.merge(options).symbolize_keys |
| - | # _options[:only] = _options.delete(:resources) |
| - | |
| - | # reader = Locomotive::Mounter::Reader::Api.instance |
| - | # self.validate_resources(_options[:only], reader.readers) |
| - | # reader.run!(_options.merge(connection_info)) |
| - | |
| - | # writer = Locomotive::Mounter::Writer::FileSystem.instance |
| - | # writer.run!(_options.merge(mounting_point: reader.mounting_point, target_path: path)) |
| + | def self.pull(env, path, options = {}, shell) |
| + | require_relative 'wagon/commands/pull_command' |
| + | Locomotive::Wagon::PullCommand.pull(env, path, options, shell) |
| end | |
| # Clone a site from a remote LocomotiveCMS engine. | |
| @@ | @@ -107,22 +95,6 @@ module Locomotive |
| def self.clone(name, path, options, shell) | |
| require_relative 'wagon/commands/clone_command' | |
| Locomotive::Wagon::CloneCommand.clone(name, path, options, shell) | |
| - | |
| - | # raise 'TODO' |
| - | # target_path = File.expand_path(File.join(path, name)) |
| - | |
| - | # if File.exists?(target_path) |
| - | # puts "Path already exists. If it's an existing site, you might want to pull instead of clone." |
| - | # return false |
| - | # end |
| - | |
| - | # # generate an almost blank site |
| - | # require 'locomotive/wagon/generators/site' |
| - | # generator = Locomotive::Wagon::Generators::Site::Cloned |
| - | # generator.start [name, path, true, connection_info.symbolize_keys] |
| - | |
| - | # # pull the remote site |
| - | # self.pull(target_path, options.merge(connection_info).with_indifferent_access, { disable_misc: true }) |
| end | |
| # Destroy a remote site | |
locomotive/wagon/cli.rb b/lib/locomotive/wagon/cli.rb
+19
-10
| @@ | @@ -21,7 +21,9 @@ module Locomotive |
| path = path == '.' ? Dir.pwd : File.expand_path(path) | |
| - | (File.exists?(File.join(path, 'config', 'site.yml')) ? path : nil).tap do |_path| |
| + | site_or_deploy_file = File.exists?(File.join(path, 'config', 'site.yml')) || File.exists?(File.join(path, 'config', 'deploy.yml')) |
| + | |
| + | (site_or_deploy_file ? path : nil).tap do |_path| |
| if _path.nil? | |
| say 'The path does not point to a LocomotiveCMS site', :red | |
| end | |
| @@ | @@ -35,7 +37,7 @@ module Locomotive |
| def force_color_if_asked(options) | |
| if options[:force_color] | |
| # thor | |
| - | require 'locomotive/wagon/misc/thor' |
| + | require 'locomotive/wagon/tools/thor' |
| self.shell = Thor::Shell::ForceColor.new | |
| # bypass colorize code | |
| @@ | @@ -216,8 +218,9 @@ module Locomotive |
| desc 'clone NAME HOST [PATH]', 'Clone a remote LocomotiveCMS site' | |
| method_option :verbose, aliases: '-v', type: 'boolean', default: false, desc: 'display the full error stack trace if an error occurs' | |
| + | method_option :handle, aliases: '-h', desc: 'handle of your site' |
| method_option :email, aliases: '-e', desc: 'email of an administrator account' | |
| - | method_option :password, aliases: '-p', desc: 'password of an administrator account' |
| + | method_option :password, aliases: '-p', desc: 'password of an administrator account (use api_key instead)' |
| method_option :api_key, aliases: '-a', desc: 'api key of an administrator account' | |
| def clone(name, host, path = '.') | |
| begin | |
| @@ | @@ -320,14 +323,20 @@ module Locomotive |
| method_option :verbose, aliases: '-v', type: 'boolean', default: false, desc: 'display the full error stack trace if an error occurs' | |
| def pull(env, path = '.') | |
| if check_path!(path) | |
| - | if connection_info = self.retrieve_connection_info(env, path) |
| - | begin |
| - | Locomotive::Wagon.pull(path, connection_info, options) |
| - | rescue Exception => e |
| - | self.print_exception(e, options[:verbose]) |
| - | exit(1) |
| - | end |
| + | begin |
| + | Locomotive::Wagon.pull(env, path, options, options[:shell] ? shell : nil) |
| + | rescue Exception => e |
| + | self.print_exception(e, options[:verbose]) |
| + | exit(1) |
| end | |
| + | # if connection_info = self.retrieve_connection_info(env, path) |
| + | # begin |
| + | # Locomotive::Wagon.pull(path, connection_info, options) |
| + | # rescue Exception => e |
| + | # self.print_exception(e, options[:verbose]) |
| + | # exit(1) |
| + | # end |
| + | # end |
| end | |
| end | |
locomotive/wagon/commands/clone_command.rb b/lib/locomotive/wagon/commands/clone_command.rb
+21
-1
| @@ | @@ -7,7 +7,27 @@ module Locomotive::Wagon |
| end | |
| def clone | |
| - | # TODO |
| + | # create an empty site with the minimal settings |
| + | create_site |
| + | |
| + | # pull the pages, content_types, basically any resources from the remote site |
| + | pull_site |
| + | end |
| + | |
| + | def connection_info |
| + | options.symbolize_keys.slice(:host, :handle, :email, :api_key, :password) |
| + | end |
| + | |
| + | private |
| + | |
| + | def create_site |
| + | require 'locomotive/wagon/generators/site' |
| + | generator = Locomotive::Wagon::Generators::Site::Cloned |
| + | generator.start [name, path, true, connection_info] |
| + | end |
| + | |
| + | def pull_site |
| + | raise 'TODO: call the pull command' |
| end | |
| end | |
locomotive/wagon/commands/loggers/base_logger.rb b/lib/locomotive/wagon/commands/loggers/base_logger.rb
+31
-0
| @@ | @@ -0,0 +1,31 @@ |
| + | module Locomotive::Wagon |
| + | |
| + | class BaseLogger |
| + | |
| + | private |
| + | |
| + | def log(message, color = nil, ident = nil, print = false) |
| + | ident = ' ' * (ident || 0) |
| + | |
| + | message = "#{ident}#{message.gsub("\n", "\n" + ident)}" |
| + | message = message.colorize(color) if color |
| + | |
| + | if print |
| + | print message |
| + | else |
| + | puts message |
| + | end |
| + | end |
| + | |
| + | def _subscribe(type, action = nil, &block) |
| + | name = ['wagon', type, [*action]].flatten.compact.join('.') |
| + | |
| + | ActiveSupport::Notifications.subscribe(name) do |*args| |
| + | event = ActiveSupport::Notifications::Event.new *args |
| + | yield(event) |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/loggers/pull_logger.rb b/lib/locomotive/wagon/commands/loggers/pull_logger.rb
+43
-0
| @@ | @@ -0,0 +1,43 @@ |
| + | require_relative 'base_logger' |
| + | |
| + | module Locomotive::Wagon |
| + | |
| + | class PullLogger < BaseLogger |
| + | |
| + | def initialize |
| + | # subscribe 'site_created' do |event| |
| + | # log "We created the config/site.yml file", { mode: :bold } |
| + | # end |
| + | |
| + | subscribe :start do |event| |
| + | log "\n" |
| + | log "Pulling #{event.payload[:name].camelcase}", { color: :black, background: :white } |
| + | end |
| + | |
| + | # subscribe :persist do |event| |
| + | # log "persisting #{event.payload[:label]}", :white, 2, true |
| + | # end |
| + | |
| + | # subscribe :skip_persisting do |event| |
| + | # log ' [' + 'skip'.colorize(:yellow) + ']' |
| + | # end |
| + | |
| + | # subscribe :persist_with_success do |event| |
| + | # log ' [' + 'done'.colorize(:green) + ']' |
| + | # end |
| + | |
| + | # subscribe :persist_with_error do |event| |
| + | # log ' [' + 'failed'.colorize(:red) + ']' |
| + | # log event.payload[:message], :red, 4 |
| + | # end |
| + | end |
| + | |
| + | private |
| + | |
| + | def subscribe(action = nil, &block) |
| + | _subscribe('pull', action, &block) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/loggers/push_logger.rb b/lib/locomotive/wagon/commands/loggers/push_logger.rb
+23
-17
| @@ | @@ -1,6 +1,8 @@ |
| + | require_relative 'base_logger' |
| + | |
| module Locomotive::Wagon | |
| - | class PushLogger |
| + | class PushLogger < BaseLogger |
| def initialize | |
| subscribe 'site_created' do |event| | |
| @@ | @@ -32,28 +34,32 @@ module Locomotive::Wagon |
| private | |
| - | def log(message, color = nil, ident = nil, print = false) |
| - | ident = ' ' * (ident || 0) |
| + | # def log(message, color = nil, ident = nil, print = false) |
| + | # ident = ' ' * (ident || 0) |
| - | message = "#{ident}#{message.gsub("\n", "\n" + ident)}" |
| - | message = message.colorize(color) if color |
| + | # message = "#{ident}#{message.gsub("\n", "\n" + ident)}" |
| + | # message = message.colorize(color) if color |
| - | if print |
| - | print message |
| - | else |
| - | puts message |
| - | end |
| - | end |
| + | # if print |
| + | # print message |
| + | # else |
| + | # puts message |
| + | # end |
| + | # end |
| def subscribe(action = nil, &block) | |
| - | name = ['wagon', 'push', [*action]].flatten.compact.join('.') |
| - | |
| - | ActiveSupport::Notifications.subscribe(name) do |*args| |
| - | event = ActiveSupport::Notifications::Event.new *args |
| - | yield(event) |
| - | end |
| + | _subscribe('push', action, &block) |
| end | |
| + | # def subscribe(action = nil, &block) |
| + | # name = ['wagon', 'push', [*action]].flatten.compact.join('.') |
| + | |
| + | # ActiveSupport::Notifications.subscribe(name) do |*args| |
| + | # event = ActiveSupport::Notifications::Event.new *args |
| + | # yield(event) |
| + | # end |
| + | # end |
| + | |
| end | |
| end | |
locomotive/wagon/commands/pull_command.rb b/lib/locomotive/wagon/commands/pull_command.rb
+56
-0
| @@ | @@ -0,0 +1,56 @@ |
| + | require 'locomotive/common' |
| + | |
| + | require_relative '../tools/styled_yaml' |
| + | |
| + | require_relative 'loggers/pull_logger' |
| + | |
| + | require_relative_all 'concerns' |
| + | |
| + | require_relative 'pull_sub_commands/pull_base_command' |
| + | require_relative_all 'pull_sub_commands' |
| + | |
| + | module Locomotive::Wagon |
| + | |
| + | class PullCommand < Struct.new(:env, :path, :options, :shell) |
| + | |
| + | # RESOURCES = %w(site pages content_types content_entries snippets theme_assets translations).freeze |
| + | RESOURCES = %w(pages).freeze |
| + | |
| + | include ApiConcern |
| + | include DeployFileConcern |
| + | include InstrumentationConcern |
| + | |
| + | def self.pull(env, path, options, shell) |
| + | self.new(env, path, options, shell).pull |
| + | end |
| + | |
| + | def pull |
| + | PullLogger.new if options[:verbose] |
| + | |
| + | api_client = api_site_client(connection_information) |
| + | site = api_client.current_site.get |
| + | |
| + | each_resource do |klass| |
| + | klass.pull(api_client, site, path) |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def each_resource |
| + | RESOURCES.each do |name| |
| + | next if !options[:resources].blank? && !options[:resources].include?(name) |
| + | |
| + | klass = "Locomotive::Wagon::Pull#{name.camelcase}Command".constantize |
| + | |
| + | yield klass |
| + | end |
| + | end |
| + | |
| + | def connection_information |
| + | read_deploy_settings(self.env, self.path) |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/pull_sub_commands/concerns/assets_concern.rb b/lib/locomotive/wagon/commands/pull_sub_commands/concerns/assets_concern.rb
+64
-0
| @@ | @@ -0,0 +1,64 @@ |
| + | require 'tempfile' |
| + | |
| + | module Locomotive::Wagon |
| + | |
| + | module AssetsConcern |
| + | |
| + | # The content assets on the remote engine follows the format: /sites/<id>/assets/<type>/<file> |
| + | # This method replaces these urls by their local representation. <type>/<file> |
| + | # |
| + | # @param [ String ] content The text where the assets will be replaced. |
| + | # |
| + | def replace_asset_urls(content) |
| + | return '' if content.blank? |
| + | |
| + | content.force_encoding('utf-8').gsub(/\/sites\/[0-9a-f]{24}\/(assets|pages)\/(([^;.]+)\/)*([a-zA-Z_\-0-9]+)\.([a-z]{2,3})/) do |url| |
| + | if filepath = write_asset(url, File.join(path, 'public', 'samples', $1, "#{$4}.#{$5}")) |
| + | "/samples/#{$1}/#{File.basename(filepath)}" |
| + | else |
| + | '' |
| + | end |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def find_unique_filepath(filepath, binary_file, index = 1) |
| + | if File.exists?(filepath) |
| + | # required because we need to make sure we use the content of file from its start |
| + | binary_file.rewind |
| + | |
| + | return filepath if FileUtils.compare_stream(binary_file, File.open(filepath)) |
| + | |
| + | folder, ext = File.dirname(filepath), File.extname(filepath) |
| + | basename = File.basename(filepath, ext) |
| + | |
| + | find_unique_filepath(File.join(folder, "#{basename}-#{index}#{ext}"), binary, index + 1) |
| + | else |
| + | filepath |
| + | end |
| + | end |
| + | |
| + | def get_asset_binary(url) |
| + | unless url =~ /\Ahttp:\/\// |
| + | base = api_client.uri.dup.tap { |u| u.path = '' }.to_s |
| + | url = URI.join(base, url).to_s |
| + | end |
| + | |
| + | binary = Faraday.get(url).body rescue nil |
| + | end |
| + | |
| + | def write_asset(url, filepath) |
| + | if binary = get_asset_binary(url) |
| + | FileUtils.mkdir_p(File.dirname(filepath)) |
| + | |
| + | (binary_file = Tempfile.new(File.basename(filepath))).write(binary) |
| + | |
| + | find_unique_filepath(filepath, binary_file).tap do |filepath| |
| + | File.open(filepath, 'wb') { |f| f.write(binary) } |
| + | end |
| + | else |
| + | instrument :missing_asset, url: url |
| + | nil |
| + | end |
| + | end |
locomotive/wagon/commands/pull_sub_commands/pull_base_command.rb b/lib/locomotive/wagon/commands/pull_sub_commands/pull_base_command.rb
+62
-0
| @@ | @@ -0,0 +1,62 @@ |
| + | require_relative 'concerns/assets_concern' |
| + | |
| + | module Locomotive::Wagon |
| + | |
| + | class PullBaseCommand < Struct.new(:api_client, :current_site, :path) |
| + | |
| + | include Locomotive::Wagon::AssetsConcern |
| + | |
| + | def self.pull(api_client, current_site, path) |
| + | new(api_client, current_site, path).pull |
| + | end |
| + | |
| + | def pull |
| + | instrument do |
| + | instrument :start |
| + | self._pull_with_timezone |
| + | instrument :done |
| + | end |
| + | end |
| + | |
| + | def _pull_with_timezone |
| + | Time.use_zone(current_site.try(:timezone)) do |
| + | _pull |
| + | end |
| + | end |
| + | |
| + | def instrument(action = nil, payload = {}, &block) |
| + | name = ['wagon.pull', [*action]].flatten.compact.join('.') |
| + | ActiveSupport::Notifications.instrument(name, { name: resource_name }.merge(payload), &block) |
| + | end |
| + | |
| + | def dump(attributes, options) |
| + | _attributes = attributes.dup |
| + | |
| + | [*options[:inline]].each do |name| |
| + | _attributes[name] = StyledYAML.inline(_attributes[name]) |
| + | end |
| + | |
| + | StyledYAML.dump(_attributes).gsub(/\A---\n/, '') |
| + | end |
| + | |
| + | def write_to_file(filepath, content = nil, &block) |
| + | File.open(File.join(path, filepath), 'w+') do |file| |
| + | file.write(content ? content : yield) |
| + | end |
| + | end |
| + | |
| + | def resource_name |
| + | self.class.name[/::Pull(\w+)Command$/, 1].underscore |
| + | end |
| + | |
| + | def default_locale |
| + | current_site.locales.first |
| + | end |
| + | |
| + | def locales |
| + | current_site.locales |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/pull_sub_commands/pull_content_assets_command.rb b/lib/locomotive/wagon/commands/pull_sub_commands/pull_content_assets_command.rb
+11
-0
| @@ | @@ -0,0 +1,11 @@ |
| + | module Locomotive::Wagon |
| + | |
| + | class PullContentAssetsCommand < PullBaseCommand |
| + | |
| + | def pull |
| + | puts 'TODO pulling content assets' |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/pull_sub_commands/pull_pages_command.rb b/lib/locomotive/wagon/commands/pull_sub_commands/pull_pages_command.rb
+59
-0
| @@ | @@ -0,0 +1,59 @@ |
| + | module Locomotive::Wagon |
| + | |
| + | class PullPagesCommand < PullBaseCommand |
| + | |
| + | attr_reader :fullpaths |
| + | |
| + | def _pull |
| + | @fullpaths = {} |
| + | |
| + | locales.each do |locale| |
| + | api_client.pages.all(locale).each do |page| |
| + | fullpaths[page._id] = page.fullpath if locale == default_locale |
| + | write_page(page, locale) |
| + | end |
| + | end |
| + | end |
| + | |
| + | def write_page(page, locale = nil) |
| + | write_to_file(page_filepath(page, locale)) do |
| + | <<-EOF |
| + | #{yaml_attributes(page, locale)}--- |
| + | #{replace_asset_urls(page.template)} |
| + | EOF |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def yaml_attributes(page, locale) |
| + | _attributes = page.attributes.slice('title', 'slug', 'handle', 'position', 'listed', 'published', 'redirect_url', 'is_layout', 'content_type', 'seo_title', 'meta_description', 'meta_keywords') |
| + | |
| + | if locale != default_locale |
| + | _attributes.delete_if { |k, _| %w(handle position listed published is_layout content_type).include?(k) } |
| + | end |
| + | |
| + | # editable elements |
| + | _attributes['editable_elements'] = page.editable_elements.inject({}) do |hash, el| |
| + | hash["#{el['block']}/#{el['slug']}"] = replace_asset_urls(el['content']) |
| + | hash |
| + | end |
| + | |
| + | # remove nil or empty values |
| + | _attributes.delete_if { |_, v| v.nil? || v == '' || (v.is_a?(Hash) && v.empty?) } |
| + | |
| + | _attributes.to_yaml |
| + | end |
| + | |
| + | def page_filepath(page, locale) |
| + | fullpath = locale == default_locale ? page.fullpath : "#{fullpaths[page._id]}.#{locale}" |
| + | |
| + | filepath = File.join('app', 'views', 'pages', fullpath + '.liquid').tap do |filepath| |
| + | folder = File.dirname(filepath) |
| + | FileUtils.mkdir_p(folder) unless File.exists?(folder) |
| + | end |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/commands/pull_sub_commands/pull_site_command.rb b/lib/locomotive/wagon/commands/pull_sub_commands/pull_site_command.rb
+53
-0
| @@ | @@ -0,0 +1,53 @@ |
| + | module Locomotive::Wagon |
| + | |
| + | class PullSiteCommand < PullBaseCommand |
| + | |
| + | def _pull |
| + | attributes = current_site.attributes.slice('name', 'locales', 'domains', 'timezone', 'seo_title', 'meta_keywords', 'meta_description', 'picture_thumbnail_url') |
| + | |
| + | locales.each_with_index do |locale, index| |
| + | if index == 0 |
| + | transform_in_default_locale(attributes, locale) |
| + | else |
| + | add_other_locale(attributes, locale) |
| + | end |
| + | end if locales.size > 1 |
| + | |
| + | write_icon(attributes.delete('picture_thumbnail_url')) |
| + | |
| + | write_to_file(File.join('config', 'site.yml')) do |
| + | dump(attributes, inline: %w(locales domains)) |
| + | end |
| + | end |
| + | |
| + | private |
| + | |
| + | def write_icon(url) |
| + | unless url =~ /\Ahttp:\/\// |
| + | base = api_client.uri.dup.tap { |u| u.path = '' }.to_s |
| + | url = URI.join(base, url).to_s |
| + | end |
| + | |
| + | File.open(File.join(path, 'icon.png'), 'wb') do |file| |
| + | file.write Faraday.get(url).body |
| + | end |
| + | end |
| + | |
| + | def localized_attributes(&block) |
| + | %w(seo_title meta_keywords meta_description).each do |name| |
| + | yield(name) |
| + | end |
| + | end |
| + | |
| + | def transform_in_default_locale(attributes, locale) |
| + | localized_attributes { |k| attributes[k] = { locale => attributes[k] } } |
| + | end |
| + | |
| + | def add_other_locale(attributes, locale) |
| + | _site = api_client.current_site.get(locale) |
| + | localized_attributes { |k| attributes[k][locale] = _site.attributes[k] } |
| + | end |
| + | |
| + | end |
| + | |
| + | end |
locomotive/wagon/generators/site.rb b/lib/locomotive/wagon/generators/site.rb
+0
-2
| @@ | @@ -110,8 +110,6 @@ module Locomotive |
| path: path, | |
| icon: icon && File.exists?(icon) ? icon : nil, | |
| options: class_options_to_json(template) | |
| - | |
| - | |
| } | |
| end.to_json | |
| end | |
locomotive/wagon/generators/site/cloned.rb b/lib/locomotive/wagon/generators/site/cloned.rb
+1
-1
| @@ | @@ -24,4 +24,4 @@ module Locomotive |
| end | |
| end | |
| end | |
| - | end |
| \ No newline at end of file | |
| + | end |
locomotive/wagon/tools/deployment_connection.rb b/lib/locomotive/wagon/tools/deployment_connection.rb
+0
-120
| @@ | @@ -1,120 +0,0 @@ |
| - | # require 'locomotive/wagon/misc/hosting_api' |
| - | # require 'active_support/core_ext/hash' |
| - | # require 'netrc' |
| - | # require 'erb' |
| - | |
| - | # module Locomotive |
| - | # module Wagon |
| - | |
| - | # class DeploymentConnection |
| - | |
| - | # # Create a connection for the deployment |
| - | # # from the path of a Wagon site. |
| - | # # |
| - | # # @param [ String ] path Path to a Wagon site |
| - | # # |
| - | # def initialize(path, shell = nil) |
| - | # @path = path |
| - | # @shell = shell |
| - | # end |
| - | |
| - | # # Retrieve information connection from the |
| - | # # config/deploy.yml file and for a specific environment. |
| - | # # If the env is hosting and does not have an entry in that file, |
| - | # # then it looks for an api key in the ~/.netrc file, assuming |
| - | # # that the user authenticates himself previously thanks to the |
| - | # # auth wagon command. |
| - | # # |
| - | # # @param [ String ] env The target environment to deploy the site. |
| - | # # |
| - | # def get_information(env) |
| - | # connection_info = read_from_yaml_file(env) |
| - | |
| - | # # if the user owns a hosting account, then use his credentials |
| - | # # to create a new site. |
| - | # if connection_info.nil? && env == 'hosting' |
| - | # connection_info = read_from_hosting |
| - | # end |
| - | |
| - | # if connection_info.nil? |
| - | # raise "No #{env.to_s} environment found in the config/deploy.yml file" |
| - | # end |
| - | |
| - | # connection_info = connection_info.with_indifferent_access |
| - | |
| - | # if connection_info[:ssl] && !connection_info[:host].start_with?('https') |
| - | # connection_info[:host] = 'https://' + connection_info[:host] |
| - | # end |
| - | |
| - | # connection_info |
| - | # end |
| - | |
| - | # private |
| - | |
| - | # def deploy_file |
| - | # File.join(@path, 'config', 'deploy.yml') |
| - | # end |
| - | |
| - | # def read_from_yaml_file(env) |
| - | # # pre-processing: erb code to parse and render? |
| - | # parsed_deploy_file = ERB.new(File.open(deploy_file).read).result |
| - | |
| - | # # finally, get the hash from the YAML file |
| - | # environments = YAML::load(parsed_deploy_file) |
| - | # (environments.is_a?(Hash) ? environments : {})[env.to_s] |
| - | # rescue Exception => e |
| - | # raise "Unable to read the config/deploy.yml file (#{e.message})" |
| - | # end |
| - | |
| - | # def read_from_hosting |
| - | # hosting_api = new_hosting_api |
| - | |
| - | # # create the site (READ the site.yml file to get the information) |
| - | # site = hosting_api.create_site(site_attributes) |
| - | |
| - | # if site.success? |
| - | # # now we've got the subdomain, build the target host |
| - | # host = [site['subdomain'], hosting_api.domain_with_port].join('.') |
| - | |
| - | # # return the connection information |
| - | # { 'host' => host, 'api_key' => hosting_api.api_key }.tap do |hash| |
| - | # # add ssl only if it is asked |
| - | # hash['ssl'] = true if hosting_api.ssl? |
| - | |
| - | # # insert a new entry for hosting env in the current deploy.yml |
| - | # File.open(deploy_file, 'a+') do |f| |
| - | # f.write({ 'hosting' => hash }.to_yaml.sub(/^---/, '')) |
| - | # end |
| - | # end |
| - | # else |
| - | # raise "We were unable to create a new site on the hosting, reason(s): #{site.error_messages.join(', ')}" |
| - | # end |
| - | # end |
| - | |
| - | # def new_hosting_api |
| - | # Locomotive::HostingAPI.new.tap do |hosting_api| |
| - | # netrc = Netrc.read |
| - | # email, api_key = netrc[hosting_api.domain_with_port] |
| - | |
| - | # # get a new auth token for further API calls |
| - | # hosting_api.authenticate(api_key: api_key) |
| - | # end |
| - | # end |
| - | |
| - | # def config_file |
| - | # File.join(@path, 'config', 'site.yml') |
| - | # end |
| - | |
| - | # def site_attributes |
| - | # YAML::load(File.read(config_file)).tap do |attributes| |
| - | # # ask for the subdomain |
| - | # if attributes['subdomain'].blank? && @shell |
| - | # attributes['subdomain'] = @shell.ask("Please, what's your subdomain? (leave it blank for a random one)") |
| - | # end |
| - | # end |
| - | # end |
| - | |
| - | # end |
| - | |
| - | # end |
| - | # end |
locomotive/wagon/tools/hosting_api.rb b/lib/locomotive/wagon/tools/hosting_api.rb
+0
-117
| @@ | @@ -1,117 +0,0 @@ |
| - | # require 'httparty' |
| - | |
| - | # module Locomotive |
| - | # class HostingAPI |
| - | |
| - | # include HTTParty |
| - | |
| - | # base_uri ENV['HOSTING_URL'] || 'http://www.locomotivehosting.com' |
| - | # # base_uri ENV['HOSTING_URL'] || 'http://www.locomotivehosting.fr' |
| - | # # base_uri ENV['HOSTING_URL'] || 'http://www.locomotivehosting.dev:3000' |
| - | |
| - | # def initialize(credentials = nil) |
| - | # authenticate(credentials) if credentials |
| - | # end |
| - | |
| - | # def self.host |
| - | # URI(base_uri).host |
| - | # end |
| - | |
| - | # def base_uri; self.class.base_uri; end |
| - | # def host; self.class.host; end |
| - | # def port; URI(self.class.base_uri).port; end |
| - | |
| - | # def domain |
| - | # host.split('.')[1..-1].join('.') # TLD length of 2 |
| - | # end |
| - | |
| - | # def domain_with_port |
| - | # if port != 80 |
| - | # self.domain + ":#{port}" |
| - | # else |
| - | # self.domain |
| - | # end |
| - | # end |
| - | |
| - | # def ssl? |
| - | # URI(self.class.base_uri).scheme == 'https' |
| - | # end |
| - | |
| - | # def authenticate(credentials) |
| - | # response = self.class.post('/locomotive/api/tokens.json', { body: credentials }) |
| - | |
| - | # if response.success? |
| - | # @auth_token = response['token'] |
| - | # end |
| - | # end |
| - | |
| - | # def authenticated? |
| - | # !!@auth_token |
| - | # end |
| - | |
| - | # def api_key |
| - | # @api_key ||= api_key! |
| - | # end |
| - | |
| - | # def api_key! |
| - | # return false unless authenticated? |
| - | |
| - | # my_account['api_key'] |
| - | # end |
| - | |
| - | # def my_account |
| - | # self.class.get('/locomotive/api/my_account.json', { query: { auth_token: @auth_token }}) |
| - | # end |
| - | |
| - | # def create_account(attributes) |
| - | # attributes[:password_confirmation] = attributes[:password] |
| - | |
| - | # _response = self.class.post('/locomotive/api/my_account.json', { body: { account: attributes }}) |
| - | |
| - | # Response.new(_response.parsed_response).tap do |response| |
| - | # response.success = _response.success? |
| - | # end |
| - | # end |
| - | |
| - | # def create_site(attributes) |
| - | # _response = self.class.post('/locomotive/api/sites.json', { body: { auth_token: @auth_token, site: attributes }}) |
| - | |
| - | # Response.new(_response.parsed_response).tap do |response| |
| - | # response.success = _response.success? |
| - | # end |
| - | # end |
| - | |
| - | # class Response < Hash |
| - | |
| - | # attr_writer :success |
| - | |
| - | # def initialize(attributes = {}) |
| - | # replace(attributes) |
| - | # end |
| - | |
| - | # def success? |
| - | # !!@success |
| - | # end |
| - | |
| - | # def errors |
| - | # return nil if success? |
| - | |
| - | # @errors ||= if self['error'] |
| - | # [[nil, [self['error']]]] |
| - | # elsif self['errors'] |
| - | # self['errors'] |
| - | # else |
| - | # self.to_a |
| - | # end.delete_if { |attribute, errors| errors.empty? } |
| - | # end |
| - | |
| - | # def error_messages |
| - | # return nil if success? || errors.nil? |
| - | |
| - | # errors.to_a.map { |attribute, messages| messages.map { |message| [attribute, message].compact.join(' ') } }.flatten |
| - | # end |
| - | |
| - | # end |
| - | |
| - | # end |
| - | # end |
locomotive/wagon/tools/styled_yaml.rb b/lib/locomotive/wagon/tools/styled_yaml.rb
+122
-0
| @@ | @@ -0,0 +1,122 @@ |
| + | require 'psych' |
| + | require 'stringio' |
| + | |
| + | # Public: A Psych extension to enable choosing output styles for specific |
| + | # objects. |
| + | # |
| + | # Thanks to Tenderlove for help in <http://stackoverflow.com/q/9640277/11687> |
| + | # |
| + | # Examples |
| + | # |
| + | # data = { |
| + | # response: { body: StyledYAML.literal(json_string), status: 200 }, |
| + | # person: StyledYAML.inline({ 'name' => 'Stevie', 'age' => 12 }), |
| + | # array: StyledYAML.inline(%w[ apples bananas oranges ]) |
| + | # } |
| + | # |
| + | # StyledYAML.dump data, $stdout |
| + | # |
| + | module StyledYAML |
| + | # Tag strings to be output using literal style |
| + | def self.literal obj |
| + | obj.extend LiteralScalar |
| + | return obj |
| + | end |
| + | |
| + | # http://www.yaml.org/spec/1.2/spec.html#id2795688 |
| + | module LiteralScalar |
| + | def yaml_style() Psych::Nodes::Scalar::LITERAL end |
| + | end |
| + | |
| + | # Tag Hashes or Arrays to be output all on one line |
| + | def self.inline obj |
| + | case obj |
| + | when Hash then obj.extend FlowMapping |
| + | when Array then obj.extend FlowSequence |
| + | else |
| + | warn "#{self}: unrecognized type to inline (#{obj.class.name})" |
| + | end |
| + | return obj |
| + | end |
| + | |
| + | # http://www.yaml.org/spec/1.2/spec.html#id2790832 |
| + | module FlowMapping |
| + | def yaml_style() Psych::Nodes::Mapping::FLOW end |
| + | end |
| + | |
| + | # http://www.yaml.org/spec/1.2/spec.html#id2790320 |
| + | module FlowSequence |
| + | def yaml_style() Psych::Nodes::Sequence::FLOW end |
| + | end |
| + | |
| + | # Custom tree builder class to recognize scalars tagged with `yaml_style` |
| + | class TreeBuilder < Psych::TreeBuilder |
| + | attr_writer :next_sequence_or_mapping_style |
| + | |
| + | def initialize(*args) |
| + | super |
| + | @next_sequence_or_mapping_style = nil |
| + | end |
| + | |
| + | def next_sequence_or_mapping_style default_style |
| + | style = @next_sequence_or_mapping_style || default_style |
| + | @next_sequence_or_mapping_style = nil |
| + | style |
| + | end |
| + | |
| + | def scalar value, anchor, tag, plain, quoted, style |
| + | if style_any?(style) and value.respond_to?(:yaml_style) and style = value.yaml_style |
| + | if style_literal? style |
| + | plain = false |
| + | quoted = true |
| + | end |
| + | end |
| + | super |
| + | end |
| + | |
| + | def style_any?(style) Psych::Nodes::Scalar::ANY == style end |
| + | |
| + | def style_literal?(style) Psych::Nodes::Scalar::LITERAL == style end |
| + | |
| + | %w[sequence mapping].each do |type| |
| + | class_eval <<-RUBY |
| + | def start_#{type}(anchor, tag, implicit, style) |
| + | style = next_sequence_or_mapping_style(style) |
| + | super |
| + | end |
| + | RUBY |
| + | end |
| + | end |
| + | |
| + | # Custom tree class to handle Hashes and Arrays tagged with `yaml_style` |
| + | class YAMLTree < Psych::Visitors::YAMLTree |
| + | %w[Hash Array Psych_Set Psych_Omap].each do |klass| |
| + | class_eval <<-RUBY |
| + | def visit_#{klass} o |
| + | if o.respond_to? :yaml_style |
| + | @emitter.next_sequence_or_mapping_style = o.yaml_style |
| + | end |
| + | super |
| + | end |
| + | RUBY |
| + | end |
| + | end |
| + | |
| + | # A Psych.dump alternative that uses the custom TreeBuilder |
| + | def self.dump obj, io = nil, options = {} |
| + | real_io = io || StringIO.new(''.encode('utf-8')) |
| + | visitor = YAMLTree.new(options, TreeBuilder.new) |
| + | visitor << obj |
| + | ast = visitor.tree |
| + | |
| + | begin |
| + | ast.yaml real_io |
| + | rescue |
| + | # The `yaml` method was introduced in later versions, so fall back to |
| + | # constructing a visitor |
| + | Psych::Visitors::Emitter.new(real_io).accept ast |
| + | end |
| + | |
| + | io ? io : real_io.string |
| + | end |
| + | end |
locomotivecms_wagon.gemspec
+1
-1
| @@ | @@ -25,7 +25,7 @@ Gem::Specification.new do |gem| |
| gem.add_dependency 'rubyzip', '~> 1.1.7' | |
| gem.add_dependency 'netrc', '~> 0.10.3' | |
| - | gem.add_dependency 'locomotivecms_coal', '~> 1.0.0-alpha.3' |
| + | # gem.add_dependency 'locomotivecms_coal', '~> 1.0.0-alpha.3' |
| gem.add_dependency 'locomotivecms_steam', '~> 1.0.0-alpha.2' | |
| gem.add_dependency 'listen', '~> 2.10.0' | |