google-cloud-storage 1.47.0 → 1.54.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb6046c8eb979e1cbd733518d8fd242e1332813d6241f85e65b07f6d7d9e631f
4
- data.tar.gz: 1124d71be6c1954b38f3fb6c8c3814891d9dd108fc0862f2c5436db18c111782
3
+ metadata.gz: 67fa1effce117003750f759eba79de92380616365652f2a19ba49b1986c75634
4
+ data.tar.gz: 9729e6dc51f15a9a5e2e0370771f980908f9d6284973503c9c4d4c1e561b8d84
5
5
  SHA512:
6
- metadata.gz: 2e8598d2cf01a52f20c7bd554b593d7049134a367f17571721e2779a0634013452ad42025c22d59f8542c030a411092c3f2f63edfe8489fee0a9dcb9ccb5c774
7
- data.tar.gz: 4918a472cd83aab2c7d1a5ffe6be9957c0113686a00769f082522799fd9cc713c3315de8d8b2d87caa22b37d7d54c2c82702fb2b5b9e1ed30ef011319dc841cf
6
+ metadata.gz: ec9022c921c0714ebf7f47131c745c113bb0480a34a376ca10055ccdee024821a518d1a87f742486118d7fb3e570beaeef5746f12676d5790e6ae697439dabd9
7
+ data.tar.gz: d5e57fd75d565a8328cf79ce42374883e4da7f875c7fd9571e928f9648c05578bee5743d68465819f3e5d488469d277749aecebd44810198fd1a1ca0cac6f3c3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # Release History
2
2
 
