reap 4.5.2 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,124 @@
1
+
2
+
3
+ module Reap
4
+
5
+ class Application
6
+
7
+ def initialize
8
+ @tasks = {}
9
+ end
10
+
11
+ attr :tasks
12
+ attr_accessor :last_desc
13
+
14
+ def define_task( args, &block )
15
+ raise ArgumentError, "#{args.size} for 1" if Hash===args and args.size != 1
16
+ name, deps = parse_args( args )
17
+ new_task = Task.new( last_desc, deps, &block )
18
+ new_task.application = self
19
+ last_desc = nil
20
+ @tasks[name] = new_task
21
+ end
22
+
23
+ def attach_help( task, doc )
24
+ raise unless @tasks.has_key?(task.to_sym)
25
+ @tasks[task].help = doc
26
+ end
27
+
28
+ def run( task )
29
+ @tasks[task.to_sym].call
30
+ end
31
+
32
+ private
33
+
34
+ def parse_args( args )
35
+ if Hash === args
36
+ raise ArgumentError, "#{args.size} for 1" if args.size != 1
37
+ name, deps = *(args.to_a.flatten)
38
+ name = name.to_sym
39
+ deps = [deps].compact.collect{ |e| e.to_sym }
40
+ else
41
+ name, deps = args.to_sym, []
42
+ end
43
+ return name, deps
44
+ end
45
+
46
+ end
47
+
48
+
49
+ class Task
50
+
51
+ def initialize( name, deps, &action )
52
+ @name = name
53
+ @dependencies = deps
54
+ @action = action
55
+ @complete = false
56
+ end
57
+
58
+ attr :dependencies
59
+ attr_accessor :help, :application
60
+
61
+ def complete?
62
+ @complete
63
+ end
64
+
65
+ def call
66
+ @dependencies.each{ |d|
67
+ application.tasks[d].call unless application.tasks[d].complete?
68
+ }
69
+ @action.call
70
+ @complete = true
71
+ end
72
+
73
+ def to_proc
74
+ @action
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+
81
+
82
+
83
+ module Reap
84
+
85
+ def application
86
+ @application ||= Reap::Application.new
87
+ end
88
+
89
+ def desc( line )
90
+ application.last_desc = line.gsub("\n",'')
91
+ end
92
+
93
+ def task( args, &block )
94
+ application.define_task( args, &block )
95
+ end
96
+
97
+ # Define help documentation for a task.
98
+ def help( task_name, doc )
99
+ application.attach_help( task_name, doc )
100
+ end
101
+
102
+ end
103
+
104
+
105
+ include Reap
106
+
107
+
108
+
109
+
110
+ desc "Milk the cow!"
111
+ task :milk do
112
+ puts "milk"
113
+ end
114
+
115
+ desc "Jump over the moon!"
116
+ task :jump => [ :milk, :milk ] do
117
+ #milk; milk
118
+ puts "jump"
119
+ end
120
+
121
+ task :package, Package
122
+
123
+ application.run( :jump )
124
+
@@ -0,0 +1,42 @@
1
+
2
+ An Introduction to Reap
3
+ A Ruby Package Assitant
4
+
5
+
6
+
7
+ task :name do
8
+
9
+ when { projectfile? }
10
+
11
+ help <<-end
12
+ Help information.
13
+ end
14
+
15
+ run do |x|
16
+ # do the task
17
+ end
18
+
19
+ end
20
+
21
+
22
+
23
+
24
+ desc "This is a description"
25
+
26
+ task :name do |x|
27
+ # do the task
28
+ end
29
+
30
+ cont do
31
+
32
+ help <<-end
33
+ This is help text.
34
+ end
35
+
36
+ when do
37
+ projectfile?
38
+ end
39
+
40
+ end
41
+
42
+
File without changes
@@ -0,0 +1,74 @@
1
+
2
+ module Reap
3
+
4
+ def self.application
5
+ Application.instance
6
+ end
7
+
8
+ class Application
9
+
10
+ def self.instance
11
+ @application ||= self.new
12
+ end
13
+
14
+ attr :tasks, :projectfile
15
+
16
+ def initialize
17
+ @tasks = {}
18
+ @projectfile = ProjectInfo.find
19
+ if @projectfile
20
+ @projectdir = File.dirname( @projectfile )
21
+ Dir.chdir( @projectdir )
22
+ end
23
+ require_custom_tasks
24
+ if @projectfile
25
+ require_custom_project_tasks
26
+ @projectinfo = ProjectInfo.load( @projectfile )
27
+ end
28
+ initialize_tasks
29
+ initialize_special_tasks
30
+ end
31
+
32
+ def projectfile?() @projectfile end
33
+
34
+ def add_task( task )
35
+ @tasks[task.task_name] = task
36
+ end
37
+
38
+ # Load custom tasks.
39
+ def require_custom_tasks
40
+ # Universal custom tasks for all projects.
41
+ dir = File.join( Config::CONFIG['datadir'], 'reap/task' )
42
+ require_all( File.join(dir, '*') ) if File.directory?(dir)
43
+ # Personal tasks for all projects.
44
+ dir = File.expand_path( '~/.share/reap/task' )
45
+ require_all( File.join(dir, '*') ) if File.directory?(dir)
46
+ end
47
+
48
+ # Project specific tasks.
49
+ def require_custom_project_tasks
50
+ require_all('task/*') if File.directory?('task')
51
+ end
52
+
53
+ def initialize_tasks
54
+ return unless @projectinfo
55
+ @projectinfo.each { |key, value|
56
+ add_task( value ) if Reap::Task === value
57
+ }
58
+ end
59
+
60
+ # Load special tasks. There are tasks that don't require
61
+ # a ProjectInfo section or other special requirements.
62
+ def initialize_special_tasks
63
+ Reap.registry.each { |taskclass|
64
+ if taskclass.available?( self )
65
+ task = taskclass.new({})
66
+ task.task_name = taskclass.task_class
67
+ tasks[task.task_name] = task
68
+ end
69
+ }
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -6,11 +6,8 @@ require 'facets'
6
6
  require 'consoleapp'
