thor 0.16.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +15 -0
- data/README.md +23 -6
- data/bin/thor +1 -1
- data/lib/thor/actions/create_file.rb +34 -35
- data/lib/thor/actions/create_link.rb +9 -5
- data/lib/thor/actions/directory.rb +33 -23
- data/lib/thor/actions/empty_directory.rb +75 -85
- data/lib/thor/actions/file_manipulation.rb +103 -36
- data/lib/thor/actions/inject_into_file.rb +46 -36
- data/lib/thor/actions.rb +90 -68
- data/lib/thor/base.rb +302 -244
- data/lib/thor/command.rb +142 -0
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +52 -24
- data/lib/thor/error.rb +90 -10
- data/lib/thor/group.rb +70 -74
- data/lib/thor/invocation.rb +63 -55
- data/lib/thor/line_editor/basic.rb +37 -0
- data/lib/thor/line_editor/readline.rb +88 -0
- data/lib/thor/line_editor.rb +17 -0
- data/lib/thor/nested_context.rb +29 -0
- data/lib/thor/parser/argument.rb +24 -28
- data/lib/thor/parser/arguments.rb +110 -102
- data/lib/thor/parser/option.rb +53 -15
- data/lib/thor/parser/options.rb +174 -97
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/rake_compat.rb +12 -11
- data/lib/thor/runner.rb +159 -155
- data/lib/thor/shell/basic.rb +216 -93
- data/lib/thor/shell/color.rb +53 -40
- data/lib/thor/shell/html.rb +61 -58
- data/lib/thor/shell.rb +29 -36
- data/lib/thor/util.rb +231 -213
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +303 -166
- data/thor.gemspec +27 -24
- metadata +36 -226
- data/.gitignore +0 -44
- data/.rspec +0 -2
- data/.travis.yml +0 -7
- data/CHANGELOG.rdoc +0 -134
- data/Gemfile +0 -15
- data/Thorfile +0 -30
- data/bin/rake2thor +0 -86
- data/lib/thor/core_ext/dir_escape.rb +0 -0
- data/lib/thor/core_ext/file_binary_read.rb +0 -9
- data/lib/thor/core_ext/ordered_hash.rb +0 -100
- data/lib/thor/task.rb +0 -132
- data/spec/actions/create_file_spec.rb +0 -170
- data/spec/actions/create_link_spec.rb +0 -81
- data/spec/actions/directory_spec.rb +0 -149
- data/spec/actions/empty_directory_spec.rb +0 -130
- data/spec/actions/file_manipulation_spec.rb +0 -370
- data/spec/actions/inject_into_file_spec.rb +0 -135
- data/spec/actions_spec.rb +0 -331
- data/spec/base_spec.rb +0 -279
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -43
- data/spec/core_ext/ordered_hash_spec.rb +0 -115
- data/spec/exit_condition_spec.rb +0 -19
- data/spec/fixtures/application.rb +0 -2
- data/spec/fixtures/app{1}/README +0 -3
- data/spec/fixtures/bundle/execute.rb +0 -6
- data/spec/fixtures/bundle/main.thor +0 -1
- data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
- data/spec/fixtures/doc/COMMENTER +0 -10
- data/spec/fixtures/doc/README +0 -3
- data/spec/fixtures/doc/block_helper.rb +0 -3
- data/spec/fixtures/doc/components/.empty_directory +0 -0
- data/spec/fixtures/doc/config.rb +0 -1
- data/spec/fixtures/doc/config.yaml.tt +0 -1
- data/spec/fixtures/enum.thor +0 -10
- data/spec/fixtures/group.thor +0 -114
- data/spec/fixtures/invoke.thor +0 -112
- data/spec/fixtures/path with spaces +0 -0
- data/spec/fixtures/script.thor +0 -190
- data/spec/fixtures/task.thor +0 -10
- data/spec/group_spec.rb +0 -216
- data/spec/invocation_spec.rb +0 -100
- data/spec/parser/argument_spec.rb +0 -53
- data/spec/parser/arguments_spec.rb +0 -66
- data/spec/parser/option_spec.rb +0 -202
- data/spec/parser/options_spec.rb +0 -330
- data/spec/rake_compat_spec.rb +0 -72
- data/spec/register_spec.rb +0 -135
- data/spec/runner_spec.rb +0 -241
- data/spec/shell/basic_spec.rb +0 -300
- data/spec/shell/color_spec.rb +0 -81
- data/spec/shell/html_spec.rb +0 -32
- data/spec/shell_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -59
- data/spec/task_spec.rb +0 -80
- data/spec/thor_spec.rb +0 -418
- data/spec/util_spec.rb +0 -196
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 30e79d2b0a96e87c8e6348467db577c6ad1e9acbbbac5d375417bc3e5a2b7698
|
4
|
+
data.tar.gz: 701f1ab842da90e599b96bd00d90481d716eb29e39e0283b5ff527c2033fc742
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 73b1ac80575d4422204cd8072950b5594739db3b6f3fde0f2f04359d51b1d4428524d25b9a3003ae9ec3f6be615cf635f3057bbc65558e6a17ba490ff045988b
|
7
|
+
data.tar.gz: eb7761a5e6f3674cb3231398145978b0eb53a6fa2c10e4cb9e99d8d523988efcefc8cae5dd163b8a3d6ead7424422d58b92311c200790ad6e2416e3f9757a90e
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Pull Requests
|
2
|
+
-------------
|
3
|
+
Here are some reasons why a pull request may not be merged:
|
4
|
+
|
5
|
+
1. It hasn’t been reviewed.
|
6
|
+
2. It doesn’t include specs for new functionality.
|
7
|
+
3. It doesn’t include documentation for new functionality.
|
8
|
+
4. It changes behavior without changing the relevant documentation, comments, or specs.
|
9
|
+
5. It changes behavior of an existing public API, breaking backward compatibility.
|
10
|
+
6. It breaks the tests on a supported platform.
|
11
|
+
7. It doesn’t merge cleanly (requiring Git rebasing and conflict resolution).
|
12
|
+
|
13
|
+
If you would like to help in this process, you can start by evaluating open pull requests against the criteria above. For example, if a pull request does not include specs for new functionality, you can add a comment like: “If you would like this feature to be added to Thor, please add specs to ensure that it does not break in the future.” This will help move a pull request closer to being merged.
|
14
|
+
|
15
|
+
Include this emoji in the top of your ticket to signal to us that you read this file: 🌈
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
-
[![Build Status](https://secure.travis-ci.org/wycats/thor.png?branch=master)](http://travis-ci.org/wycats/thor)
|
2
|
-
|
3
1
|
Thor
|
4
2
|
====
|
5
3
|
|
4
|
+
[![Gem Version](http://img.shields.io/gem/v/thor.svg)][gem]
|
5
|
+
|
6
|
+
[gem]: https://rubygems.org/gems/thor
|
7
|
+
|
6
8
|
Description
|
7
9
|
-----------
|
8
10
|
Thor is a simple and efficient tool for building self-documenting command line
|
@@ -11,7 +13,13 @@ utilities. It removes the pain of parsing command line options, writing
|
|
11
13
|
build tool. The syntax is Rake-like, so it should be familiar to most Rake
|
12
14
|
users.
|
13
15
|
|
14
|
-
|
16
|
+
Please note: Thor, by design, is a system tool created to allow seamless file and url
|
17
|
+
access, which should not receive application user input. It relies on [open-uri][open-uri],
|
18
|
+
which combined with application user input would provide a command injection attack
|
19
|
+
vector.
|
20
|
+
|
21
|
+
[rake]: https://github.com/ruby/rake
|
22
|
+
[open-uri]: https://ruby-doc.org/stdlib-2.5.1/libdoc/open-uri/rdoc/index.html
|
15
23
|
|
16
24
|
Installation
|
17
25
|
------------
|
@@ -19,10 +27,19 @@ Installation
|
|
19
27
|
|
20
28
|
Usage and documentation
|
21
29
|
-----------------------
|
22
|
-
Please see
|
30
|
+
Please see the [wiki][] for basic usage and other documentation on using Thor. You can also checkout the [official homepage][homepage].
|
31
|
+
|
32
|
+
[wiki]: https://github.com/rails/thor/wiki
|
33
|
+
[homepage]: http://whatisthor.com/
|
34
|
+
|
35
|
+
Contributing
|
36
|
+
------------
|
37
|
+
If you would like to help, please read the [CONTRIBUTING][] file for suggestions.
|
38
|
+
|
39
|
+
[contributing]: CONTRIBUTING.md
|
23
40
|
|
24
41
|
License
|
25
42
|
-------
|
26
|
-
Released under the MIT License. See the [LICENSE][
|
43
|
+
Released under the MIT License. See the [LICENSE][] file for further details.
|
27
44
|
|
28
|
-
[license]:
|
45
|
+
[license]: LICENSE.md
|
data/bin/thor
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
5
|
-
|
6
5
|
# Create a new file relative to the destination root with the given data,
|
7
6
|
# which is the return value of a block or a data string.
|
8
7
|
#
|
@@ -25,7 +24,7 @@ class Thor
|
|
25
24
|
data = args.first
|
26
25
|
action CreateFile.new(self, destination, block || data.to_s, config)
|
27
26
|
end
|
28
|
-
|
27
|
+
alias_method :add_file, :create_file
|
29
28
|
|
30
29
|
# CreateFile is a subset of Template, which instead of rendering a file with
|
31
30
|
# ERB, it gets the content from the user.
|
@@ -33,7 +32,7 @@ class Thor
|
|
33
32
|
class CreateFile < EmptyDirectory #:nodoc:
|
34
33
|
attr_reader :data
|
35
34
|
|
36
|
-
def initialize(base, destination, data, config={})
|
35
|
+
def initialize(base, destination, data, config = {})
|
37
36
|
@data = data
|
38
37
|
super(base, destination, config)
|
39
38
|
end
|
@@ -59,47 +58,47 @@ class Thor
|
|
59
58
|
|
60
59
|
def invoke!
|
61
60
|
invoke_with_conflict_check do
|
61
|
+
require "fileutils"
|
62
62
|
FileUtils.mkdir_p(File.dirname(destination))
|
63
|
-
File.open(destination,
|
63
|
+
File.open(destination, "wb") { |f| f.write render }
|
64
64
|
end
|
65
65
|
given_destination
|
66
66
|
end
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
# Now on conflict we check if the file is identical or not.
|
71
|
-
#
|
72
|
-
def on_conflict_behavior(&block)
|
73
|
-
if identical?
|
74
|
-
say_status :identical, :blue
|
75
|
-
else
|
76
|
-
options = base.options.merge(config)
|
77
|
-
force_or_skip_or_conflict(options[:force], options[:skip], &block)
|
78
|
-
end
|
79
|
-
end
|
68
|
+
protected
|
80
69
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
elsif skip
|
90
|
-
say_status :skip, :yellow
|
91
|
-
else
|
92
|
-
say_status :conflict, :red
|
93
|
-
force_or_skip_or_conflict(force_on_collision?, true, &block)
|
94
|
-
end
|
70
|
+
# Now on conflict we check if the file is identical or not.
|
71
|
+
#
|
72
|
+
def on_conflict_behavior(&block)
|
73
|
+
if identical?
|
74
|
+
say_status :identical, :blue
|
75
|
+
else
|
76
|
+
options = base.options.merge(config)
|
77
|
+
force_or_skip_or_conflict(options[:force], options[:skip], &block)
|
95
78
|
end
|
79
|
+
end
|
96
80
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
81
|
+
# If force is true, run the action, otherwise check if it's not being
|
82
|
+
# skipped. If both are false, show the file_collision menu, if the menu
|
83
|
+
# returns true, force it, otherwise skip.
|
84
|
+
#
|
85
|
+
def force_or_skip_or_conflict(force, skip, &block)
|
86
|
+
if force
|
87
|
+
say_status :force, :yellow
|
88
|
+
yield unless pretend?
|
89
|
+
elsif skip
|
90
|
+
say_status :skip, :yellow
|
91
|
+
else
|
92
|
+
say_status :conflict, :red
|
93
|
+
force_or_skip_or_conflict(force_on_collision?, true, &block)
|
101
94
|
end
|
95
|
+
end
|
102
96
|
|
97
|
+
# Shows the file collision menu to the user and gets the result.
|
98
|
+
#
|
99
|
+
def force_on_collision?
|
100
|
+
base.shell.file_collision(destination) { render }
|
101
|
+
end
|
103
102
|
end
|
104
103
|
end
|
105
104
|
end
|
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
require_relative "create_file"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
5
|
-
|
6
5
|
# Create a new file relative to the destination root from the given source.
|
7
6
|
#
|
8
7
|
# ==== Parameters
|
@@ -15,12 +14,12 @@ class Thor
|
|
15
14
|
#
|
16
15
|
# create_link "config/apache.conf", "/etc/apache.conf"
|
17
16
|
#
|
18
|
-
def create_link(destination, *args
|
17
|
+
def create_link(destination, *args)
|
19
18
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
20
19
|
source = args.first
|
21
20
|
action CreateLink.new(self, destination, source, config)
|
22
21
|
end
|
23
|
-
|
22
|
+
alias_method :add_link, :create_link
|
24
23
|
|
25
24
|
# CreateLink is a subset of CreateFile, which instead of taking a block of
|
26
25
|
# data, just takes a source string from the user.
|
@@ -34,11 +33,13 @@ class Thor
|
|
34
33
|
# Boolean:: true if it is identical, false otherwise.
|
35
34
|
#
|
36
35
|
def identical?
|
37
|
-
|
36
|
+
source = File.expand_path(render, File.dirname(destination))
|
37
|
+
exists? && File.identical?(source, destination)
|
38
38
|
end
|
39
39
|
|
40
40
|
def invoke!
|
41
41
|
invoke_with_conflict_check do
|
42
|
+
require "fileutils"
|
42
43
|
FileUtils.mkdir_p(File.dirname(destination))
|
43
44
|
# Create a symlink by default
|
44
45
|
config[:symbolic] = true if config[:symbolic].nil?
|
@@ -52,6 +53,9 @@ class Thor
|
|
52
53
|
given_destination
|
53
54
|
end
|
54
55
|
|
56
|
+
def exists?
|
57
|
+
super || File.symlink?(destination)
|
58
|
+
end
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "empty_directory"
|
2
2
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
@@ -38,6 +38,8 @@ class Thor
|
|
38
38
|
# destination<String>:: the relative path to the destination root.
|
39
39
|
# config<Hash>:: give :verbose => false to not log the status.
|
40
40
|
# If :recursive => false, does not look for paths recursively.
|
41
|
+
# If :mode => :preserve, preserve the file mode from the source.
|
42
|
+
# If :exclude_pattern => /regexp/, prevents copying files that match that regexp.
|
41
43
|
#
|
42
44
|
# ==== Examples
|
43
45
|
#
|
@@ -53,10 +55,10 @@ class Thor
|
|
53
55
|
class Directory < EmptyDirectory #:nodoc:
|
54
56
|
attr_reader :source
|
55
57
|
|
56
|
-
def initialize(base, source, destination=nil, config={}, &block)
|
57
|
-
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
58
|
+
def initialize(base, source, destination = nil, config = {}, &block)
|
59
|
+
@source = File.expand_path(Dir[Util.escape_globs(base.find_in_source_paths(source.to_s))].first)
|
58
60
|
@block = block
|
59
|
-
super(base, destination, {
|
61
|
+
super(base, destination, {:recursive => true}.merge(config))
|
60
62
|
end
|
61
63
|
|
62
64
|
def invoke!
|
@@ -68,31 +70,39 @@ class Thor
|
|
68
70
|
execute!
|
69
71
|
end
|
70
72
|
|
71
|
-
|
73
|
+
protected
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
def execute!
|
76
|
+
lookup = Util.escape_globs(source)
|
77
|
+
lookup = config[:recursive] ? File.join(lookup, "**") : lookup
|
78
|
+
lookup = file_level_lookup(lookup)
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
80
|
+
files(lookup).sort.each do |file_source|
|
81
|
+
next if File.directory?(file_source)
|
82
|
+
next if config[:exclude_pattern] && file_source.match(config[:exclude_pattern])
|
83
|
+
file_destination = File.join(given_destination, file_source.gsub(source, "."))
|
84
|
+
file_destination.gsub!("/./", "/")
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
86
|
+
case file_source
|
87
|
+
when /\.empty_directory$/
|
88
|
+
dirname = File.dirname(file_destination).gsub(%r{/\.$}, "")
|
89
|
+
next if dirname == given_destination
|
90
|
+
base.empty_directory(dirname, config)
|
91
|
+
when /#{TEMPLATE_EXTNAME}$/
|
92
|
+
base.template(file_source, file_destination[0..-4], config, &@block)
|
93
|
+
else
|
94
|
+
base.copy_file(file_source, file_destination, config, &@block)
|
93
95
|
end
|
94
96
|
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def file_level_lookup(previous_lookup)
|
100
|
+
File.join(previous_lookup, "*")
|
101
|
+
end
|
95
102
|
|
103
|
+
def files(lookup)
|
104
|
+
Dir.glob(lookup, File::FNM_DOTMATCH)
|
105
|
+
end
|
96
106
|
end
|
97
107
|
end
|
98
108
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
class Thor
|
2
2
|
module Actions
|
3
|
-
|
4
3
|
# Creates an empty directory.
|
5
4
|
#
|
6
5
|
# ==== Parameters
|
@@ -11,7 +10,7 @@ class Thor
|
|
11
10
|
#
|
12
11
|
# empty_directory "doc"
|
13
12
|
#
|
14
|
-
def empty_directory(destination, config={})
|
13
|
+
def empty_directory(destination, config = {})
|
15
14
|
action EmptyDirectory.new(self, destination, config)
|
16
15
|
end
|
17
16
|
|
@@ -32,8 +31,9 @@ class Thor
|
|
32
31
|
# destination<String>:: Relative path to the destination of this file
|
33
32
|
# config<Hash>:: give :verbose => false to not log the status.
|
34
33
|
#
|
35
|
-
def initialize(base, destination, config={})
|
36
|
-
@base
|
34
|
+
def initialize(base, destination, config = {})
|
35
|
+
@base = base
|
36
|
+
@config = {:verbose => true}.merge(config)
|
37
37
|
self.destination = destination
|
38
38
|
end
|
39
39
|
|
@@ -43,111 +43,101 @@ class Thor
|
|
43
43
|
# Boolean:: true if the file exists, false otherwise.
|
44
44
|
#
|
45
45
|
def exists?
|
46
|
-
::File.
|
46
|
+
::File.exist?(destination)
|
47
47
|
end
|
48
48
|
|
49
49
|
def invoke!
|
50
50
|
invoke_with_conflict_check do
|
51
|
+
require "fileutils"
|
51
52
|
::FileUtils.mkdir_p(destination)
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
56
|
def revoke!
|
56
57
|
say_status :remove, :red
|
58
|
+
require "fileutils"
|
57
59
|
::FileUtils.rm_rf(destination) if !pretend? && exists?
|
58
60
|
given_destination
|
59
61
|
end
|
60
62
|
|
61
|
-
|
63
|
+
protected
|
62
64
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
# Shortcut for pretend.
|
66
|
+
#
|
67
|
+
def pretend?
|
68
|
+
base.options[:pretend]
|
69
|
+
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
71
|
+
# Sets the absolute destination value from a relative destination value.
|
72
|
+
# It also stores the given and relative destination. Let's suppose our
|
73
|
+
# script is being executed on "dest", it sets the destination root to
|
74
|
+
# "dest". The destination, given_destination and relative_destination
|
75
|
+
# are related in the following way:
|
76
|
+
#
|
77
|
+
# inside "bar" do
|
78
|
+
# empty_directory "baz"
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# destination #=> dest/bar/baz
|
82
|
+
# relative_destination #=> bar/baz
|
83
|
+
# given_destination #=> baz
|
84
|
+
#
|
85
|
+
def destination=(destination)
|
86
|
+
return unless destination
|
87
|
+
@given_destination = convert_encoded_instructions(destination.to_s)
|
88
|
+
@destination = ::File.expand_path(@given_destination, base.destination_root)
|
89
|
+
@relative_destination = base.relative_to_original_destination_root(@destination)
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
92
|
+
# Filenames in the encoded form are converted. If you have a file:
|
93
|
+
#
|
94
|
+
# %file_name%.rb
|
95
|
+
#
|
96
|
+
# It calls #file_name from the base and replaces %-string with the
|
97
|
+
# return value (should be String) of #file_name:
|
98
|
+
#
|
99
|
+
# user.rb
|
100
|
+
#
|
101
|
+
# The method referenced can be either public or private.
|
102
|
+
#
|
103
|
+
def convert_encoded_instructions(filename)
|
104
|
+
filename.gsub(/%(.*?)%/) do |initial_string|
|
105
|
+
method = $1.strip
|
106
|
+
base.respond_to?(method, true) ? base.send(method) : initial_string
|
107
107
|
end
|
108
|
+
end
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
raise Thor::PrivateMethodEncodedError,
|
119
|
-
"Method #{base.class}##{sym} should be public, not private"
|
120
|
-
else
|
121
|
-
nil
|
122
|
-
end
|
110
|
+
# Receives a hash of options and just execute the block if some
|
111
|
+
# conditions are met.
|
112
|
+
#
|
113
|
+
def invoke_with_conflict_check(&block)
|
114
|
+
if exists?
|
115
|
+
on_conflict_behavior(&block)
|
116
|
+
else
|
117
|
+
yield unless pretend?
|
118
|
+
say_status :create, :green
|
123
119
|
end
|
124
120
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
if exists?
|
130
|
-
on_conflict_behavior(&block)
|
131
|
-
else
|
132
|
-
say_status :create, :green
|
133
|
-
block.call unless pretend?
|
134
|
-
end
|
135
|
-
|
136
|
-
destination
|
137
|
-
end
|
121
|
+
destination
|
122
|
+
rescue Errno::EISDIR, Errno::EEXIST
|
123
|
+
on_file_clash_behavior
|
124
|
+
end
|
138
125
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
say_status :exist, :blue
|
143
|
-
end
|
126
|
+
def on_file_clash_behavior
|
127
|
+
say_status :file_clash, :red
|
128
|
+
end
|
144
129
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
130
|
+
# What to do when the destination file already exists.
|
131
|
+
#
|
132
|
+
def on_conflict_behavior
|
133
|
+
say_status :exist, :blue
|
134
|
+
end
|
150
135
|
|
136
|
+
# Shortcut to say_status shell method.
|
137
|
+
#
|
138
|
+
def say_status(status, color)
|
139
|
+
base.shell.say_status status, relative_destination, color if config[:verbose]
|
140
|
+
end
|
151
141
|
end
|
152
142
|
end
|
153
143
|
end
|