модуль Bundler::Thor::Actions
Константы
- WARNINGS
-
Вставляет заданное содержимое в файл. В отличие от
gsub_file, этот метод обратим.Параметры
- destination<String>
-
Относительный путь к корневой папке назначения
- data<String>
-
Dataдля добавления в файл. Может быть задан как блок. - config<Hash>
-
Установите :verbose => false, чтобы не регистрировать состояние, и флаг для вставки (:after или :before), или :force => true, чтобы вставить то же содержимое два или более раз.
Примеры
insert_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n" insert_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do gems = ask "Which gems would you like to add?" gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n") end
Атрибуты
Публичные методы класса
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 72
def initialize(args = [], options = {}, config = {})
self.behavior = case config[:behavior].to_s
when "force", "skip"
_cleanup_options_and_set(options, config[:behavior])
:invoke
when "revoke"
:revoke
else
:invoke
end
super
self.destination_root = config[:destination_root]
end Расширяет инициализатор, добавляя дополнительные параметры конфигурации.
Конфигурация
- behavior<Symbol>
-
Поведение по умолчанию для действий. Может быть :invoke или :revoke. Также поддерживает :force, :skip и :pretend для настройки поведения и соответствующих параметров.
-
destination_root<String> -
Корневой каталог, необходимый для некоторых действий.
Общедоступные методы экземпляра
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 195
def append_to_file(path, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
config[:before] = /\z/
insert_into_file(path, *(args << config), &block)
end Добавляет текст в файл. Поскольку это зависит от insert_into_file, он обратим.
Параметры
- path<String>
-
путь к файлу, который необходимо изменить
- data<String>
-
данные, которые нужно добавить в файл, также могут быть переданы в виде блока.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
append_to_file 'config/environments/test.rb', 'config.gem "rspec"' append_to_file 'config/environments/test.rb' do 'config.gem "rspec"' end
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 212
def apply(path, config = {})
verbose = config.fetch(:verbose, true)
is_uri = path =~ %r{^https?\://}
path = find_in_source_paths(path) unless is_uri
say_status :apply, path, verbose
shell.padding += 1 if verbose
contents = if is_uri
require "open-uri"
open(path, "Accept" => "application/x-thor-template", &:read)
else
open(path, &:read)
end
instance_eval(contents, path)
shell.padding -= 1 if verbose
end Загружает внешний файл и выполняет его в связанном экземпляре.
Параметры
- path<String>
-
Путь к файлу для выполнения. Может быть веб-адресом или относительным путем от корня источника.
Примеры
apply "http://gist.github.com/103208" apply "recipes/jquery.rb"
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 148
def chmod(path, mode, config = {})
return unless behavior == :invoke
path = File.expand_path(path, destination_root)
say_status :chmod, relative_to_original_destination_root(path), config.fetch(:verbose, true)
unless options[:pretend]
require "fileutils"
FileUtils.chmod_R(mode, path)
end
end Изменяет режим указанного файла или каталога.
Параметры
- mode<Integer>
-
режим файла
- path<String>
-
имя файла, для которого нужно изменить режим
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
chmod "script/server", 0755
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 310
def comment_lines(path, flag, *args)
flag = flag.respond_to?(:source) ? flag.source : flag
gsub_file(path, /^(\s*)([^#\n]*#{flag})/, '\1# \2', *args)
end Комментирует все строки, соответствующие заданному регулярному выражению. Пробел перед началом строки сохраняется, а после знака # добавляется одиночный пробел.
Параметры
- path<String>
-
путь к файлу, который необходимо изменить
- flag<Regexp|String>
-
регулярное выражение или строка, используемые для определения строк, которые нужно закомментировать
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
comment_lines 'config/initializers/session_store.rb', /cookie_store/
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 21
def copy_file(source, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source
source = File.expand_path(find_in_source_paths(source.to_s))
resulting_destination = create_file destination, nil, config do
content = File.binread(source)
content = yield(content) if block
content
end
if config[:mode] == :preserve
mode = File.stat(source).mode
chmod(resulting_destination, mode, config)
end
end Примеры
copy_file "README", "doc/README" copy_file "doc/README"
# File lib/bundler/vendor/thor/lib/thor/actions/create_file.rb, line 22
def create_file(destination, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
data = args.first
action CreateFile.new(self, destination, block || data.to_s, config)
end Создает новый файл относительно корня назначения с заданными данными, которые являются результатом выполнения блока или строкой данных.
Параметры
- destination<String>
-
относительный путь к корню назначения.
- data<String|NilClass>
-
данные, которые нужно добавить в файл.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
create_file "lib/fun_party.rb" do
hostname = ask("What is the virtual hostname I should use?")
"vhost.name = #{hostname}"
end
create_file "config/apache.conf", "your apache config"
# File lib/bundler/vendor/thor/lib/thor/actions/create_link.rb, line 17
def create_link(destination, *args)
config = args.last.is_a?(Hash) ? args.pop : {}
source = args.first
action CreateLink.new(self, destination, source, config)
end Создает новый файл относительно корня назначения из заданного источника.
Параметры
- destination<String>
-
относительный путь к корню назначения.
- source<String|NilClass>
-
относительный путь к корню источника.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
-
установите :symbolic => false для жесткой ссылки.
Примеры
create_link "config/apache.conf", "/etc/apache.conf"
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 99 def destination_root @destination_stack.last end
Возвращает корень для этого класса thor (также псевдоним корня назначения).
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 106 def destination_root=(root) @destination_stack ||= [] @destination_stack[0] = File.expand_path(root || "") end
Устанавливает корень для этого класса thor. Относительные пути добавляются к каталогу, в котором был вызван скрипт и расширен.
# File lib/bundler/vendor/thor/lib/thor/actions/directory.rb, line 49
def directory(source, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source
action Directory.new(self, source, destination || source, config, &block)
end Рекурсивно копирует файлы из каталога source в корневой каталог. Если какой-либо из файлов заканчивается на .tt, он рассматривается как шаблон и помещается в место назначения без расширения .tt. Если найден пустой каталог, он копируется, а все файлы с именем .empty_directory игнорируются. Если имя файла заключено в знаки %, текст внутри знаков % выполняется как метод и заменяется возвращаемым значением. Предположим каталог doc со следующими файлами:
doc/ components/.empty_directory README rdoc.rb.tt %app_name%.rb
При вызове:
directory "doc"
Это создаст каталог doc в месте назначения со следующими файлами (предполагая, что метод `app_name` возвращает значение «blog»):
doc/ components/ README rdoc.rb blog.rb
Примечание о закодированном пути: поскольку внутренности Bundler::Thor используют Object#respond_to? для проверки возможности расширения %something%, это `something` должно быть общедоступным методом в классе, вызывающем directory. Если метод является закрытым, стек Bundler::Thor генерирует ошибку PrivateMethodEncodedError.
Параметры
- source<String>
-
относительный путь к корню источника.
- destination<String>
-
относительный путь к корню назначения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус. Если :recursive => false, не ищет пути рекурсивно. Если :mode => :preserve, сохраняет режим файла из источника. Если :exclude_pattern => /regexp/, предотвращает копирование файлов, соответствующих этому регулярному выражению.
Примеры
directory "doc" directory "doc", "docs", :recursive => false
# File lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb, line 13
def empty_directory(destination, config = {})
action EmptyDirectory.new(self, destination, config)
end Создает пустой каталог.
Параметры
- destination<String>
-
относительный путь к корню назначения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
empty_directory "doc"
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 133
def find_in_source_paths(file)
possible_files = [file, file + TEMPLATE_EXTNAME]
relative_root = relative_to_original_destination_root(destination_root, false)
source_paths.each do |source|
possible_files.each do |f|
source_file = File.expand_path(f, File.join(source, relative_root))
return source_file if File.exist?(source_file)
end
end
message = "Could not find #{file.inspect} in any of your source paths. ".dup
unless self.class.source_root
message << "Please invoke #{self.class.name}.source_root(PATH) with the PATH containing your templates. "
end
message << if source_paths.empty?
"Currently you have no source paths."
else
"Your current source paths are: \n#{source_paths.join("\n")}"
end
raise Error, message
end Принимает файл или каталог и ищет его в путях источника.
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 79
def get(source, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first
render = if source =~ %r{^https?\://}
require "open-uri"
URI.send(:open, source) { |input| input.binmode.read }
else
source = File.expand_path(find_in_source_paths(source.to_s))
open(source) { |input| input.binmode.read }
end
destination ||= if block_given?
block.arity == 1 ? yield(render) : yield
else
File.basename(source)
end
create_file destination, render, config
end Получает содержимое по заданному адресу и помещает его в указанное относительное место назначения. Если вместо места назначения задан блок, содержимое URL передается в блок и используется как местоположение.
get использует open-uri, поэтому передача входных данных пользователя приложения создаст вектор атаки на внедрение кода.
Параметры
- source<String>
-
адрес заданного содержимого.
- destination<String>
-
относительный путь к корню места назначения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
get "http://gist.github.com/103208", "doc/README"
get "http://gist.github.com/103208" do |content|
content.split("\n").first
end
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 264
def gsub_file(path, flag, *args, &block)
return unless behavior == :invoke
config = args.last.is_a?(Hash) ? args.pop : {}
path = File.expand_path(path, destination_root)
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
unless options[:pretend]
content = File.binread(path)
content.gsub!(flag, *args, &block)
File.open(path, "wb") { |file| file.write(content) }
end
end Выполняет замену по регулярному выражению в файле.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- flag<Regexp|String>
-
регулярное выражение или строка, которые нужно заменить
- replacement<String>
-
замена, может быть также задана как блок
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
gsub_file 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1' gsub_file 'README', /rake/, :green do |match| match << " no more. Use thor!" end
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 196
def in_root
inside(@destination_stack.first) { yield }
end Переходит в корень и выполняет указанный блок.
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 219
def inject_into_class(path, klass, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
config[:after] = /class #{klass}\n|class #{klass} .*\n/
insert_into_file(path, *(args << config), &block)
end Вставляет текст сразу после определения класса. Так как зависит от insert_into_file, это обратимо.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- klass<String|Class>
-
класс, который нужно изменить
- data<String>
-
данные, которые нужно добавить к классу, также может быть задан как блок.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n" inject_into_class "app/controllers/application_controller.rb", ApplicationController do " filter_parameter :password\n" end
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 242
def inject_into_module(path, module_name, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
config[:after] = /module #{module_name}\n|module #{module_name} .*\n/
insert_into_file(path, *(args << config), &block)
end Вставляет текст сразу после определения модуля. Так как зависит от insert_into_file, это обратимо.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- module_name<String|Class>
-
модуль, который нужно изменить
- data<String>
-
данные, которые нужно добавить к модулю, также может быть задан как блок.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n" inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do " def help; 'help'; end\n" end
# File lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb, line 26
def insert_into_file(destination, *args, &block)
data = block_given? ? block : args.shift
config = args.shift || {}
config[:after] = /\z/ unless config.key?(:before) || config.key?(:after)
action InjectIntoFile.new(self, destination, data, config)
end # File lib/bundler/vendor/thor/lib/thor/actions.rb, line 168
def inside(dir = "", config = {}, &block)
verbose = config.fetch(:verbose, false)
pretend = options[:pretend]
say_status :inside, dir, verbose
shell.padding += 1 if verbose
@destination_stack.push File.expand_path(dir, destination_root)
# If the directory doesnt exist and we're not pretending
if !File.exist?(destination_root) && !pretend
require "fileutils"
FileUtils.mkdir_p(destination_root)
end
if pretend
# In pretend mode, just yield down to the block
block.arity == 1 ? yield(destination_root) : yield
else
require "fileutils"
FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
end
@destination_stack.pop
shell.padding -= 1 if verbose
end Выполняет действие в корне или в заданной подпапке. Если задан относительный путь, он ссылается на текущий корень. Полный путь передается в блок, который вы предоставляете. Путь возвращается к предыдущему значению при выходе из метода.
Параметры
- dir<String>
-
каталог, в который нужно переместиться.
- config<Hash>
-
установите :verbose => true, чтобы регистрировать и использовать отступы.
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 51
def link_file(source, *args)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source
source = File.expand_path(find_in_source_paths(source.to_s))
create_link destination, source, config
end Создает ссылку на файл из относительного источника в относительное место назначения. Если место назначения не указано, предполагается, что оно равно источнику.
Параметры
- source<String>
-
относительный путь к корню источника.
- destination<String>
-
относительный путь к корню места назначения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
link_file "README", "doc/README" link_file "doc/README"
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 173
def prepend_to_file(path, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
config[:after] = /\A/
insert_into_file(path, *(args << config), &block)
end Добавляет текст в начало файла. Так как зависит от insert_into_file, это обратимо.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- data<String>
-
данные, которые нужно добавить в начало файла, также может быть задан как блок.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
prepend_to_file 'config/environments/test.rb', 'config.gem "rspec"' prepend_to_file 'config/environments/test.rb' do 'config.gem "rspec"' end
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 114
def relative_to_original_destination_root(path, remove_dot = true)
root = @destination_stack[0]
if path.start_with?(root) && [File::SEPARATOR, File::ALT_SEPARATOR, nil, ''].include?(path[root.size..root.size])
path = path.dup
path[0...root.size] = '.'
remove_dot ? (path[2..-1] || "") : path
else
path
end
end Возвращает заданный путь относительно абсолютного корня (т.е. корня, с которого стартовал скрипт).
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 327
def remove_file(path, config = {})
return unless behavior == :invoke
path = File.expand_path(path, destination_root)
say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
if !options[:pretend] && File.exist?(path)
require "fileutils"
::FileUtils.rm_rf(path)
end
end Удаляет файл по заданному пути.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
remove_file 'README' remove_file 'app/controllers/application_controller.rb'
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 244
def run(command, config = {})
return unless behavior == :invoke
destination = relative_to_original_destination_root(destination_root, false)
desc = "#{command} from #{destination.inspect}"
if config[:with]
desc = "#{File.basename(config[:with].to_s)} #{desc}"
command = "#{config[:with]} #{command}"
end
say_status :run, desc, config.fetch(:verbose, true)
return if options[:pretend]
env_splat = [config[:env]] if config[:env]
if config[:capture]
require "open3"
result, status = Open3.capture2e(*env_splat, command.to_s)
success = status.success?
else
result = system(*env_splat, command.to_s)
success = result
end
abort if !success && config.fetch(:abort_on_failure, self.class.exit_on_failure?)
result
end Выполняет команду и возвращает ее вывод.
Параметры
- command<String>
-
команда для выполнения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус, :capture => true, чтобы скрыть вывод. Укажите :with, чтобы добавить исполняемый файл к выполнению команды.
Пример
inside('vendor') do
run('ln -s ~/edge rails')
end
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 281
def run_ruby_script(command, config = {})
return unless behavior == :invoke
run command, config.merge(:with => Bundler::Thor::Util.ruby_command)
end Выполняет скрипт Ruby (с учётом особенностей платформы WIN32).
Параметры
- command<String>
-
команда для выполнения.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 127 def source_paths @source_paths ||= self.class.source_paths_for_search end
Хранит пути к исходным файлам в экземпляре для возможности их изменения.
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 115
def template(source, *args, &block)
config = args.last.is_a?(Hash) ? args.pop : {}
destination = args.first || source.sub(/#{TEMPLATE_EXTNAME}$/, "")
source = File.expand_path(find_in_source_paths(source.to_s))
context = config.delete(:context) || instance_eval("binding")
create_file destination, nil, config do
match = ERB.version.match(/(\d+\.\d+\.\d+)/)
capturable_erb = if match && match[1] >= "2.2.0" # Ruby 2.6+
CapturableERB.new(::File.binread(source), :trim_mode => "-", :eoutvar => "@output_buffer")
else
CapturableERB.new(::File.binread(source), nil, "-", "@output_buffer")
end
content = capturable_erb.tap do |erb|
erb.filename = source
end.result(context)
content = yield(content) if block
content
end
end Получает шаблон ERB по относительному пути к исходному файлу, выполняет его и создаёт копию по относительному пути к целевому файлу. Если путь к целевому файлу не указан, он предполагается равным пути к исходному файлу, из которого удалено расширение .tt.
Параметры
- source<String>
-
относительный путь к исходному каталогу.
- destination<String>
-
относительный путь к целевому каталогу.
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Примеры
template "README", "doc/README" template "doc/README"
# File lib/bundler/vendor/thor/lib/thor/actions.rb, line 304
def thor(command, *args)
config = args.last.is_a?(Hash) ? args.pop : {}
verbose = config.key?(:verbose) ? config.delete(:verbose) : true
pretend = config.key?(:pretend) ? config.delete(:pretend) : false
capture = config.key?(:capture) ? config.delete(:capture) : false
args.unshift(command)
args.push Bundler::Thor::Options.to_switches(config)
command = args.join(" ").strip
run command, :with => :thor, :verbose => verbose, :pretend => pretend, :capture => capture
end Выполняет команду thor. Хэш опций может быть передан и преобразован в параметры командной строки.
Параметры
- command<String>
-
команда для вызова
- args<Array>
-
аргументы для команды
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус, :capture => true для скрытия вывода. Другие параметры передаются в Bundler::Thor.
Примеры
thor :install, "http://gist.github.com/103208" #=> thor install http://gist.github.com/103208 thor :list, :all => true, :substring => 'rails' #=> thor list --all --substring=rails
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 291
def uncomment_lines(path, flag, *args)
flag = flag.respond_to?(:source) ? flag.source : flag
gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
end Разкомментирует все строки, соответствующие заданному регулярному выражению. Оставит пробелы, существовавшие перед символом комментария, но удалит любые пробелы между символом комментария и началом строки.
Параметры
- path<String>
-
путь к файлу, который нужно изменить
- flag<Regexp|String>
-
регулярное выражение или строка, используемые для определения строк, которые нужно разкомментировать
- config<Hash>
-
установите :verbose => false, чтобы не регистрировать статус.
Пример
uncomment_lines 'config/initializers/session_store.rb', /active_record/
Приватные методы экземпляра
# File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 348
def capture(*args)
with_output_buffer { yield(*args) }
end # File lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb, line 344 def concat(string) @output_buffer.concat(string) end
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.