cnvrg 1.6.36 → 1.6.38
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/lib/cnvrg/cli.rb +11 -7
- data/lib/cnvrg/datafiles.rb +204 -201
- data/lib/cnvrg/project.rb +8 -1
- data/lib/cnvrg/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e5953510af9633c925be99ac1463aef31667eed5f83f5b0c610672ab9fe375cb
|
|
4
|
+
data.tar.gz: 7bd8fce2d93a20ed695e4c202f2b29092de84bf90332385a3921844046a0c591
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b93cd899060800095895967dbe2b8f3391e2d77b6f29ea05cd6651de4d26de2ba24fdaedaa8dafad82a22e250d95abf7651d2b77afe2dcf68b883461774c965
|
|
7
|
+
data.tar.gz: a4dc324e6f58b628013bb00278a74233f6b2c6e4ffa260e9edf74ea2557ca144907449078defb1abdb22ffe411fdde196b2e029bd66e67233140cf54d6caf67d
|
data/lib/cnvrg/cli.rb
CHANGED
|
@@ -2211,6 +2211,7 @@ module Cnvrg
|
|
|
2211
2211
|
method_option :return_id, :type => :boolean, :aliases => ["-r", "--return_id"], :default => false
|
|
2212
2212
|
method_option :files, :type => :string, :aliases => ["--files"], :default => nil
|
|
2213
2213
|
method_option :output_dir, :type => :string, :aliases => ["--output_dir"], :default => nil
|
|
2214
|
+
method_option :git_diff, :type => :boolean, :aliases => ["--git_diff"], :default => false
|
|
2214
2215
|
method_option :job_slug, :type => :string, :aliases => ["--job"], :default => nil, :hide=>true
|
|
2215
2216
|
method_option :job_type, :type => :string, :aliases => [ "--job_type"], :default => nil, :hide=>true
|
|
2216
2217
|
|
|
@@ -2235,19 +2236,21 @@ module Cnvrg
|
|
|
2235
2236
|
spec_files_to_upload = spec_files_to_upload.split(",")
|
|
2236
2237
|
end
|
|
2237
2238
|
if @project.is_git
|
|
2239
|
+
list = []
|
|
2238
2240
|
git_output_dir = options["output_dir"] || output_dir
|
|
2239
2241
|
if git_output_dir.present?
|
|
2240
2242
|
if git_output_dir.ends_with? "/"
|
|
2241
2243
|
git_output_dir = git_output_dir[0..-2]
|
|
2242
2244
|
end
|
|
2243
2245
|
list = @project.generate_output_dir(git_output_dir)
|
|
2244
|
-
spec_files_to_upload = list
|
|
2245
|
-
if spec_files_to_upload.blank?
|
|
2246
|
-
log_message("#{check} Project is up to date", Thor::Shell::Color::GREEN, (((options["sync"] or sync) and !direct) ? false : true))
|
|
2247
|
-
return true
|
|
2248
|
-
end
|
|
2249
|
-
force = true
|
|
2250
2246
|
end
|
|
2247
|
+
list += @project.generate_git_diff if options["git_diff"]
|
|
2248
|
+
spec_files_to_upload = list
|
|
2249
|
+
if spec_files_to_upload.blank?
|
|
2250
|
+
log_message("#{check} Project is up to date", Thor::Shell::Color::GREEN, (((options["sync"] or sync) and !direct) ? false : true))
|
|
2251
|
+
return true
|
|
2252
|
+
end
|
|
2253
|
+
force = true
|
|
2251
2254
|
end
|
|
2252
2255
|
|
|
2253
2256
|
if ignore.nil? or ignore.empty?
|
|
@@ -2892,6 +2895,7 @@ module Cnvrg
|
|
|
2892
2895
|
method_option :job_type, :type => :string, :aliases => ["-jt", "--job_type"], :default => nil
|
|
2893
2896
|
method_option :files, :type => :string, :aliases => ["--files"], :default => nil
|
|
2894
2897
|
method_option :output_dir, :type => :string, :aliases => ["--output_dir"], :default => nil
|
|
2898
|
+
method_option :git_diff, :type => :boolean, :aliases => ["--git_diff"], :default => false
|
|
2895
2899
|
def sync(direct = true)
|
|
2896
2900
|
verify_logged_in(true) if direct
|
|
2897
2901
|
@project = Project.new(get_project_home)
|
|
@@ -2912,7 +2916,7 @@ module Cnvrg
|
|
|
2912
2916
|
end
|
|
2913
2917
|
invoke :upload, [false, true, direct, "",in_exp,options[:force], options["output_dir"],job_type, job_slug ], :new_branch => options["new_branch"], :verbose => options["verbose"], :sync => true,
|
|
2914
2918
|
:ignore => options[:ignore], :force => options[:force], :message => options[:message], :deploy => options["deploy"], :return_id => options["return_id"],
|
|
2915
|
-
:files => options["files"], :output_dir => options["output_dir"], :job_slug => job_slug, :job_type => job_type
|
|
2919
|
+
:files => options["files"], :output_dir => options["output_dir"], :job_slug => job_slug, :job_type => job_type, :git_diff=> options["git_diff"]
|
|
2916
2920
|
end
|
|
2917
2921
|
|
|
2918
2922
|
desc 'run cmd', 'Runs an experiment'
|
data/lib/cnvrg/datafiles.rb
CHANGED
|
@@ -9,8 +9,8 @@ module Cnvrg
|
|
|
9
9
|
class Datafiles
|
|
10
10
|
ParallelThreads ||= Cnvrg::Helpers.parallel_threads
|
|
11
11
|
|
|
12
|
-
LARGE_FILE=1024*1024*5
|
|
13
|
-
MULTIPART_SPLIT=10000000
|
|
12
|
+
LARGE_FILE = 1024 * 1024 * 5
|
|
13
|
+
MULTIPART_SPLIT = 10000000
|
|
14
14
|
|
|
15
15
|
attr_reader :base_resource
|
|
16
16
|
|
|
@@ -33,7 +33,7 @@ module Cnvrg
|
|
|
33
33
|
|
|
34
34
|
def check_file_sha1(filename, org_sha1, tag: 'conflict')
|
|
35
35
|
file_loc = "#{Dir.pwd}/#{filename}"
|
|
36
|
-
sha1 =
|
|
36
|
+
sha1 = OpenSSL::Digest::SHA1.file(file_loc).hexdigest
|
|
37
37
|
return 0 if sha1 == org_sha1
|
|
38
38
|
FileUtils.cp(file_loc, "#{file_loc}.#{tag}")
|
|
39
39
|
return 1
|
|
@@ -52,7 +52,7 @@ module Cnvrg
|
|
|
52
52
|
end
|
|
53
53
|
raise SignalException.new(1, "Cant find file #{file}") unless File.exists? "#{Dir.pwd}/#{file}"
|
|
54
54
|
end
|
|
55
|
-
paths.map{|p| p.gsub(/^\.\//, '')}
|
|
55
|
+
paths.map { |p| p.gsub(/^\.\//, '') }
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def check_files_sha1(files, resolver, tag)
|
|
@@ -83,11 +83,11 @@ module Cnvrg
|
|
|
83
83
|
prefix = @dataset.get_dataset["bucket_prefix"]
|
|
84
84
|
batch_size = 10000
|
|
85
85
|
pbar = ProgressBar.create(:title => "Download Progress",
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
:progress_mark => '=',
|
|
87
|
+
:format => "%b%i| %c Files downloaded",
|
|
88
|
+
:starting_at => 0,
|
|
89
|
+
:total => nil,
|
|
90
|
+
:autofinish => true)
|
|
91
91
|
parallel_options = {
|
|
92
92
|
in_threads: ParallelThreads,
|
|
93
93
|
in_processes: Cnvrg::CLI::ParallelProcesses,
|
|
@@ -116,7 +116,7 @@ module Cnvrg
|
|
|
116
116
|
if response.present?
|
|
117
117
|
msg = response['result']
|
|
118
118
|
else
|
|
119
|
-
msg =
|
|
119
|
+
msg = "Cant save changes in the dataset"
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
Cnvrg::Result.new(Cnvrg::CLI.is_response_success(response, false), msg)
|
|
@@ -171,9 +171,9 @@ module Cnvrg
|
|
|
171
171
|
end
|
|
172
172
|
@temp_upload_progressbar.progress += 1 if @temp_upload_progressbar.present?
|
|
173
173
|
end
|
|
174
|
-
blob_ids = files.values.map {|f| f['bv_id']}
|
|
174
|
+
blob_ids = files.values.map { |f| f['bv_id'] }
|
|
175
175
|
if blob_ids.present?
|
|
176
|
-
dirs = tree.keys.select {|k| tree[k].nil?} || []
|
|
176
|
+
dirs = tree.keys.select { |k| tree[k].nil? } || []
|
|
177
177
|
Cnvrg::Logger.info("Sending Upload files save")
|
|
178
178
|
upload_resp = Cnvrg::API.request(@base_resource + "upload_files_save", "POST", {commit: commit_sha1, blob_ids: blob_ids, dirs: dirs})
|
|
179
179
|
unless Cnvrg::CLI.is_response_success(upload_resp, false)
|
|
@@ -208,12 +208,12 @@ module Cnvrg
|
|
|
208
208
|
file_size = File.size(absolute_path).to_f
|
|
209
209
|
mime_type = MimeMagic.by_path(absolute_path)
|
|
210
210
|
content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
|
|
211
|
-
sha1 =
|
|
211
|
+
sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
|
|
212
212
|
if (absolute_path.include? "_tags.yml" or absolute_path.include? "_tags.yaml")
|
|
213
213
|
is_valid = false
|
|
214
214
|
begin
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
content = open(absolute_path).read()
|
|
216
|
+
hash = YAML.load(open(absolute_path).read())
|
|
217
217
|
# if level 1 keys count is 1
|
|
218
218
|
if hash.keys.count == 1
|
|
219
219
|
if hash["tags"].present?
|
|
@@ -221,7 +221,7 @@ module Cnvrg
|
|
|
221
221
|
elsif hash[hash.keys.first].class != Hash
|
|
222
222
|
is_valid = true
|
|
223
223
|
end
|
|
224
|
-
|
|
224
|
+
# if level 1 keys count is greater than 1
|
|
225
225
|
elsif hash.keys.count > 1
|
|
226
226
|
if hash["tags"].present? and hash["tags"].class == Hash
|
|
227
227
|
is_valid = false
|
|
@@ -255,6 +255,7 @@ module Cnvrg
|
|
|
255
255
|
return s3_res
|
|
256
256
|
end
|
|
257
257
|
end
|
|
258
|
+
|
|
258
259
|
def upload_tar_file(absolute_path, relative_path, commit_sha1)
|
|
259
260
|
begin
|
|
260
261
|
file_name = File.basename relative_path
|
|
@@ -262,24 +263,24 @@ module Cnvrg
|
|
|
262
263
|
mime_type = MimeMagic.by_path(absolute_path)
|
|
263
264
|
content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
|
|
264
265
|
begin
|
|
265
|
-
chunked_bytes = [100, (file_size*0.01)].min
|
|
266
|
+
chunked_bytes = [100, (file_size * 0.01)].min
|
|
266
267
|
total_yanked = ""
|
|
267
268
|
open(absolute_path, "rb") do |f|
|
|
268
269
|
total_yanked = f.read(chunked_bytes)
|
|
269
270
|
end
|
|
270
271
|
if !total_yanked.empty?
|
|
271
|
-
sha1 =
|
|
272
|
+
sha1 = OpenSSL::Digest::SHA1.hexdigest(total_yanked)
|
|
272
273
|
else
|
|
273
|
-
sha1 =
|
|
274
|
+
sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
|
|
274
275
|
end
|
|
275
276
|
rescue
|
|
276
|
-
sha1 =
|
|
277
|
+
sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
|
|
277
278
|
end
|
|
278
279
|
|
|
279
280
|
upload_resp = Cnvrg::API.request(@base_resource + "upload_tar_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
|
|
280
281
|
commit_sha1: commit_sha1, file_name: file_name,
|
|
281
282
|
file_size: file_size, file_content_type: content_type, sha1: sha1,
|
|
282
|
-
|
|
283
|
+
new_version: true})
|
|
283
284
|
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
|
284
285
|
path = upload_resp["result"]["path"]
|
|
285
286
|
s3_res = upload_large_files_s3(upload_resp, absolute_path)
|
|
@@ -315,14 +316,15 @@ module Cnvrg
|
|
|
315
316
|
return false
|
|
316
317
|
|
|
317
318
|
end
|
|
318
|
-
|
|
319
|
+
|
|
320
|
+
def upload_data_log_file(absolute_path, relative_path, data_commit_sha)
|
|
319
321
|
file_name = File.basename relative_path
|
|
320
322
|
file_size = File.size(absolute_path).to_f
|
|
321
323
|
content_type = "text/x-log"
|
|
322
324
|
upload_resp = Cnvrg::API.request("/users/#{@owner}/" + "upload_data_log", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
data_commit_sha1:data_commit_sha})
|
|
325
|
+
file_name: file_name, log_date: Time.now,
|
|
326
|
+
file_size: file_size, file_content_type: content_type,
|
|
327
|
+
data_commit_sha1: data_commit_sha})
|
|
326
328
|
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
|
327
329
|
path = upload_resp["result"]["path"]
|
|
328
330
|
s3_res = upload_small_files_s3(path, absolute_path, "text/plain")
|
|
@@ -413,15 +415,15 @@ module Cnvrg
|
|
|
413
415
|
|
|
414
416
|
end
|
|
415
417
|
|
|
416
|
-
def upload_cnvrg_image(absolute_path, image_name,secret)
|
|
418
|
+
def upload_cnvrg_image(absolute_path, image_name, secret)
|
|
417
419
|
file_name = File.basename relative_path
|
|
418
420
|
file_size = File.size(absolute_path).to_f
|
|
419
421
|
mime_type = MimeMagic.by_path(absolute_path)
|
|
420
422
|
content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
|
|
421
423
|
upload_resp = Cnvrg::API.request("images/#{image_name}/upload_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: absolute_path,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
424
|
+
file_name: file_name,
|
|
425
|
+
file_size: file_size, file_content_type: content_type,
|
|
426
|
+
secret: secret})
|
|
425
427
|
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
|
426
428
|
path = upload_resp["result"]["path"]
|
|
427
429
|
s3_res = upload_large_files_s3(upload_resp, absolute_path)
|
|
@@ -465,7 +467,7 @@ module Cnvrg
|
|
|
465
467
|
sts_path = upload_resp["result"]["path_sts"]
|
|
466
468
|
|
|
467
469
|
retries = 0
|
|
468
|
-
success= false
|
|
470
|
+
success = false
|
|
469
471
|
while !success and retries < 20
|
|
470
472
|
begin
|
|
471
473
|
if !Helpers.is_verify_ssl
|
|
@@ -475,7 +477,7 @@ module Cnvrg
|
|
|
475
477
|
end
|
|
476
478
|
success = true
|
|
477
479
|
rescue => e
|
|
478
|
-
retries +=1
|
|
480
|
+
retries += 1
|
|
479
481
|
sleep(5)
|
|
480
482
|
|
|
481
483
|
end
|
|
@@ -487,33 +489,33 @@ module Cnvrg
|
|
|
487
489
|
key = split[0]
|
|
488
490
|
iv = split[1]
|
|
489
491
|
is_s3 = upload_resp["result"]["is_s3"]
|
|
490
|
-
access =
|
|
492
|
+
access = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["sts_a"])
|
|
491
493
|
|
|
492
|
-
secret =
|
|
494
|
+
secret = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["sts_s"])
|
|
493
495
|
|
|
494
|
-
session =
|
|
495
|
-
region =
|
|
496
|
+
session = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["sts_st"])
|
|
497
|
+
region = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["region"])
|
|
496
498
|
|
|
497
|
-
bucket =
|
|
498
|
-
server_side_encryption =upload_resp["result"]["server_side_encryption"]
|
|
499
|
+
bucket = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["bucket"])
|
|
500
|
+
server_side_encryption = upload_resp["result"]["server_side_encryption"]
|
|
499
501
|
use_accelerate_endpoint = false
|
|
500
502
|
if is_s3 or is_s3.nil?
|
|
501
503
|
|
|
502
|
-
use_accelerate_endpoint =true
|
|
504
|
+
use_accelerate_endpoint = true
|
|
503
505
|
client = Aws::S3::Client.new(
|
|
504
|
-
:access_key_id =>access,
|
|
506
|
+
:access_key_id => access,
|
|
505
507
|
:secret_access_key => secret,
|
|
506
508
|
:session_token => session,
|
|
507
509
|
:region => region,
|
|
508
510
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
509
511
|
else
|
|
510
|
-
endpoint = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["endpoint"])
|
|
512
|
+
endpoint = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["endpoint"])
|
|
511
513
|
use_accelerate_endpoint = false
|
|
512
514
|
client = Aws::S3::Client.new(
|
|
513
|
-
:access_key_id =>access,
|
|
515
|
+
:access_key_id => access,
|
|
514
516
|
:secret_access_key => secret,
|
|
515
517
|
:region => region,
|
|
516
|
-
:endpoint=> endpoint
|
|
518
|
+
:endpoint => endpoint, :force_path_style => true, :ssl_verify_peer => false,
|
|
517
519
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
518
520
|
end
|
|
519
521
|
|
|
@@ -525,13 +527,11 @@ module Cnvrg
|
|
|
525
527
|
end
|
|
526
528
|
|
|
527
529
|
|
|
528
|
-
|
|
529
|
-
|
|
530
530
|
s3 = Aws::S3::Resource.new(client: client)
|
|
531
531
|
|
|
532
532
|
resp = s3.bucket(bucket).
|
|
533
|
-
object(upload_resp["result"]["path"]+"/"+File.basename(file_path)).
|
|
534
|
-
upload_file(file_path,options)
|
|
533
|
+
object(upload_resp["result"]["path"] + "/" + File.basename(file_path)).
|
|
534
|
+
upload_file(file_path, options)
|
|
535
535
|
|
|
536
536
|
|
|
537
537
|
return resp
|
|
@@ -588,6 +588,7 @@ module Cnvrg
|
|
|
588
588
|
response = Cnvrg::API.request(@base_resource + "create_dir", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
|
|
589
589
|
return Cnvrg::CLI.is_response_success(response, false)
|
|
590
590
|
end
|
|
591
|
+
|
|
591
592
|
def download_list_files_in_query(response, dataset_home)
|
|
592
593
|
sts_path = response["path_sts"]
|
|
593
594
|
if !Helpers.is_verify_ssl
|
|
@@ -599,29 +600,29 @@ module Cnvrg
|
|
|
599
600
|
key = split[0]
|
|
600
601
|
iv = split[1]
|
|
601
602
|
|
|
602
|
-
access =
|
|
603
|
+
access = Cnvrg::Helpers.decrypt(key, iv, response["sts_a"])
|
|
603
604
|
|
|
604
|
-
secret =
|
|
605
|
+
secret = Cnvrg::Helpers.decrypt(key, iv, response["sts_s"])
|
|
605
606
|
|
|
606
|
-
session =
|
|
607
|
-
region =
|
|
607
|
+
session = Cnvrg::Helpers.decrypt(key, iv, response["sts_st"])
|
|
608
|
+
region = Cnvrg::Helpers.decrypt(key, iv, response["region"])
|
|
608
609
|
|
|
609
|
-
bucket =
|
|
610
|
+
bucket = Cnvrg::Helpers.decrypt(key, iv, response["bucket"])
|
|
610
611
|
is_s3 = response["is_s3"]
|
|
611
612
|
if is_s3 or is_s3.nil?
|
|
612
613
|
client = Aws::S3::Client.new(
|
|
613
|
-
:access_key_id =>access,
|
|
614
|
+
:access_key_id => access,
|
|
614
615
|
:secret_access_key => secret,
|
|
615
616
|
:session_token => session,
|
|
616
617
|
:region => region,
|
|
617
618
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
618
619
|
else
|
|
619
|
-
endpoint = Cnvrg::Helpers.decrypt(key,iv, response["endpoint_url"])
|
|
620
|
+
endpoint = Cnvrg::Helpers.decrypt(key, iv, response["endpoint_url"])
|
|
620
621
|
client = Aws::S3::Client.new(
|
|
621
|
-
:access_key_id =>access,
|
|
622
|
+
:access_key_id => access,
|
|
622
623
|
:secret_access_key => secret,
|
|
623
624
|
:region => region,
|
|
624
|
-
:endpoint=> endpoint
|
|
625
|
+
:endpoint => endpoint, :force_path_style => true, :ssl_verify_peer => false,
|
|
625
626
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
626
627
|
end
|
|
627
628
|
list_files = response["files"]
|
|
@@ -638,18 +639,18 @@ module Cnvrg
|
|
|
638
639
|
}
|
|
639
640
|
download_count = 0
|
|
640
641
|
Parallel.map((list_files), parallel_options) do |f|
|
|
641
|
-
file_key =
|
|
642
|
+
file_key = Cnvrg::Helpers.decrypt(key, iv, f["path"])
|
|
642
643
|
begin
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
644
|
+
begin
|
|
645
|
+
dir = File.dirname f["fullpath"]
|
|
646
|
+
FileUtils.mkdir_p(dataset_home + "/" + dir) unless File.exist? (dataset_home + "/" + dir)
|
|
647
|
+
end
|
|
647
648
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
649
|
+
File.open(dataset_home + "/" + f["fullpath"], 'w+') do |file|
|
|
650
|
+
resp = client.get_object({bucket: bucket,
|
|
651
|
+
key: file_key}, target: file)
|
|
652
|
+
end
|
|
653
|
+
download_count += 1
|
|
653
654
|
rescue
|
|
654
655
|
end
|
|
655
656
|
|
|
@@ -661,97 +662,95 @@ module Cnvrg
|
|
|
661
662
|
end
|
|
662
663
|
|
|
663
664
|
|
|
664
|
-
|
|
665
|
-
|
|
666
665
|
end
|
|
667
666
|
|
|
668
667
|
|
|
669
|
-
def download_file_s3(absolute_path, relative_path, project_home, conflict=false, commit_sha1=nil, as_link=false)
|
|
668
|
+
def download_file_s3(absolute_path, relative_path, project_home, conflict = false, commit_sha1 = nil, as_link = false)
|
|
670
669
|
begin
|
|
671
|
-
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1
|
|
670
|
+
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1, new_version: true, as_link: as_link})
|
|
672
671
|
Cnvrg::CLI.is_response_success(res, false)
|
|
673
|
-
|
|
674
|
-
|
|
672
|
+
if res["result"]
|
|
673
|
+
file_url = res["result"]["file_url"]
|
|
675
674
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
absolute_path += ".conflict" if conflict
|
|
697
|
-
sts_path = download_resp["result"]["path_sts"]
|
|
698
|
-
retries = 0
|
|
699
|
-
success= false
|
|
700
|
-
while !success and retries < 20
|
|
701
|
-
begin
|
|
702
|
-
if !Helpers.is_verify_ssl
|
|
703
|
-
body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
|
|
704
|
-
else
|
|
705
|
-
body = open(sts_path).read
|
|
706
|
-
end
|
|
707
|
-
success = true
|
|
708
|
-
rescue => e
|
|
709
|
-
retries +=1
|
|
710
|
-
sleep(5)
|
|
675
|
+
if as_link
|
|
676
|
+
return res["result"]
|
|
677
|
+
end
|
|
678
|
+
# begin
|
|
679
|
+
# if !Helpers.is_verify_ssl
|
|
680
|
+
# tempfile = Down.download(file_url,open_timeout: 60,ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE )
|
|
681
|
+
#
|
|
682
|
+
# else
|
|
683
|
+
# tempfile = Down.download(file_url,open_timeout: 60)
|
|
684
|
+
#
|
|
685
|
+
# end
|
|
686
|
+
#
|
|
687
|
+
# FileUtils.move(tempfile.path, project_home+"/"+ absolute_path)
|
|
688
|
+
# return true
|
|
689
|
+
# rescue
|
|
690
|
+
#
|
|
691
|
+
# end
|
|
692
|
+
download_resp = res
|
|
693
|
+
filename = download_resp["result"]["filename"]
|
|
711
694
|
|
|
695
|
+
absolute_path += ".conflict" if conflict
|
|
696
|
+
sts_path = download_resp["result"]["path_sts"]
|
|
697
|
+
retries = 0
|
|
698
|
+
success = false
|
|
699
|
+
while !success and retries < 20
|
|
700
|
+
begin
|
|
701
|
+
if !Helpers.is_verify_ssl
|
|
702
|
+
body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
|
|
703
|
+
else
|
|
704
|
+
body = open(sts_path).read
|
|
712
705
|
end
|
|
706
|
+
success = true
|
|
707
|
+
rescue => e
|
|
708
|
+
retries += 1
|
|
709
|
+
sleep(5)
|
|
710
|
+
|
|
713
711
|
end
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
712
|
+
end
|
|
713
|
+
if !success
|
|
714
|
+
return false
|
|
715
|
+
end
|
|
716
|
+
split = body.split("\n")
|
|
717
|
+
key = split[0]
|
|
718
|
+
iv = split[1]
|
|
720
719
|
|
|
721
|
-
|
|
720
|
+
access = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_a"])
|
|
722
721
|
|
|
723
|
-
|
|
722
|
+
secret = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_s"])
|
|
724
723
|
|
|
725
|
-
|
|
726
|
-
|
|
724
|
+
session = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_st"])
|
|
725
|
+
region = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["region"])
|
|
727
726
|
|
|
728
|
-
|
|
729
|
-
|
|
727
|
+
bucket = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["bucket"])
|
|
728
|
+
file_key = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["key"])
|
|
730
729
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
730
|
+
is_s3 = download_resp["result"]["is_s3"]
|
|
731
|
+
if is_s3 or is_s3.nil?
|
|
732
|
+
client = Aws::S3::Client.new(
|
|
733
|
+
:access_key_id => access,
|
|
734
|
+
:secret_access_key => secret,
|
|
735
|
+
:session_token => session,
|
|
736
|
+
:region => region,
|
|
737
|
+
:http_open_timeout => 60, :retry_limit => 20)
|
|
738
|
+
else
|
|
739
|
+
endpoint = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["endpoint_url"])
|
|
740
|
+
client = Aws::S3::Client.new(
|
|
741
|
+
:access_key_id => access,
|
|
742
|
+
:secret_access_key => secret,
|
|
743
|
+
:region => region,
|
|
744
|
+
:endpoint => endpoint, :force_path_style => true, :ssl_verify_peer => false,
|
|
745
|
+
:http_open_timeout => 60, :retry_limit => 20)
|
|
746
|
+
end
|
|
748
747
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
end
|
|
753
|
-
return true
|
|
748
|
+
File.open(project_home + "/" + absolute_path, 'w+') do |file|
|
|
749
|
+
resp = client.get_object({bucket: bucket,
|
|
750
|
+
key: file_key}, target: file)
|
|
754
751
|
end
|
|
752
|
+
return true
|
|
753
|
+
end
|
|
755
754
|
|
|
756
755
|
rescue => e
|
|
757
756
|
return false
|
|
@@ -761,7 +760,7 @@ module Cnvrg
|
|
|
761
760
|
|
|
762
761
|
def download_data_file(commit_sha1, dataset_home)
|
|
763
762
|
begin
|
|
764
|
-
res = Cnvrg::API.request(@base_resource + "download_data_file", 'POST', {commit_sha1: commit_sha1,new_version:true})
|
|
763
|
+
res = Cnvrg::API.request(@base_resource + "download_data_file", 'POST', {commit_sha1: commit_sha1, new_version: true})
|
|
765
764
|
Cnvrg::CLI.is_response_success(res, false)
|
|
766
765
|
if res["result"]
|
|
767
766
|
download_resp = res
|
|
@@ -778,38 +777,38 @@ module Cnvrg
|
|
|
778
777
|
iv = split[1]
|
|
779
778
|
|
|
780
779
|
|
|
781
|
-
access =
|
|
780
|
+
access = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_a"])
|
|
782
781
|
|
|
783
|
-
secret =
|
|
782
|
+
secret = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_s"])
|
|
784
783
|
|
|
785
|
-
session =
|
|
786
|
-
region =
|
|
784
|
+
session = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_st"])
|
|
785
|
+
region = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["region"])
|
|
787
786
|
|
|
788
|
-
bucket =
|
|
789
|
-
file_key =
|
|
787
|
+
bucket = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["bucket"])
|
|
788
|
+
file_key = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["key"])
|
|
790
789
|
|
|
791
790
|
is_s3 = download_resp["result"]["is_s3"]
|
|
792
791
|
if is_s3 or is_s3.nil?
|
|
793
792
|
client = Aws::S3::Client.new(
|
|
794
|
-
:access_key_id =>access,
|
|
793
|
+
:access_key_id => access,
|
|
795
794
|
:secret_access_key => secret,
|
|
796
795
|
:session_token => session,
|
|
797
796
|
:region => region,
|
|
798
797
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
799
798
|
else
|
|
800
|
-
endpoint = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["endpoint_url"])
|
|
799
|
+
endpoint = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["endpoint_url"])
|
|
801
800
|
client = Aws::S3::Client.new(
|
|
802
|
-
:access_key_id =>access,
|
|
801
|
+
:access_key_id => access,
|
|
803
802
|
:secret_access_key => secret,
|
|
804
803
|
:region => region,
|
|
805
|
-
:endpoint=> endpoint
|
|
804
|
+
:endpoint => endpoint, :force_path_style => true, :ssl_verify_peer => false,
|
|
806
805
|
:http_open_timeout => 60, :retry_limit => 20)
|
|
807
806
|
end
|
|
808
807
|
|
|
809
808
|
|
|
810
|
-
File.open(dataset_home+"/"+filename, 'w+') do |file|
|
|
809
|
+
File.open(dataset_home + "/" + filename, 'w+') do |file|
|
|
811
810
|
resp = client.get_object({bucket: bucket,
|
|
812
|
-
|
|
811
|
+
key: file_key}, target: file)
|
|
813
812
|
end
|
|
814
813
|
return filename
|
|
815
814
|
end
|
|
@@ -820,7 +819,7 @@ module Cnvrg
|
|
|
820
819
|
end
|
|
821
820
|
end
|
|
822
821
|
|
|
823
|
-
def download_file(absolute_path, relative_path, project_home, conflict=false)
|
|
822
|
+
def download_file(absolute_path, relative_path, project_home, conflict = false)
|
|
824
823
|
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path})
|
|
825
824
|
Cnvrg::CLI.is_response_success(res, false)
|
|
826
825
|
if res["result"]
|
|
@@ -858,7 +857,7 @@ module Cnvrg
|
|
|
858
857
|
puts FileUtils.rmtree("#{absolute_path}")
|
|
859
858
|
end
|
|
860
859
|
|
|
861
|
-
def revoke_download_file(absolute_path, filename, conflict=false)
|
|
860
|
+
def revoke_download_file(absolute_path, filename, conflict = false)
|
|
862
861
|
begin
|
|
863
862
|
file_location = absolute_path.gsub(/#{filename}\/?$/, "")
|
|
864
863
|
|
|
@@ -869,6 +868,7 @@ module Cnvrg
|
|
|
869
868
|
return false
|
|
870
869
|
end
|
|
871
870
|
end
|
|
871
|
+
|
|
872
872
|
def revoke_download(tar_files, extracted_files)
|
|
873
873
|
begin
|
|
874
874
|
|
|
@@ -882,32 +882,35 @@ module Cnvrg
|
|
|
882
882
|
return true
|
|
883
883
|
|
|
884
884
|
end
|
|
885
|
+
|
|
885
886
|
def delete_commit(commit_sha1)
|
|
886
887
|
response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'DELETE')
|
|
887
888
|
Cnvrg::CLI.is_response_success(response, true)
|
|
888
889
|
return response
|
|
889
890
|
end
|
|
891
|
+
|
|
890
892
|
def get_commit(commit_sha1)
|
|
891
893
|
response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'GET')
|
|
892
894
|
Cnvrg::CLI.is_response_success(response, true)
|
|
893
895
|
return response
|
|
894
896
|
end
|
|
895
897
|
|
|
896
|
-
def start_commit(new_branch,force=false,delete_commit=nil, chunks: 0, dataset: @dataset, message:nil)
|
|
898
|
+
def start_commit(new_branch, force = false, delete_commit = nil, chunks: 0, dataset: @dataset, message: nil)
|
|
897
899
|
begin
|
|
898
900
|
#if we are pushing with force or to branch we dont need to send current/next commit cause we want to
|
|
899
901
|
# create a new commit.
|
|
900
902
|
idx = (force || new_branch) ? {} : dataset.get_idx
|
|
901
903
|
commit = idx[:commit]
|
|
902
904
|
next_commit = idx[:next_commit]
|
|
903
|
-
response = Cnvrg::API.request("#{base_resource}/commit/start", 'POST', {dataset_slug: @dataset_slug, new_branch: new_branch,force:force,
|
|
904
|
-
username: @owner,current_commit: commit, next_commit: next_commit, total_chunks: chunks, message: message})
|
|
905
|
+
response = Cnvrg::API.request("#{base_resource}/commit/start", 'POST', {dataset_slug: @dataset_slug, new_branch: new_branch, force: force,
|
|
906
|
+
username: @owner, current_commit: commit, next_commit: next_commit, total_chunks: chunks, message: message})
|
|
905
907
|
Cnvrg::CLI.is_response_success(response, true)
|
|
906
908
|
return response
|
|
907
909
|
rescue => e
|
|
908
910
|
return false
|
|
909
911
|
end
|
|
910
912
|
end
|
|
913
|
+
|
|
911
914
|
def last_valid_commit()
|
|
912
915
|
begin
|
|
913
916
|
#if we are pushing with force or to branch we dont need to send current/next commit cause we want to
|
|
@@ -920,9 +923,9 @@ module Cnvrg
|
|
|
920
923
|
end
|
|
921
924
|
end
|
|
922
925
|
|
|
923
|
-
def end_commit(commit_sha1,force, success: true, uploaded_files: 0
|
|
926
|
+
def end_commit(commit_sha1, force, success: true, uploaded_files: 0)
|
|
924
927
|
begin
|
|
925
|
-
response = Cnvrg::API.request("#{base_resource}/commit/end", 'POST', {commit_sha1: commit_sha1,force:force, success: success, uploaded_files: uploaded_files})
|
|
928
|
+
response = Cnvrg::API.request("#{base_resource}/commit/end", 'POST', {commit_sha1: commit_sha1, force: force, success: success, uploaded_files: uploaded_files})
|
|
926
929
|
Cnvrg::CLI.is_response_success(response, true)
|
|
927
930
|
return response
|
|
928
931
|
rescue => e
|
|
@@ -948,13 +951,13 @@ module Cnvrg
|
|
|
948
951
|
end
|
|
949
952
|
|
|
950
953
|
def get_trees(commit: "latest")
|
|
951
|
-
response = Cnvrg::API.request("#{@base_resource}/clone_trees", 'POST',{commit: commit})
|
|
954
|
+
response = Cnvrg::API.request("#{@base_resource}/clone_trees", 'POST', {commit: commit})
|
|
952
955
|
return nil unless Cnvrg::CLI.is_response_success(response, false)
|
|
953
956
|
response['result']['files']
|
|
954
957
|
end
|
|
955
958
|
|
|
956
959
|
def get_clone_chunk(latest_id: nil, chunk_size: 1000, commit: 'latest')
|
|
957
|
-
response = Cnvrg::API.request("#{@base_resource}/clone_chunk", 'POST',{commit: commit, chunk_size: chunk_size, latest_id: latest_id})
|
|
960
|
+
response = Cnvrg::API.request("#{@base_resource}/clone_chunk", 'POST', {commit: commit, chunk_size: chunk_size, latest_id: latest_id})
|
|
958
961
|
unless Cnvrg::CLI.is_response_success(response, false)
|
|
959
962
|
Cnvrg::Logger.log_info("#{{commit: commit, chunk_size: chunk_size, latest_id: latest_id}}")
|
|
960
963
|
return nil
|
|
@@ -985,26 +988,26 @@ module Cnvrg
|
|
|
985
988
|
end
|
|
986
989
|
end
|
|
987
990
|
|
|
988
|
-
def download_multiple_chunks(commit, chunk_size=1000, progress: nil)
|
|
991
|
+
def download_multiple_chunks(commit, chunk_size = 1000, progress: nil)
|
|
989
992
|
begin
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
993
|
+
last_chunk_size = chunk_size
|
|
994
|
+
q = {commit: commit, chunk_size: chunk_size}
|
|
995
|
+
overall = 0
|
|
996
|
+
while last_chunk_size > 0
|
|
997
|
+
response = Cnvrg::API.request("users/#{@owner}/datasets/#{@dataset_slug}/clone", 'POST', q)
|
|
998
|
+
if Cnvrg::CLI.is_response_success(response, false)
|
|
999
|
+
files = response['files']
|
|
1000
|
+
data_home = "#{Dir.pwd}/#{response['name']}"
|
|
1001
|
+
last_chunk_size = files['keys'].length
|
|
1002
|
+
break if last_chunk_size == 0
|
|
1003
|
+
res = download_multiple_files_s3(files, data_home, read_only: false, progressbar: progress)
|
|
1004
|
+
overall += last_chunk_size
|
|
1005
|
+
q[:latest] = files['latest']
|
|
1006
|
+
else
|
|
1007
|
+
last_chunk_size = 0
|
|
1008
|
+
end
|
|
1005
1009
|
end
|
|
1006
|
-
|
|
1007
|
-
Cnvrg::Result.new(true, "Cloned #{overall} files!")
|
|
1010
|
+
Cnvrg::Result.new(true, "Cloned #{overall} files!")
|
|
1008
1011
|
rescue => e
|
|
1009
1012
|
Cnvrg::Result.new(false, "Cant download chunk", e.message, e.backtrace)
|
|
1010
1013
|
|
|
@@ -1012,10 +1015,10 @@ module Cnvrg
|
|
|
1012
1015
|
end
|
|
1013
1016
|
|
|
1014
1017
|
def generate_parallel_idx
|
|
1015
|
-
|
|
1018
|
+
|
|
1016
1019
|
end
|
|
1017
1020
|
|
|
1018
|
-
def download_multiple_files_s3(files, project_home, conflict: false, progressbar: nil, read_only:false)
|
|
1021
|
+
def download_multiple_files_s3(files, project_home, conflict: false, progressbar: nil, read_only: false)
|
|
1019
1022
|
begin
|
|
1020
1023
|
refresh_storage_token
|
|
1021
1024
|
parallel_options = {
|
|
@@ -1024,31 +1027,31 @@ module Cnvrg
|
|
|
1024
1027
|
}
|
|
1025
1028
|
Parallel.map(files["keys"], parallel_options) do |f|
|
|
1026
1029
|
begin
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1030
|
+
local_path = @dataset.local_path + '/' + f['name']
|
|
1031
|
+
Cnvrg::Logger.log_info("Downloading #{local_path}")
|
|
1032
|
+
progressbar.progress += 1 if progressbar.present?
|
|
1033
|
+
if local_path.end_with? "/"
|
|
1034
|
+
@downloader.mkdir(local_path, recursive: true)
|
|
1035
|
+
next
|
|
1036
|
+
end
|
|
1034
1037
|
# blob
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1038
|
+
local_path = "#{local_path}.conflict" if conflict
|
|
1039
|
+
storage_path = f["path"]
|
|
1040
|
+
if File.exists? local_path
|
|
1041
|
+
Cnvrg::Logger.log_info("Trying to download #{local_path} but its already exists, skipping..")
|
|
1042
|
+
next
|
|
1043
|
+
end
|
|
1044
|
+
resp = @downloader.download(storage_path, local_path)
|
|
1045
|
+
Cnvrg::Logger.log_info("Download #{local_path} success resp: #{resp}")
|
|
1043
1046
|
rescue => e
|
|
1044
1047
|
Cnvrg::Logger.log_error(e)
|
|
1045
1048
|
end
|
|
1046
1049
|
end
|
|
1047
|
-
return Cnvrg::Result.new(true,"Downloaded successfully")
|
|
1050
|
+
return Cnvrg::Result.new(true, "Downloaded successfully")
|
|
1048
1051
|
rescue => e
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
end
|
|
1052
|
+
Cnvrg::Logger.log_error(e)
|
|
1053
|
+
return Cnvrg::Result.new(false, "Could not download some files", e.message, e.backtrace)
|
|
1052
1054
|
end
|
|
1055
|
+
end
|
|
1053
1056
|
end
|
|
1054
1057
|
end
|
data/lib/cnvrg/project.rb
CHANGED
|
@@ -370,6 +370,13 @@ module Cnvrg
|
|
|
370
370
|
File.open(@working_dir + "/.cnvrg/config.yml", "w+") {|f| f.write new_config.to_yaml}
|
|
371
371
|
end
|
|
372
372
|
|
|
373
|
+
def generate_git_diff
|
|
374
|
+
git_diff = `git diff --name-only`
|
|
375
|
+
git_diff.split("\n")
|
|
376
|
+
rescue
|
|
377
|
+
[]
|
|
378
|
+
end
|
|
379
|
+
|
|
373
380
|
def generate_output_dir(output_dir)
|
|
374
381
|
Cnvrg::Logger.log_info("Generating output dir for #{output_dir}")
|
|
375
382
|
upload_list = []
|
|
@@ -387,7 +394,7 @@ module Cnvrg
|
|
|
387
394
|
upload_list << output_dir + "/"
|
|
388
395
|
end
|
|
389
396
|
Cnvrg::Logger.log_info("Uploading: #{upload_list.join(", ")}")
|
|
390
|
-
|
|
397
|
+
upload_list
|
|
391
398
|
end
|
|
392
399
|
def generate_output_dir_tmp(output_dir)
|
|
393
400
|
upload_list = []
|
data/lib/cnvrg/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cnvrg
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.6.
|
|
4
|
+
version: 1.6.38
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yochay Ettun
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2020-06-
|
|
13
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: bundler
|