ratch 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby +99 -0
- data/COPYING +203 -21
- data/History.rdoc +35 -0
- data/License.txt +204 -0
- data/README.rdoc +113 -0
- data/Version +1 -0
- data/bin/ludo +16 -0
- data/bin/ratch +1 -8
- data/lib/ratch.rb +28 -0
- data/lib/ratch.yml +99 -0
- data/lib/ratch/batch.rb +500 -0
- data/lib/ratch/console.rb +199 -0
- data/lib/ratch/core_ext.rb +1 -4
- data/lib/ratch/core_ext/facets.rb +15 -1
- data/lib/ratch/core_ext/filetest.rb +29 -0
- data/lib/ratch/core_ext/{string.rb → to_actual_filename.rb} +0 -23
- data/lib/ratch/core_ext/to_console.rb +30 -12
- data/lib/ratch/core_ext/{object.rb → to_yamlfrag.rb} +1 -0
- data/lib/ratch/core_ext/unfold_paragraphs.rb +27 -0
- data/lib/ratch/file_list.rb +411 -0
- data/lib/ratch/script.rb +99 -5
- data/lib/ratch/script/help.rb +84 -0
- data/lib/ratch/shell.rb +783 -0
- data/lib/ratch/system.rb +15 -0
- data/lib/ratch/utils/cli.rb +49 -0
- data/lib/ratch/utils/config.rb +52 -0
- data/lib/ratch/{emailer.rb → utils/email.rb} +43 -6
- data/lib/ratch/utils/ftp.rb +134 -0
- data/lib/ratch/utils/pom.rb +22 -0
- data/lib/ratch/utils/rdoc.rb +48 -0
- data/lib/ratch/utils/tar.rb +88 -0
- data/lib/ratch/utils/xdg.rb +39 -0
- data/lib/ratch/utils/zlib.rb +54 -0
- data/spec/01_shell.rdoc +198 -0
- data/spec/02_script.rdoc +34 -0
- data/spec/03_batch.rdoc +71 -0
- data/spec/04_system.rdoc +3 -0
- data/spec/applique/array.rb +8 -0
- data/spec/applique/setup.rb +20 -0
- data/test/case_batch.rb +63 -0
- data/test/case_shell.rb +46 -0
- data/test/core_ext/case_pathname.rb +361 -0
- data/test/helper.rb +4 -0
- data/test/utils/case_cli.rb +6 -0
- data/test/utils/case_config.rb +12 -0
- data/test/utils/case_email.rb +10 -0
- data/test/utils/case_ftp.rb +6 -0
- data/test/utils/case_pom.rb +17 -0
- data/test/utils/case_rdoc.rb +23 -0
- data/test/utils/case_tar.rb +6 -0
- data/test/utils/case_zlib.rb +11 -0
- data/test/utils/fixtures/pom_sample/Profile +4 -0
- data/test/utils/fixtures/rdoc_sample/README.rdoc +4 -0
- data/test/utils/fixtures/rdoc_sample/lib/rdoc_sample/rdoc_sample.rb +9 -0
- metadata +139 -82
- data/HISTORY +0 -6
- data/MANIFEST +0 -53
- data/NEWS +0 -12
- data/README +0 -87
- data/VERSION +0 -1
- data/demo/tryme-task.ratch +0 -12
- data/demo/tryme1.ratch +0 -6
- data/doc/log/basic_stats/index.html +0 -39
- data/doc/log/notes.xml +0 -18
- data/doc/log/stats.log +0 -14
- data/doc/log/syntax.log +0 -0
- data/doc/log/testunit.log +0 -156
- data/lib/ratch/commandline.rb +0 -16
- data/lib/ratch/core_ext/pathname.rb +0 -38
- data/lib/ratch/dsl.rb +0 -420
- data/lib/ratch/index.rb +0 -4
- data/lib/ratch/io.rb +0 -116
- data/lib/ratch/plugin.rb +0 -65
- data/lib/ratch/service.rb +0 -33
- data/lib/ratch/task.rb +0 -249
- data/lib/ratch/task2.rb +0 -298
- data/meta/abstract +0 -4
- data/meta/author +0 -1
- data/meta/contact +0 -1
- data/meta/homepage +0 -1
- data/meta/name +0 -1
- data/meta/requires +0 -4
- data/meta/summary +0 -1
- data/test/README +0 -1
- data/test/test_helper.rb +0 -4
- data/test/test_task.rb +0 -46
data/lib/ratch/system.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# TODO: Build it!
|
4
|
+
#
|
5
|
+
# The System class provides a robust interface for interacting with
|
6
|
+
# system commands. It is essenatially a wrapper around popen3 or popen4.
|
7
|
+
#
|
8
|
+
# Having a separate class rather integrating this into Shell (as
|
9
|
+
# Ruby's standard Shell class does) provides a better SOC.
|
10
|
+
#
|
11
|
+
class System
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# TODO: How best to support CLI interface?
|
4
|
+
module CLI
|
5
|
+
|
6
|
+
#
|
7
|
+
def self.included(base)
|
8
|
+
require 'facets/argvector'
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
def self.extended(base)
|
13
|
+
require 'facets/argvector'
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
def initialize(*args)
|
18
|
+
argv = ArgVector.new(ARGV)
|
19
|
+
|
20
|
+
@arguments, parameters = *argv.parameters
|
21
|
+
|
22
|
+
args << {} unless Hash === args.last
|
23
|
+
|
24
|
+
opts = args.last
|
25
|
+
|
26
|
+
opts.merge!(parameters)
|
27
|
+
|
28
|
+
super(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
def arguments
|
33
|
+
@arguments
|
34
|
+
end
|
35
|
+
|
36
|
+
# DEPRECATE!
|
37
|
+
#alias_method :commandline, :cli
|
38
|
+
|
39
|
+
# DEPRECATE!
|
40
|
+
#alias_method :command, :cli
|
41
|
+
|
42
|
+
#
|
43
|
+
#def commandline
|
44
|
+
# #@commandline ||= ArgVector.new(ARGV)
|
45
|
+
# @commandline
|
46
|
+
#end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# Utility extensions for working with configuration files.
|
4
|
+
#--
|
5
|
+
# TODO: Perhaps utilize confectionary gem in future?
|
6
|
+
#++
|
7
|
+
module ConfigUtils
|
8
|
+
|
9
|
+
#
|
10
|
+
def self.included(base)
|
11
|
+
require 'yaml'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.extended(base)
|
15
|
+
included(base)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Load configuration data from a file. Results are cached and an empty
|
19
|
+
# Hash is returned if the file is not found.
|
20
|
+
#
|
21
|
+
# Since they are YAML files, they can optionally end with '.yaml' or '.yml'.
|
22
|
+
def configuration(file)
|
23
|
+
@configuration ||= {}
|
24
|
+
@configuration[file] ||= (
|
25
|
+
begin
|
26
|
+
configuration!(file)
|
27
|
+
rescue LoadError
|
28
|
+
Hash.new{ |h,k| h[k] = {} }
|
29
|
+
end
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Load configuration data from a file. The "bang" version will raise an error
|
34
|
+
# if file is not found. It also does not cache the results.
|
35
|
+
#
|
36
|
+
# Since they are YAML files, they can optionally end with '.yaml' or '.yml'.
|
37
|
+
def configuration!(file)
|
38
|
+
@configuration ||= {}
|
39
|
+
patt = file + "{.yml,.yaml,}"
|
40
|
+
path = Dir.glob(patt, File::FNM_CASEFOLD).find{ |f| File.file?(f) }
|
41
|
+
if path
|
42
|
+
# The || {} is in case the file is empty.
|
43
|
+
data = YAML::load(File.open(path)) || {}
|
44
|
+
@configuration[file] = data
|
45
|
+
else
|
46
|
+
raise LoadError, "Missing file -- #{path}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -1,11 +1,37 @@
|
|
1
|
-
|
2
|
-
require 'facets/net/smtp_tls'
|
3
|
-
rescue LoadError
|
4
|
-
require 'net/smtp'
|
5
|
-
end
|
1
|
+
module Ratch
|
6
2
|
|
3
|
+
# The Mail utility module provides an easy to use +email+ method.
|
4
|
+
module EmailUtils
|
7
5
|
|
8
|
-
|
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
|
9
35
|
|
10
36
|
# Emailer class makes it easy send out an email.
|
11
37
|
#
|
@@ -67,6 +93,8 @@ module Ratch
|
|
67
93
|
|
68
94
|
#
|
69
95
|
def initialize(options={})
|
96
|
+
require_smtp
|
97
|
+
|
70
98
|
options = options.rekey
|
71
99
|
|
72
100
|
if not options[:server]
|
@@ -171,6 +199,15 @@ module Ratch
|
|
171
199
|
return inp
|
172
200
|
end
|
173
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
|
+
|
174
211
|
end
|
175
212
|
|
176
213
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# FIXME: This module needs major work. Methods #ftp_files and
|
4
|
+
# ftp_stage_transfer need to either be generalized and moved to
|
5
|
+
# Shell or Script, or removed.
|
6
|
+
#
|
7
|
+
module FTPUtils
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
require 'net/ftp'
|
11
|
+
require 'net/sftp'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.extended(base)
|
15
|
+
included(base)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Use ftp to upload files.
|
19
|
+
#
|
20
|
+
def ftp(keys)
|
21
|
+
keys = upload_parameters(keys)
|
22
|
+
|
23
|
+
# set transfer rules
|
24
|
+
if keys.stage
|
25
|
+
trans = ftp_stage_transfer(keys.stage)
|
26
|
+
else
|
27
|
+
ftp_files(keys.dir, keys.copy).each do |from|
|
28
|
+
trans << [from,from]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# append location of publication dir to from
|
33
|
+
dir = keys.dir
|
34
|
+
trans.collect!{ |from,to| [File.join(dir,from), to] }
|
35
|
+
|
36
|
+
if keys.dryrun
|
37
|
+
puts "ftp open #{keys.user}@#{keys.host}:#{keys.root}/"
|
38
|
+
keys.trans.each do |f, t|
|
39
|
+
puts "ftp put #{f} #{t}"
|
40
|
+
end
|
41
|
+
else
|
42
|
+
Net::FTP.open(keys.host) do |ftp|
|
43
|
+
ftp.login(keys.user) #password?
|
44
|
+
ftp.chdir(keys.root)
|
45
|
+
keys.trans.each do |f, t|
|
46
|
+
puts "ftp #{f} #{t}" unless keys.quiet
|
47
|
+
ftp.putbinaryfile( f, t, 1024 )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Use sftp to upload files.
|
54
|
+
#
|
55
|
+
def sftp( keys )
|
56
|
+
keys = upload_parameters(keys)
|
57
|
+
|
58
|
+
# set transfer rules
|
59
|
+
if keys.stage
|
60
|
+
trans = ftp_stage_transfer(keys.stage)
|
61
|
+
else
|
62
|
+
ftp_files(keys.dir, keys.copy).each do |from|
|
63
|
+
trans << [from,from]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# append location of publication dir to from
|
68
|
+
dir = keys.dir
|
69
|
+
trans.collect!{ |from,to| [File.join(dir,from), to] }
|
70
|
+
|
71
|
+
if keys.dryrun
|
72
|
+
puts "sftp open #{keys.user}@#{keys.host}:#{keys.root}/"
|
73
|
+
keys.trans.each do |f,t|
|
74
|
+
puts "sftp put #{f} #{t}"
|
75
|
+
end
|
76
|
+
else
|
77
|
+
Net::SFTP.start(keys.host, keys.user, keys.pass) do |sftp|
|
78
|
+
#sftp.login( user )
|
79
|
+
sftp.chdir(keys.root)
|
80
|
+
keys.trans.each do |f,t|
|
81
|
+
puts "sftp #{f} #{t}" unless keys.quiet
|
82
|
+
sftp.put_file(f,t) #, 1024 )
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Put together the list of files to copy.
|
89
|
+
def ftp_files( dir, copy )
|
90
|
+
Dir.chdir(dir) do
|
91
|
+
del, add = copy.partition{ |f| /^[-]/ =~ f }
|
92
|
+
|
93
|
+
# remove - and + prefixes
|
94
|
+
del.collect!{ |f| f.sub(/^[-]/,'') }
|
95
|
+
add.collect!{ |f| f.sub(/^[+]/,'') }
|
96
|
+
|
97
|
+
#del.concat(must_exclude)
|
98
|
+
|
99
|
+
ftp_files = []
|
100
|
+
add.each{ |g| files += Dir.glob(g) }
|
101
|
+
del.each{ |g| files -= Dir.glob(g) }
|
102
|
+
|
103
|
+
files.collect!{ |f| f.sub(/^\//,'') }
|
104
|
+
|
105
|
+
return files
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Combine three part stage list into a two part from->to list.
|
110
|
+
#
|
111
|
+
# Using the stage list of three space separated fields.
|
112
|
+
#
|
113
|
+
# fromdir file todir
|
114
|
+
#
|
115
|
+
# This is used to generate a from -> to list of the form:
|
116
|
+
#
|
117
|
+
# fromdir/file todir/file
|
118
|
+
#
|
119
|
+
def ftp_stage_transfer( list )
|
120
|
+
trans = []
|
121
|
+
list.each do |line|
|
122
|
+
trans << Shellwords.shellwords(line)
|
123
|
+
end
|
124
|
+
|
125
|
+
trans.collect! do |from, base, to|
|
126
|
+
file = File.join(from,base)
|
127
|
+
to = File.join(to,base)
|
128
|
+
[from, to]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# Methods for utilizing Ruby POM.
|
4
|
+
module POMUtils
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
require 'pom'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.extended(base)
|
11
|
+
included(base)
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
def project
|
16
|
+
@project ||= ::POM::Project.new
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Ratch
|
2
|
+
|
3
|
+
# Provides a pure-Ruby method for generating RDocs.
|
4
|
+
module RDocUtils
|
5
|
+
|
6
|
+
DEFAULT_RDOC_OPTIONS = {
|
7
|
+
:quiet => true
|
8
|
+
}
|
9
|
+
|
10
|
+
# RDoc command.
|
11
|
+
#
|
12
|
+
# :call-seq:
|
13
|
+
# rdoc(file1, file2, ..., :opt1 => val1, ...)
|
14
|
+
#
|
15
|
+
def rdoc(*files)
|
16
|
+
require 'rdoc/rdoc'
|
17
|
+
|
18
|
+
options = Hash===files.last ? files.pop : {}
|
19
|
+
options.rekey!(&:to_s)
|
20
|
+
|
21
|
+
options['title'] ||= options.delete('T')
|
22
|
+
|
23
|
+
options['debug'] = options['debug'] #|| debug?
|
24
|
+
options['quiet'] = options['quiet'] #|| quiet?
|
25
|
+
options['verbose'] = options['verbose'] #|| verbose?
|
26
|
+
|
27
|
+
# apply pom (todo?)
|
28
|
+
#options['title'] ||= metadata.title
|
29
|
+
|
30
|
+
options = DEFAULT_RDOC_OPTIONS.merge(options)
|
31
|
+
|
32
|
+
locally do
|
33
|
+
rdoc = RDoc::RDoc.new
|
34
|
+
opts = options.to_argv + files
|
35
|
+
$stderr.puts("rdoc " + opts.join(' ')) if ($VERBOSE || $DEBUG)
|
36
|
+
disable_warnings do
|
37
|
+
rdoc.document(options.to_argv + files)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# TODO: Implement ri doc generator.
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'ratch/utils/zlib'
|
2
|
+
|
3
|
+
module Ratch
|
4
|
+
|
5
|
+
# Utility methods for working with tarballs archives.
|
6
|
+
#--
|
7
|
+
# TODO: Add compress support ?
|
8
|
+
# TODO: Add bzip support ?
|
9
|
+
#++
|
10
|
+
module TarUtils
|
11
|
+
|
12
|
+
# When included include GZipUtils too.
|
13
|
+
def self.included(base)
|
14
|
+
#require 'zlib'
|
15
|
+
include ZLibUtils
|
16
|
+
require 'archive/tar/minitar'
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
def self.extended(base)
|
21
|
+
included(base)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Tar
|
25
|
+
def tar(folder, file=nil, options={})
|
26
|
+
noop, verbose = *util_options(options)
|
27
|
+
file ||= File.basename(File.expand_path(folder)) + '.tar'
|
28
|
+
cmd = "tar -cf #{file} #{folder}"
|
29
|
+
puts cmd if verbose
|
30
|
+
unless noop
|
31
|
+
locally do
|
32
|
+
gzIO = File.open(file, 'wb')
|
33
|
+
Archive::Tar::Minitar.pack(folder, gzIO)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
path(file)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Untar
|
40
|
+
def untar(file, options={})
|
41
|
+
noop, verbose = *util_options(options)
|
42
|
+
#file ||= File.basename(File.expand_path(folder)) + '.tar'
|
43
|
+
cmd = "untar #{file}"
|
44
|
+
puts cmd if verbose
|
45
|
+
unless noop
|
46
|
+
locally do
|
47
|
+
gzIO = File.open(file, 'wb')
|
48
|
+
Archive::Tar::Minitar.unpack(gzIO)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
path(file)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Tar Gzip
|
55
|
+
def tar_gzip(folder, file=nil, options={})
|
56
|
+
noop, verbose = *util_options(options)
|
57
|
+
file ||= File.basename(File.expand_path(folder)) + '.tar.gz' # '.tgz' which ?
|
58
|
+
cmd = "tar --gzip -czf #{file} #{folder}"
|
59
|
+
puts cmd if verbose
|
60
|
+
unless noop
|
61
|
+
locally do #folder, file = localize(folder), localize(file)
|
62
|
+
gzIO = Zlib::GzipWriter.new(File.open(file, 'wb'))
|
63
|
+
Archive::Tar::Minitar.pack(folder, gzIO)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
path(file)
|
67
|
+
end
|
68
|
+
|
69
|
+
alias_method :tar_z, :tar_gzip
|
70
|
+
|
71
|
+
# Untar Gzip
|
72
|
+
#
|
73
|
+
# FIXME: Write unified untar_gzip function.
|
74
|
+
def untar_gzip(file, options={})
|
75
|
+
untar(ungzip(file, options), options)
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :untar_z, :untar_gzip
|
79
|
+
|
80
|
+
#def tgz(folder, file=nil, options={})
|
81
|
+
# file ||= File.basename(File.expand_path(folder)) + '.tgz'
|
82
|
+
# tar_gzip(folder, file, options)
|
83
|
+
#end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|