7
7
  #require 'console/command'
8
8
 
9
-
10
-
11
9
  require 'reap/reap'
12
10
 
13
-
14
11
  class ReapCommand < Console::Command
15
12
 
16
13
  # to do first for every task
@@ -57,8 +54,6 @@ class ReapCommand < Console::Command
57
54
  #def _f( pif ) ; $PROJECT_FILE = pif ; end
58
55
  #alias_method :_f, :__file
59
56
 
60
- # Commands
61
-
62
57
  # default action
63
58
 
64
59
  def default
@@ -68,15 +63,19 @@ class ReapCommand < Console::Command
68
63
  # display version
69
64
 
70
65
  def version
71
- puts "Reap v#{Reap::Version}"
66
+ puts "Reap v#{Reap::Version}"
72
67
  exit 0
73
68
  end
74
69
 
75
70
  # display help
76
71
 
77
- def help(*args)
78
- unless args.empty?
79
- t = Reap.tasks[args[0]]
72
+ def help(tsk=nil)
73
+ if tsk
74
+ t = Reap.application.tasks[tsk]
75
+ unless t
76
+ puts "Unknown task '#{tsk}'."
77
+ exit 0
78
+ end
80
79
  s = "\n"
81
80
  s << "#{args[0]}: "
82
81
  s << t.task_desc.sub(/^\n+/, '').rstrip
@@ -95,93 +94,58 @@ class ReapCommand < Console::Command
95
94
  # list available tasks
96
95
 
97
96
  def tasks
