detroit 0.1.0

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.
Files changed (51) hide show
  1. data/.ruby +45 -0
  2. data/COPYING.rdoc +19 -0
  3. data/EXAMPLE.md +188 -0
  4. data/GPL3.txt +675 -0
  5. data/HISTORY.rdoc +14 -0
  6. data/README.rdoc +139 -0
  7. data/bin/detroit +9 -0
  8. data/lib/detroit.rb +67 -0
  9. data/lib/detroit.yml +45 -0
  10. data/lib/detroit/application.rb +427 -0
  11. data/lib/detroit/assembly.rb +80 -0
  12. data/lib/detroit/config.rb +197 -0
  13. data/lib/detroit/control.rb +124 -0
  14. data/lib/detroit/core_ext.rb +139 -0
  15. data/lib/detroit/custom.rb +65 -0
  16. data/lib/detroit/dsl.rb +55 -0
  17. data/lib/detroit/schedule.rb +187 -0
  18. data/lib/detroit/service.rb +188 -0
  19. data/lib/detroit/standard_assembly.rb +52 -0
  20. data/lib/detroit/tool.rb +216 -0
  21. data/lib/detroit/tool/core_ext.rb +3 -0
  22. data/lib/detroit/tool/core_ext/facets.rb +11 -0
  23. data/lib/detroit/tool/core_ext/filetest.rb +29 -0
  24. data/lib/detroit/tool/core_ext/shell_extensions.rb +7 -0
  25. data/lib/detroit/tool/core_ext/to_actual_filename.rb +19 -0
  26. data/lib/detroit/tool/core_ext/to_console.rb +97 -0
  27. data/lib/detroit/tool/core_ext/to_list.rb +29 -0
  28. data/lib/detroit/tool/core_ext/to_yamlfrag.rb +9 -0
  29. data/lib/detroit/tool/core_ext/unfold_paragraphs.rb +27 -0
  30. data/lib/detroit/tool/email_utils.rb +288 -0
  31. data/lib/detroit/tool/project_utils.rb +41 -0
  32. data/lib/detroit/tool/shell_utils.rb +235 -0
  33. data/qed/01_schedule/02_initialize.md +57 -0
  34. data/qed/99_plugins/rdoc/rdoc-plugin.rdoc +22 -0
  35. data/qed/99_plugins/rdoc/sample/Syckfile +6 -0
  36. data/qed/99_plugins/rdoc/sample/lib/sandbox/.xxx +1 -0
  37. data/qed/99_plugins/rdoc/sample/lib/sandbox/hello.rb +5 -0
  38. data/qed/99_plugins/rdoc/sample/lib/sandbox/xxx.rb +6 -0
  39. data/qed/99_plugins/rdoc/sample/lib/xxx/bye.rb +4 -0
  40. data/qed/99_plugins/rdoc/sample/meta/name +1 -0
  41. data/qed/99_plugins/rdoc/sample/meta/version +1 -0
  42. data/qed/samples/example_project/.ruby +0 -0
  43. data/qed/samples/example_project/Schedule +9 -0
  44. data/qed/samples/example_project/lib/foo/.xxx +1 -0
  45. data/qed/samples/example_project/lib/foo/hello.rb +7 -0
  46. data/qed/samples/example_project/lib/foo/xxx.rb +6 -0
  47. data/qed/samples/example_project/lib/foo/xxx/bye.rb +4 -0
  48. data/qed/samples/example_project/meta/name +1 -0
  49. data/qed/samples/example_project/meta/version +1 -0
  50. data/qed/samples/example_schedule.rb +57 -0
  51. metadata +139 -0
