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
data/bin/rake2thor
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'ruby2ruby'
|
4
|
-
require 'parse_tree'
|
5
|
-
if Ruby2Ruby::VERSION >= "1.2.0"
|
6
|
-
require 'parse_tree_extensions'
|
7
|
-
end
|
8
|
-
require 'rake'
|
9
|
-
|
10
|
-
input = ARGV[0] || 'Rakefile'
|
11
|
-
output = ARGV[1] || 'Thorfile'
|
12
|
-
|
13
|
-
$requires = []
|
14
|
-
|
15
|
-
module Kernel
|
16
|
-
def require_with_record(file)
|
17
|
-
$requires << file if caller[1] =~ /rake2thor:/
|
18
|
-
require_without_record file
|
19
|
-
end
|
20
|
-
alias_method :require_without_record, :require
|
21
|
-
alias_method :require, :require_with_record
|
22
|
-
end
|
23
|
-
|
24
|
-
load input
|
25
|
-
|
26
|
-
@private_methods = []
|
27
|
-
|
28
|
-
def file_task_name(name)
|
29
|
-
"compile_" + name.gsub('/', '_slash_').gsub('.', '_dot_').gsub(/\W/, '_')
|
30
|
-
end
|
31
|
-
|
32
|
-
def method_for_task(task)
|
33
|
-
file_task = task.is_a?(Rake::FileTask)
|
34
|
-
comment = task.instance_variable_get('@comment')
|
35
|
-
prereqs = task.instance_variable_get('@prerequisites').select(&Rake::Task.method(:task_defined?))
|
36
|
-
actions = task.instance_variable_get('@actions')
|
37
|
-
name = task.name.gsub(/^([^:]+:)+/, '')
|
38
|
-
name = file_task_name(name) if file_task
|
39
|
-
meth = ''
|
40
|
-
|
41
|
-
meth << "desc #{name.inspect}, #{comment.inspect}\n" if comment
|
42
|
-
meth << "def #{name}\n"
|
43
|
-
|
44
|
-
meth << prereqs.map do |pre|
|
45
|
-
pre = pre.to_s
|
46
|
-
pre = file_task_name(pre) if Rake::Task[pre].is_a?(Rake::FileTask)
|
47
|
-
' ' + pre
|
48
|
-
end.join("\n")
|
49
|
-
|
50
|
-
meth << "\n\n" unless prereqs.empty? || actions.empty?
|
51
|
-
|
52
|
-
meth << actions.map do |act|
|
53
|
-
act = act.to_ruby
|
54
|
-
unless act.gsub!(/^proc \{ \|(\w+)\|\n/,
|
55
|
-
" \\1 = Struct.new(:name).new(#{name.inspect}) # A crude mock Rake::Task object\n")
|
56
|
-
act.gsub!(/^proc \{\n/, '')
|
57
|
-
end
|
58
|
-
act.gsub(/\n\}$/, '')
|
59
|
-
end.join("\n")
|
60
|
-
|
61
|
-
meth << "\nend"
|
62
|
-
|
63
|
-
if file_task
|
64
|
-
@private_methods << meth
|
65
|
-
return
|
66
|
-
end
|
67
|
-
|
68
|
-
meth
|
69
|
-
end
|
70
|
-
|
71
|
-
body = Rake::Task.tasks.map(&method(:method_for_task)).compact.map { |meth| meth.gsub(/^/, ' ') }.join("\n\n")
|
72
|
-
|
73
|
-
unless @private_methods.empty?
|
74
|
-
body << "\n\n private\n\n"
|
75
|
-
body << @private_methods.map { |meth| meth.gsub(/^/, ' ') }.join("\n\n")
|
76
|
-
end
|
77
|
-
|
78
|
-
requires = $requires.map { |r| "require #{r.inspect}" }.join("\n")
|
79
|
-
|
80
|
-
File.open(output, 'w') { |f| f.write(<<END.lstrip) }
|
81
|
-
#{requires}
|
82
|
-
|
83
|
-
class Default < Thor
|
84
|
-
#{body}
|
85
|
-
end
|
86
|
-
END
|
File without changes
|
@@ -1,100 +0,0 @@
|
|
1
|
-
class Thor
|
2
|
-
module CoreExt #:nodoc:
|
3
|
-
|
4
|
-
if RUBY_VERSION >= '1.9'
|
5
|
-
class OrderedHash < ::Hash
|
6
|
-
end
|
7
|
-
else
|
8
|
-
# This class is based on the Ruby 1.9 ordered hashes.
|
9
|
-
#
|
10
|
-
# It keeps the semantics and most of the efficiency of normal hashes
|
11
|
-
# while also keeping track of the order in which elements were set.
|
12
|
-
#
|
13
|
-
class OrderedHash #:nodoc:
|
14
|
-
include Enumerable
|
15
|
-
|
16
|
-
Node = Struct.new(:key, :value, :next, :prev)
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@hash = {}
|
20
|
-
end
|
21
|
-
|
22
|
-
def [](key)
|
23
|
-
@hash[key] && @hash[key].value
|
24
|
-
end
|
25
|
-
|
26
|
-
def []=(key, value)
|
27
|
-
if node = @hash[key]
|
28
|
-
node.value = value
|
29
|
-
else
|
30
|
-
node = Node.new(key, value)
|
31
|
-
|
32
|
-
if @first.nil?
|
33
|
-
@first = @last = node
|
34
|
-
else
|
35
|
-
node.prev = @last
|
36
|
-
@last.next = node
|
37
|
-
@last = node
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
@hash[key] = node
|
42
|
-
value
|
43
|
-
end
|
44
|
-
|
45
|
-
def delete(key)
|
46
|
-
if node = @hash[key]
|
47
|
-
prev_node = node.prev
|
48
|
-
next_node = node.next
|
49
|
-
|
50
|
-
next_node.prev = prev_node if next_node
|
51
|
-
prev_node.next = next_node if prev_node
|
52
|
-
|
53
|
-
@first = next_node if @first == node
|
54
|
-
@last = prev_node if @last == node
|
55
|
-
|
56
|
-
value = node.value
|
57
|
-
end
|
58
|
-
|
59
|
-
@hash.delete(key)
|
60
|
-
value
|
61
|
-
end
|
62
|
-
|
63
|
-
def keys
|
64
|
-
self.map { |k, v| k }
|
65
|
-
end
|
66
|
-
|
67
|
-
def values
|
68
|
-
self.map { |k, v| v }
|
69
|
-
end
|
70
|
-
|
71
|
-
def each
|
72
|
-
return unless @first
|
73
|
-
yield [@first.key, @first.value]
|
74
|
-
node = @first
|
75
|
-
yield [node.key, node.value] while node = node.next
|
76
|
-
self
|
77
|
-
end
|
78
|
-
|
79
|
-
def merge(other)
|
80
|
-
hash = self.class.new
|
81
|
-
|
82
|
-
self.each do |key, value|
|
83
|
-
hash[key] = value
|
84
|
-
end
|
85
|
-
|
86
|
-
other.each do |key, value|
|
87
|
-
hash[key] = value
|
88
|
-
end
|
89
|
-
|
90
|
-
hash
|
91
|
-
end
|
92
|
-
|
93
|
-
def empty?
|
94
|
-
@hash.empty?
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|
data/lib/thor/task.rb
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
class Thor
|
2
|
-
class Task < Struct.new(:name, :description, :long_description, :usage, :options)
|
3
|
-
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
|
4
|
-
|
5
|
-
def initialize(name, description, long_description, usage, options=nil)
|
6
|
-
super(name.to_s, description, long_description, usage, options || {})
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize_copy(other) #:nodoc:
|
10
|
-
super(other)
|
11
|
-
self.options = other.options.dup if other.options
|
12
|
-
end
|
13
|
-
|
14
|
-
def hidden?
|
15
|
-
false
|
16
|
-
end
|
17
|
-
|
18
|
-
# By default, a task invokes a method in the thor class. You can change this
|
19
|
-
# implementation to create custom tasks.
|
20
|
-
def run(instance, args=[])
|
21
|
-
arity = nil
|
22
|
-
|
23
|
-
if private_method?(instance)
|
24
|
-
instance.class.handle_no_task_error(name)
|
25
|
-
elsif public_method?(instance)
|
26
|
-
arity = instance.method(name).arity
|
27
|
-
instance.send(name, *args)
|
28
|
-
elsif local_method?(instance, :method_missing)
|
29
|
-
instance.send(:method_missing, name.to_sym, *args)
|
30
|
-
else
|
31
|
-
instance.class.handle_no_task_error(name)
|
32
|
-
end
|
33
|
-
rescue ArgumentError => e
|
34
|
-
handle_argument_error?(instance, e, caller) ?
|
35
|
-
instance.class.handle_argument_error(self, e, arity) : (raise e)
|
36
|
-
rescue NoMethodError => e
|
37
|
-
handle_no_method_error?(instance, e, caller) ?
|
38
|
-
instance.class.handle_no_task_error(name) : (raise e)
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns the formatted usage by injecting given required arguments
|
42
|
-
# and required options into the given usage.
|
43
|
-
def formatted_usage(klass, namespace = true, subcommand = false)
|
44
|
-
if namespace
|
45
|
-
namespace = klass.namespace
|
46
|
-
formatted = "#{namespace.gsub(/^(default)/,'')}:"
|
47
|
-
end
|
48
|
-
formatted = "#{klass.namespace.split(':').last} " if subcommand
|
49
|
-
|
50
|
-
formatted ||= ""
|
51
|
-
|
52
|
-
# Add usage with required arguments
|
53
|
-
formatted << if klass && !klass.arguments.empty?
|
54
|
-
usage.to_s.gsub(/^#{name}/) do |match|
|
55
|
-
match << " " << klass.arguments.map{ |a| a.usage }.compact.join(' ')
|
56
|
-
end
|
57
|
-
else
|
58
|
-
usage.to_s
|
59
|
-
end
|
60
|
-
|
61
|
-
# Add required options
|
62
|
-
formatted << " #{required_options}"
|
63
|
-
|
64
|
-
# Strip and go!
|
65
|
-
formatted.strip
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
def not_debugging?(instance)
|
71
|
-
!(instance.class.respond_to?(:debugging) && instance.class.debugging)
|
72
|
-
end
|
73
|
-
|
74
|
-
def required_options
|
75
|
-
@required_options ||= options.map{ |_, o| o.usage if o.required? }.compact.sort.join(" ")
|
76
|
-
end
|
77
|
-
|
78
|
-
# Given a target, checks if this class name is a public method.
|
79
|
-
def public_method?(instance) #:nodoc:
|
80
|
-
!(instance.public_methods & [name.to_s, name.to_sym]).empty?
|
81
|
-
end
|
82
|
-
|
83
|
-
def private_method?(instance)
|
84
|
-
!(instance.private_methods & [name.to_s, name.to_sym]).empty?
|
85
|
-
end
|
86
|
-
|
87
|
-
def local_method?(instance, name)
|
88
|
-
methods = instance.public_methods(false) + instance.private_methods(false) + instance.protected_methods(false)
|
89
|
-
!(methods & [name.to_s, name.to_sym]).empty?
|
90
|
-
end
|
91
|
-
|
92
|
-
def sans_backtrace(backtrace, caller) #:nodoc:
|
93
|
-
saned = backtrace.reject { |frame| frame =~ FILE_REGEXP || (frame =~ /\.java:/ && RUBY_PLATFORM =~ /java/) }
|
94
|
-
saned -= caller
|
95
|
-
end
|
96
|
-
|
97
|
-
def handle_argument_error?(instance, error, caller)
|
98
|
-
not_debugging?(instance) && error.message =~ /wrong number of arguments/ && begin
|
99
|
-
saned = sans_backtrace(error.backtrace, caller)
|
100
|
-
# Ruby 1.9 always include the called method in the backtrace
|
101
|
-
saned.empty? || (saned.size == 1 && RUBY_VERSION >= "1.9")
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def handle_no_method_error?(instance, error, caller)
|
106
|
-
not_debugging?(instance) &&
|
107
|
-
error.message =~ /^undefined method `#{name}' for #{Regexp.escape(instance.to_s)}$/
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# A task that is hidden in help messages but still invocable.
|
112
|
-
class HiddenTask < Task
|
113
|
-
def hidden?
|
114
|
-
true
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# A dynamic task that handles method missing scenarios.
|
119
|
-
class DynamicTask < Task
|
120
|
-
def initialize(name, options=nil)
|
121
|
-
super(name.to_s, "A dynamically-generated task", name.to_s, name.to_s, options)
|
122
|
-
end
|
123
|
-
|
124
|
-
def run(instance, args=[])
|
125
|
-
if (instance.methods & [name.to_s, name.to_sym]).empty?
|
126
|
-
super
|
127
|
-
else
|
128
|
-
instance.class.handle_no_task_error(name)
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require 'thor/actions'
|
3
|
-
|
4
|
-
describe Thor::Actions::CreateFile do
|
5
|
-
before do
|
6
|
-
::FileUtils.rm_rf(destination_root)
|
7
|
-
end
|
8
|
-
|
9
|
-
def create_file(destination=nil, config={}, options={})
|
10
|
-
@base = MyCounter.new([1,2], options, { :destination_root => destination_root })
|
11
|
-
@base.stub!(:file_name).and_return('rdoc')
|
12
|
-
|
13
|
-
@action = Thor::Actions::CreateFile.new(@base, destination, "CONFIGURATION",
|
14
|
-
{ :verbose => !@silence }.merge(config))
|
15
|
-
end
|
16
|
-
|
17
|
-
def invoke!
|
18
|
-
capture(:stdout){ @action.invoke! }
|
19
|
-
end
|
20
|
-
|
21
|
-
def revoke!
|
22
|
-
capture(:stdout){ @action.revoke! }
|
23
|
-
end
|
24
|
-
|
25
|
-
def silence!
|
26
|
-
@silence = true
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "#invoke!" do
|
30
|
-
it "creates a file" do
|
31
|
-
create_file("doc/config.rb")
|
32
|
-
invoke!
|
33
|
-
File.exists?(File.join(destination_root, "doc/config.rb")).should be_true
|
34
|
-
end
|
35
|
-
|
36
|
-
it "does not create a file if pretending" do
|
37
|
-
create_file("doc/config.rb", {}, :pretend => true)
|
38
|
-
invoke!
|
39
|
-
File.exists?(File.join(destination_root, "doc/config.rb")).should be_false
|
40
|
-
end
|
41
|
-
|
42
|
-
it "shows created status to the user" do
|
43
|
-
create_file("doc/config.rb")
|
44
|
-
invoke!.should == " create doc/config.rb\n"
|
45
|
-
end
|
46
|
-
|
47
|
-
it "does not show any information if log status is false" do
|
48
|
-
silence!
|
49
|
-
create_file("doc/config.rb")
|
50
|
-
invoke!.should be_empty
|
51
|
-
end
|
52
|
-
|
53
|
-
it "returns the given destination" do
|
54
|
-
capture(:stdout) do
|
55
|
-
create_file("doc/config.rb").invoke!.should == "doc/config.rb"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
it "converts encoded instructions" do
|
60
|
-
create_file("doc/%file_name%.rb.tt")
|
61
|
-
invoke!
|
62
|
-
File.exists?(File.join(destination_root, "doc/rdoc.rb.tt")).should be_true
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "when file exists" do
|
66
|
-
before do
|
67
|
-
create_file("doc/config.rb")
|
68
|
-
invoke!
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "and is identical" do
|
72
|
-
it "shows identical status" do
|
73
|
-
create_file("doc/config.rb")
|
74
|
-
invoke!
|
75
|
-
invoke!.should == " identical doc/config.rb\n"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe "and is not identical" do
|
80
|
-
before do
|
81
|
-
File.open(File.join(destination_root, 'doc/config.rb'), 'w'){ |f| f.write("FOO = 3") }
|
82
|
-
end
|
83
|
-
|
84
|
-
it "shows forced status to the user if force is given" do
|
85
|
-
create_file("doc/config.rb", {}, :force => true).should_not be_identical
|
86
|
-
invoke!.should == " force doc/config.rb\n"
|
87
|
-
end
|
88
|
-
|
89
|
-
it "shows skipped status to the user if skip is given" do
|
90
|
-
create_file("doc/config.rb", {}, :skip => true).should_not be_identical
|
91
|
-
invoke!.should == " skip doc/config.rb\n"
|
92
|
-
end
|
93
|
-
|
94
|
-
it "shows forced status to the user if force is configured" do
|
95
|
-
create_file("doc/config.rb", :force => true).should_not be_identical
|
96
|
-
invoke!.should == " force doc/config.rb\n"
|
97
|
-
end
|
98
|
-
|
99
|
-
it "shows skipped status to the user if skip is configured" do
|
100
|
-
create_file("doc/config.rb", :skip => true).should_not be_identical
|
101
|
-
invoke!.should == " skip doc/config.rb\n"
|
102
|
-
end
|
103
|
-
|
104
|
-
it "shows conflict status to ther user" do
|
105
|
-
create_file("doc/config.rb").should_not be_identical
|
106
|
-
$stdin.should_receive(:gets).and_return('s')
|
107
|
-
file = File.join(destination_root, 'doc/config.rb')
|
108
|
-
|
109
|
-
content = invoke!
|
110
|
-
content.should =~ /conflict doc\/config\.rb/
|
111
|
-
content.should =~ /Overwrite #{file}\? \(enter "h" for help\) \[Ynaqdh\]/
|
112
|
-
content.should =~ /skip doc\/config\.rb/
|
113
|
-
end
|
114
|
-
|
115
|
-
it "creates the file if the file collision menu returns true" do
|
116
|
-
create_file("doc/config.rb")
|
117
|
-
$stdin.should_receive(:gets).and_return('y')
|
118
|
-
invoke!.should =~ /force doc\/config\.rb/
|
119
|
-
end
|
120
|
-
|
121
|
-
it "skips the file if the file collision menu returns false" do
|
122
|
-
create_file("doc/config.rb")
|
123
|
-
$stdin.should_receive(:gets).and_return('n')
|
124
|
-
invoke!.should =~ /skip doc\/config\.rb/
|
125
|
-
end
|
126
|
-
|
127
|
-
it "executes the block given to show file content" do
|
128
|
-
create_file("doc/config.rb")
|
129
|
-
$stdin.should_receive(:gets).and_return('d')
|
130
|
-
$stdin.should_receive(:gets).and_return('n')
|
131
|
-
@base.shell.should_receive(:system).with(/diff -u/)
|
132
|
-
invoke!
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe "#revoke!" do
|
139
|
-
it "removes the destination file" do
|
140
|
-
create_file("doc/config.rb")
|
141
|
-
invoke!
|
142
|
-
revoke!
|
143
|
-
File.exists?(@action.destination).should be_false
|
144
|
-
end
|
145
|
-
|
146
|
-
it "does not raise an error if the file does not exist" do
|
147
|
-
create_file("doc/config.rb")
|
148
|
-
revoke!
|
149
|
-
File.exists?(@action.destination).should be_false
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe "#exists?" do
|
154
|
-
it "returns true if the destination file exists" do
|
155
|
-
create_file("doc/config.rb")
|
156
|
-
@action.exists?.should be_false
|
157
|
-
invoke!
|
158
|
-
@action.exists?.should be_true
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe "#identical?" do
|
163
|
-
it "returns true if the destination file and is identical" do
|
164
|
-
create_file("doc/config.rb")
|
165
|
-
@action.identical?.should be_false
|
166
|
-
invoke!
|
167
|
-
@action.identical?.should be_true
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require 'thor/actions'
|
3
|
-
require 'tempfile'
|
4
|
-
|
5
|
-
describe Thor::Actions::CreateLink do
|
6
|
-
before do
|
7
|
-
@hardlink_to = File.join(Dir.tmpdir, 'linkdest.rb')
|
8
|
-
::FileUtils.rm_rf(destination_root)
|
9
|
-
::FileUtils.rm_rf(@hardlink_to)
|
10
|
-
end
|
11
|
-
|
12
|
-
def create_link(destination=nil, config={}, options={})
|
13
|
-
@base = MyCounter.new([1,2], options, { :destination_root => destination_root })
|
14
|
-
@base.stub!(:file_name).and_return('rdoc')
|
15
|
-
|
16
|
-
@tempfile = Tempfile.new("config.rb")
|
17
|
-
|
18
|
-
@action = Thor::Actions::CreateLink.new(@base, destination, @tempfile.path,
|
19
|
-
{ :verbose => !@silence }.merge(config))
|
20
|
-
end
|
21
|
-
|
22
|
-
def invoke!
|
23
|
-
capture(:stdout){ @action.invoke! }
|
24
|
-
end
|
25
|
-
|
26
|
-
def silence!
|
27
|
-
@silence = true
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "#invoke!" do
|
31
|
-
it "creates a symbolic link for :symbolic => true" do
|
32
|
-
create_link("doc/config.rb", :symbolic => true)
|
33
|
-
invoke!
|
34
|
-
destination_path = File.join(destination_root, "doc/config.rb")
|
35
|
-
File.exists?(destination_path).should be_true
|
36
|
-
File.symlink?(destination_path).should be_true
|
37
|
-
end
|
38
|
-
|
39
|
-
it "creates a hard link for :symbolic => false" do
|
40
|
-
create_link(@hardlink_to, :symbolic => false)
|
41
|
-
invoke!
|
42
|
-
destination_path = @hardlink_to
|
43
|
-
File.exists?(destination_path).should be_true
|
44
|
-
File.symlink?(destination_path).should be_false
|
45
|
-
end
|
46
|
-
|
47
|
-
it "creates a symbolic link by default" do
|
48
|
-
create_link("doc/config.rb")
|
49
|
-
invoke!
|
50
|
-
destination_path = File.join(destination_root, "doc/config.rb")
|
51
|
-
File.exists?(destination_path).should be_true
|
52
|
-
File.symlink?(destination_path).should be_true
|
53
|
-
end
|
54
|
-
|
55
|
-
it "does not create a link if pretending" do
|
56
|
-
create_link("doc/config.rb", {}, :pretend => true)
|
57
|
-
invoke!
|
58
|
-
File.exists?(File.join(destination_root, "doc/config.rb")).should be_false
|
59
|
-
end
|
60
|
-
|
61
|
-
it "shows created status to the user" do
|
62
|
-
create_link("doc/config.rb")
|
63
|
-
invoke!.should == " create doc/config.rb\n"
|
64
|
-
end
|
65
|
-
|
66
|
-
it "does not show any information if log status is false" do
|
67
|
-
silence!
|
68
|
-
create_link("doc/config.rb")
|
69
|
-
invoke!.should be_empty
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#identical?" do
|
74
|
-
it "returns true if the destination link exists and is identical" do
|
75
|
-
create_link("doc/config.rb")
|
76
|
-
@action.identical?.should be_false
|
77
|
-
invoke!
|
78
|
-
@action.identical?.should be_true
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|