dev 2.0.268 → 2.0.269
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/dev +1 -1
- data/lib/base/array.rb +34 -4
- data/lib/base/command.rb +101 -12
- data/lib/base/dir.rb +14 -8
- data/lib/base/environment.rb +169 -52
- data/lib/base/gemspec.rb +10 -2
- data/lib/base/history.rb +26 -1
- data/lib/base/project.rb +237 -121
- data/lib/base/projects.rb +130 -66
- data/lib/base/timeout.rb +54 -16
- data/lib/base/version.rb +54 -0
- data/lib/commands.rb +4 -2
- data/lib/dev.rb +50 -44
- data/lib/tasks.rb +20 -12
- data/lib/tasks/add.rb +8 -8
- data/lib/tasks/analyze.rb +1 -1
- data/lib/tasks/build.rb +25 -9
- data/lib/tasks/commit.rb +7 -7
- data/lib/tasks/default.rb +7 -1
- data/lib/tasks/doc.rb +1 -1
- data/lib/tasks/publish.rb +7 -11
- data/lib/tasks/pull.rb +1 -4
- data/lib/tasks/push.rb +2 -2
- data/lib/tasks/setup.rb +36 -15
- data/lib/tasks/test.rb +4 -5
- data/lib/tasks/update.rb +2 -2
- metadata +5 -5
data/lib/base/projects.rb
CHANGED
@@ -8,25 +8,24 @@ require_relative('../apps/git.rb')
|
|
8
8
|
require_relative('../apps/svn.rb')
|
9
9
|
|
10
10
|
class Projects < Hash
|
11
|
-
attr_accessor :
|
11
|
+
attr_accessor :env
|
12
12
|
|
13
|
-
def initialize
|
14
|
-
@
|
15
|
-
@
|
13
|
+
def initialize env=nil
|
14
|
+
@env=env if env.kind_of?(Environment)
|
15
|
+
@env=Environment.new if @env.nil?
|
16
16
|
open
|
17
17
|
end
|
18
18
|
|
19
19
|
def filename
|
20
|
-
"#{@
|
20
|
+
"#{@env.root_dir}/data/Projects.json"
|
21
21
|
end
|
22
22
|
|
23
|
-
def update_state
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
23
|
+
#def update_state
|
24
|
+
# self.each{|k,v|
|
25
|
+
# self[k]=Project.new(v) if(v.is_a?(String))
|
26
|
+
# self[k][:fullname]=k
|
27
|
+
# }
|
28
|
+
#end
|
30
29
|
|
31
30
|
def save
|
32
31
|
Dir.make File.dirname(filename) if !File.exists? File.dirname(filename)
|
@@ -35,49 +34,132 @@ class Projects < Hash
|
|
35
34
|
|
36
35
|
def open
|
37
36
|
if File.exists? filename
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
JSON.parse(IO.read(filename)).each{|k,v|
|
38
|
+
if(v.kind_of?(Project))
|
39
|
+
self[k]=v
|
40
|
+
else
|
41
|
+
self[k]=Project.new(v)
|
42
|
+
end
|
43
|
+
}
|
44
|
+
#update_state
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
def get_projects value=''
|
49
|
+
puts "get_projects #{value.to_s}" if @env.debug?
|
50
|
+
puts "get_project total project count #{self.length}" if @env.debug?
|
51
|
+
projects=Array.new
|
52
|
+
filter=''
|
53
|
+
filter=value.to_s if !value.nil? && value.kind_of?(String)
|
54
|
+
filter=value[0].to_s if !value.nil? && value.kind_of?(Array) && !value[0].to_s.include?('=')
|
55
|
+
|
56
|
+
puts "get_project filter '#{filter}'" if @env.debug?
|
57
|
+
self.each{|k,v|
|
58
|
+
puts " checking project #{k}" if @env.debug?
|
59
|
+
puts " v.class #{v.class}" if @env.debug?
|
60
|
+
if(filter.length==0 || k.include?(filter))
|
61
|
+
if(v.kind_of?(Project))
|
62
|
+
projects << v
|
63
|
+
v.env=@env
|
64
|
+
end
|
65
|
+
end
|
66
|
+
}
|
67
|
+
projects
|
68
|
+
end
|
69
|
+
|
70
|
+
def add args
|
71
|
+
url=args[0]
|
72
|
+
project=Project.new(url)
|
73
|
+
project[:fullname]=args[1] if args.length > 1
|
74
|
+
project.set_timeout args[2] if args.length > 2
|
75
|
+
if(!self.has_key?(project[:fullname]) && project[:fullname].length > 0)
|
76
|
+
@env.out "adding #{project.fullname}\n"
|
77
|
+
self[project.fullname]=project
|
78
|
+
self.save
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def help args
|
83
|
+
end
|
84
|
+
|
85
|
+
def work args
|
86
|
+
projects=get_projects args
|
87
|
+
puts "working #{projects.length} projects..." if @env.debug?
|
88
|
+
exit_code=0
|
89
|
+
projects.each{|project|
|
90
|
+
begin
|
91
|
+
result=project.work
|
92
|
+
exit_code=result.exit_code if(result.exit_code!=0)
|
93
|
+
rescue => error
|
94
|
+
puts "error raised during work #{project.fullname}"
|
95
|
+
puts "--------------------------------------------"
|
96
|
+
puts error
|
97
|
+
puts "--------------------------------------------"
|
98
|
+
end
|
99
|
+
}
|
100
|
+
exit_code
|
101
|
+
end
|
102
|
+
|
103
|
+
def info args
|
104
|
+
projects=get_projects args
|
105
|
+
puts "collecting info for #{projects.length} projects..." if @env.debug?
|
106
|
+
exit_code=0
|
107
|
+
projects.each{|project|
|
108
|
+
begin
|
109
|
+
result=project.info
|
110
|
+
exit_code=result.exit_code if(result.exit_code!=0)
|
111
|
+
rescue => error
|
112
|
+
puts "error raised during work #{project.fullname}"
|
113
|
+
puts "--------------------------------------------"
|
114
|
+
puts error
|
115
|
+
puts "--------------------------------------------"
|
116
|
+
end
|
117
|
+
}
|
118
|
+
exit_code
|
119
|
+
end
|
120
|
+
|
121
|
+
def list args
|
122
|
+
projects=get_projects args
|
123
|
+
puts "listing #{projects.length} projects..." if @env.debug?
|
124
|
+
projects.each{|project|
|
125
|
+
project.list
|
126
|
+
|
127
|
+
}
|
48
128
|
end
|
49
129
|
|
50
130
|
def make args
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
rake_default=v.make tag
|
64
|
-
puts rake_default.summary if !rake_default.nil? && rake_default[:exit_code] != 0
|
65
|
-
end
|
66
|
-
end
|
131
|
+
projects=get_projects args
|
132
|
+
puts "making #{projects.length} projects..." if @env.debug?
|
133
|
+
exit_code=0
|
134
|
+
projects.each{|project|
|
135
|
+
begin
|
136
|
+
result=project.make
|
137
|
+
exit_code=result.exit_code if(result.exit_code!=0)
|
138
|
+
rescue => error
|
139
|
+
puts "error raised during make #{project.fullname}"
|
140
|
+
puts "--------------------------------------------"
|
141
|
+
puts error
|
142
|
+
puts "--------------------------------------------"
|
67
143
|
end
|
68
144
|
}
|
145
|
+
exit_code
|
69
146
|
end
|
70
147
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
148
|
+
def clobber args
|
149
|
+
projects=get_projects args
|
150
|
+
puts "clobbering #{projects.length} projects..." if @env.debug?
|
151
|
+
projects.each{|project|
|
152
|
+
begin
|
153
|
+
project.clobber
|
154
|
+
#Dir.remove_empty @env.wrk_dir
|
155
|
+
rescue => error
|
156
|
+
puts "error raised during clobber #{project.fullname}"
|
157
|
+
puts "--------------------------------------------"
|
158
|
+
puts error
|
159
|
+
puts "--------------------------------------------"
|
78
160
|
end
|
79
161
|
}
|
80
|
-
|
162
|
+
end
|
81
163
|
|
82
164
|
def update args
|
83
165
|
filter=''
|
@@ -122,28 +204,16 @@ class Projects < Hash
|
|
122
204
|
self.each{|k,v| v.rake if v.respond_to?("rake".to_sym)}
|
123
205
|
end
|
124
206
|
|
125
|
-
def add args
|
126
|
-
if(args.length > 1)
|
127
|
-
project=Project.new(args[1])
|
128
|
-
project[:fullname] = args[2] if args.length > 2
|
129
|
-
if(project.fullname.length > 0 && !self.has_key?(project.fullname))
|
130
|
-
puts "adding #{project.fullname}"
|
131
|
-
self[project.fullname]=project
|
132
|
-
self.save #Projects.user_projects_filename
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
207
|
def import pattern=''
|
138
|
-
wrk
|
208
|
+
wrk=@env.wrk_dir
|
139
209
|
if File.exists?(wrk)
|
140
210
|
Dir.chdir(wrk) do
|
211
|
+
puts "scanning #{wrk} for imports..."
|
141
212
|
Dir.glob('**/rakefile.rb').each{|rakefile|
|
142
213
|
rakedir=File.dirname(rakefile)
|
143
214
|
url = Project.get_url rakedir
|
144
|
-
#puts "checking #{url}"
|
145
215
|
project = Project.new(Project.get_url(rakedir))
|
146
|
-
project[:fullname]=
|
216
|
+
project[:fullname]=rakedir.gsub(@env.wrk_dir,'') if(project.fullname.include?(':'))
|
147
217
|
if(pattern.length==0 || project.fullname.include?(pattern))
|
148
218
|
if(project.fullname.length > 0 && !self.has_key?(project.fullname))
|
149
219
|
puts "importing #{project.fullname}"
|
@@ -152,13 +222,7 @@ class Projects < Hash
|
|
152
222
|
end
|
153
223
|
}
|
154
224
|
end
|
155
|
-
self.save
|
225
|
+
self.save
|
156
226
|
end
|
157
227
|
end
|
158
|
-
end
|
159
|
-
|
160
|
-
#PROJECTS=Projects.new
|
161
|
-
#PROJECTS.open Projects.user_projects_filename if File.exists? Projects.user_projects_filename
|
162
|
-
#current=Projects.current # this makes sure the current project is added to PROJECTS
|
163
|
-
#PROJECTS[current.fullname]=current if(!current.nil? && !PROJECTS.has_key?(current.fullname) && current.wrk_dir == Rake.application.original_dir)
|
164
|
-
#PROJECTS.save Projects.user_projects_filename if !File.exists? Projects.user_projects_filename
|
228
|
+
end
|
data/lib/base/timeout.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
puts __FILE__ if defined?(DEBUG)
|
2
|
-
|
3
1
|
############################################################################
|
4
2
|
# The following code is based on code originally copied from
|
5
3
|
# https://gist.github.com/lpar/1032297
|
@@ -16,13 +14,11 @@ puts __FILE__ if defined?(DEBUG)
|
|
16
14
|
def run_with_timeout(directory,command, timeout, tick)
|
17
15
|
output = ''
|
18
16
|
exit_code=1
|
19
|
-
begin
|
20
|
-
# Start task in another thread, which spawns a process
|
21
|
-
stdin, stderrout, thread = Open3.popen2e(command, :chdir=>directory)
|
22
|
-
# Get the pid of the spawned process
|
23
|
-
pid = thread[:pid]
|
24
|
-
start = Time.now
|
25
17
|
|
18
|
+
Open3.popen2e(command, :chdir=>directory) { |stdin,stderrout,thread|
|
19
|
+
pid = thread.pid
|
20
|
+
|
21
|
+
start = Time.now
|
26
22
|
while (Time.now - start) < timeout and thread.alive?
|
27
23
|
# Wait up to `tick` seconds for output/error data
|
28
24
|
Kernel.select([stderrout], nil, nil, tick)
|
@@ -33,10 +29,15 @@ def run_with_timeout(directory,command, timeout, tick)
|
|
33
29
|
# A read would block, so loop around for another select
|
34
30
|
rescue EOFError
|
35
31
|
# Command has completed, not really an error...
|
32
|
+
exit_code=wait_thread.value
|
36
33
|
break
|
37
34
|
end
|
35
|
+
|
36
|
+
sleep(0.5)
|
38
37
|
end
|
39
38
|
|
39
|
+
exit_code=wait_thread.value
|
40
|
+
|
40
41
|
# Give Ruby time to clean up the other thread
|
41
42
|
sleep 1
|
42
43
|
|
@@ -44,17 +45,54 @@ def run_with_timeout(directory,command, timeout, tick)
|
|
44
45
|
# We need to kill the process, because killing the thread leaves
|
45
46
|
# the process alive but detached, annoyingly enough.
|
46
47
|
Process.kill("TERM", pid)
|
47
|
-
|
48
|
-
exit_code=thread.value
|
49
|
-
sleep 1
|
48
|
+
exit_code=5
|
50
49
|
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
51
|
+
|
52
|
+
}
|
53
|
+
|
56
54
|
return [output,exit_code]
|
57
|
-
end
|
55
|
+
end
|
56
|
+
# begin
|
57
|
+
# # Start task in another thread, which spawns a process
|
58
|
+
# stdin, stderrout, thread = Open3.popen2e(command, :chdir=>directory)
|
59
|
+
# # Get the pid of the spawned process
|
60
|
+
# pid = thread[:pid]
|
61
|
+
# start = Time.now
|
62
|
+
#
|
63
|
+
# while (Time.now - start) < timeout and thread.alive?
|
64
|
+
# # Wait up to `tick` seconds for output/error data
|
65
|
+
# Kernel.select([stderrout], nil, nil, tick)
|
66
|
+
# # Try to read the data
|
67
|
+
# begin
|
68
|
+
# output << stderrout.read_nonblock(BUFFER_SIZE)
|
69
|
+
# rescue IO::WaitReadable
|
70
|
+
# # A read would block, so loop around for another select
|
71
|
+
# rescue EOFError
|
72
|
+
# # Command has completed, not really an error...
|
73
|
+
# exit_code=$?.exitstatus
|
74
|
+
# break
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# # Give Ruby time to clean up the other thread
|
79
|
+
# sleep 1
|
80
|
+
|
81
|
+
# if thread.alive?
|
82
|
+
# We need to kill the process, because killing the thread leaves
|
83
|
+
# the process alive but detached, annoyingly enough.
|
84
|
+
# Process.kill("TERM", pid)
|
85
|
+
# exit_code=5
|
86
|
+
# else
|
87
|
+
# sleep 1
|
88
|
+
# end
|
89
|
+
|
90
|
+
# ensure
|
91
|
+
# stdin.close if stdin
|
92
|
+
# stderrout.close if stderrout
|
93
|
+
# end
|
94
|
+
# return [output,exit_code]
|
95
|
+
#end
|
58
96
|
|
59
97
|
require 'timeout'
|
60
98
|
def run_with_timeout2(directory,command,timeout)
|
data/lib/base/version.rb
CHANGED
@@ -1,4 +1,51 @@
|
|
1
1
|
class Version
|
2
|
+
def self.extract text
|
3
|
+
[/[Vv]ersion\s*=\s*['"]([\d.]+)['"]/,
|
4
|
+
/Version\(\s*"([\d.]+)"\s*\)/].each{|regex|
|
5
|
+
scan=text.scan(regex)
|
6
|
+
if(!scan.nil?)
|
7
|
+
return scan[0][0] if(scan.length > 0 && !scan[0].nil? && scan[0].length > 0)
|
8
|
+
end
|
9
|
+
}
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.extract_from_file filename
|
14
|
+
Version.extract IO.read(filename)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.extract_from_filelist filelist
|
18
|
+
version=nil
|
19
|
+
filelist.each{|f|
|
20
|
+
version=extract_from_file f
|
21
|
+
return version if !version.nil?
|
22
|
+
}
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.update_text text, version
|
27
|
+
text=text.gsub(/version\s*=\s*'[\d.]+'/,"version='#{version}'")
|
28
|
+
text=text.gsub(/version\s*=\s*"[\d.]+"/,"version=\"#{version}\"")
|
29
|
+
text=text.gsub(/Version\s*=\s*'[\d.]+'/,"Version='#{version}'")
|
30
|
+
text=text.gsub(/Version\s*=\s*"[\d.]+"/,"Version=\"#{version}\"")
|
31
|
+
text=text.gsub(/Version\(\s*"[\d.]+"\s*\)/,"Version(\"#{version}\")")
|
32
|
+
text=text.gsub(/Name\s*=\s*"Version"\s*Value\s*=\s*"[\d.]+"/,"Name=\"Version\" Value=\"#{version}\"")
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.update_file filename, version
|
36
|
+
if(File.exists?(filename))
|
37
|
+
orig=IO.read(filename)
|
38
|
+
text=Version.update_text orig,version
|
39
|
+
File.open(filename,'w'){|f|f.write(text)} if(orig!=text)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.update_filelist filelist,version
|
44
|
+
filelist.each{|f|
|
45
|
+
Version.update_file f,version
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
2
49
|
def self.read filename
|
3
50
|
return "#{Gem::Specification.load(filename).version.to_s}" if filename.include?('.gemspec')
|
4
51
|
if filename.include?('AssemblyInfo.cs')
|
@@ -7,6 +54,10 @@ class Version
|
|
7
54
|
return scan[0][0] if(scan.length > 0 && !scan[0].nil? && scan[0].length > 0)
|
8
55
|
end
|
9
56
|
#return IO.read(filename).scan(/Version\(\"([\d.]+)\"\)/)[0][0]
|
57
|
+
scan=IO.read(wxs).scan(/Version=\"([\d.]+)\"/)
|
58
|
+
if(!scan.nil?)
|
59
|
+
return scan[0][0] if(scan.length > 0 && !scan[0].nil? && scan[0].length > 0)
|
60
|
+
end
|
10
61
|
end
|
11
62
|
'0.0.0'
|
12
63
|
end
|
@@ -18,6 +69,9 @@ class Version
|
|
18
69
|
Dir.glob('**/AssemblyInfo.cs').each{|assemblyInfo|
|
19
70
|
return Version.read assemblyInfo
|
20
71
|
}
|
72
|
+
Dir.glob('**/*.wxs').each{|wxs|
|
73
|
+
return Version.read wxs
|
74
|
+
}
|
21
75
|
'0.0.0'
|
22
76
|
end
|
23
77
|
end
|
data/lib/commands.rb
CHANGED
@@ -7,8 +7,10 @@ Dir.glob("#{File.dirname(__FILE__)}/tasks/*.rb").each{|rb|
|
|
7
7
|
require(rb)
|
8
8
|
}
|
9
9
|
class Commands < Hash
|
10
|
-
|
11
|
-
def initialize directory=
|
10
|
+
attr_accessor :env
|
11
|
+
def initialize env=nil,directory=Rake.application.original_dir
|
12
|
+
@env=env
|
13
|
+
@env=Environment.new() if @env.nil?
|
12
14
|
Dir.chdir(directory) do
|
13
15
|
self[:pull]=Pull.new
|
14
16
|
self[:update]=Update.new
|
data/lib/dev.rb
CHANGED
@@ -5,62 +5,68 @@ require_relative('apps.rb')
|
|
5
5
|
require_relative('tasks.rb')
|
6
6
|
require_relative('commands.rb')
|
7
7
|
|
8
|
-
|
9
|
-
require Environment.configuration
|
10
|
-
end
|
11
|
-
|
12
|
-
PROJECT=Project.new()
|
8
|
+
#PROJECT=Project.new()
|
13
9
|
|
14
10
|
class Dev
|
15
|
-
attr_accessor :projects,:
|
11
|
+
attr_accessor :env,:projects,:commands
|
16
12
|
|
17
13
|
def initialize env=nil
|
18
|
-
@env=
|
19
|
-
@
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
@projects=Projects.new(self)
|
24
|
-
@history=History.new(self)
|
14
|
+
@env=Environment.new(env) if !env.nil? && env.kind_of?(Hash)
|
15
|
+
@env=Environment.new() if @env.nil?
|
16
|
+
@projects=Projects.new(@env)
|
17
|
+
@commands=Commands.new(@env)
|
18
|
+
@output=''
|
25
19
|
end
|
20
|
+
|
21
|
+
def execute args
|
22
|
+
args=args.split(' ') if(args.kind_of?(String))
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
|
24
|
+
# parse arguments that are of the form KEY=VALUE
|
25
|
+
args.each{|arg|
|
26
|
+
if(arg.include?('='))
|
27
|
+
words=arg.split('=')
|
28
|
+
if(words.length==2)
|
29
|
+
ENV[words[0]]=words[1]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
}
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
if args.length == 0
|
35
|
+
return usage
|
36
|
+
else
|
37
|
+
subcommand=args[0] if args.length > 0
|
38
|
+
subargs=Array.new
|
39
|
+
subargs=args[1,args.length-1] if args.length > 1
|
40
|
+
|
41
|
+
return projects.add(subargs) if subcommand=='add'
|
42
|
+
return projects.clobber(subargs) if subcommand=='clobber'
|
43
|
+
return projects.import(subargs) if subcommand=='import'
|
44
|
+
return projects.list(subargs) if subcommand=='list'
|
45
|
+
return projects.make(subargs) if subcommand=='make'
|
46
|
+
return projects.info(subargs) if subcommand=='info'
|
47
|
+
return projects.work(subargs) if subcommand=='work'
|
48
|
+
return projects.update(subargs) if subcommand=='update'
|
49
|
+
|
50
|
+
@env.out "unknown command: '#{subcommand}'"
|
51
|
+
1
|
42
52
|
end
|
43
|
-
value
|
44
53
|
end
|
54
|
+
|
45
55
|
|
46
|
-
def execute args
|
47
|
-
if(args.kind_of?(String))
|
48
|
-
args=args.split(' ')
|
49
|
-
end
|
50
|
-
#projects=Projects.new
|
51
|
-
#projects.open Projects.user_projects_filename if File.exists? Projects.user_projects_filename
|
52
|
-
projects.add(args) if args.length > 0 && args[0] == 'add'
|
53
|
-
projects.import(args.length>1 ? args[1]:'') if args.length > 0 && args[0] == 'import'
|
54
|
-
projects.list(args.length>1 ? args[1]:'') if args.length > 0 && args[0] == 'list'
|
55
|
-
projects.make(args) if args.length > 0 && args[0] == 'make'
|
56
|
-
projects.work(args) if args.length > 0 && args[0] == 'work'
|
57
|
-
projects.update(args) if args.length > 0 && args[0] == 'update'
|
58
|
-
usage if args.length == 0
|
59
|
-
end
|
60
56
|
|
61
57
|
def usage
|
62
|
-
|
63
|
-
|
58
|
+
return 0
|
59
|
+
@env.out 'usage: dev <subcommand> [options]'
|
60
|
+
@env.out ''
|
61
|
+
@env.out 'available subcommands'
|
62
|
+
@env.out ' help'
|
63
|
+
@env.out ' list'
|
64
|
+
@env.out ' make'
|
65
|
+
@env.out ' info'
|
66
|
+
@env.out ' work'
|
67
|
+
@env.out ''
|
68
|
+
@env.out "Type 'dev help <subcommand>' for help on a specific subcommand.'"
|
69
|
+
0
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|