google-cloud-storage 1.30.0 → 1.39.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +2 -1
- data/CHANGELOG.md +106 -0
- data/CONTRIBUTING.md +3 -4
- data/OVERVIEW.md +30 -0
- data/lib/google/cloud/storage/bucket/acl.rb +12 -14
- data/lib/google/cloud/storage/bucket/cors.rb +4 -1
- data/lib/google/cloud/storage/bucket/lifecycle.rb +99 -21
- data/lib/google/cloud/storage/bucket/list.rb +3 -3
- data/lib/google/cloud/storage/bucket.rb +421 -62
- data/lib/google/cloud/storage/credentials.rb +16 -14
- data/lib/google/cloud/storage/file/acl.rb +181 -20
- data/lib/google/cloud/storage/file/list.rb +3 -3
- data/lib/google/cloud/storage/file/signer_v2.rb +3 -5
- data/lib/google/cloud/storage/file/signer_v4.rb +12 -10
- data/lib/google/cloud/storage/file/verifier.rb +2 -2
- data/lib/google/cloud/storage/file.rb +223 -32
- data/lib/google/cloud/storage/hmac_key/list.rb +3 -3
- data/lib/google/cloud/storage/policy/binding.rb +5 -3
- data/lib/google/cloud/storage/policy/bindings.rb +2 -2
- data/lib/google/cloud/storage/policy/condition.rb +4 -2
- data/lib/google/cloud/storage/policy.rb +2 -2
- data/lib/google/cloud/storage/post_object.rb +2 -1
- data/lib/google/cloud/storage/project.rb +38 -18
- data/lib/google/cloud/storage/service.rb +352 -284
- data/lib/google/cloud/storage/version.rb +1 -1
- data/lib/google/cloud/storage.rb +66 -13
- data/lib/google-cloud-storage.rb +51 -7
- metadata +24 -18
@@ -38,20 +38,22 @@ module Google
|
|
38
38
|
# storage.project_id #=> "my-project"
|
39
39
|
#
|
40
40
|
class Credentials < Google::Auth::Credentials
|
41
|
-
SCOPE =
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
SCOPE = ["https://www.googleapis.com/auth/devstorage.full_control"].freeze
|
42
|
+
PATH_ENV_VARS = [
|
43
|
+
"STORAGE_CREDENTIALS",
|
44
|
+
"STORAGE_KEYFILE",
|
45
|
+
"GOOGLE_CLOUD_CREDENTIALS",
|
46
|
+
"GOOGLE_CLOUD_KEYFILE",
|
47
|
+
"GCLOUD_KEYFILE"
|
48
|
+
].freeze
|
49
|
+
JSON_ENV_VARS = [
|
50
|
+
"STORAGE_CREDENTIALS_JSON",
|
51
|
+
"STORAGE_KEYFILE_JSON",
|
52
|
+
"GOOGLE_CLOUD_CREDENTIALS_JSON",
|
53
|
+
"GOOGLE_CLOUD_KEYFILE_JSON",
|
54
|
+
"GCLOUD_KEYFILE_JSON"
|
55
|
+
].freeze
|
56
|
+
DEFAULT_PATHS = ["~/.config/gcloud/application_default_credentials.json"].freeze
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -190,7 +190,7 @@ module Google
|
|
190
190
|
generation: generation,
|
191
191
|
user_project: user_project
|
192
192
|
entity = gapi.entity
|
193
|
-
@owners
|
193
|
+
@owners&.push entity
|
194
194
|
entity
|
195
195
|
end
|
196
196
|
|
@@ -241,7 +241,7 @@ module Google
|
|
241
241
|
generation: generation,
|
242
242
|
user_project: user_project
|
243
243
|
entity = gapi.entity
|
244
|
-
@readers
|
244
|
+
@readers&.push entity
|
245
245
|
entity
|
246
246
|
end
|
247
247
|
|
@@ -281,8 +281,8 @@ module Google
|
|
281
281
|
@service.delete_file_acl \
|
282
282
|
@bucket, @file, entity,
|
283
283
|
generation: generation, user_project: user_project
|
284
|
-
@owners
|
285
|
-
@readers
|
284
|
+
@owners&.delete entity
|
285
|
+
@readers&.delete entity
|
286
286
|
true
|
287
287
|
end
|
288
288
|
|
@@ -297,6 +297,22 @@ module Google
|
|
297
297
|
# Convenience method to apply the `authenticatedRead` predefined ACL
|
298
298
|
# rule to the file.
|
299
299
|
#
|
300
|
+
# @param [Integer] generation Select a specific revision of the file to
|
301
|
+
# update. The default is the latest version.
|
302
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
303
|
+
# on whether the file's current generation matches the given value.
|
304
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
305
|
+
# versions of the file.
|
306
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
307
|
+
# on whether the file's current generation does not match the given
|
308
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
309
|
+
# makes the operation succeed only if there is a live version of the file.
|
310
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
311
|
+
# on whether the file's current metageneration matches the given value.
|
312
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
313
|
+
# conditional on whether the file's current metageneration does not
|
314
|
+
# match the given value.
|
315
|
+
#
|
300
316
|
# @example
|
301
317
|
# require "google/cloud/storage"
|
302
318
|
#
|
@@ -307,8 +323,17 @@ module Google
|
|
307
323
|
# file = bucket.file "path/to/my-file.ext"
|
308
324
|
# file.acl.auth!
|
309
325
|
#
|
310
|
-
def auth!
|
311
|
-
|
326
|
+
def auth! generation: nil,
|
327
|
+
if_generation_match: nil,
|
328
|
+
if_generation_not_match: nil,
|
329
|
+
if_metageneration_match: nil,
|
330
|
+
if_metageneration_not_match: nil
|
331
|
+
update_predefined_acl! "authenticatedRead",
|
332
|
+
generation: generation,
|
333
|
+
if_generation_match: if_generation_match,
|
334
|
+
if_generation_not_match: if_generation_not_match,
|
335
|
+
if_metageneration_match: if_metageneration_match,
|
336
|
+
if_metageneration_not_match: if_metageneration_not_match
|
312
337
|
end
|
313
338
|
alias authenticatedRead! auth!
|
314
339
|
alias auth_read! auth!
|
@@ -319,6 +344,22 @@ module Google
|
|
319
344
|
# Convenience method to apply the `bucketOwnerFullControl` predefined
|
320
345
|
# ACL rule to the file.
|
321
346
|
#
|
347
|
+
# @param [Integer] generation Select a specific revision of the file to
|
348
|
+
# update. The default is the latest version.
|
349
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
350
|
+
# on whether the file's current generation matches the given value.
|
351
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
352
|
+
# versions of the file.
|
353
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
354
|
+
# on whether the file's current generation does not match the given
|
355
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
356
|
+
# makes the operation succeed only if there is a live version of the file.
|
357
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
358
|
+
# on whether the file's current metageneration matches the given value.
|
359
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
360
|
+
# conditional on whether the file's current metageneration does not
|
361
|
+
# match the given value.
|
362
|
+
#
|
322
363
|
# @example
|
323
364
|
# require "google/cloud/storage"
|
324
365
|
#
|
@@ -329,8 +370,17 @@ module Google
|
|
329
370
|
# file = bucket.file "path/to/my-file.ext"
|
330
371
|
# file.acl.owner_full!
|
331
372
|
#
|
332
|
-
def owner_full!
|
333
|
-
|
373
|
+
def owner_full! generation: nil,
|
374
|
+
if_generation_match: nil,
|
375
|
+
if_generation_not_match: nil,
|
376
|
+
if_metageneration_match: nil,
|
377
|
+
if_metageneration_not_match: nil
|
378
|
+
update_predefined_acl! "bucketOwnerFullControl",
|
379
|
+
generation: generation,
|
380
|
+
if_generation_match: if_generation_match,
|
381
|
+
if_generation_not_match: if_generation_not_match,
|
382
|
+
if_metageneration_match: if_metageneration_match,
|
383
|
+
if_metageneration_not_match: if_metageneration_not_match
|
334
384
|
end
|
335
385
|
alias bucketOwnerFullControl! owner_full!
|
336
386
|
|
@@ -338,6 +388,22 @@ module Google
|
|
338
388
|
# Convenience method to apply the `bucketOwnerRead` predefined ACL
|
339
389
|
# rule to the file.
|
340
390
|
#
|
391
|
+
# @param [Integer] generation Select a specific revision of the file to
|
392
|
+
# update. The default is the latest version.
|
393
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
394
|
+
# on whether the file's current generation matches the given value.
|
395
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
396
|
+
# versions of the file.
|
397
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
398
|
+
# on whether the file's current generation does not match the given
|
399
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
400
|
+
# makes the operation succeed only if there is a live version of the file.
|
401
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
402
|
+
# on whether the file's current metageneration matches the given value.
|
403
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
404
|
+
# conditional on whether the file's current metageneration does not
|
405
|
+
# match the given value.
|
406
|
+
#
|
341
407
|
# @example
|
342
408
|
# require "google/cloud/storage"
|
343
409
|
#
|
@@ -348,8 +414,17 @@ module Google
|
|
348
414
|
# file = bucket.file "path/to/my-file.ext"
|
349
415
|
# file.acl.owner_read!
|
350
416
|
#
|
351
|
-
def owner_read!
|
352
|
-
|
417
|
+
def owner_read! generation: nil,
|
418
|
+
if_generation_match: nil,
|
419
|
+
if_generation_not_match: nil,
|
420
|
+
if_metageneration_match: nil,
|
421
|
+
if_metageneration_not_match: nil
|
422
|
+
update_predefined_acl! "bucketOwnerRead",
|
423
|
+
generation: generation,
|
424
|
+
if_generation_match: if_generation_match,
|
425
|
+
if_generation_not_match: if_generation_not_match,
|
426
|
+
if_metageneration_match: if_metageneration_match,
|
427
|
+
if_metageneration_not_match: if_metageneration_not_match
|
353
428
|
end
|
354
429
|
alias bucketOwnerRead! owner_read!
|
355
430
|
|
@@ -357,6 +432,22 @@ module Google
|
|
357
432
|
# Convenience method to apply the `private` predefined ACL
|
358
433
|
# rule to the file.
|
359
434
|
#
|
435
|
+
# @param [Integer] generation Select a specific revision of the file to
|
436
|
+
# update. The default is the latest version.
|
437
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
438
|
+
# on whether the file's current generation matches the given value.
|
439
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
440
|
+
# versions of the file.
|
441
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
442
|
+
# on whether the file's current generation does not match the given
|
443
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
444
|
+
# makes the operation succeed only if there is a live version of the file.
|
445
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
446
|
+
# on whether the file's current metageneration matches the given value.
|
447
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
448
|
+
# conditional on whether the file's current metageneration does not
|
449
|
+
# match the given value.
|
450
|
+
#
|
360
451
|
# @example
|
361
452
|
# require "google/cloud/storage"
|
362
453
|
#
|
@@ -367,14 +458,39 @@ module Google
|
|
367
458
|
# file = bucket.file "path/to/my-file.ext"
|
368
459
|
# file.acl.private!
|
369
460
|
#
|
370
|
-
def private!
|
371
|
-
|
461
|
+
def private! generation: nil,
|
462
|
+
if_generation_match: nil,
|
463
|
+
if_generation_not_match: nil,
|
464
|
+
if_metageneration_match: nil,
|
465
|
+
if_metageneration_not_match: nil
|
466
|
+
update_predefined_acl! "private",
|
467
|
+
generation: generation,
|
468
|
+
if_generation_match: if_generation_match,
|
469
|
+
if_generation_not_match: if_generation_not_match,
|
470
|
+
if_metageneration_match: if_metageneration_match,
|
471
|
+
if_metageneration_not_match: if_metageneration_not_match
|
372
472
|
end
|
373
473
|
|
374
474
|
##
|
375
475
|
# Convenience method to apply the `projectPrivate` predefined ACL
|
376
476
|
# rule to the file.
|
377
477
|
#
|
478
|
+
# @param [Integer] generation Select a specific revision of the file to
|
479
|
+
# update. The default is the latest version.
|
480
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
481
|
+
# on whether the file's current generation matches the given value.
|
482
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
483
|
+
# versions of the file.
|
484
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
485
|
+
# on whether the file's current generation does not match the given
|
486
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
487
|
+
# makes the operation succeed only if there is a live version of the file.
|
488
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
489
|
+
# on whether the file's current metageneration matches the given value.
|
490
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
491
|
+
# conditional on whether the file's current metageneration does not
|
492
|
+
# match the given value.
|
493
|
+
#
|
378
494
|
# @example
|
379
495
|
# require "google/cloud/storage"
|
380
496
|
#
|
@@ -385,8 +501,17 @@ module Google
|
|
385
501
|
# file = bucket.file "path/to/my-file.ext"
|
386
502
|
# file.acl.project_private!
|
387
503
|
#
|
388
|
-
def project_private!
|
389
|
-
|
504
|
+
def project_private! generation: nil,
|
505
|
+
if_generation_match: nil,
|
506
|
+
if_generation_not_match: nil,
|
507
|
+
if_metageneration_match: nil,
|
508
|
+
if_metageneration_not_match: nil
|
509
|
+
update_predefined_acl! "projectPrivate",
|
510
|
+
generation: generation,
|
511
|
+
if_generation_match: if_generation_match,
|
512
|
+
if_generation_not_match: if_generation_not_match,
|
513
|
+
if_metageneration_match: if_metageneration_match,
|
514
|
+
if_metageneration_not_match: if_metageneration_not_match
|
390
515
|
end
|
391
516
|
alias projectPrivate! project_private!
|
392
517
|
|
@@ -394,6 +519,22 @@ module Google
|
|
394
519
|
# Convenience method to apply the `publicRead` predefined ACL
|
395
520
|
# rule to the file.
|
396
521
|
#
|
522
|
+
# @param [Integer] generation Select a specific revision of the file to
|
523
|
+
# update. The default is the latest version.
|
524
|
+
# @param [Integer] if_generation_match Makes the operation conditional
|
525
|
+
# on whether the file's current generation matches the given value.
|
526
|
+
# Setting to 0 makes the operation succeed only if there are no live
|
527
|
+
# versions of the file.
|
528
|
+
# @param [Integer] if_generation_not_match Makes the operation conditional
|
529
|
+
# on whether the file's current generation does not match the given
|
530
|
+
# value. If no live file exists, the precondition fails. Setting to 0
|
531
|
+
# makes the operation succeed only if there is a live version of the file.
|
532
|
+
# @param [Integer] if_metageneration_match Makes the operation conditional
|
533
|
+
# on whether the file's current metageneration matches the given value.
|
534
|
+
# @param [Integer] if_metageneration_not_match Makes the operation
|
535
|
+
# conditional on whether the file's current metageneration does not
|
536
|
+
# match the given value.
|
537
|
+
#
|
397
538
|
# @example
|
398
539
|
# require "google/cloud/storage"
|
399
540
|
#
|
@@ -404,8 +545,17 @@ module Google
|
|
404
545
|
# file = bucket.file "path/to/my-file.ext"
|
405
546
|
# file.acl.public!
|
406
547
|
#
|
407
|
-
def public!
|
408
|
-
|
548
|
+
def public! generation: nil,
|
549
|
+
if_generation_match: nil,
|
550
|
+
if_generation_not_match: nil,
|
551
|
+
if_metageneration_match: nil,
|
552
|
+
if_metageneration_not_match: nil
|
553
|
+
update_predefined_acl! "publicRead",
|
554
|
+
generation: generation,
|
555
|
+
if_generation_match: if_generation_match,
|
556
|
+
if_generation_not_match: if_generation_not_match,
|
557
|
+
if_metageneration_match: if_metageneration_match,
|
558
|
+
if_metageneration_not_match: if_metageneration_not_match
|
409
559
|
end
|
410
560
|
alias publicRead! public!
|
411
561
|
alias public_read! public!
|
@@ -418,9 +568,21 @@ module Google
|
|
418
568
|
self
|
419
569
|
end
|
420
570
|
|
421
|
-
def update_predefined_acl! acl_role
|
571
|
+
def update_predefined_acl! acl_role,
|
572
|
+
generation: nil,
|
573
|
+
if_generation_match: nil,
|
574
|
+
if_generation_not_match: nil,
|
575
|
+
if_metageneration_match: nil,
|
576
|
+
if_metageneration_not_match: nil
|
422
577
|
patched_file = Google::Apis::StorageV1::Object.new acl: []
|
423
|
-
@service.patch_file @bucket,
|
578
|
+
@service.patch_file @bucket,
|
579
|
+
@file,
|
580
|
+
patched_file,
|
581
|
+
generation: generation,
|
582
|
+
if_generation_match: if_generation_match,
|
583
|
+
if_generation_not_match: if_generation_not_match,
|
584
|
+
if_metageneration_match: if_metageneration_match,
|
585
|
+
if_metageneration_not_match: if_metageneration_not_match,
|
424
586
|
predefined_acl: acl_role,
|
425
587
|
user_project: user_project
|
426
588
|
clear!
|
@@ -428,8 +590,7 @@ module Google
|
|
428
590
|
|
429
591
|
def entities_from_acls acls, role
|
430
592
|
selected = acls.select { |acl| acl.role == role }
|
431
|
-
|
432
|
-
entities
|
593
|
+
selected.map(&:entity)
|
433
594
|
end
|
434
595
|
end
|
435
596
|
end
|
@@ -141,17 +141,17 @@ module Google
|
|
141
141
|
# puts file.name
|
142
142
|
# end
|
143
143
|
#
|
144
|
-
def all request_limit: nil
|
144
|
+
def all request_limit: nil, &block
|
145
145
|
request_limit = request_limit.to_i if request_limit
|
146
146
|
unless block_given?
|
147
147
|
return enum_for :all, request_limit: request_limit
|
148
148
|
end
|
149
149
|
results = self
|
150
150
|
loop do
|
151
|
-
results.each
|
151
|
+
results.each(&block)
|
152
152
|
if request_limit
|
153
153
|
request_limit -= 1
|
154
|
-
break if request_limit
|
154
|
+
break if request_limit.negative?
|
155
155
|
end
|
156
156
|
break unless results.next?
|
157
157
|
results = results.next
|
@@ -48,7 +48,7 @@ module Google
|
|
48
48
|
#
|
49
49
|
def ext_path
|
50
50
|
path = "/#{@bucket}/#{@path}"
|
51
|
-
escaped = Addressable::URI.
|
51
|
+
escaped = Addressable::URI.encode_component path, Addressable::URI::CharacterClasses::PATH
|
52
52
|
special_var = "${filename}"
|
53
53
|
# Restore the unencoded `${filename}` variable, if present.
|
54
54
|
if path.include? special_var
|
@@ -147,10 +147,8 @@ module Google
|
|
147
147
|
"&Expires=#{expires}" \
|
148
148
|
"&Signature=#{url_escape signed_string}"
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
url << "&#{url_escape name}=#{url_escape value}"
|
153
|
-
end
|
150
|
+
query&.each do |name, value|
|
151
|
+
url << "&#{url_escape name}=#{url_escape value}"
|
154
152
|
end
|
155
153
|
|
156
154
|
url
|
@@ -60,7 +60,7 @@ module Google
|
|
60
60
|
|
61
61
|
p = {}
|
62
62
|
p["conditions"] = policy_conditions base_fields, conditions, fields
|
63
|
-
expires ||= 60*60*24
|
63
|
+
expires ||= 60 * 60 * 24
|
64
64
|
p["expiration"] = (now + expires).strftime "%Y-%m-%dT%H:%M:%SZ"
|
65
65
|
|
66
66
|
policy_str = escape_characters p.to_json
|
@@ -100,7 +100,7 @@ module Google
|
|
100
100
|
|
101
101
|
algorithm = "GOOG4-RSA-SHA256"
|
102
102
|
expires = determine_expires expires
|
103
|
-
credential = issuer
|
103
|
+
credential = "#{issuer}/#{scope}"
|
104
104
|
canonical_query_str = canonical_query query, algorithm, credential, goog_date, expires, signed_headers_str
|
105
105
|
|
106
106
|
# From AWS: You don't include a payload hash in the Canonical
|
@@ -129,11 +129,10 @@ module Google
|
|
129
129
|
end
|
130
130
|
|
131
131
|
# methods below are public visibility only for unit testing
|
132
|
+
# rubocop:disable Style/StringLiterals
|
132
133
|
def escape_characters str
|
133
134
|
str.split("").map do |s|
|
134
|
-
if
|
135
|
-
escape_special_unicode s
|
136
|
-
else
|
135
|
+
if s.ascii_only?
|
137
136
|
case s
|
138
137
|
when "\\"
|
139
138
|
'\\'
|
@@ -152,12 +151,15 @@ module Google
|
|
152
151
|
else
|
153
152
|
s
|
154
153
|
end
|
154
|
+
else
|
155
|
+
escape_special_unicode s
|
155
156
|
end
|
156
157
|
end.join
|
157
158
|
end
|
159
|
+
# rubocop:enable Style/StringLiterals
|
158
160
|
|
159
161
|
def escape_special_unicode str
|
160
|
-
str.unpack("U*").map { |i|
|
162
|
+
str.unpack("U*").map { |i| "\\u#{i.to_s(16).rjust(4, '0')}" }.join
|
161
163
|
end
|
162
164
|
|
163
165
|
protected
|
@@ -212,14 +214,14 @@ module Google
|
|
212
214
|
if signer.is_a? Proc
|
213
215
|
lambda do |string_to_sign|
|
214
216
|
sig = signer.call string_to_sign
|
215
|
-
sig.
|
217
|
+
sig.unpack1 "H*"
|
216
218
|
end
|
217
219
|
else
|
218
220
|
signer = OpenSSL::PKey::RSA.new signer unless signer.respond_to? :sign
|
219
221
|
# Sign string to sign
|
220
222
|
lambda do |string_to_sign|
|
221
223
|
sig = signer.sign OpenSSL::Digest::SHA256.new, string_to_sign
|
222
|
-
sig.
|
224
|
+
sig.unpack1 "H*"
|
223
225
|
end
|
224
226
|
end
|
225
227
|
end
|
@@ -324,7 +326,7 @@ module Google
|
|
324
326
|
#
|
325
327
|
def post_object_ext_path
|
326
328
|
path = "/#{@bucket_name}/#{@file_name}"
|
327
|
-
escaped = Addressable::URI.
|
329
|
+
escaped = Addressable::URI.encode_component path, Addressable::URI::CharacterClasses::PATH
|
328
330
|
special_var = "${filename}"
|
329
331
|
# Restore the unencoded `${filename}` variable, if present.
|
330
332
|
if path.include? special_var
|
@@ -359,7 +361,7 @@ module Google
|
|
359
361
|
end
|
360
362
|
packed_signature = signing_key.sign OpenSSL::Digest::SHA256.new, data
|
361
363
|
end
|
362
|
-
packed_signature.
|
364
|
+
packed_signature.unpack1("H*").force_encoding "utf-8"
|
363
365
|
end
|
364
366
|
end
|
365
367
|
end
|
@@ -50,7 +50,7 @@ module Google
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def self.md5_for local_file
|
53
|
-
if local_file.respond_to? :
|
53
|
+
if local_file.respond_to? :to_path
|
54
54
|
::File.open Pathname(local_file).to_path, "rb" do |f|
|
55
55
|
::Digest::MD5.file(f).base64digest
|
56
56
|
end
|
@@ -63,7 +63,7 @@ module Google
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def self.crc32c_for local_file
|
66
|
-
if local_file.respond_to? :
|
66
|
+
if local_file.respond_to? :to_path
|
67
67
|
::File.open Pathname(local_file).to_path, "rb" do |f|
|
68
68
|
::Digest::CRC32c.file(f).base64digest
|
69
69
|
end
|