transcriptic 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.
- data/bin/transcriptic +12 -0
- data/lib/transcriptic.rb +3 -0
- data/lib/transcriptic/api.rb +73 -0
- data/lib/transcriptic/api/errors.rb +24 -0
- data/lib/transcriptic/api/sequences.rb +33 -0
- data/lib/transcriptic/api/version.rb +5 -0
- data/lib/transcriptic/auth.rb +223 -0
- data/lib/transcriptic/cli.rb +12 -0
- data/lib/transcriptic/client.rb +332 -0
- data/lib/transcriptic/command.rb +233 -0
- data/lib/transcriptic/command/analyze.rb +20 -0
- data/lib/transcriptic/command/base.rb +195 -0
- data/lib/transcriptic/command/console.rb +10 -0
- data/lib/transcriptic/command/data.rb +8 -0
- data/lib/transcriptic/command/help.rb +124 -0
- data/lib/transcriptic/command/history.rb +8 -0
- data/lib/transcriptic/command/login.rb +35 -0
- data/lib/transcriptic/command/run.rb +60 -0
- data/lib/transcriptic/command/sequences.rb +45 -0
- data/lib/transcriptic/command/status.rb +17 -0
- data/lib/transcriptic/helpers.rb +311 -0
- data/lib/transcriptic/version.rb +3 -0
- data/lib/vendor/transcriptic/okjson.rb +557 -0
- metadata +161 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
module Transcriptic::Command
|
2
|
+
|
3
|
+
# list commands and display help
|
4
|
+
#
|
5
|
+
class Help < Base
|
6
|
+
PRIMARY_NAMESPACES = %w( analyze data history run status sequences)
|
7
|
+
|
8
|
+
# help [COMMAND]
|
9
|
+
#
|
10
|
+
# list available commands or display help for a specific command
|
11
|
+
#
|
12
|
+
def index
|
13
|
+
if command = args.shift
|
14
|
+
help_for_command(command)
|
15
|
+
else
|
16
|
+
help_for_root
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_command "-h", "help"
|
21
|
+
alias_command "--help", "help"
|
22
|
+
|
23
|
+
def self.usage_for_command(command)
|
24
|
+
command = new.send(:commands)[command]
|
25
|
+
"Usage: transcriptic #{command[:banner]}" if command
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def commands_for_namespace(name)
|
31
|
+
Transcriptic::Command.commands.values.select do |command|
|
32
|
+
command[:namespace] == name && command[:command] != name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def namespaces
|
37
|
+
namespaces = Transcriptic::Command.namespaces
|
38
|
+
namespaces.delete("app")
|
39
|
+
namespaces
|
40
|
+
end
|
41
|
+
|
42
|
+
def commands
|
43
|
+
Transcriptic::Command.commands
|
44
|
+
end
|
45
|
+
|
46
|
+
def legacy_help_for_namespace(namespace)
|
47
|
+
instance = Transcriptic::Command::Help.groups.map do |group|
|
48
|
+
[ group.title, group.select { |c| c.first =~ /^#{namespace}/ }.length ]
|
49
|
+
end.sort_by { |l| l.last }.last
|
50
|
+
return nil unless instance
|
51
|
+
return nil if instance.last.zero?
|
52
|
+
instance.first
|
53
|
+
end
|
54
|
+
|
55
|
+
def primary_namespaces
|
56
|
+
PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
|
57
|
+
end
|
58
|
+
|
59
|
+
def additional_namespaces
|
60
|
+
(namespaces.values - primary_namespaces)
|
61
|
+
end
|
62
|
+
|
63
|
+
def summary_for_namespaces(namespaces)
|
64
|
+
size = longest(namespaces.map { |n| n[:name] })
|
65
|
+
namespaces.sort_by {|namespace| namespace[:name]}.each do |namespace|
|
66
|
+
name = namespace[:name]
|
67
|
+
namespace[:description]
|
68
|
+
puts " %-#{size}s # %s" % [ name, namespace[:description] ]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def help_for_root
|
73
|
+
puts "Usage: transcriptic COMMAND [command-specific-options]"
|
74
|
+
puts
|
75
|
+
puts "Primary help topics, type \"transcriptic help TOPIC\" for more details:"
|
76
|
+
puts
|
77
|
+
summary_for_namespaces(primary_namespaces)
|
78
|
+
puts
|
79
|
+
puts "Additional topics:"
|
80
|
+
puts
|
81
|
+
summary_for_namespaces(additional_namespaces)
|
82
|
+
puts
|
83
|
+
end
|
84
|
+
|
85
|
+
def help_for_namespace(name)
|
86
|
+
namespace_commands = commands_for_namespace(name)
|
87
|
+
|
88
|
+
unless namespace_commands.empty?
|
89
|
+
size = longest(namespace_commands.map { |c| c[:banner] })
|
90
|
+
namespace_commands.sort_by { |c| c[:banner].to_s }.each do |command|
|
91
|
+
next if command[:help] =~ /DEPRECATED/
|
92
|
+
command[:summary]
|
93
|
+
puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def help_for_command(name)
|
99
|
+
if command_alias = Transcriptic::Command.command_aliases[name]
|
100
|
+
display("Alias: #{name} redirects to #{command_alias}")
|
101
|
+
name = command_alias
|
102
|
+
end
|
103
|
+
if command = commands[name]
|
104
|
+
puts "Usage: transcriptic #{command[:banner]}"
|
105
|
+
|
106
|
+
if command[:help].strip.length > 0
|
107
|
+
puts command[:help].split("\n")[1..-1].join("\n")
|
108
|
+
end
|
109
|
+
puts
|
110
|
+
end
|
111
|
+
|
112
|
+
if commands_for_namespace(name).size > 0
|
113
|
+
puts "Additional commands, type \"transcriptic help COMMAND\" for more details:"
|
114
|
+
puts
|
115
|
+
help_for_namespace(name)
|
116
|
+
puts
|
117
|
+
elsif command.nil?
|
118
|
+
error "#{name} is not a transcriptic command. See `transcriptic help`."
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# login, logout, and view your api token
|
2
|
+
#
|
3
|
+
class Transcriptic::Command::Auth < Transcriptic::Command::Base
|
4
|
+
|
5
|
+
# auth:login
|
6
|
+
#
|
7
|
+
# log in with your transcriptic account
|
8
|
+
#
|
9
|
+
def login
|
10
|
+
Transcriptic::Auth.login
|
11
|
+
display "Authentication successful."
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_command "login", "auth:login"
|
15
|
+
|
16
|
+
# auth:logout
|
17
|
+
#
|
18
|
+
# clear local authentication credentials
|
19
|
+
#
|
20
|
+
def logout
|
21
|
+
Transcriptic::Auth.logout
|
22
|
+
display "Local credentials cleared."
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_command "logout", "auth:logout"
|
26
|
+
|
27
|
+
# auth:token
|
28
|
+
#
|
29
|
+
# display your api token
|
30
|
+
#
|
31
|
+
def token
|
32
|
+
display Transcriptic::Auth.api_key
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'zipruby'
|
2
|
+
require 'net/http/post/multipart'
|
3
|
+
|
4
|
+
module Transcriptic::Command
|
5
|
+
|
6
|
+
# upload and run a protocol
|
7
|
+
#
|
8
|
+
class Run < Base
|
9
|
+
|
10
|
+
# transcriptic run [FILENAME|DIRECTORY]
|
11
|
+
#
|
12
|
+
# upload FILENAME or DIRECTORY and launch it
|
13
|
+
#
|
14
|
+
def index
|
15
|
+
path = args.shift
|
16
|
+
upload_protocol(path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def upload_protocol(path)
|
20
|
+
begin
|
21
|
+
stat = File.stat(path)
|
22
|
+
rescue
|
23
|
+
puts "No such path: #{path}"
|
24
|
+
return
|
25
|
+
end
|
26
|
+
if stat.directory?
|
27
|
+
files = Pathname.glob("#{path}/**/**")
|
28
|
+
file_count = files.reject(&:directory?).length
|
29
|
+
dir_count = files.reject(&:file?).length
|
30
|
+
puts "Package detected, compressing #{file_count} files (#{dir_count} directories)..."
|
31
|
+
upfile = Tempfile.new('protocol')
|
32
|
+
Zip::Archive.open(upfile.path, Zip::CREATE) do |ar|
|
33
|
+
ar.add_dir(path)
|
34
|
+
Dir.glob("#{path}/**/**").each do |path|
|
35
|
+
if File.directory?(path)
|
36
|
+
ar.add_dir(path)
|
37
|
+
else
|
38
|
+
ar.add_file(path, path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
else
|
43
|
+
upfile = path
|
44
|
+
end
|
45
|
+
puts "Uploading `#{path}` to Transcriptic..."
|
46
|
+
url = URI.parse('http://client.transcriptic.com/receive')
|
47
|
+
File.open(upfile) do |zf|
|
48
|
+
req = Net::HTTP::Post::Multipart.new url.path,
|
49
|
+
"file" => UploadIO.new(zf, "application/zip", "protocol.zip")
|
50
|
+
res = Net::HTTP.start(url.host, url.port) do |http|
|
51
|
+
http.request(req)
|
52
|
+
end
|
53
|
+
if res.code != 200
|
54
|
+
puts "HTTP Error: #{res.message} (#{res.code})"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Transcriptic::Command
|
2
|
+
|
3
|
+
# manage sequence data
|
4
|
+
#
|
5
|
+
class Sequences < Base
|
6
|
+
|
7
|
+
# sequences
|
8
|
+
#
|
9
|
+
# list all sequence entries
|
10
|
+
#
|
11
|
+
#Examples:
|
12
|
+
#
|
13
|
+
# $ transcriptic sequences
|
14
|
+
# ...
|
15
|
+
#
|
16
|
+
def index
|
17
|
+
validate_arguments!
|
18
|
+
end
|
19
|
+
|
20
|
+
# sequences:add FILENAME.EXT
|
21
|
+
#
|
22
|
+
# upload new sequence data file. EXT must be .gb or .fasta
|
23
|
+
#
|
24
|
+
#Examples:
|
25
|
+
#
|
26
|
+
# $ transcriptic sequences:add myvector.fasta
|
27
|
+
# ...
|
28
|
+
#
|
29
|
+
def add
|
30
|
+
end
|
31
|
+
|
32
|
+
# sequences:delete NAME
|
33
|
+
#
|
34
|
+
# delete sequence by name NAME
|
35
|
+
#
|
36
|
+
#Examples:
|
37
|
+
#
|
38
|
+
# $ transcriptic sequences:delete myvector20110204
|
39
|
+
# ...
|
40
|
+
#
|
41
|
+
def remove
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Transcriptic::Command
|
2
|
+
|
3
|
+
# view the status of your runs
|
4
|
+
#
|
5
|
+
class Status < Base
|
6
|
+
|
7
|
+
# transcriptic status [RUNID]
|
8
|
+
#
|
9
|
+
# list active runs, or if RUNID supplied, show details of that run
|
10
|
+
#
|
11
|
+
def index
|
12
|
+
run_id = args.shift
|
13
|
+
puts run_id
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,311 @@
|
|
1
|
+
require "vendor/transcriptic/okjson"
|
2
|
+
|
3
|
+
module Transcriptic
|
4
|
+
module Helpers
|
5
|
+
def home_directory
|
6
|
+
running_on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
|
7
|
+
end
|
8
|
+
|
9
|
+
def running_on_windows?
|
10
|
+
RUBY_PLATFORM =~ /mswin32|mingw32/
|
11
|
+
end
|
12
|
+
|
13
|
+
def running_on_a_mac?
|
14
|
+
RUBY_PLATFORM =~ /-darwin\d/
|
15
|
+
end
|
16
|
+
|
17
|
+
def display(msg="", newline=true)
|
18
|
+
if newline
|
19
|
+
puts(msg)
|
20
|
+
else
|
21
|
+
print(msg)
|
22
|
+
STDOUT.flush
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def redisplay(line, line_break = false)
|
27
|
+
display("\r\e[0K#{line}", line_break)
|
28
|
+
end
|
29
|
+
|
30
|
+
def deprecate(version)
|
31
|
+
display "!!! DEPRECATION WARNING: This command will be removed in version #{version}"
|
32
|
+
display
|
33
|
+
end
|
34
|
+
|
35
|
+
def error(msg)
|
36
|
+
STDERR.puts(msg)
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def confirm_billing
|
41
|
+
display
|
42
|
+
display "This action will cause your account to be billed at the end of the month"
|
43
|
+
display "For more information, see http://devcenter.heroku.com/articles/billing"
|
44
|
+
display "Are you sure you want to do this? (y/n) ", false
|
45
|
+
if ask.downcase == 'y'
|
46
|
+
heroku.confirm_billing
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def confirm(message = "Are you sure you wish to continue? (y/n)?")
|
52
|
+
display("#{message} ", false)
|
53
|
+
ask.downcase == 'y'
|
54
|
+
end
|
55
|
+
|
56
|
+
def confirm_command(app = app)
|
57
|
+
raise(Transcriptic::Command::CommandFailed, "No app specified.\nRun this command from app folder or set it adding --app <app name>") unless app
|
58
|
+
|
59
|
+
confirmed_app = extract_option('--confirm', false)
|
60
|
+
if confirmed_app
|
61
|
+
unless confirmed_app == app
|
62
|
+
raise(Transcriptic::Command::CommandFailed, "Confirmed app #{confirmed_app} did not match the selected app #{app}.")
|
63
|
+
end
|
64
|
+
return true
|
65
|
+
else
|
66
|
+
display
|
67
|
+
display " ! WARNING: Potentially Destructive Action"
|
68
|
+
display " ! This command will affect the app: #{app}"
|
69
|
+
display " ! To proceed, type \"#{app}\" or re-run this command with --confirm #{app}"
|
70
|
+
display
|
71
|
+
display "> ", false
|
72
|
+
if ask.downcase != app
|
73
|
+
display " ! Input did not match #{app}. Aborted."
|
74
|
+
false
|
75
|
+
else
|
76
|
+
true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def format_date(date)
|
82
|
+
date = Time.parse(date) if date.is_a?(String)
|
83
|
+
date.strftime("%Y-%m-%d %H:%M %Z")
|
84
|
+
end
|
85
|
+
|
86
|
+
def ask
|
87
|
+
gets.strip
|
88
|
+
end
|
89
|
+
|
90
|
+
def shell(cmd)
|
91
|
+
FileUtils.cd(Dir.pwd) {|d| return `#{cmd}`}
|
92
|
+
end
|
93
|
+
|
94
|
+
def run_command(command, args=[])
|
95
|
+
Transcriptic::Command.run(command, args)
|
96
|
+
end
|
97
|
+
|
98
|
+
def retry_on_exception(*exceptions)
|
99
|
+
retry_count = 0
|
100
|
+
begin
|
101
|
+
yield
|
102
|
+
rescue *exceptions => ex
|
103
|
+
raise ex if retry_count >= 3
|
104
|
+
sleep 3
|
105
|
+
retry_count += 1
|
106
|
+
retry
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def has_git?
|
111
|
+
%x{ git --version }
|
112
|
+
$?.success?
|
113
|
+
end
|
114
|
+
|
115
|
+
def git(args)
|
116
|
+
return "" unless has_git?
|
117
|
+
flattened_args = [args].flatten.compact.join(" ")
|
118
|
+
%x{ git #{flattened_args} 2>&1 }.strip
|
119
|
+
end
|
120
|
+
|
121
|
+
def time_ago(elapsed)
|
122
|
+
if elapsed < 60
|
123
|
+
"#{elapsed.floor}s ago"
|
124
|
+
elsif elapsed < (60 * 60)
|
125
|
+
"#{(elapsed / 60).floor}m ago"
|
126
|
+
else
|
127
|
+
"#{(elapsed / 60 / 60).floor}h ago"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def truncate(text, length)
|
132
|
+
if text.size > length
|
133
|
+
text[0, length - 2] + '..'
|
134
|
+
else
|
135
|
+
text
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
@@kb = 1024
|
140
|
+
@@mb = 1024 * @@kb
|
141
|
+
@@gb = 1024 * @@mb
|
142
|
+
def format_bytes(amount)
|
143
|
+
amount = amount.to_i
|
144
|
+
return '(empty)' if amount == 0
|
145
|
+
return amount if amount < @@kb
|
146
|
+
return "#{(amount / @@kb).round}k" if amount < @@mb
|
147
|
+
return "#{(amount / @@mb).round}M" if amount < @@gb
|
148
|
+
return "#{(amount / @@gb).round}G"
|
149
|
+
end
|
150
|
+
|
151
|
+
def quantify(string, num)
|
152
|
+
"%d %s" % [ num, num.to_i == 1 ? string : "#{string}s" ]
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_git_remote(app, remote)
|
156
|
+
return unless has_git?
|
157
|
+
return if git('remote').split("\n").include?(remote)
|
158
|
+
return unless File.exists?(".git")
|
159
|
+
git "remote add #{remote} git@#{heroku.host}:#{app}.git"
|
160
|
+
display "Git remote #{remote} added"
|
161
|
+
end
|
162
|
+
|
163
|
+
def app_urls(name)
|
164
|
+
"http://#{name}.heroku.com/ | git@heroku.com:#{name}.git"
|
165
|
+
end
|
166
|
+
|
167
|
+
def longest(items)
|
168
|
+
items.map { |i| i.to_s.length }.sort.last
|
169
|
+
end
|
170
|
+
|
171
|
+
def display_table(objects, columns, headers)
|
172
|
+
lengths = []
|
173
|
+
columns.each_with_index do |column, index|
|
174
|
+
header = headers[index]
|
175
|
+
lengths << longest([header].concat(objects.map { |o| o[column].to_s }))
|
176
|
+
end
|
177
|
+
display_row headers, lengths
|
178
|
+
display_row headers.map { |header| "-" * header.length }, lengths
|
179
|
+
objects.each do |row|
|
180
|
+
display_row columns.map { |column| row[column] }, lengths
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def display_row(row, lengths)
|
185
|
+
row.zip(lengths).each do |column, length|
|
186
|
+
format = column.is_a?(Fixnum) ? "%#{length}s " : "%-#{length}s "
|
187
|
+
display format % column, false
|
188
|
+
end
|
189
|
+
display
|
190
|
+
end
|
191
|
+
|
192
|
+
def json_encode(object)
|
193
|
+
Transcriptic::OkJson.encode(object)
|
194
|
+
rescue Transcriptic::OkJson::ParserError
|
195
|
+
nil
|
196
|
+
end
|
197
|
+
|
198
|
+
def json_decode(json)
|
199
|
+
Transcriptic::OkJson.decode(json)
|
200
|
+
rescue Transcriptic::OkJson::ParserError
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
|
204
|
+
def set_buffer(enable)
|
205
|
+
return unless $stdin.tty?
|
206
|
+
|
207
|
+
if enable
|
208
|
+
`stty icanon echo`
|
209
|
+
else
|
210
|
+
`stty -icanon -echo`
|
211
|
+
end
|
212
|
+
rescue
|
213
|
+
# fails on windows
|
214
|
+
end
|
215
|
+
|
216
|
+
def get_terminal_environment
|
217
|
+
{ "TERM" => ENV["TERM"], "COLUMNS" => `tput cols`, "LINES" => `tput lines` }
|
218
|
+
rescue
|
219
|
+
{ "TERM" => ENV["TERM"] }
|
220
|
+
end
|
221
|
+
|
222
|
+
def fail(message)
|
223
|
+
raise Transcriptic::Command::CommandFailed, message
|
224
|
+
end
|
225
|
+
|
226
|
+
## DISPLAY HELPERS
|
227
|
+
|
228
|
+
def arrow(message)
|
229
|
+
"-----> #{message}"
|
230
|
+
end
|
231
|
+
|
232
|
+
def action(message)
|
233
|
+
display "#{arrow(message)}... ", false
|
234
|
+
Transcriptic::Helpers.enable_error_capture
|
235
|
+
yield
|
236
|
+
Transcriptic::Helpers.disable_error_capture
|
237
|
+
display "done", false
|
238
|
+
display(", #{@status}", false) if @status
|
239
|
+
display
|
240
|
+
end
|
241
|
+
|
242
|
+
def status(message)
|
243
|
+
@status = message
|
244
|
+
end
|
245
|
+
|
246
|
+
def output(message="")
|
247
|
+
return if message.to_s.strip == ""
|
248
|
+
display " " + message.split("\n").join("\n ")
|
249
|
+
end
|
250
|
+
|
251
|
+
def output_with_arrow(message="")
|
252
|
+
return if message.to_s.strip == ""
|
253
|
+
display "-----> " + message.split("\n").join("\n ")
|
254
|
+
end
|
255
|
+
|
256
|
+
def error_with_failure(message)
|
257
|
+
display "failed"
|
258
|
+
message.gsub!(/^ +! */, '')
|
259
|
+
display message.split("\n").map { |line| " ! #{line}" }.join("\n")
|
260
|
+
exit 1
|
261
|
+
end
|
262
|
+
|
263
|
+
def self.included_into
|
264
|
+
@@included_into ||= []
|
265
|
+
end
|
266
|
+
|
267
|
+
def self.extended_into
|
268
|
+
@@extended_into ||= []
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.included(base)
|
272
|
+
included_into << base
|
273
|
+
end
|
274
|
+
|
275
|
+
def self.extended(base)
|
276
|
+
extended_into << base
|
277
|
+
end
|
278
|
+
|
279
|
+
def self.enable_error_capture
|
280
|
+
included_into.each do |base|
|
281
|
+
base.send(:alias_method, :error_without_failure, :error)
|
282
|
+
base.send(:alias_method, :error, :error_with_failure)
|
283
|
+
end
|
284
|
+
extended_into.each do |base|
|
285
|
+
class << base
|
286
|
+
alias_method :error_without_failure, :error
|
287
|
+
alias_method :error, :error_with_failure
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.disable_error_capture
|
293
|
+
included_into.each do |base|
|
294
|
+
base.send(:alias_method, :error, :error_without_failure)
|
295
|
+
end
|
296
|
+
extended_into.each do |base|
|
297
|
+
class << base
|
298
|
+
alias_method :error, :error_without_failure
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
unless String.method_defined?(:shellescape)
|
306
|
+
class String
|
307
|
+
def shellescape
|
308
|
+
empty? ? "''" : gsub(/([^A-Za-z0-9_\-.,:\/@\n])/n, '\\\\\\1').gsub(/\n/, "'\n'")
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|