@@ -0,0 +1,9 @@
1
+ class Object
2
+
3
+ #
4
+ def to_yamlfrag
5
+ to_yaml.sub("---",'').rstrip
6
+ end
7
+
8
+ end
9
+
@@ -0,0 +1,27 @@
1
+ # TODO: Replace with facets/string/unfold
2
+
3
+ class String
4
+
5
+ #
6
+ def unfold_paragraphs
7
+ blank = false
8
+ text = ''
9
+ split(/\n/).each do |line|
10
+ if /\S/ !~ line
11
+ text << "\n\n"
12
+ blank = true
13
+ else
14
+ if /^(\s+|[*])/ =~ line
15
+ text << (line.rstrip + "\n")
16
+ else
17
+ text << (line.rstrip + " ")
18
+ end
19
+ blank = false
20
+ end
21
+ end
22
+ text = text.gsub("\n\n\n","\n\n")
23
+ return text
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,288 @@
1
+ module Detroit
2
+
3
+ # The Mail utility module provides an easy to use +email+ method.
4
+ module EmailUtils
5
+
6
+ # Email function to easily send out an email.
7
+ #
8
+ # Settings:
9
+ #
10
+ # subject Subject of email message.
11
+ # from Message FROM address [email].
12
+ # to Email address to send announcemnt.
13
+ # server Email server to route message.
14
+ # port Email server's port.
15
+ # domain Email server's domain name.
16
+ # account Email account name if needed.
17
+ # password Password for login..
18
+ # login Login type: plain, cram_md5 or login [plain].
19
+ # secure Uses TLS security, true or false? [false]
20
+ # message Mesage to send -or-
21
+ # file File that contains message.
22
+ #
23
+ def email(options)
24
+ #options[:file] = localize(options[:file]) if options[:file]
25
+ emailer = Emailer.new(options.rekey)
26
+ success = emailer.email
27
+ if Exception === success
28
+ puts "Email failed: #{success.message}."
29
+ else
30
+ puts "Email sent successfully to #{success.join(';')}."
31
+ end
32
+ end
33
+
34
+ end
35
+
36
+ # Emailer class makes it easy send out an email.
37
+ #
38
+ # Settings:
39
+ #
40
+ # subject Subject of email message.
41
+ # from Message FROM address [email].
42
+ # to Email address to send announcemnt.
43
+ # server Email server to route message.
44
+ # port Email server's port.
45
+ # port_secure Email server's port.
46
+ # domain Email server's domain name.
47
+ # account Email account name if needed.
48
+ # password Password for login..
49
+ # login Login type: plain, cram_md5 or login [plain].
50
+ # secure Uses TLS security, true or false? [false]
51
+ # message Mesage to send -or-
52
+ # file File that contains message.
53
+ #
54
+ class Emailer
55
+
56
+ class << self
57
+ # Used for caching password between usages.
58
+ attr_accessor :password
59
+
60
+ #
61
+ def environment_options
62
+ options = {}
63
+ options[:server] = ENV['EMAIL_SERVER']
64
+ options[:from] = ENV['EMAIL_FROM']
65
+ options[:account] = ENV['EMAIL_ACCOUNT'] || ENV['EMAIL_FROM']
66
+ options[:password] = ENV['EMAIL_PASSWORD']
67
+ options[:port] = ENV['EMAIL_PORT']
68
+ options[:domain] = ENV['EMAIL_DOMAIN']
69
+ options[:login] = ENV['EMAIL_LOGIN']
70
+ options[:secure] = ENV['EMAIL_SECURE']
71
+ options
72
+ end
73
+
74
+ def new_with_environment(options={})
75
+ environment_options.merge(options.rekey)
76
+ new(options)
77
+ end
78
+ end
79
+
80
+ attr_accessor :server
81
+ attr_accessor :port
82
+ attr_accessor :account
83
+ attr_accessor :passwd
84
+ attr_accessor :login
85
+ attr_accessor :secure
86
+ attr_accessor :domain
87
+ attr_accessor :from
88
+ attr_accessor :mailto
89
+ attr_accessor :subject
90
+ attr_accessor :message
91
+
92
+ #
93
+
94
+ #
95
+ def initialize(options={})
96
+ require_smtp
97
+
98
+ options = options.rekey
99
+
100
+ if not options[:server]
101
+ options = self.class.environment_options.merge(options)
102
+ end
103
+
104
+ @mailto = options[:to] || options[:mailto]
105
+
106
+ @from = options[:from]
107
+ @message = options[:message]
108
+ @subject = options[:subject]
109
+ @server = options[:server]
110
+ @account = options[:account]
111
+ @passwd = options[:password]
112
+ @login = options[:login]
113
+ @secure = options[:secure] #.to_b
114
+ @domain = options[:domain]
115
+ @port = options[:port]
116
+
117
+ @port ||= secure ? 465 : 25
118
+ @port = @port.to_i
119
+
120
+ @account ||= @from
121
+
122
+ @login ||= :plain
123
+ @login = @login.to_sym
124
+
125
+ @passwd ||= self.class.password
126
+
127
+ @domain ||= @server
128
+
129
+ # save the password for later use
130
+ self.class.password = @passwd
131
+ end
132
+
133
+ #
134
+
135
+ def email(options={})
136
+ options.rekey
137
+
138
+ message = options[:message] || self.message
139
+ subject = options[:subject] || self.subject
140
+ from = options[:from] || self.from
141
+ mailto = options[:mailto] || options[:to] || self.mailto
142
+
143
+ raise ArgumentError, "missing email field -- server" unless server
144
+ raise ArgumentError, "missing email field -- account" unless account
145
+
146
+ raise ArgumentError, "missing email field -- from" unless from
147
+ raise ArgumentError, "missing email field -- mailto" unless mailto
148
+ raise ArgumentError, "missing email field -- subject" unless subject
149
+
150
+ passwd ||= password("#{account} password:")
151
+
152
+ mailto = [mailto].flatten.compact
153
+
154
+ msg = ""
155
+ msg << "From: #{from}\n"
156
+ msg << "To: #{mailto.join(';')}\n"
157
+ msg << "Subject: #{subject}\n"
158
+ msg << ""
159
+ msg << message
160
+
161
+ #p server, port, domain, account, passwd, login, secure if verbose?
162
+
163
+ begin
164
+ if Net::SMTP.respond_to?(:enable_tls) && secure
165
+ Net::SMTP.enable_tls
166
+ Net::SMTP.start(server, port, domain, account, passwd, login, secure) do |smtp|
167
+ smtp.send_message(msg, from, mailto)
168
+ end
169
+ else
170
+ Net::SMTP.start(server, port, domain, account, passwd, login) do |smtp|
171
+ smtp.send_message(msg, from, mailto)
172
+ end
173
+ end
174
+ return mailto
175
+ rescue Exception => e
176
+ return e
177
+ end
178
+ end
179
+
180
+ # Ask for a password.
181
+ #
182
+ # FIXME: Does not hide password.
183
+
184
+ def password(msg=nil)
185
+ msg ||= "Enter Password: "
186
+ inp = ''
187
+
188
+ $stdout << msg
189
+
190
+ inp = STDIN.gets.chomp
191
+
192
+ #begin
193
+ # system "stty -echo"
194
+ # inp = gets.chomp
195
+ #ensure
196
+ # system "stty echo"
197
+ #end
198
+
199
+ return inp
200
+ end
201
+
202
+ #
203
+ def require_smtp
204
+ begin
205
+ require 'facets/net/smtp_tls'
206
+ rescue LoadError
207
+ require 'net/smtp'
208
+ end
209
+ end
210
+
211
+ end
212
+
213
+ end
214
+
215
+
216
+
217
+ =begin
218
+ # Email function to easily send out an email.
219
+ #
220
+ # Settings:
221
+ #
222
+ # subject Subject of email message.
223
+ # from Message FROM address [email].
224
+ # to Email address to send announcemnt.
225
+ # server Email server to route message.
226
+ # port Email server's port.
227
+ # domain Email server's domain name.
228
+ # account Email account name if needed.
229
+ # password Password for login..
230
+ # login Login type: plain, cram_md5 or login [plain].
231
+ # secure Uses TLS security, true or false? [false]
232
+ # message Mesage to send -or-
233
+ # file File that contains message.
234
+ #
235
+ def email(message, settings)
236
+ settings ||= {}
237
+ settings.rekey!
238
+
239
+ server = settings[:server]
240
+ account = settings[:account] || ENV['EMAIL_ACCOUNT']
241
+ passwd = settings[:password] || ENV['EMAIL_PASSWORD']
242
+ login = settings[:login].to_sym
243
+ subject = settings[:subject]
244
+ mail_to = settings[:to] || settings[:mail_to]
245
+ mail_from = settings[:from] || settings[:mail_from]
246
+ secure = settings[:secure]
247
+ domain = settings[:domain] || server
248
+
249
+ port ||= (secure ? 465 : 25)
250
+ account ||= mail_from
251
+ login ||= :plain
252
+
253
+ #mail_to = nil if mail_to.empty?
254
+
255
+ raise ArgumentError, "missing email field -- server" unless server
256
+ raise ArgumentError, "missing email field -- account" unless account
257
+ raise ArgumentError, "missing email field -- subject" unless subject
258
+ raise ArgumentError, "missing email field -- to" unless mail_to
259
+ raise ArgumentError, "missing email field -- from" unless mail_from
260
+
261
+ passwd ||= password(account)
262
+
263
+ mail_to = [mail_to].flatten.compact
264
+
265
+ msg = ""
266
+ msg << "From: #{mail_from}\n"
267
+ msg << "To: #{mail_to.join(';')}\n"
268
+ msg << "Subject: #{subject}\n"
269
+ msg << ""
270
+ msg << message
271
+
272
+ begin
273
+ Net::SMTP.enable_tls if Net::SMTP.respond_to?(:enable_tls) and secure
274
+ Net::SMTP.start(server, port, domain, account, passwd, login) do |s|
275
+ s.send_message( msg, mail_from, mail_to )
276
+ end
277
+ puts "Email sent successfully to #{mail_to.join(';')}."
278
+ return true
279
+ rescue => e
280
+ if trace?
281
+ raise e
282
+ else
283
+ abort "Email delivery failed."
284
+ end
285
+ end
286
+ end
287
+ =end
288
+
@@ -0,0 +1,41 @@
1
+ module Detroit
2
+
3
+ #
4
+ require 'pom'
5
+
6
+ #
7
+ module ProjectUtils
8
+
9
+ # Common access to project.
10
+ def self.project(path=Dir.pwd)
11
+ if root = ::POM::Project.root(path)
12
+ @@projects ||= {}
13
+ @@projects[root] ||= ::POM::Project.new(root)
14
+ else
15
+ nil # ?
16
+ end
17
+ end
18
+
19
+ #
20
+ def project(path=Dir.pwd)
21
+ @project ||= ProjectUtils.project(path)
22
+ end
23
+
24
+ # Set project manutally.
25
+ def project=(proj)
26
+ @project = proj
27
+ end
28
+
29
+ #
30
+ def metadata
31
+ project.metadata
32
+ end
33
+
34
+ #
35
+ def root
36
+ project.root
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,235 @@
1
+ require 'detroit/tool/core_ext/shell_extensions'
2
+ require 'rbconfig'
3
+
4
+ module Detroit
5
+
6
+ # ShellUtils provides the whole slew of FileUtils,
7
+ # FileTest and File class methods in a single module
8
+ # and modifies methods according to noop? and verbose?
9
+ # options.
10
+ module ShellUtils
11
+
12
+ #
13
+ def initialize_extension_defaults
14
+ @quiet = false
15
+ @trial = false
16
+ @noop = false
17
+ @force = false
18
+ super() if defined?(super)
19
+ end
20
+
21
+ #
22
+ def initialize_extensions
23
+ extend(fileutils)
24
+ super() if defined?(super)
25
+ end
26
+
27
+ # A path is required for shell methods to operate.
28
+ # If no path is set than the current working path is used.
29
+ def path
30
+ @path ||= Dir.pwd
31
+ end
32
+
33
+ # Set shell path.
34
+ def path=(dir)
35
+ @path = dir
36
+ end
37
+
38
+ attr_writer :stdout
39
+ attr_writer :stdin
40
+ attr_writer :stderr
41
+
42
+ def stdout
43
+ @stdout ||= $stdout
44
+ end
45
+
46
+ def stdin
47
+ @stdin ||= $stdin
48
+ end
49
+
50
+ def stderr
51
+ @stdout ||= $stderr
52
+ end
53
+
54
+ attr_writer :force
55
+ attr_writer :quiet
56
+ attr_writer :trace
57
+ attr_writer :trial
58
+ attr_writer :debug
59
+ attr_writer :verbose
60
+
61
+ def force? ; @force ; end
62
+
63
+ def quiet? ; @quiet ; end
64
+ def trial? ; @trial ; end
65
+
66
+ def trace? ; @trace ; end
67
+ def debug? ; @debug ; end
68
+
69
+ def verbose? ; @verbose ; end
70
+ def noop? ; @trial ; end
71
+ def dryrun? ; verbose? && noop? ; end
72
+
73
+ #
74
+ def print(str=nil)
75
+ stdout.print(str.to_s) unless quiet?
76
+ end
77
+
78
+ #
79
+ def puts(str=nil)
80
+ stdout.puts(str.to_s) unless quiet?
81
+ end
82
+
83
+ # TODO: deprecate in favor of #report ?
84
+ def report(message)
85
+ stderr.puts message unless quiet?
86
+ end
87
+
88
+ alias_method :status, :report
89
+
90
+ # Internal trace report. Only output if in trace mode.
91
+ def trace(message)
92
+ stderr.puts message if trace?
93
+ end
94
+
95
+ # Convenient method to get simple console reply.
96
+ def ask(question)
97
+ stdout.print "#{question} "
98
+ stdout.flush
99
+ input = stdin.gets #until inp = stdin.gets ; sleep 1 ; end
100
+ input.strip
101
+ end
102
+
103
+ # TODO: Until we have better support for getting input across
104
+ # platforms, we are using #ask for passwords too.
105
+ def password(prompt=nil)
106
+ prompt ||= "Enter Password: "
107
+ ask(prompt)
108
+ end
109
+
110
+ # Delegate to Ratch::Shell instance.
111
+ #def shell(path=Dir.pwd)
112
+ # @shell ||= {}
113
+ # @shell[path] ||= (
114
+ # mode = {
115
+ # :noop => trial?,
116
+ # :verbose => trace? || (trial? && !quiet?),
117
+ # :quiet => quiet?
118
+ # }
119
+ # Ratch::Shell.new(path, mode)
120
+ # )
121
+ #end
122
+
123
+ # Shell runner.
124
+ def sh(cmd)
125
+ trace cmd
126
+ return true if noop?
127
+
128
+ if quiet?
129
+ silently{ system(cmd) }
130
+ else
131
+ system(cmd)
132
+ end
133
+ end
134
+
135
+ # Current ruby binary.
136
+ RUBY = File.join(::Config::CONFIG['bindir'], ::Config::CONFIG['ruby_install_name']).sub(/.*\s.*/m, '"\&"')
137
+
138
+ # Shell-out to ruby.
139
+ def ruby(cmd)
140
+ sh RUBY + " " + cmd
141
+ end
142
+
143
+
144
+ # TODO: Ultimately merge #glob and #multiglob.
145
+ def multiglob(*args, &blk)
146
+ Dir.multiglob(*args, &blk)
147
+ end
148
+
149
+ #
150
+ def multiglob_r(*args, &blk)
151
+ Dir.multiglob_r(*args, &blk)
152
+ end
153
+
154
+ # -- File IO Shortcuts ----------------------------------------------------
155
+
156
+ # Read file.
157
+ def read(path)
158
+ File.read(path)
159
+ end
160
+
161
+ # Write file.
162
+ def write(path, text)
163
+ $stderr.puts "write #{path}" if trace?
164
+ File.open(path, 'w'){ |f| f << text } unless noop?
165
+ end
166
+
167
+ # Append to file.
168
+ def append(path, text)
169
+ $stderr.puts "append #{path}" if trace?
170
+ File.open(path, 'a'){ |f| f << text } unless noop?
171
+ end
172
+
173
+ # -- File Testing ---------------------------------------------------------
174
+
175
+ def size(path) ; FileTest.size(path) ; end
176
+ def size?(path) ; FileTest.size?(path) ; end
177
+ def directory?(path) ; FileTest.directory?(path) ; end
178
+ def symlink?(path) ; FileTest.symlink?(path) ; end
179
+ def readable?(path) ; FileTest.readable?(path) ; end
180
+ def chardev?(path) ; FileTest.chardev?(path) ; end
181
+ def exist?(path) ; FileTest.exist?(path) ; end
182
+ def exists?(path) ; FileTest.exists?(path) ; end
183
+ def zero?(path) ; FileTest.zero?(path) ; end
184
+ def pipe?(path) ; FileTest.pipe?(path) ; end
185
+ def file?(path) ; FileTest.file?(path) ; end
186
+ def sticky?(path) ; FileTest.sticky?(path) ; end
187
+ def blockdev?(path) ; FileTest.blockdev?(path) ; end
188
+ def grpowned?(path) ; FileTest.grpowned?(path) ; end
189
+ def setgid?(path) ; FileTest.setgid?(path) ; end
190
+ def setuid?(path) ; FileTest.setuid?(path) ; end
191
+ def socket?(path) ; FileTest.socket?(path) ; end
192
+ def owned?(path) ; FileTest.owned?(path) ; end
193
+ def writable?(path) ; FileTest.writable?(path) ; end
194
+ def executable?(path) ; FileTest.executable?(path) ; end
195
+
196
+ def safe?(path) ; FileTest.safe?(path) ; end
197
+
198
+ def relative?(path) ; FileTest.relative?(path) ; end
199
+ def absolute?(path) ; FileTest.absolute?(path) ; end
200
+
201
+ def writable_real?(path) ; FileTest.writable_real?(path) ; end
202
+ def executable_real?(path) ; FileTest.executable_real?(path) ; end
203
+ def readable_real?(path) ; FileTest.readable_real?(path) ; end
204
+
205
+ def identical?(path, other)
206
+ FileTest.identical?(path, other)
207
+ end
208
+ alias_method :compare_file, :identical?
209
+
210
+ # -- File Methods ---------------------------------------------------------
211
+
212
+ def atime(*args) ; File.ctime(*args) ; end
213
+ def ctime(*args) ; File.ctime(*args) ; end
214
+ def mtime(*args) ; File.mtime(*args) ; end
215
+
216
+ def utime(*args) ; File.utime(*args) unless noop? ; end
217
+
218
+ private # -----------------------------------------------------------------
219
+
220
+ # Returns FileUtils module based on mode.
221
+ def fileutils
222
+ if dryrun?
223
+ ::FileUtils::DryRun
224
+ elsif noop? or trial?
225
+ ::FileUtils::Noop
226
+ elsif trace?
227
+ ::FileUtils::Verbose
228
+ else
229
+ ::FileUtils
230
+ end
231
+ end
232
+
233
+ end
234
+
235
+ end