3
+ ### 1.54.0 (2024-12-11)
4
+
5
+ #### Features
6
+
7
+ * Updated required Ruby version to 3.0 or later ([#27599](https://github.com/googleapis/google-cloud-ruby/issues/27599))
8
+
9
+ ### 1.53.0 (2024-12-04)
10
+
11
+ #### Features
12
+
13
+ * add integration test for universe domain ([#27384](https://github.com/googleapis/google-cloud-ruby/issues/27384))
14
+ * fetch file and bucket details from url ([#27322](https://github.com/googleapis/google-cloud-ruby/issues/27322))
15
+
16
+ ### 1.52.0 (2024-05-31)
17
+
18
+ #### Features
19
+
20
+ * support for hierarchical namespace (folders) ([#25967](https://github.com/googleapis/google-cloud-ruby/issues/25967))
21
+
22
+ ### 1.51.0 (2024-04-25)
23
+
24
+ #### Features
25
+
26
+ * Respect custom endpoint for signed_url ([#25469](https://github.com/googleapis/google-cloud-ruby/issues/25469))
27
+
28
+ ### 1.50.0 (2024-04-19)
29
+
30
+ #### Features
31
+
32
+ * Add support for soft deletion ([#25340](https://github.com/googleapis/google-cloud-ruby/issues/25340))
33
+ #### Bug Fixes
34
+
35
+ * Set configured univer_domain and endpoint when initializing through Service ([#25665](https://github.com/googleapis/google-cloud-ruby/issues/25665))
36
+
37
+ ### 1.49.0 (2024-02-21)
38
+
39
+ #### Features
40
+
41
+ * Support of Managed Folders ([#24809](https://github.com/googleapis/google-cloud-ruby/issues/24809))
42
+
43
+ ### 1.48.1 (2024-01-26)
44
+
45
+ #### Bug Fixes
46
+
47
+ * Raise an error on mismatching universe domain ([#24486](https://github.com/googleapis/google-cloud-ruby/issues/24486))
48
+
49
+ ### 1.48.0 (2024-01-25)
50
+
51
+ #### Features
52
+
53
+ * Support for universe_domain ([#24449](https://github.com/googleapis/google-cloud-ruby/issues/24449))
54
+
3
55
  ### 1.47.0 (2024-01-09)
4
56
 
5
57
  #### Features
@@ -182,7 +182,7 @@ module Google
182
182
  @origin = Array(origin)
183
183
  @methods = Array(methods)
184
184
  @headers = Array(headers)
185
- @max_age = (max_age || 1800)
185
+ @max_age = max_age || 1800
186
186
  end
187
187
 
188
188
  # @private
@@ -195,7 +195,7 @@ module Google
195
195
 
196
196
  # @private
197
197
  def self.from_gapi gapi
198
- new gapi.origin.dup, gapi.http_method.dup, \
198
+ new gapi.origin.dup, gapi.http_method.dup,
199
199
  headers: gapi.response_header.dup,
200
200
  max_age: gapi.max_age_seconds
201
201
  end
@@ -1194,6 +1194,121 @@ module Google
1194
1194
  patch_gapi! :rpo
1195
1195
  end
1196
1196
 
1197
+ ##
1198
+ # The bucket's soft delete policy. If this policy is set, any deleted
1199
+ # objects will be soft-deleted according to the time specified in the
1200
+ # policy.
1201
+ # This value can be modified by calling {#soft_delete_policy=}.
1202
+ #
1203
+ # @return [Google::Apis::StorageV1::Bucket::SoftDeletePolicy] The default retention policy is for 7
1204
+ # days.
1205
+ #
1206
+ # @example
1207
+ # require "google/cloud/storage"
1208
+ #
1209
+ # storage = Google::Cloud::Storage.new
1210
+ #
1211
+ # bucket = storage.bucket "my-bucket"
1212
+ #
1213
+ # bucket.soft_delete_policy
1214
+ #
1215
+ def soft_delete_policy
1216
+ @gapi.soft_delete_policy
1217
+ end
1218
+
1219
+ ##
1220
+ # Sets the value for Soft Delete Policy in the bucket. This value can
1221
+ # be queried by calling {#soft_delete_policy}.
1222
+ #
1223
+ # @param [Google::Apis::StorageV1::Bucket::SoftDeletePolicy,
1224
+ # Hash(String => String)] new_soft_delete_policy The bucket's
1225
+ # new Soft Delete Policy.
1226
+ #
1227
+ # @example Set Soft Delete Policy to 10 days using SoftDeletePolicy class:
1228
+ # require "google/cloud/storage"
1229
+ # require "date"
1230
+ #
1231
+ # storage = Google::Cloud::Storage.new
1232
+ #
1233
+ # bucket = storage.bucket "my-bucket"
1234
+ #
1235
+ # soft_delete_policy = Google::Apis::StorageV1::Bucket::SoftDeletePolicy.new
1236
+ # soft_delete_policy.retention_duration_seconds = 10*24*60*60
1237
+ #
1238
+ # bucket.soft_delete_policy = soft_delete_policy
1239
+ #
1240
+ # @example Set Soft Delete Policy to 5 days using Hash:
1241
+ # require "google/cloud/storage"
1242
+ # require "date"
1243
+ #
1244
+ # storage = Google::Cloud::Storage.new
1245
+ #
1246
+ # bucket = storage.bucket "my-bucket"
1247
+ #
1248
+ # soft_delete_policy = { retention_duration_seconds: 432000 }
1249
+ # bucket.soft_delete_policy = soft_delete_policy
1250
+ #
1251
+ def soft_delete_policy= new_soft_delete_policy
1252
+ @gapi.soft_delete_policy = new_soft_delete_policy || {}
1253
+ patch_gapi! :soft_delete_policy
1254
+ end
1255
+
1256
+ ##
1257
+ # The bucket's hierarchical namespace (Folders) configuration.
1258
+ # This value can be modified by calling {#hierarchical_namespace=}.
1259
+ #
1260
+ # @return [Google::Apis::StorageV1::Bucket::HierarchicalNamespace]
1261
+ #
1262
+ # @example
1263
+ # require "google/cloud/storage"
1264
+ #
1265
+ # storage = Google::Cloud::Storage.new
1266
+ #
1267
+ # bucket = storage.bucket "my-bucket"
1268
+ #
1269
+ # bucket.hierarchical_namespace
1270
+ #
1271
+ def hierarchical_namespace
1272
+ @gapi.hierarchical_namespace
1273
+ end
1274
+
1275
+ ##
1276
+ # Sets the value of Hierarchical Namespace (Folders) for the bucket.
1277
+ # This can only be enabled at bucket create time. If this is enabled,
1278
+ # Uniform Bucket-Level Access must also be enabled.
1279
+ # This value can be queried by calling {#hierarchical_namespace}.
1280
+ #
1281
+ # @param [Google::Apis::StorageV1::Bucket::HierarchicalNamespace,
1282
+ # Hash(String => String)] new_hierarchical_namespace The
1283
+ # bucket's new Hierarchical Namespace Configuration.
1284
+ #
1285
+ # @example Enabled Hierarchical Namespace using HierarchicalNamespace class:
1286
+ # require "google/cloud/storage"
1287
+ #
1288
+ # storage = Google::Cloud::Storage.new
1289
+ #
1290
+ # bucket = storage.bucket "my-bucket"
1291
+ #
1292
+ # hierarchical_namespace = Google::Apis::StorageV1::Bucket::HierarchicalNamespace.new
1293
+ # hierarchical_namespace.enabled = true
1294
+ #
1295
+ # bucket.hierarchical_namespace = hierarchical_namespace
1296
+ #
1297
+ # @example Disable Hierarchical Namespace using Hash:
1298
+ # require "google/cloud/storage"
1299
+ #
1300
+ # storage = Google::Cloud::Storage.new
1301
+ #
1302
+ # bucket = storage.bucket "my-bucket"
1303
+ #
1304
+ # hierarchical_namespace = { enabled: false }
1305
+ # bucket.hierarchical_namespace = hierarchical_namespace
1306
+ #
1307
+ def hierarchical_namespace= new_hierarchical_namespace
1308
+ @gapi.hierarchical_namespace = new_hierarchical_namespace || {}
1309
+ patch_gapi! :hierarchical_namespace
1310
+ end
1311
+
1197
1312
  ##
1198
1313
  # Updates the bucket with changes made in the given block in a single
1199
1314
  # PATCH request. The following attributes may be set: {#cors},
@@ -1319,6 +1434,11 @@ module Google
1319
1434
  # as distinct results. The default is `false`. For more information,
1320
1435
  # see [Object Versioning
1321
1436
  # ](https://cloud.google.com/storage/docs/object-versioning).
1437
+ # @param [Boolean] include_folders_as_prefixes If `true`, will also include
1438
+ # folders and managed folders, besides objects, in the returned prefixes.
1439
+ # Only applicable if delimiter is set to '/'.
1440
+ # @param [Boolean] soft_deleted If true, only soft-deleted object
1441
+ # versions will be listed. The default is false.
1322
1442
  #
1323
1443
  # @return [Array<Google::Cloud::Storage::File>] (See
1324
1444
  # {Google::Cloud::Storage::File::List})
@@ -1346,17 +1466,22 @@ module Google
1346
1466
  # end
1347
1467
  #
1348
1468
  def files prefix: nil, delimiter: nil, token: nil, max: nil,
1349
- versions: nil, match_glob: nil
1469
+ versions: nil, match_glob: nil, include_folders_as_prefixes: nil,
1470
+ soft_deleted: nil
1350
1471
  ensure_service!
1351
1472
  gapi = service.list_files name, prefix: prefix, delimiter: delimiter,
1352
1473
  token: token, max: max,
1353
1474
  versions: versions,
1354
1475
  user_project: user_project,
1355
- match_glob: match_glob
1476
+ match_glob: match_glob,
1477
+ include_folders_as_prefixes: include_folders_as_prefixes,
1478
+ soft_deleted: soft_deleted
1356
1479
  File::List.from_gapi gapi, service, name, prefix, delimiter, max,
1357
1480
  versions,
1358
1481
  user_project: user_project,
1359
- match_glob: match_glob
1482
+ match_glob: match_glob,
1483
+ include_folders_as_prefixes: include_folders_as_prefixes,
1484
+ soft_deleted: soft_deleted
1360
1485
  end
1361
1486
  alias find_files files
1362
1487
 
@@ -1392,6 +1517,8 @@ module Google
1392
1517
  # @param [String] encryption_key Optional. The customer-supplied,
1393
1518
  # AES-256 encryption key used to encrypt the file, if one was provided
1394
1519
  # to {#create_file}. (Not used if `skip_lookup` is also set.)
1520
+ # @param [Boolean] soft_deleted Optional. If true, only soft-deleted
1521
+ # object versions will be listed. The default is false.
1395
1522
  #
1396
1523
  # @return [Google::Cloud::Storage::File, nil] Returns nil if file does
1397
1524
  # not exist
@@ -1413,7 +1540,8 @@ module Google
1413
1540
  if_metageneration_match: nil,
1414
1541
  if_metageneration_not_match: nil,
1415
1542
  skip_lookup: nil,
1416
- encryption_key: nil
1543
+ encryption_key: nil,
1544
+ soft_deleted: nil
1417
1545
  ensure_service!
1418
1546
  if skip_lookup
1419
1547
  return File.new_lazy name, path, service,
@@ -1426,7 +1554,8 @@ module Google
1426
1554
  if_metageneration_match: if_metageneration_match,
1427
1555
  if_metageneration_not_match: if_metageneration_not_match,
1428
1556
  key: encryption_key,
1429
- user_project: user_project
1557
+ user_project: user_project,
1558
+ soft_deleted: soft_deleted
1430
1559
  File.from_gapi gapi, service, user_project: user_project
1431
1560
  rescue Google::Cloud::NotFoundError
1432
1561
  nil
@@ -1707,6 +1836,77 @@ module Google
1707
1836
  alias upload_file create_file
1708
1837
  alias new_file create_file
1709
1838
 
1839
+ ##
1840
+ # Restores a soft-deleted object.
1841
+ #
1842
+ # @param [String] file_path
1843
+ # Name of the file.
1844
+ # @param [Fixnum] generation
1845
+ # Selects a specific revision of this object.
1846
+ # @param [Boolean] copy_source_acl
1847
+ # If true, copies the source file's ACL; otherwise, uses the
1848
+ # bucket's default file ACL. The default is false.
1849
+ # @param [Fixnum] if_generation_match
1850
+ # Makes the operation conditional on whether the file's one live
1851
+ # generation matches the given value. Setting to 0 makes the
1852
+ # operation succeed only if there are no live versions of the file.
1853
+ # @param [Fixnum] if_generation_not_match
1854
+ # Makes the operation conditional on whether none of the file's live
1855
+ # generations match the given value. If no live file exists, the
1856
+ # precondition fails. Setting to 0 makes the operation succeed only
1857
+ # if there is a live version of the file.
1858
+ # @param [Fixnum] if_metageneration_match
1859
+ # Makes the operation conditional on whether the file's one live
1860
+ # metageneration matches the given value.
1861
+ # @param [Fixnum] if_metageneration_not_match
1862
+ # Makes the operation conditional on whether none of the object's
1863
+ # live metagenerations match the given value.
1864
+ # @param [String] projection
1865
+ # Set of properties to return. Defaults to full.
1866
+ # @param [String] user_project
1867
+ # The project to be billed for this request. Required for Requester
1868
+ # Pays buckets.
1869
+ # @param [String] fields
1870
+ # Selector specifying which fields to include in a partial response.
1871
+ #
1872
+ # @return [Google::Cloud::Storage::File]
1873
+ #
1874
+ # @example
1875
+ # require "google/cloud/storage"
1876
+ #
1877
+ # storage = Google::Cloud::Storage.new
1878
+ #
1879
+ # bucket = storage.bucket "my-bucket"
1880
+ #
1881
+ # bucket.restore_file "path/of/file", <generation-of-the-file>
1882
+ #
1883
+ def restore_file file_path,
1884
+ generation,
1885
+ copy_source_acl: nil,
1886
+ if_generation_match: nil,
1887
+ if_generation_not_match: nil,
1888
+ if_metageneration_match: nil,
1889
+ if_metageneration_not_match: nil,
1890
+ projection: nil,
1891
+ user_project: nil,
1892
+ fields: nil,
1893
+ options: {}
1894
+ ensure_service!
1895
+ gapi = service.restore_file name,
1896
+ file_path,
1897
+ generation,
1898
+ copy_source_acl: File::Acl.predefined_rule_for(copy_source_acl),
1899
+ if_generation_match: if_generation_match,
1900
+ if_generation_not_match: if_generation_not_match,
1901
+ if_metageneration_match: if_metageneration_match,
1902
+ if_metageneration_not_match: if_metageneration_not_match,
1903
+ projection: projection,
1904
+ user_project: user_project,
1905
+ fields: fields,
1906
+ options: options
1907
+ File.from_gapi gapi, service, user_project: user_project
1908
+ end
1909
+
1710
1910
  ##
1711
1911
  # Concatenates a list of existing files in the bucket into a new file in
1712
1912
  # the bucket. There is a limit (currently 32) to the number of files
@@ -2987,9 +3187,9 @@ module Google
2987
3187
  attributes.flatten!
2988
3188
  return if attributes.empty?
2989
3189
  ensure_service!
2990
- patch_args = Hash[attributes.map do |attr|
3190
+ patch_args = attributes.to_h do |attr|
2991
3191
  [attr, @gapi.send(attr)]
2992
- end]
3192
+ end
2993
3193
  patch_gapi = API::Bucket.new(**patch_args)
2994
3194
  @gapi = service.patch_bucket name,
2995
3195
  patch_gapi,
@@ -3007,9 +3207,9 @@ module Google
3007
3207
  attributes.flatten!
3008
3208
  return if attributes.empty?
3009
3209
  ensure_service!
3010
- update_args = Hash[attributes.map do |attr|
3210
+ update_args = attributes.to_h do |attr|
3011
3211
  [attr, @gapi.send(attr)]
3012
- end]
3212
+ end
3013
3213
  update_gapi = API::Bucket.new(**update_args)
3014
3214
  @gapi = service.update_bucket name,
3015
3215
  update_gapi,
@@ -165,8 +165,9 @@ module Google
165
165
  # Google::Apis::StorageV1::Objects object.
166
166
  def self.from_gapi gapi_list, service, bucket = nil, prefix = nil,
167
167
  delimiter = nil, max = nil, versions = nil,
168
- user_project: nil,
169
- match_glob: nil
168
+ user_project: nil, match_glob: nil,
169
+ include_folders_as_prefixes: nil,
170
+ soft_deleted: nil
170
171
  files = new(Array(gapi_list.items).map do |gapi_object|
171
172
  File.from_gapi gapi_object, service, user_project: user_project
172
173
  end)
@@ -180,6 +181,8 @@ module Google
180
181
  files.instance_variable_set :@versions, versions
181
182
  files.instance_variable_set :@user_project, user_project
182
183
  files.instance_variable_set :@match_glob, match_glob
184
+ files.instance_variable_set :@include_folders_as_prefixes, include_folders_as_prefixes
185
+ files.instance_variable_set :@soft_deleted, soft_deleted
183
186
  files
184
187
  end
185
188
 
@@ -60,7 +60,8 @@ module Google
60
60
  ##
61
61
  # The external url to the file.
62
62
  def ext_url
63
- "#{GOOGLEAPIS_URL}#{ext_path}"
63
+ root_url = @service.service.root_url.chomp "/"
64
+ "#{root_url}#{ext_path}"
64
65
  end
65
66
 
66
67
  def apply_option_defaults options
@@ -91,7 +92,7 @@ module Google
91
92
 
92
93
  def error_msg attr_name
93
94
  "Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
94
- "see https://cloud.google.com/iam/docs/service-accounts"
95
+ "see https://cloud.google.com/iam/docs/service-accounts"
95
96
  end
96
97
 
97
98
  def post_object options
@@ -144,8 +145,8 @@ module Google
144
145
 
145
146
  def generate_signed_url issuer, signed_string, expires, query
146
147
  url = "#{ext_url}?GoogleAccessId=#{url_escape issuer}" \
147
- "&Expires=#{expires}" \
148
- "&Signature=#{url_escape signed_string}"
148
+ "&Expires=#{expires}" \
149
+ "&Signature=#{url_escape signed_string}"
149
150
 
150
151
  query&.each do |name, value|
151
152
  url << "&#{url_escape name}=#{url_escape value}"
@@ -131,7 +131,7 @@ module Google
131
131
  # methods below are public visibility only for unit testing
132
132
  # rubocop:disable Style/StringLiterals
133
133
  def escape_characters str
134
- str.split("").map do |s|
134
+ str.chars.map do |s|
135
135
  if s.ascii_only?
136
136
  case s
137
137
  when "\\"
@@ -207,7 +207,7 @@ module Google
207
207
 
208
208
  def error_msg attr_name
209
209
  "Service account credentials '#{attr_name}' is missing. To generate service account credentials " \
210
- "see https://cloud.google.com/iam/docs/service-accounts"
210
+ "see https://cloud.google.com/iam/docs/service-accounts"
211
211
  end
212
212
 
213
213
  def service_account_signer signer
@@ -243,7 +243,7 @@ module Google
243
243
  headers_arr = canonical_headers.map do |k, v|
244
244
  [k.downcase, v.strip.gsub(/[^\S\t]+/, " ").gsub(/\t+/, " ")]
245
245
  end
246
- canonical_headers = Hash[headers_arr]
246
+ canonical_headers = headers_arr.to_h
247
247
  canonical_headers["host"] = host_name virtual_hosted_style, bucket_bound_hostname
248
248
 
249
249
  canonical_headers = canonical_headers.sort_by(&:first).to_h
@@ -295,13 +295,13 @@ module Google
295
295
  ##
296
296
  # The external path to the bucket, with trailing slash.
297
297
  def bucket_path path_style
298
- return "/#{@bucket_name}/" if path_style
298
+ "/#{@bucket_name}/" if path_style
299
299
  end
300
300
 
301
301
  ##
302
302
  # The external url to the file.
303
303
  def ext_url scheme, virtual_hosted_style, bucket_bound_hostname
304
- url = GOOGLEAPIS_URL.dup
304
+ url = @service.service.root_url.chomp "/"
305
305
  if virtual_hosted_style
306
306
  parts = url.split "//"
307
307
  parts[1] = "#{@bucket_name}.#{parts[1]}"
@@ -763,6 +763,30 @@ module Google
763
763
  @gapi.retention_expiration_time
764
764
  end
765
765
 
766
+ ##
767
+ # This soft delete time is the time when the object became
768
+ # soft-deleted.
769
+ #
770
+ # @return [DateTime, nil] A DateTime representing the time at
771
+ # which the object became soft-deleted, or `nil` if the file was
772
+ # not deleted.
773
+ #
774
+ def soft_delete_time
775
+ @gapi.soft_delete_time
776
+ end
777
+
778
+ ##
779
+ # This hard delete time is The time when the file will be permanently
780
+ # deleted.
781
+ #
782
+ # @return [DateTime, nil] A DateTime representing the time at
783
+ # which the file will be permanently deleted, or `nil` if the file is
784
+ # not soft deleted.
785
+ #
786
+ def hard_delete_time
787
+ @gapi.hard_delete_time
788
+ end
789
+
766
790
  ##
767
791
  # Retrieves a list of versioned files for the current object.
768
792
  #
@@ -2048,15 +2072,59 @@ module Google
2048
2072
  def self.gapi_from_attrs gapi, attributes
2049
2073
  attributes.flatten!
2050
2074
  return nil if attributes.empty?
2051
- attr_params = Hash[attributes.map do |attr|
2052
- [attr, gapi.send(attr)]
2053
- end]
2075
+ attr_params = attributes.to_h do |attr|
2076
+ [attr, gapi.send(attr)]
2077
+ end
2054
2078
  # Sending nil metadata results in an Apiary runtime error:
2055
2079
  # NoMethodError: undefined method `each' for nil:NilClass
2056
2080
  attr_params.reject! { |k, v| k == :metadata && v.nil? }
2057
2081
  Google::Apis::StorageV1::Object.new(**attr_params)
2058
2082
  end
2059
2083
 
2084
+ ##
2085
+ # from_gs_url is a method to fetch bucket details and file details from a gs url
2086
+ #
2087
+ # @return [Hash(String => String)]
2088
+ #
2089
+ # @example Fetch bucket_name and file_Path from gs url:
2090
+ # require "google/cloud/storage"
2091
+ # gs_url= "gs://my-todo-app/avatars/heidi.jpeg"
2092
+ # file=Google::Cloud::Storage::File
2093
+ # file.from_gs_url(gs_url)
2094
+ # =>
2095
+ # {"bucket_name"=>"my-todo-app", "file_path"=>"avatars/heidi.jpeg"}
2096
+ #
2097
+ # @example Fetch bucket_name , file_Path and other query params from gs url:
2098
+ # require "google/cloud/storage"
2099
+ # gs_url= "gs://my-todo-app/test_sub_folder/heidi.jpeg?params1=test1&params2=test2"
2100
+ # file=Google::Cloud::Storage::File
2101
+ # file.from_gs_url(gs_url)
2102
+ # =>{
2103
+ # "bucket_name"=>"my-todo-app",
2104
+ # "file_path"=>"test_sub_folder/heidi.jpeg",
2105
+ # "options" => {
2106
+ # "params1"=>"test1",
2107
+ # "params2"=>"test2"
2108
+ # }
2109
+ # }
2110
+
2111
+ def self.from_gs_url gs_url
2112
+ prefix = "gs://".freeze
2113
+ raise ArgumentError, "Invalid GCS URL" unless gs_url.start_with? prefix
2114
+ # seprating params from input url
2115
+ path, query = gs_url.sub(prefix, "").split("?", 2)
2116
+ # parsing the url
2117
+ bucket_name, file_path = path.split "/", 2
2118
+ query_params = URI.decode_www_form(query).to_h if query
2119
+ url_items = {
2120
+ "bucket_name" => bucket_name,
2121
+ "file_path" => file_path
2122
+ }
2123
+ # adding url params to output hash
2124
+ url_items.merge! "options" => query_params if query
2125
+ url_items
2126
+ end
2127
+
2060
2128
  protected
2061
2129
 
2062
2130
  ##
@@ -2172,10 +2240,8 @@ module Google
2172
2240
  [dest_bucket, dest_path]
2173
2241
  end
2174
2242
 
2175
- # rubocop:disable Style/MultipleComparison
2176
-
2177
2243
  def verify_file! file, verify = :md5
2178
- verify_md5 = verify == :md5 || verify == :all
2244
+ verify_md5 = verify == :md5 || verify == :all
2179
2245
  verify_crc32c = verify == :crc32c || verify == :all
2180
2246
  Verifier.verify_md5! self, file if verify_md5 && md5
2181
2247
  Verifier.verify_crc32c! self, file if verify_crc32c && crc32c
@@ -62,6 +62,15 @@ module Google
62
62
  @service = service
63
63
  end
64
64
 
65
+ ##
66
+ # The universe domain the client is connected to
67
+ #
68
+ # @return [String]
69
+ #
70
+ def universe_domain
71
+ service.universe_domain
72
+ end
73
+
65
74
  ##
66
75
  # The Storage project connected to.
67
76
  #
@@ -412,6 +421,7 @@ module Google
412
421
  # b.lifecycle.add_set_storage_class_rule "COLDLINE", age: 10
413
422
  # end
414
423
  #
424
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
415
425
  def create_bucket bucket_name,
416
426
  acl: nil,
417
427
  default_acl: nil,
@@ -426,11 +436,13 @@ module Google
426
436
  requester_pays: nil,
427
437
  user_project: nil,
428
438
  autoclass_enabled: false,
429
- enable_object_retention: nil
439
+ enable_object_retention: nil,
440
+ hierarchical_namespace: nil
430
441
  params = {
431
442
  name: bucket_name,
432
443
  location: location,
433
- custom_placement_config: custom_placement_config
444
+ custom_placement_config: custom_placement_config,
445
+ hierarchical_namespace: hierarchical_namespace
434
446
  }.delete_if { |_, v| v.nil? }
435
447
  new_bucket = Google::Apis::StorageV1::Bucket.new(**params)
436
448
  storage_class = storage_class_for storage_class
@@ -443,6 +455,7 @@ module Google
443
455
  b.website_404 = website_404 unless website_404.nil?
444
456
  b.versioning = versioning unless versioning.nil?
445
457
  b.requester_pays = requester_pays unless requester_pays.nil?
458
+ b.hierarchical_namespace = hierarchical_namespace unless hierarchical_namespace.nil?
446
459
  end
447
460
  yield updater if block_given?
448
461
  updater.check_for_changed_labels!
@@ -454,6 +467,7 @@ module Google
454
467
  enable_object_retention: enable_object_retention
455
468
  Bucket.from_gapi gapi, service, user_project: user_project
456
469
  end
470
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
457
471
 
458
472
  ##
459
473
  # Creates a new HMAC key.
@@ -15,6 +15,7 @@
15
15
 
16
16
  require "google/cloud/storage/version"
17
17
  require "google/apis/storage_v1"
18
+ require "google/cloud/config"
18
19
  require "digest"
19
20
  require "mini_mime"
20
21
  require "pathname"
@@ -36,6 +37,11 @@ module Google
36
37
  # @private
37
38
  attr_accessor :credentials
38
39
 
40
+ # @private
41
+ def universe_domain
42
+ service.universe_domain
43
+ end
44
+
39
45
  ##
40
46
  # Creates a new Service instance.
41
47
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -43,7 +49,8 @@ module Google
43
49
  timeout: nil, open_timeout: nil, read_timeout: nil,
44
50
  send_timeout: nil, host: nil, quota_project: nil,
45
51
  max_elapsed_time: nil, base_interval: nil, max_interval: nil,
46
- multiplier: nil, upload_chunk_size: nil
52
+ multiplier: nil, upload_chunk_size: nil, universe_domain: nil
53
+ host ||= Google::Cloud::Storage.configure.endpoint
47
54
  @project = project
48
55
  @credentials = credentials
49
56
  @service = API::StorageService.new
@@ -68,6 +75,13 @@ module Google
68
75
  @service.request_options.upload_chunk_size = upload_chunk_size if upload_chunk_size
69
76
  @service.authorization = @credentials.client if @credentials
70
77
  @service.root_url = host if host
78
+ @service.universe_domain = universe_domain || Google::Cloud::Storage.configure.universe_domain
79
+ begin
80
+ @service.verify_universe_domain!
81
+ rescue Google::Apis::UniverseDomainError => e
82
+ # TODO: Create a Google::Cloud::Error subclass for this.
83
+ raise Google::Cloud::Error, e.message
84
+ end
71
85
  end
72
86
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
73
87
 
@@ -351,8 +365,8 @@ module Google
351
365
  # Retrieves a list of files matching the criteria.
352
366
  def list_files bucket_name, delimiter: nil, max: nil, token: nil,
353
367
  prefix: nil, versions: nil, user_project: nil,
354
- match_glob: nil,
355
- options: {}
368
+ match_glob: nil, include_folders_as_prefixes: nil,
369
+ soft_deleted: nil, options: {}
356
370
  execute do
357
371
  service.list_objects \
358
372
  bucket_name, delimiter: delimiter, max_results: max,
@@ -360,6 +374,8 @@ module Google
360
374
  versions: versions,
361
375
  user_project: user_project(user_project),
362
376
  match_glob: match_glob,
377
+ include_folders_as_prefixes: include_folders_as_prefixes,
378
+ soft_deleted: soft_deleted,
363
379
  options: options
364
380
  end
365
381
  end
@@ -443,6 +459,7 @@ module Google
443
459
  if_metageneration_not_match: nil,
444
460
  key: nil,
445
461
  user_project: nil,
462
+ soft_deleted: nil,
446
463
  options: {}
447
464
  execute do
448
465
  service.get_object \
@@ -453,6 +470,7 @@ module Google
453
470
  if_metageneration_match: if_metageneration_match,
454
471
  if_metageneration_not_match: if_metageneration_not_match,
455
472
  user_project: user_project(user_project),
473
+ soft_deleted: soft_deleted,
456
474
  options: key_options(key).merge(options)
457
475
  end
458
476
  end
@@ -525,7 +543,6 @@ module Google
525
543
  if_metageneration_match: nil,
526
544
  user_project: nil,
527
545
  options: {}
528
-
529
546
  source_objects = compose_file_source_objects source_files, if_source_generation_match
530
547
  compose_req = Google::Apis::StorageV1::ComposeRequest.new source_objects: source_objects,
531
548
  destination: destination_gapi
@@ -620,7 +637,6 @@ module Google
620
637
  if_metageneration_not_match: nil,
621
638
  user_project: nil,
622
639
  options: {}
623
-
624
640
  if options[:retries].nil?
625
641
  is_idempotent = retry? generation: generation, if_generation_match: if_generation_match
626
642
  options = is_idempotent ? {} : { retries: 0 }
@@ -638,6 +654,39 @@ module Google
638
654
  end
639
655
  end
640
656
 
657
+ ##
658
+ # Restores a soft-deleted object.
659
+ def restore_file bucket_name,
660
+ file_path,
661
+ generation,
662
+ copy_source_acl: nil,
663
+ if_generation_match: nil,
664
+ if_generation_not_match: nil,
665
+ if_metageneration_match: nil,
666
+ if_metageneration_not_match: nil,
667
+ projection: nil,
668
+ user_project: nil,
669
+ fields: nil,
670
+ options: {}
671
+ if options[:retries].nil?
672
+ is_idempotent = retry? generation: generation, if_generation_match: if_generation_match
673
+ options = is_idempotent ? {} : { retries: 0 }
674
+ end
675
+
676
+ execute do
677
+ service.restore_object bucket_name, file_path, generation,
678
+ copy_source_acl: copy_source_acl,
679
+ if_generation_match: if_generation_match,
680
+ if_generation_not_match: if_generation_not_match,
681
+ if_metageneration_match: if_metageneration_match,
682
+ if_metageneration_not_match: if_metageneration_not_match,
683
+ projection: projection,
684
+ user_project: user_project(user_project),
685
+ fields: fields,
686
+ options: options
687
+ end
688
+ end
689
+
641
690
  ##
642
691
  # Retrieves a list of ACLs for the given file.
643
692
  def list_file_acls bucket_name, file_name, user_project: nil, options: {}
@@ -686,7 +735,6 @@ module Google
686
735
  # Returns Google::Apis::StorageV1::HmacKey.
687
736
  def create_hmac_key service_account_email, project_id: nil,
688
737
  user_project: nil, options: {}
689
-
690
738
  if options[:retries].nil?
691
739
  options = options.merge({ retries: 0 })
692
740
  end
@@ -16,7 +16,7 @@
16
16
  module Google
17
17
  module Cloud
18
18
  module Storage
19
- VERSION = "1.47.0".freeze
19
+ VERSION = "1.54.0".freeze
20
20
  end
21
21
  end
22
22
  end
@@ -67,6 +67,8 @@ module Google
67
67
  # @param [Integer] send_timeout How long, in seconds, before receiving response from server times out. Optional.
68
68
  # @param [String] endpoint Override of the endpoint host name. Optional.
69
69
  # If the param is nil, uses the default endpoint.
70
+ # @param universe_domain [String] Override of the universe domain. Optional.
71
+ # If unset or nil, uses the default unvierse domain
70
72
  # @param [Integer] upload_chunk_size The chunk size of storage upload, in bytes.
71
73
  # The default value is 100 MB, i.e. 104_857_600 bytes. To disable chunking and upload
72
74
  # the complete file regardless of size, pass 0 as the chunk size.
@@ -92,20 +94,21 @@ module Google
92
94
  timeout: nil, open_timeout: nil, read_timeout: nil,
93
95
  send_timeout: nil, endpoint: nil, project: nil, keyfile: nil,
94
96
  max_elapsed_time: nil, base_interval: nil, max_interval: nil,
95
- multiplier: nil, upload_chunk_size: nil
97
+ multiplier: nil, upload_chunk_size: nil, universe_domain: nil
96
98
  scope ||= configure.scope
97
99
  retries ||= configure.retries
98
100
  timeout ||= configure.timeout
99
- open_timeout ||= (configure.open_timeout || timeout)
100
- read_timeout ||= (configure.read_timeout || timeout)
101
- send_timeout ||= (configure.send_timeout || timeout)
101
+ open_timeout ||= configure.open_timeout || timeout
102
+ read_timeout ||= configure.read_timeout || timeout
103
+ send_timeout ||= configure.send_timeout || timeout
102
104
  endpoint ||= configure.endpoint
103
- credentials ||= (keyfile || default_credentials(scope: scope))
105
+ credentials ||= keyfile || default_credentials(scope: scope)
104
106
  max_elapsed_time ||= configure.max_elapsed_time
105
107
  base_interval ||= configure.base_interval
106
108
  max_interval ||= configure.max_interval
107
109
  multiplier ||= configure.multiplier
108
110
  upload_chunk_size ||= configure.upload_chunk_size
111
+ universe_domain ||= configure.universe_domain
109
112
 
110
113
  unless credentials.is_a? Google::Auth::Credentials
111
114
  credentials = Storage::Credentials.new credentials, scope: scope
@@ -121,7 +124,8 @@ module Google
121
124
  read_timeout: read_timeout, send_timeout: send_timeout,
122
125
  host: endpoint, quota_project: configure.quota_project,
123
126
  max_elapsed_time: max_elapsed_time, base_interval: base_interval,
124
- max_interval: max_interval, multiplier: multiplier, upload_chunk_size: upload_chunk_size
127
+ max_interval: max_interval, multiplier: multiplier, upload_chunk_size: upload_chunk_size,
128
+ universe_domain: universe_domain
125
129
  )
126
130
  )
127
131
  end
@@ -145,6 +149,8 @@ module Google
145
149
  # @param [Integer] send_timeout How long, in seconds, before receiving response from server times out. Optional.
146
150
  # @param [String] endpoint Override of the endpoint host name. Optional.
147
151
  # If the param is nil, uses the default endpoint.
152
+ # @param universe_domain [String] Override of the universe domain. Optional.
153
+ # If unset or nil, uses the default unvierse domain
148
154
  # @param [Integer] upload_chunk_size The chunk size of storage upload, in bytes.
149
155
  # The default value is 100 MB, i.e. 104_857_600 bytes. To disable chunking and upload
150
156
  # the complete file regardless of size, pass 0 as the chunk size.
@@ -166,7 +172,7 @@ module Google
166
172
  def self.anonymous retries: nil, timeout: nil, open_timeout: nil,
167
173
  read_timeout: nil, send_timeout: nil, endpoint: nil,
168
174
  max_elapsed_time: nil, base_interval: nil, max_interval: nil,
169
- multiplier: nil, upload_chunk_size: nil
175
+ multiplier: nil, upload_chunk_size: nil, universe_domain: nil
170
176
  open_timeout ||= timeout
171
177
  read_timeout ||= timeout
172
178
  send_timeout ||= timeout
@@ -175,7 +181,8 @@ module Google
175
181
  nil, nil, retries: retries, timeout: timeout, open_timeout: open_timeout,
176
182
  read_timeout: read_timeout, send_timeout: send_timeout, host: endpoint,
177
183
  max_elapsed_time: max_elapsed_time, base_interval: base_interval,
178
- max_interval: max_interval, multiplier: multiplier, upload_chunk_size: upload_chunk_size
184
+ max_interval: max_interval, multiplier: multiplier, upload_chunk_size: upload_chunk_size,
185
+ universe_domain: universe_domain
179
186
  )
180
187
  )
181
188
  end
@@ -79,11 +79,11 @@ module Google
79
79
  def storage scope: nil, retries: nil, timeout: nil, open_timeout: nil, read_timeout: nil, send_timeout: nil,
80
80
  max_elapsed_time: nil, base_interval: nil, max_interval: nil, multiplier: nil, upload_chunk_size: nil
81
81
  Google::Cloud.storage @project, @keyfile, scope: scope,
82
- retries: (retries || @retries),
83
- timeout: (timeout || @timeout),
84
- open_timeout: (open_timeout || timeout),
85
- read_timeout: (read_timeout || timeout),
86
- send_timeout: (send_timeout || timeout),
82
+ retries: retries || @retries,
83
+ timeout: timeout || @timeout,
84
+ open_timeout: open_timeout || timeout,
85
+ read_timeout: read_timeout || timeout,
86
+ send_timeout: send_timeout || timeout,
87
87
  max_elapsed_time: max_elapsed_time,
88
88
  base_interval: base_interval,
89
89
  max_interval: max_interval,
@@ -149,9 +149,9 @@ module Google
149
149
  scope: scope,
150
150
  retries: retries,
151
151
  timeout: timeout,
152
- open_timeout: (open_timeout || timeout),
153
- read_timeout: (read_timeout || timeout),
154
- send_timeout: (send_timeout || timeout),
152
+ open_timeout: open_timeout || timeout,
153
+ read_timeout: read_timeout || timeout,
154
+ send_timeout: send_timeout || timeout,
155
155
  max_elapsed_time: max_elapsed_time,
156
156
  base_interval: base_interval,
157
157
  max_interval: max_interval,
@@ -162,7 +162,6 @@ module Google
162
162
  end
163
163
 
164
164
  # Set the default storage configuration
165
- # rubocop:disable Metrics/BlockLength
166
165
  Google::Cloud.configure.add_config! :storage do |config|
167
166
  default_project = Google::Cloud::Config.deferred do
168
167
  ENV["STORAGE_PROJECT"]
@@ -192,7 +191,6 @@ Google::Cloud.configure.add_config! :storage do |config|
192
191
  config.add_field! :read_timeout, nil, match: Integer
193
192
  config.add_field! :send_timeout, nil, match: Integer
194
193
  config.add_field! :upload_chunk_size, nil, match: Integer
195
- # TODO: Remove once discovery document is updated.
196
- config.add_field! :endpoint, "https://storage.googleapis.com/", match: String
194
+ config.add_field! :endpoint, nil, match: String, allow_nil: true
195
+ config.add_field! :universe_domain, nil, match: String, allow_nil: true
197
196
  end
198
- # rubocop:enable Metrics/BlockLength
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-cloud-storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.47.0
4
+ version: 1.54.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Moore
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-01-09 00:00:00.000000000 Z
12
+ date: 2024-12-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: google-cloud-core
@@ -25,54 +25,62 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '1.6'
28
+ - !ruby/object:Gem::Dependency
29
+ name: google-apis-core
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '0.13'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '0.13'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: google-apis-iamcredentials_v1
30
44
  requirement: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - "~>"
33
47
  - !ruby/object:Gem::Version
34
- version: '0.1'
48
+ version: '0.18'
35
49
  type: :runtime
36
50
  prerelease: false
37
51
  version_requirements: !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - "~>"
40
54
  - !ruby/object:Gem::Version
41
- version: '0.1'
55
+ version: '0.18'
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: google-apis-storage_v1
44
58
  requirement: !ruby/object:Gem::Requirement
45
59
  requirements:
46
60
  - - "~>"
47
61
  - !ruby/object:Gem::Version
48
- version: 0.31.0
62
+ version: '0.38'
49
63
  type: :runtime
50
64
  prerelease: false
51
65
  version_requirements: !ruby/object:Gem::Requirement
52
66
  requirements:
53
67
  - - "~>"
54
68
  - !ruby/object:Gem::Version
55
- version: 0.31.0
69
+ version: '0.38'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: googleauth
58
72
  requirement: !ruby/object:Gem::Requirement
59
73
  requirements:
60
- - - ">="
61
- - !ruby/object:Gem::Version
62
- version: 0.16.2
63
- - - "<"
74
+ - - "~>"
64
75
  - !ruby/object:Gem::Version
65
- version: 2.a
76
+ version: '1.9'
66
77
  type: :runtime
67
78
  prerelease: false
68
79
  version_requirements: !ruby/object:Gem::Requirement
69
80
  requirements:
70
- - - ">="
71
- - !ruby/object:Gem::Version
72
- version: 0.16.2
73
- - - "<"
81
+ - - "~>"
74
82
  - !ruby/object:Gem::Version
75
- version: 2.a
83
+ version: '1.9'
76
84
  - !ruby/object:Gem::Dependency
77
85
  name: digest-crc
78
86
  requirement: !ruby/object:Gem::Requirement
@@ -121,14 +129,14 @@ dependencies:
121
129
  requirements:
122
130
  - - "~>"
123
131
  - !ruby/object:Gem::Version
124
- version: 1.25.1
132
+ version: 1.30.0
125
133
  type: :development
126
134
  prerelease: false
127
135
  version_requirements: !ruby/object:Gem::Requirement
128
136
  requirements:
129
137
  - - "~>"
130
138
  - !ruby/object:Gem::Version
131
- version: 1.25.1
139
+ version: 1.30.0
132
140
  - !ruby/object:Gem::Dependency
133
141
  name: minitest
134
142
  requirement: !ruby/object:Gem::Requirement
@@ -325,14 +333,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
325
333
  requirements:
326
334
  - - ">="
327
335
  - !ruby/object:Gem::Version
328
- version: '2.7'
336
+ version: 3.0.0
329
337
  required_rubygems_version: !ruby/object:Gem::Requirement
330
338
  requirements:
331
339
  - - ">="
332
340
  - !ruby/object:Gem::Version
333
341
  version: '0'
334
342
  requirements: []
335
- rubygems_version: 3.5.3
343
+ rubygems_version: 3.5.23
336
344
  signing_key:
337
345
  specification_version: 4
338
346
  summary: API Client library for Google Cloud Storage