raykit 0.0.304 → 0.0.305
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.
- checksums.yaml +4 -4
- data/bin/raykit +4 -2
- data/lib/raykit/command.rb +238 -241
- data/lib/raykit/console.rb +256 -260
- data/lib/raykit/dir.rb +39 -36
- data/lib/raykit/dotnet.rb +90 -90
- data/lib/raykit/environment.rb +77 -77
- data/lib/raykit/git/commit.rb +12 -13
- data/lib/raykit/git/directory.rb +142 -147
- data/lib/raykit/git/files.rb +43 -42
- data/lib/raykit/git/repositories.rb +75 -77
- data/lib/raykit/git/repository.rb +90 -93
- data/lib/raykit/log.rb +39 -37
- data/lib/raykit/logevent.rb +30 -28
- data/lib/raykit/logging.rb +47 -47
- data/lib/raykit/msbuild.rb +19 -11
- data/lib/raykit/nugetpackage.rb +8 -8
- data/lib/raykit/project.rb +261 -274
- data/lib/raykit/rake.rb +29 -31
- data/lib/raykit/runner.rb +37 -37
- data/lib/raykit/secrets.rb +30 -30
- data/lib/raykit/sourceImport.rb +62 -63
- data/lib/raykit/sourceImports.rb +35 -38
- data/lib/raykit/string.rb +14 -12
- data/lib/raykit/tasks.rb +46 -48
- data/lib/raykit/text.rb +24 -22
- data/lib/raykit/timer.rb +24 -22
- data/lib/raykit/version.rb +79 -86
- data/lib/raykit/vstest.rb +17 -15
- data/lib/raykit/zip.rb +35 -37
- data/lib/raykit.rb +14 -14
- metadata +11 -11
data/lib/raykit/console.rb
CHANGED
@@ -1,290 +1,286 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "slop"
|
5
|
+
require_relative("./logging")
|
4
6
|
|
5
7
|
module Raykit
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@opts = Slop.parse do |o|
|
11
|
-
o.string '-t','--task','rake task', default: 'default'
|
12
|
-
o.bool '-v','--verbose','print detailed output', default: false
|
13
|
-
o.bool '-q','--quiet','minimal output', default: false
|
14
|
-
o.bool '-s','--stop','stop on error', default: true
|
15
|
-
end
|
8
|
+
# The implementation for the raykit console application
|
9
|
+
class Console
|
10
|
+
attr_accessor :opts
|
16
11
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
def initialize
|
13
|
+
@opts = Slop.parse do |o|
|
14
|
+
o.string "-t", "--task", "rake task", default: "default"
|
15
|
+
o.bool "-v", "--verbose", "print detailed output", default: false
|
16
|
+
o.bool "-q", "--quiet", "minimal output", default: false
|
17
|
+
o.bool "-s", "--stop", "stop on error", default: true
|
18
|
+
end
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
usage
|
29
|
-
when "add"
|
30
|
-
add
|
31
|
-
when "remove"
|
32
|
-
remove
|
33
|
-
when "show"
|
34
|
-
show
|
35
|
-
when "work"
|
36
|
-
work
|
37
|
-
when "import"
|
38
|
-
import
|
39
|
-
when "clean"
|
40
|
-
clean
|
41
|
-
when "sync_version"
|
42
|
-
sync_version
|
43
|
-
when "copy"
|
44
|
-
copy
|
45
|
-
when "pull"
|
46
|
-
pull
|
47
|
-
else
|
48
|
-
puts 'unrecognized command ' + verb
|
49
|
-
return 1
|
50
|
-
end
|
51
|
-
end
|
20
|
+
if opts.verbose?
|
21
|
+
puts "options: #{Rainbow(@opts.to_hash).yellow.bright}"
|
22
|
+
puts "arguments:#{Rainbow(@opts.arguments).yellow.bright}"
|
23
|
+
end
|
24
|
+
end
|
52
25
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
26
|
+
def run
|
27
|
+
verb = "usage"
|
28
|
+
verb = @opts.arguments[0] if @opts.arguments.length.positive?
|
29
|
+
case verb
|
30
|
+
when "usage"
|
31
|
+
usage
|
32
|
+
when "add"
|
33
|
+
add
|
34
|
+
when "remove"
|
35
|
+
remove
|
36
|
+
when "show"
|
37
|
+
show
|
38
|
+
when "work"
|
39
|
+
work
|
40
|
+
when "import"
|
41
|
+
import
|
42
|
+
when "clean"
|
43
|
+
clean
|
44
|
+
when "sync_version"
|
45
|
+
sync_version
|
46
|
+
when "copy"
|
47
|
+
copy
|
48
|
+
when "pull"
|
49
|
+
pull
|
50
|
+
else
|
51
|
+
puts "unrecognized command #{verb}"
|
52
|
+
1
|
53
|
+
end
|
54
|
+
end
|
76
55
|
|
77
|
-
|
56
|
+
def verb_descriptions
|
57
|
+
{ "add" => "add a git url",
|
58
|
+
"remove" => "remove one or more git urls",
|
59
|
+
"show" => "show git urls matching a specific pattern",
|
60
|
+
"work" => "clone and rake a git repository",
|
61
|
+
"import" => "import git urls matching a specific pattern",
|
62
|
+
"clean" => "clean one or more working directories",
|
63
|
+
"pull" => "preform git pull on one or more working directories",
|
64
|
+
"sync_version" => "synchronize the version number between two files",
|
65
|
+
"copy" => "copy a file" }
|
66
|
+
end
|
78
67
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
68
|
+
def verb_usage
|
69
|
+
{ "add" => "add GIT_URL",
|
70
|
+
"remove" => "remove URL_PATTERN",
|
71
|
+
"show" => "show URL_PATTERN",
|
72
|
+
"work" => "work URL_PATTERN [--task RAKE_TASK]",
|
73
|
+
"import" => "import URL_PATTERN",
|
74
|
+
"clean" => "clean URL_PATTERN",
|
75
|
+
"pull" => "pull URL_PATTERN",
|
76
|
+
"sync_version" => "sync_version SOURCE_FILENAME DESTINATION_FILENAME",
|
77
|
+
"copy" => "copy SOURCE DESTINATION" }
|
78
|
+
end
|
87
79
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
REPOSITORIES << url
|
98
|
-
REPOSITORIES.save(REPOSITORIES.filename)
|
99
|
-
puts 'url ' + url + ' added.'
|
100
|
-
end
|
101
|
-
end
|
80
|
+
def usage
|
81
|
+
puts "Usage: raykit VERB [GIT_URL|PATTERN] [OPTIONS]"
|
82
|
+
verb_descriptions.each do |k, v|
|
83
|
+
puts "#{k.ljust(15, " ")} - #{v}"
|
84
|
+
end
|
85
|
+
# puts @opts
|
86
|
+
# puts "verbs: " + verbs.to_s
|
87
|
+
0
|
88
|
+
end
|
102
89
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
puts 'url ' + url + ' removed.'
|
118
|
-
}
|
119
|
-
REPOSITORIES.save(REPOSITORIES.filename)
|
120
|
-
end
|
121
|
-
end
|
90
|
+
def add
|
91
|
+
if @opts.arguments.length < 2
|
92
|
+
puts "add requires a url"
|
93
|
+
return 1
|
94
|
+
end
|
95
|
+
url = @opts.arguments[1]
|
96
|
+
if REPOSITORIES.include?(url)
|
97
|
+
puts "url #{url} already exists."
|
98
|
+
else
|
99
|
+
REPOSITORIES << url
|
100
|
+
REPOSITORIES.save(REPOSITORIES.filename)
|
101
|
+
puts "url #{url} added."
|
102
|
+
end
|
103
|
+
end
|
122
104
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
105
|
+
def remove
|
106
|
+
if @opts.arguments.length < 2
|
107
|
+
puts "remove requires a url or pattern"
|
108
|
+
return 1
|
109
|
+
end
|
110
|
+
pattern = ""
|
111
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
112
|
+
remove_urls = REPOSITORIES.matches(pattern)
|
113
|
+
if remove_urls.length.zero?
|
114
|
+
puts "no matching urls found."
|
115
|
+
else
|
116
|
+
remove_urls.each do |url|
|
117
|
+
REPOSITORIES.delete(url)
|
118
|
+
puts "url #{url} removed."
|
129
119
|
end
|
120
|
+
REPOSITORIES.save(REPOSITORIES.filename)
|
121
|
+
end
|
122
|
+
end
|
130
123
|
|
131
|
-
|
132
|
-
|
133
|
-
|
124
|
+
def show
|
125
|
+
pattern = ""
|
126
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
127
|
+
REPOSITORIES.matches(pattern).each do |url|
|
128
|
+
puts url
|
129
|
+
end
|
130
|
+
end
|
134
131
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
work_repositories.each{|url|
|
139
|
-
exitstatus = work_url(url)
|
140
|
-
puts ' ' if(@opts.verbose?)
|
141
|
-
return exitstatus if(@opts[:stop] && exitstatus != 0)
|
142
|
-
}
|
143
|
-
0
|
144
|
-
end
|
132
|
+
def work
|
133
|
+
pattern = ""
|
134
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
145
135
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
136
|
+
work_repositories = REPOSITORIES.matches(pattern)
|
137
|
+
errors = []
|
138
|
+
puts "work: found #{work_repositories.length} matching urls"
|
139
|
+
work_repositories.each do |url|
|
140
|
+
exitstatus = work_url(url)
|
141
|
+
puts " " if @opts.verbose?
|
142
|
+
return exitstatus if @opts[:stop] && exitstatus != 0
|
143
|
+
end
|
144
|
+
0
|
145
|
+
end
|
146
|
+
|
147
|
+
def work_url(url)
|
148
|
+
return 0 if url == "https://gitlab.com/lou-parslow/raykit.git"
|
149
|
+
|
150
|
+
puts Rainbow(url).yellow.bright if @opts.verbose?
|
151
|
+
repo = Raykit::Git::Repository.new(url)
|
152
|
+
work = Raykit::Git::Directory.new(repo.get_dev_dir("work"))
|
153
|
+
unless Dir.exist?(work.directory)
|
154
|
+
clone = Command.new("git clone #{url} #{work.directory} --recursive")
|
155
|
+
puts clone.summary unless @opts.quiet?
|
156
|
+
if clone.exitstatus != 0
|
157
|
+
clone.details
|
158
|
+
return clone.exitstatus
|
159
|
+
end
|
160
|
+
end
|
161
|
+
if Dir.exist?(work.directory)
|
162
|
+
Dir.chdir(work.directory) do
|
163
|
+
if File.exist?("rakefile.rb")
|
164
|
+
rake = Raykit::Command.new("rake #{@opts[:task]}")
|
165
|
+
rake.summary(true) if !@opts.quiet? || rake.exitstatus != 0
|
166
|
+
if rake.exitstatus != 0
|
167
|
+
rake.details
|
168
|
+
rake.summary true
|
169
|
+
return rake.exitstatus
|
174
170
|
end
|
171
|
+
else
|
172
|
+
puts("rakefile.rb not found in #{work.directory}") if @opts.verbose?
|
175
173
|
return 0
|
174
|
+
end
|
176
175
|
end
|
176
|
+
end
|
177
|
+
0
|
178
|
+
end
|
177
179
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
cmd.summary if(@opts.verbose?)
|
180
|
+
def pull
|
181
|
+
pattern = ""
|
182
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
183
|
+
REPOSITORIES.matches(pattern).each do |url|
|
184
|
+
repo = Raykit::Git::Repository.new(url)
|
185
|
+
work = Raykit::Git::Directory.new(repo.get_dev_dir("work"))
|
186
|
+
if Dir.exist?(work.directory) && !work.directory == ".git"
|
187
|
+
Dir.chdir(work.directory) do
|
188
|
+
diff = `git diff`.strip
|
189
|
+
status = `git status`.strip
|
190
|
+
if diff.length.zero? && status.include?("nothing to commit")
|
191
|
+
cmd = Command.new("git pull")
|
192
|
+
cmd.summary if @opts.verbose?
|
192
193
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
rescue => error
|
203
|
-
issue = 'error occurred for pull of ' + url +' ' + error.to_s
|
204
|
-
if(@opts.quit?)
|
205
|
-
abort Rainbow(issue).blue.bright
|
206
|
-
else
|
207
|
-
puts Rainbow(issue).blue.bright
|
208
|
-
end
|
209
|
-
end
|
210
|
-
}
|
194
|
+
if cmd.exitstatus != 0
|
195
|
+
cmd.details
|
196
|
+
abort Rainbow(cmd.summary).blue.bright if @opts.quit?
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
211
200
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
REPOSITORIES.import(pattern)
|
219
|
-
new_count=REPOSITORIES.length-count
|
220
|
-
puts "imported #{new_count} git repositories"
|
201
|
+
rescue StandardError => e
|
202
|
+
issue = "error occurred for pull of #{url} #{e}"
|
203
|
+
if @opts.quit?
|
204
|
+
abort Rainbow(issue).blue.bright
|
205
|
+
else
|
206
|
+
puts Rainbow(issue).blue.bright
|
221
207
|
end
|
208
|
+
end
|
209
|
+
end
|
222
210
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
FileUtils.rm_rf(work.directory,secure:true)
|
233
|
-
rescue
|
234
|
-
puts 'error removing ' + work.directory
|
235
|
-
end
|
236
|
-
end
|
237
|
-
}
|
238
|
-
end
|
211
|
+
def import
|
212
|
+
pattern = ""
|
213
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
214
|
+
puts "scanning..."
|
215
|
+
count = REPOSITORIES.length
|
216
|
+
REPOSITORIES.import(pattern)
|
217
|
+
new_count = REPOSITORIES.length - count
|
218
|
+
puts "imported #{new_count} git repositories"
|
219
|
+
end
|
239
220
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
# Raykit::Version::sync_file_versions(source,dest)
|
248
|
-
# version = Raykit::Version::detect(source,false)
|
249
|
-
# puts "version #{version} detected in #{source}, updating #{dest} to match."
|
250
|
-
#end
|
221
|
+
def clean
|
222
|
+
pattern = ""
|
223
|
+
pattern = @opts.arguments[1] if @opts.arguments.length > 1
|
224
|
+
REPOSITORIES.matches(pattern).each do |url|
|
225
|
+
repo = Raykit::Git::Repository.new(url)
|
226
|
+
work = Raykit::Git::Directory.new(repo.get_dev_dir("work"))
|
227
|
+
next unless Dir.exist?(work.directory)
|
251
228
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
source = @opts.arguments[1]
|
258
|
-
dest = @opts.arguments[2]
|
259
|
-
FileUtils.cp(source,dest)
|
260
|
-
puts "copied #{source} to #{dest}"
|
229
|
+
puts "removing #{work.directory}"
|
230
|
+
begin
|
231
|
+
FileUtils.rm_rf(work.directory, secure: true)
|
232
|
+
rescue StandardError
|
233
|
+
puts "error removing #{work.directory}"
|
261
234
|
end
|
235
|
+
end
|
236
|
+
end
|
262
237
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
238
|
+
# def sync_version
|
239
|
+
# if(@opts.arguments.length < 3)
|
240
|
+
# puts 'source and destination arguments are required for sync_version'
|
241
|
+
# return 1
|
242
|
+
# end
|
243
|
+
# source = @opts.arguments[1]
|
244
|
+
# dest = @opts.arguments[2]
|
245
|
+
# Raykit::Version::sync_file_versions(source,dest)
|
246
|
+
# version = Raykit::Version::detect(source,false)
|
247
|
+
# puts "version #{version} detected in #{source}, updating #{dest} to match."
|
248
|
+
# end
|
249
|
+
|
250
|
+
def copy
|
251
|
+
if @opts.arguments.length < 3
|
252
|
+
puts "source and destination arguments are required for copy"
|
253
|
+
return 1
|
254
|
+
end
|
255
|
+
source = @opts.arguments[1]
|
256
|
+
dest = @opts.arguments[2]
|
257
|
+
FileUtils.cp(source, dest)
|
258
|
+
puts "copied #{source} to #{dest}"
|
259
|
+
end
|
285
260
|
|
286
|
-
|
261
|
+
def rake(hash)
|
262
|
+
REPOSITORIES.each do |remote|
|
263
|
+
next unless remote.include?(hash[:pattern])
|
264
|
+
|
265
|
+
begin
|
266
|
+
puts "remote: #{remote}"
|
267
|
+
cmd = Raykit::Rake.run(remote, "master")
|
268
|
+
elapsed_str = Timer.get_elapsed_str(cmd.elapsed)
|
269
|
+
if cmd.exitstatus.zero?
|
270
|
+
puts "#{elapsed_str} #{Rainbow(SECRETS.hide(cmd.command)).yellow.bright} (#{cmd.directory})"
|
271
|
+
else
|
272
|
+
puts "\r\n#{cmd.command}\r\n"
|
273
|
+
puts "\r\n#{cmd.output}\r\n"
|
274
|
+
puts "\r\n#{cmd.error}\r\n"
|
275
|
+
puts ""
|
276
|
+
puts "#{Rainbow(elapsed_str).red.bright} #{Rainbow(cmd.command).white}"
|
277
|
+
end
|
278
|
+
rescue StandardError
|
279
|
+
puts "rescued..."
|
280
|
+
end
|
281
|
+
end
|
287
282
|
end
|
283
|
+
end
|
288
284
|
end
|
289
285
|
|
290
|
-
#CONSOLE=Raykit::Console.new
|
286
|
+
# CONSOLE=Raykit::Console.new
|
data/lib/raykit/dir.rb
CHANGED
@@ -1,46 +1,49 @@
|
|
1
|
-
|
2
|
-
require_relative './environment.rb'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
File.read("#{dir}/#{relative_name}")
|
7
|
-
end
|
3
|
+
require "tmpdir"
|
4
|
+
require_relative "./environment"
|
8
5
|
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
class Dir
|
7
|
+
def self.get_text(dir, relative_name)
|
8
|
+
File.read("#{dir}/#{relative_name}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.set_text(dir, relative_name, text)
|
12
|
+
File.open("#{dir}/#{relative_name}", "w") { |f| f.write text }
|
13
|
+
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
15
|
+
def self.get_git_directories(dir)
|
16
|
+
git_dirs = []
|
17
|
+
Dir.chdir(dir) do
|
18
|
+
Dir.glob("**/.git/index") do |f|
|
19
|
+
git_dir = File.dirname(File.dirname(f))
|
20
|
+
git_dirs << git_dir
|
20
21
|
end
|
21
|
-
git_dirs
|
22
22
|
end
|
23
|
+
git_dirs
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
}
|
26
|
+
def self.get_git_urls(dir)
|
27
|
+
urls = Set.new
|
28
|
+
Dir.chdir(dir) do
|
29
|
+
get_git_directories(dir).each do |git_dir|
|
30
|
+
Dir.chdir(git_dir) do
|
31
|
+
url = `git config --get remote.origin.url`.strip
|
32
|
+
urls.add(url)
|
33
|
+
end
|
33
34
|
end
|
34
|
-
urls
|
35
35
|
end
|
36
|
+
urls
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
home_dir = Raykit::Environment.home_dir
|
43
|
-
return home_dir if Dir.exist?(home_dir)
|
44
|
-
Dir.tmpdir()
|
39
|
+
def self.get_data_dir
|
40
|
+
unless ENV["DATA_DIR"].nil?
|
41
|
+
data_dir = ENV["DATA_DIR"]
|
42
|
+
return data_dir if Dir.exist?(data_dir)
|
45
43
|
end
|
46
|
-
|
44
|
+
home_dir = Raykit::Environment.home_dir
|
45
|
+
return home_dir if Dir.exist?(home_dir)
|
46
|
+
|
47
|
+
Dir.tmpdir
|
48
|
+
end
|
49
|
+
end
|