98
- #if Reap.projectfile?
99
- tasklist = []
100
- taskhash = {}
101
- Reap.tasks.each { |key,taskclass|
102
- taskhash[key] = taskclass #if taskclass.available?
103
- }
104
- if taskhash.empty?
105
- puts "No tasks available."
106
- else
107
- sorted = taskhash.keys.sort
108
- margin = sorted.collect{ |n| n.size }.max + 6
109
- sorted.each do |name|
110
- taskclass = taskhash[name]
111
- tasklist << " #{name}".ljust(margin) + "#{taskclass.task_desc}"
112
- end
113
- puts
114
- puts tasklist.join("\n")
115
- puts
97
+ app = Reap.application
98
+ tasklist = []
99
+ if app.tasks.empty?
100
+ puts "No tasks available."
101
+ else
102
+ sorted = app.tasks.keys.sort
103
+ margin = sorted.collect{ |t| t.size }.max + 6
104
+ sorted.each do |name|
105
+ tasklist << " #{name}".ljust(margin) + "#{app.tasks[name].task_desc}"
116
106
  end
117
- #else
118
- # puts "No project information file found."
119
- #end
120
- #exit 0
107
+ puts "(#{Dir.pwd})"
108
+ puts
109
+ puts tasklist.join("\n")
110
+ puts
111
+ end
121
112
  end
122
- alias_method :ls, :tasks
113
+ #alias_method :ls, :tasks
123
114
 
124
115
  # Add all the reap tasks.
125
116
 
126
- Reap.register
127
-
128
- Reap.tasks.each { |sym,taskclass|
129
- #if taskclass.available? #taskclass.section_required? or (taskclass.section_required? and pi)
130
- define_method(sym) { |*args|
131
- taskclass.new(*args).execute
132
- }
133
- #end
134
- }
117
+ app = Reap.application
118
+ app.tasks.each do |name, task|
119
+ define_method(name) { |*args|
120
+ #puts "(#{Dir.pwd})"
121
+ task.execute( *args )
122
+ }
123
+ end
135
124
 
136
125
  end
137
126
 
138
127
 
139
128
  HELP = <<-HERE
140
129
 
141
- reap v#{::Reap::Version}
142
-
143
- USAGE: reap [options...] <command> [arguments...]
130
+ reap [options...] <command> [arguments...]
144
131
 
145
132
  COMMANDS:
146
133
 
147
134
  tasks
148
135
  List all the current tasks with descriptions.
149
- This is the default action if no command
150
- is given. (Also aliased as 'ls'.)
136
+ (This is the default if no command is given.)
151
137
 
152
138
  help [task]
153
- Displays this help information. If a task name
154
- is given, it will provide help information
155
- specific to that task.
156
-
157
- template
158
- Copies a ProjectInfo template into the current
159
- directory (if it does not already exist).
160
-
161
- scaffold [type]
162
- Builds a starter project in the current directory.
163
- There are two types: 'standard' and 'subversion'.
164
- These can be abbreviated 'std' and 'svn', repectively.
165
- If no type is given then standard is used.
139
+ Displays this help information. If a task name is given,
140
+ it will provide help information specific to that task.
166
141
 
167
142
  OPTIONS:
168
143
 
169
- -v --version
170
- Display the current version.
171
-
172
- -V --verbose
173
- Provides extra verbose processing information.
174
-
175
- -f --force
176
- Forces certain operations to be performed.
177
-
178
- -D --debug
179
- Provides extra verbose processing information.
180
-
181
- -f --file
182
- Specify alternate project file.
183
-
184
- -h --help
185
- Display this help information.
144
+ -h --help Display this help information.
145
+ -v --version Display the current version.
146
+ -V --verbose Provides extra verbose processing information.
147
+ -f --force Forces certain operations to be performed.
148
+ -D --debug Provides extra verbose processing information.
149
+ -f --file Specify alternate project file.
186
150
 
187
151
  HERE
@@ -9,21 +9,6 @@ require 'facet/kernel/require_all'
9
9
  require 'facet/basicobject'
10
10
 
11
11
 
