thor 0.12.0 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +3 -5
- data/Thorfile +2 -1
- data/bin/thor +1 -0
- data/lib/thor/actions/create_file.rb +2 -2
- data/lib/thor/actions/directory.rb +2 -4
- data/lib/thor/actions/file_manipulation.rb +10 -6
- data/lib/thor/actions/inject_into_file.rb +1 -1
- data/lib/thor/actions.rb +6 -5
- data/lib/thor/base.rb +30 -32
- data/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/thor/group.rb +44 -36
- data/lib/thor/runner.rb +44 -40
- data/lib/thor/shell/basic.rb +49 -29
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/task.rb +32 -43
- data/lib/thor/util.rb +4 -22
- data/lib/thor/version.rb +1 -1
- data/lib/thor.rb +43 -43
- data/spec/actions/create_file_spec.rb +7 -7
- data/spec/actions/directory_spec.rb +5 -4
- data/spec/actions/file_manipulation_spec.rb +29 -16
- data/spec/actions_spec.rb +14 -13
- data/spec/base_spec.rb +1 -1
- data/spec/fixtures/bundle/main.thor +1 -0
- data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
- data/spec/fixtures/doc/README +3 -0
- data/spec/fixtures/group.thor +83 -0
- data/spec/fixtures/invoke.thor +112 -0
- data/spec/fixtures/script.thor +130 -0
- data/spec/fixtures/task.thor +10 -0
- data/spec/group_spec.rb +1 -7
- data/spec/runner_spec.rb +35 -39
- data/spec/shell/basic_spec.rb +56 -62
- data/spec/shell/color_spec.rb +6 -6
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +4 -4
- data/spec/task_spec.rb +14 -32
- data/spec/thor_spec.rb +21 -22
- data/spec/util_spec.rb +7 -31
- metadata +28 -19
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
class MyCounter < Thor::Group
|
|
2
|
+
include Thor::Actions
|
|
3
|
+
add_runtime_options!
|
|
4
|
+
|
|
5
|
+
def self.get_from_super
|
|
6
|
+
from_superclass(:get_from_super, 13)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.source_root
|
|
10
|
+
File.expand_path(File.dirname(__FILE__))
|
|
11
|
+
end
|
|
12
|
+
source_paths << File.expand_path("broken", File.dirname(__FILE__))
|
|
13
|
+
|
|
14
|
+
argument :first, :type => :numeric
|
|
15
|
+
argument :second, :type => :numeric, :default => 2
|
|
16
|
+
|
|
17
|
+
class_option :third, :type => :numeric, :desc => "The third argument", :default => 3,
|
|
18
|
+
:banner => "THREE", :aliases => "-t"
|
|
19
|
+
class_option :fourth, :type => :numeric, :desc => "The fourth argument"
|
|
20
|
+
|
|
21
|
+
desc <<-FOO
|
|
22
|
+
Description:
|
|
23
|
+
This generator run three tasks: one, two and three.
|
|
24
|
+
FOO
|
|
25
|
+
|
|
26
|
+
def one
|
|
27
|
+
first
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def two
|
|
31
|
+
second
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def three
|
|
35
|
+
options[:third]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.inherited(base)
|
|
39
|
+
super
|
|
40
|
+
base.source_paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "doc")))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class ClearCounter < MyCounter
|
|
45
|
+
remove_argument :first, :second, :undefine => true
|
|
46
|
+
remove_class_option :third
|
|
47
|
+
|
|
48
|
+
def self.source_root
|
|
49
|
+
File.expand_path(File.join(File.dirname(__FILE__), "bundle"))
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class BrokenCounter < MyCounter
|
|
54
|
+
namespace "app:broken:counter"
|
|
55
|
+
class_option :fail, :type => :boolean, :default => false
|
|
56
|
+
|
|
57
|
+
class << self
|
|
58
|
+
undef_method :source_root
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def one
|
|
62
|
+
options[:first]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def four
|
|
66
|
+
respond_to?(:fail)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def five
|
|
70
|
+
options[:fail] ? this_method_does_not_exist : 5
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class WhinyGenerator < Thor::Group
|
|
75
|
+
include Thor::Actions
|
|
76
|
+
|
|
77
|
+
def self.source_root
|
|
78
|
+
File.expand_path(File.dirname(__FILE__))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def wrong_arity(required)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
class A < Thor
|
|
2
|
+
include Thor::Actions
|
|
3
|
+
|
|
4
|
+
desc "one", "invoke one"
|
|
5
|
+
def one
|
|
6
|
+
p 1
|
|
7
|
+
invoke :two
|
|
8
|
+
invoke :three
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
desc "two", "invoke two"
|
|
12
|
+
def two
|
|
13
|
+
p 2
|
|
14
|
+
invoke :three
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
desc "three", "invoke three"
|
|
18
|
+
def three
|
|
19
|
+
p 3
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "four", "invoke four"
|
|
23
|
+
def four
|
|
24
|
+
p 4
|
|
25
|
+
invoke "defined:five"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "five N", "check if number is equal 5"
|
|
29
|
+
def five(number)
|
|
30
|
+
number == 5
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "invoker", "invoke a b task"
|
|
34
|
+
def invoker(*args)
|
|
35
|
+
invoke :b, :one, ["Jose"]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class B < Thor
|
|
40
|
+
class_option :last_name, :type => :string
|
|
41
|
+
|
|
42
|
+
desc "one FIRST_NAME", "invoke one"
|
|
43
|
+
def one(first_name)
|
|
44
|
+
"#{options.last_name}, #{first_name}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc "two", "invoke two"
|
|
48
|
+
def two
|
|
49
|
+
options
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
desc "three", "invoke three"
|
|
53
|
+
def three
|
|
54
|
+
self
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class C < Thor::Group
|
|
59
|
+
include Thor::Actions
|
|
60
|
+
|
|
61
|
+
def one
|
|
62
|
+
p 1
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def two
|
|
66
|
+
p 2
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def three
|
|
70
|
+
p 3
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
class Defined < Thor::Group
|
|
75
|
+
class_option :unused, :type => :boolean, :desc => "This option has no use"
|
|
76
|
+
|
|
77
|
+
def one
|
|
78
|
+
p 1
|
|
79
|
+
invoke "a:two"
|
|
80
|
+
invoke "a:three"
|
|
81
|
+
invoke "a:four"
|
|
82
|
+
invoke "defined:five"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def five
|
|
86
|
+
p 5
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def print_status
|
|
90
|
+
say_status :finished, :counting
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class E < Thor::Group
|
|
95
|
+
invoke Defined
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class F < Thor::Group
|
|
99
|
+
invoke "b:one" do |instance, klass, task|
|
|
100
|
+
instance.invoke klass, task, [ "Jose" ], :last_name => "Valim"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class G < Thor::Group
|
|
105
|
+
class_option :invoked, :type => :string, :default => "defined"
|
|
106
|
+
invoke_from_option :invoked
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class H < Thor::Group
|
|
110
|
+
class_option :defined, :type => :boolean, :default => true
|
|
111
|
+
invoke_from_option :defined
|
|
112
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
class MyScript < Thor
|
|
2
|
+
group :script
|
|
3
|
+
default_task :example_default_task
|
|
4
|
+
|
|
5
|
+
map "-T" => :animal, ["-f", "--foo"] => :foo
|
|
6
|
+
|
|
7
|
+
desc "zoo", "zoo around"
|
|
8
|
+
def zoo
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc "animal TYPE", "horse around"
|
|
13
|
+
|
|
14
|
+
no_tasks do
|
|
15
|
+
def this_is_not_a_task
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def animal(type)
|
|
20
|
+
[type]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
desc "foo BAR", <<END
|
|
24
|
+
do some fooing
|
|
25
|
+
This is more info!
|
|
26
|
+
Everyone likes more info!
|
|
27
|
+
END
|
|
28
|
+
method_option :force, :type => :boolean, :desc => "Force to do some fooing"
|
|
29
|
+
def foo(bar)
|
|
30
|
+
[bar, options]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "example_default_task", "example!"
|
|
34
|
+
def example_default_task
|
|
35
|
+
options.empty? ? "default task" : options
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
desc "call_myself_with_wrong_arity", "get the right error"
|
|
39
|
+
def call_myself_with_wrong_arity
|
|
40
|
+
call_myself_with_wrong_arity(4)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "call_unexistent_method", "Call unexistent method inside a task"
|
|
44
|
+
def call_unexistent_method
|
|
45
|
+
boom!
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc "long_description", "a" * 80
|
|
49
|
+
def long_description
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
method_options :all => :boolean
|
|
53
|
+
desc "with_optional NAME", "invoke with optional name"
|
|
54
|
+
def with_optional(name=nil)
|
|
55
|
+
[ name, options ]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class AnotherScript < Thor
|
|
59
|
+
desc "baz", "do some bazing"
|
|
60
|
+
def baz
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def method_missing(meth, *args)
|
|
67
|
+
if meth == :boom!
|
|
68
|
+
super
|
|
69
|
+
else
|
|
70
|
+
[meth, args]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
desc "what", "what"
|
|
75
|
+
def what
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
class MyChildScript < MyScript
|
|
80
|
+
remove_task :bar
|
|
81
|
+
|
|
82
|
+
method_options :force => :boolean, :param => :numeric
|
|
83
|
+
def initialize(*args)
|
|
84
|
+
super
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
desc "zoo", "zoo around"
|
|
88
|
+
method_options :param => :required
|
|
89
|
+
def zoo
|
|
90
|
+
options
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
desc "animal TYPE", "horse around"
|
|
94
|
+
def animal(type)
|
|
95
|
+
[type, options]
|
|
96
|
+
end
|
|
97
|
+
method_option :other, :type => :string, :default => "method default", :for => :animal
|
|
98
|
+
desc "animal KIND", "fish around", :for => :animal
|
|
99
|
+
|
|
100
|
+
desc "boom", "explodes everything"
|
|
101
|
+
def boom
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
remove_task :boom, :undefine => true
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
module Scripts
|
|
108
|
+
class MyScript < MyChildScript
|
|
109
|
+
argument :accessor, :type => :string
|
|
110
|
+
class_options :force => :boolean
|
|
111
|
+
method_option :new_option, :type => :string, :for => :example_default_task
|
|
112
|
+
|
|
113
|
+
def zoo
|
|
114
|
+
self.accessor
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class MyDefaults < Thor
|
|
119
|
+
namespace :default
|
|
120
|
+
desc "test", "prints 'test'"
|
|
121
|
+
def test
|
|
122
|
+
puts "test"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
class ChildDefault < Thor
|
|
127
|
+
namespace "default:child"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
data/spec/group_spec.rb
CHANGED
|
@@ -29,7 +29,7 @@ describe Thor::Group do
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
it "invokes help message if any of the shortcuts is given" do
|
|
32
|
-
|
|
32
|
+
MyCounter.should_receive(:help)
|
|
33
33
|
MyCounter.start(["-h"])
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -66,12 +66,6 @@ describe Thor::Group do
|
|
|
66
66
|
@content.must =~ /Options/
|
|
67
67
|
@content.must =~ /\[\-\-third=THREE\]/
|
|
68
68
|
end
|
|
69
|
-
|
|
70
|
-
it "shows only usage if a short help is required" do
|
|
71
|
-
content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new, :short => true) }
|
|
72
|
-
content.must =~ /my_counter N \[N\]/
|
|
73
|
-
content.must_not =~ /Options/
|
|
74
|
-
end
|
|
75
69
|
end
|
|
76
70
|
|
|
77
71
|
describe "#invoke" do
|
data/spec/runner_spec.rb
CHANGED
|
@@ -26,11 +26,11 @@ describe Thor::Runner do
|
|
|
26
26
|
|
|
27
27
|
it "shows information about a specific Thor group class" do
|
|
28
28
|
content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
|
|
29
|
-
content.must =~ /my_counter N
|
|
29
|
+
content.must =~ /my_counter N/
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "raises error if a class/task cannot be found" do
|
|
33
|
-
|
|
33
|
+
Thor::Runner.should_receive(:exit).with(1)
|
|
34
34
|
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
|
35
35
|
content.must =~ /could not find Thor class or task 'unknown'/
|
|
36
36
|
end
|
|
@@ -39,7 +39,7 @@ describe Thor::Runner do
|
|
|
39
39
|
describe "#start" do
|
|
40
40
|
it "invokes a task from Thor::Runner" do
|
|
41
41
|
ARGV.replace ["list"]
|
|
42
|
-
capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N
|
|
42
|
+
capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N/
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
it "invokes a task from a specific Thor class" do
|
|
@@ -68,7 +68,7 @@ describe Thor::Runner do
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
it "raises an error if class/task can't be found" do
|
|
71
|
-
|
|
71
|
+
Thor::Runner.should_receive(:exit).with(1)
|
|
72
72
|
ARGV.replace ["unknown"]
|
|
73
73
|
capture(:stderr){ Thor::Runner.start }.must =~ /could not find Thor class or task 'unknown'/
|
|
74
74
|
end
|
|
@@ -78,12 +78,12 @@ describe Thor::Runner do
|
|
|
78
78
|
lambda { Thor::Runner.start }.must raise_error(NoMethodError)
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
it "does not swallow Thor::Group
|
|
81
|
+
it "does not swallow Thor::Group InvocationError" do
|
|
82
82
|
ARGV.replace ["whiny_generator"]
|
|
83
83
|
lambda { Thor::Runner.start }.must raise_error(ArgumentError, /Are you sure it has arity equals to 0\?/)
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
it "does not swallow Thor
|
|
86
|
+
it "does not swallow Thor InvocationError" do
|
|
87
87
|
ARGV.replace ["my_script:animal"]
|
|
88
88
|
capture(:stderr) { Thor::Runner.start }.must =~ /'animal' was called incorrectly\. Call as 'my_script:animal TYPE'/
|
|
89
89
|
end
|
|
@@ -96,26 +96,28 @@ describe Thor::Runner do
|
|
|
96
96
|
"random" => {
|
|
97
97
|
:location => @location,
|
|
98
98
|
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
|
|
99
|
-
:
|
|
99
|
+
:namespaces => ["amazing"]
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
root_file = File.join(Thor::Util.thor_root, "thor.yml")
|
|
104
|
+
|
|
103
105
|
# Stub load and save to avoid thor.yaml from being overwritten
|
|
104
|
-
stub(
|
|
105
|
-
stub(
|
|
106
|
-
stub(
|
|
106
|
+
YAML.stub!(:load_file).and_return(@original_yaml)
|
|
107
|
+
File.stub!(:exists?).with(root_file).and_return(true)
|
|
108
|
+
File.stub!(:open).with(root_file, "w")
|
|
107
109
|
end
|
|
108
110
|
|
|
109
111
|
describe "list" do
|
|
110
112
|
it "gives a list of the available tasks" do
|
|
111
113
|
ARGV.replace ["list"]
|
|
112
114
|
content = capture(:stdout) { Thor::Runner.start }
|
|
113
|
-
content.must =~ /amazing:describe NAME
|
|
115
|
+
content.must =~ /amazing:describe NAME\s+# say that someone is amazing/m
|
|
114
116
|
end
|
|
115
117
|
|
|
116
118
|
it "gives a list of the available Thor::Group classes" do
|
|
117
119
|
ARGV.replace ["list"]
|
|
118
|
-
capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N
|
|
120
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N/
|
|
119
121
|
end
|
|
120
122
|
|
|
121
123
|
it "can filter a list of the available tasks by --group" do
|
|
@@ -141,33 +143,19 @@ describe Thor::Runner do
|
|
|
141
143
|
|
|
142
144
|
it "presents tasks in the default namespace with an empty namespace" do
|
|
143
145
|
ARGV.replace ["list"]
|
|
144
|
-
capture(:stdout) { Thor::Runner.start }.must =~
|
|
146
|
+
capture(:stdout) { Thor::Runner.start }.must =~ /^thor :test\s+# prints 'test'/m
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
it "runs tasks with an empty namespace from the default namespace" do
|
|
148
150
|
ARGV.replace [":test"]
|
|
149
151
|
capture(:stdout) { Thor::Runner.start }.must == "test\n"
|
|
150
152
|
end
|
|
151
|
-
|
|
152
|
-
it "updates the yaml file when invoked" do
|
|
153
|
-
capture(:stdout) { Thor::Runner.start(["list"]) }
|
|
154
|
-
@original_yaml["random"][:namespaces].must == ["amazing"]
|
|
155
|
-
end
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
describe "update" do
|
|
159
|
-
it "updates existing thor files" do
|
|
160
|
-
mock.instance_of(Thor::Runner).install(@original_yaml["random"][:location]) { true }
|
|
161
|
-
stub(File).delete(File.join(Thor::Util.thor_root, @original_yaml["random"][:filename]))
|
|
162
|
-
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
|
163
|
-
end
|
|
164
153
|
end
|
|
165
154
|
|
|
166
155
|
describe "uninstall" do
|
|
167
156
|
before(:each) do
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
stub(@original_yaml).delete(anything)
|
|
157
|
+
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
|
158
|
+
FileUtils.should_receive(:rm_rf).with(path)
|
|
171
159
|
end
|
|
172
160
|
|
|
173
161
|
it "uninstalls existing thor modules" do
|
|
@@ -177,26 +165,34 @@ describe Thor::Runner do
|
|
|
177
165
|
|
|
178
166
|
describe "installed" do
|
|
179
167
|
before(:each) do
|
|
180
|
-
|
|
168
|
+
Dir.should_receive(:[]).and_return([])
|
|
181
169
|
end
|
|
182
170
|
|
|
183
171
|
it "displays the modules installed in a pretty way" do
|
|
184
172
|
stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
|
|
185
173
|
stdout.must =~ /random\s*amazing/
|
|
186
|
-
stdout.must =~ /amazing:describe NAME
|
|
174
|
+
stdout.must =~ /amazing:describe NAME\s+# say that someone is amazing/m
|
|
187
175
|
end
|
|
188
176
|
end
|
|
189
177
|
|
|
190
|
-
describe "install" do
|
|
191
|
-
|
|
192
|
-
|
|
178
|
+
describe "install/update" do
|
|
179
|
+
before(:each) do
|
|
180
|
+
FileUtils.stub!(:mkdir_p)
|
|
181
|
+
FileUtils.stub!(:touch)
|
|
182
|
+
$stdin.stub!(:gets).and_return("Y")
|
|
193
183
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
stub(FileUtils).touch
|
|
184
|
+
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
|
|
185
|
+
File.should_receive(:open).with(path, "w")
|
|
186
|
+
end
|
|
198
187
|
|
|
199
|
-
|
|
188
|
+
it "updates existing thor files" do
|
|
189
|
+
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
|
190
|
+
File.should_receive(:delete).with(path)
|
|
191
|
+
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it "installs thor files" do
|
|
195
|
+
ARGV.replace ["install", @location]
|
|
200
196
|
silence(:stdout) { Thor::Runner.start }
|
|
201
197
|
end
|
|
202
198
|
end
|