12
- module Reap
13
-
14
- def self.register #( alternative_project_file=nil )
15
- pi = ProjectInfo.load( nil, true )
16
- pi.require_custom_tasks if pi
17
- pi
18
- end
19
-
20
- def self.projectfile?
21
- ProjectInfo.instance.info_file
22
- end
23
-
24
- end
25
-
26
-
27
12
  # Project information, generally read from a file.
28
13
  # Simply by calling 'ProjectInfo.load'.
29
14
  #
@@ -49,20 +34,6 @@ class ProjectInfo
49
34
  @instance ||= new( *args, &block )
50
35
  end
51
36
 
52
- # Load the project information from a file. Generally
53
- # no file needs to be specified; the file will be found
54
- # by ascending up the current path until a default
55
- # file name is found (eg. ProjectInfo or Reapfile).
56
-
57
- def load( fpath=nil, report=false )
58
- if fpath
59
- new.read( fpath, report )
60
- else
61
- fpath = find
62
- instance.read( fpath, report )
63
- end
64
- end
65
-
66
37
  # Find project information file.
67
38
 
68
39
  def find
@@ -75,9 +46,14 @@ class ProjectInfo
75
46
  return File.join( info_dir, info_file )
76
47
  end
77
48
 
78
- #def add_file( f )
79
- # INFO_FILES.unshift( f )
80
- #end
49
+ # Load the project information from a file. Generally
50
+ # no file needs to be specified; the file will be found
51
+ # by ascending up the current path until a default
52
+ # file name is found (eg. ProjectInfo or Reapfile).
53
+
54
+ def load( fpath=nil )
55
+ instance.read( fpath )
56
+ end
81
57
 
82
58
  end
83
59
 
@@ -111,7 +87,7 @@ class ProjectInfo
111
87
 
112
88
  # Load project information from YAML file.
113
89
 
114
- def read( fpath, report=true )
90
+ def read( fpath )
115
91
  return unless fpath
116
92
 
117
93
  @info_dir = File.dirname( fpath )
@@ -119,14 +95,15 @@ class ProjectInfo
119
95
  @info_stream = File.read( fpath ).strip
120
96
  @info = YAML::load( info_stream ).traverse{ |k,v| [k.to_s.downcase, v] }
121
97
 
122
- Dir.chdir(@info_dir)
123
- if report
124
- puts "(in #{Dir.pwd})" #unless dir == Dir.pwd
125
- end
126
-
127
98
  #validate
128
99
  defaults
129
100
 
101
+ @info.each do |key, value|
102
+ case value when Reap::Task
103
+ value.task_name = key
104
+ end
105
+ end
106
+
130
107
  self
131
108
  end
132
109
 
@@ -177,19 +154,6 @@ class ProjectInfo
177
154
  self['homepage'] ||= self['rubyforge'] ? self['rubyforge']['homepage'] : nil
178
155
  end
179
156
 
180
- # Load custom tasks.
181
-
182
- def require_custom_tasks
183
- # Universal custom tasks for all projects.
184
- dir = File.join( Config::CONFIG['datadir'], 'reap/task' )
185
- require_all( File.join(dir, '*') ) if File.directory?(dir)
186
- # Personal tasks for all projects.
187
- dir = File.expand_path( '~/.share/reap/task' )
188
- require_all( File.join(dir, '*') ) if File.directory?(dir)
189
- # Project specific tasks.
190
- require_all('task/*') if File.directory?('task')
191
- end
192
-
193
157
  # Convert to a CascadinOpenObject.
194
158
 
195
159
  def to_cascading_open_object
@@ -208,10 +172,14 @@ class ProjectInfo
208
172
  info[name] = x
209
173
  end
210
174
 
175
+ def each( &block )
176
+ @info.each( &block )
177
+ end
178
+
211
179
  # Information to hash.
212
180
 
213
181
  def to_h
214
- @info
182
+ @info.dup
215
183
  end
216
184
 
217
185
  end