lib/google/cloud/storage/file.rb in google-cloud-storage-0.25.0 vs lib/google/cloud/storage/file.rb in google-cloud-storage-1.0.0
- old
+ new
@@ -169,11 +169,11 @@
# Updates the
# [Cache-Control](https://tools.ietf.org/html/rfc7234#section-5.2)
# directive for the file data.
def cache_control= cache_control
@gapi.cache_control = cache_control
- patch_gapi! :cache_control
+ update_gapi! :cache_control
end
##
# The [Content-Disposition](https://tools.ietf.org/html/rfc6266) of the
# file data.
@@ -184,11 +184,11 @@
##
# Updates the [Content-Disposition](https://tools.ietf.org/html/rfc6266)
# of the file data.
def content_disposition= content_disposition
@gapi.content_disposition = content_disposition
- patch_gapi! :content_disposition
+ update_gapi! :content_disposition
end
##
# The [Content-Encoding
# ](https://tools.ietf.org/html/rfc7231#section-3.1.2.2) of the file
@@ -201,11 +201,11 @@
# Updates the [Content-Encoding
# ](https://tools.ietf.org/html/rfc7231#section-3.1.2.2) of the file
# data.
def content_encoding= content_encoding
@gapi.content_encoding = content_encoding
- patch_gapi! :content_encoding
+ update_gapi! :content_encoding
end
##
# The [Content-Language](http://tools.ietf.org/html/bcp47) of the file
# data.
@@ -216,11 +216,11 @@
##
# Updates the [Content-Language](http://tools.ietf.org/html/bcp47) of
# the file data.
def content_language= content_language
@gapi.content_language = content_language
- patch_gapi! :content_language
+ update_gapi! :content_language
end
##
# The [Content-Type](https://tools.ietf.org/html/rfc2616#section-14.17)
# of the file data.
@@ -232,11 +232,11 @@
# Updates the
# [Content-Type](https://tools.ietf.org/html/rfc2616#section-14.17) of
# the file data.
def content_type= content_type
@gapi.content_type = content_type
- patch_gapi! :content_type
+ update_gapi! :content_type
end
##
# A hash of custom, user-provided web-safe keys and arbitrary string
# values that will returned with requests for the file as "x-goog-meta-"
@@ -251,11 +251,11 @@
# Updates the hash of custom, user-provided web-safe keys and arbitrary
# string values that will returned with requests for the file as
# "x-goog-meta-" response headers.
def metadata= metadata
@gapi.metadata = metadata
- patch_gapi! :metadata
+ update_gapi! :metadata
end
##
# An [RFC 4648](https://tools.ietf.org/html/rfc4648#section-4)
# Base64-encoded string of the SHA256 hash of the [customer-supplied
@@ -290,13 +290,12 @@
# Class](https://cloud.google.com/storage/docs/per-object-storage-class).
# The default value is the default storage class for the bucket. See
# {Bucket#storage_class}.
# @param [Symbol, String] storage_class Storage class of the file.
def storage_class= storage_class
- resp = service.update_file_storage_class \
- bucket, name, storage_class_for(storage_class)
- @gapi = resp.resource
+ @gapi.storage_class = storage_class_for(storage_class)
+ update_gapi! :storage_class
end
##
# Updates the file with changes made in the given block in a single
# PATCH request. The following attributes may be set: {#cache_control=},
@@ -327,11 +326,11 @@
#
def update
updater = Updater.new gapi
yield updater
updater.check_for_changed_metadata!
- patch_gapi! updater.updates unless updater.updates.empty?
+ update_gapi! updater.updates unless updater.updates.empty?
end
##
# Download the file's contents to a local file or an IO instance.
#
@@ -467,10 +466,11 @@
# @param [Integer] generation Select a specific revision of the file to
# copy. The default is the latest version.
# @param [String] encryption_key Optional. The customer-supplied,
# AES-256 encryption key used to encrypt the file, if one was provided
# to {Bucket#create_file}.
+ # @yield [file] a block yielding a delegate object for updating
#
# @return [Google::Cloud::Storage::File]
#
# @example The file can be copied to a new path in the current bucket:
# require "google/cloud/storage"
@@ -502,21 +502,47 @@
#
# file = bucket.file "path/to/my-file.ext"
# file.copy "copy/of/previous/generation/file.ext",
# generation: 123456
#
+ # @example The file can be modified during copying:
+ # require "google/cloud/storage"
+ #
+ # storage = Google::Cloud::Storage.new
+ #
+ # bucket = storage.bucket "my-bucket"
+ #
+ # file = bucket.file "path/to/my-file.ext"
+ # file.copy "new-destination-bucket",
+ # "path/to/destination/file.ext" do |f|
+ # f.metadata["copied_from"] = "#{file.bucket}/#{file.name}"
+ # end
+ #
def copy dest_bucket_or_path, dest_path = nil, acl: nil,
generation: nil, encryption_key: nil
ensure_service!
- options = { acl: acl, generation: generation,
- key: encryption_key }
+ options = { acl: acl, generation: generation, key: encryption_key }
dest_bucket, dest_path, options = fix_copy_args dest_bucket_or_path,
dest_path, options
- gapi = service.copy_file bucket, name,
- dest_bucket, dest_path, options
- File.from_gapi gapi, service
+ copy_gapi = nil
+ if block_given?
+ updater = Updater.new gapi
+ yield updater
+ updater.check_for_changed_metadata!
+ copy_gapi = gapi_from_attrs(updater.updates) if updater.updates.any?
+ end
+
+ resp = service.copy_file bucket, name, dest_bucket, dest_path,
+ copy_gapi, options
+ until resp.done
+ sleep 1
+ resp = service.copy_file bucket, name, dest_bucket, dest_path,
+ copy_gapi,
+ options.merge(token: resp.rewrite_token)
+ end
+ File.from_gapi resp.resource, service
end
##
# [Rewrites](https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite)
# the file to the same {#bucket} and {#name} with a new
@@ -564,14 +590,15 @@
#
def rotate encryption_key: nil, new_encryption_key: nil
ensure_service!
options = { source_key: encryption_key,
destination_key: new_encryption_key }
- gapi = service.rewrite_file bucket, name, bucket, name, options
+ gapi = service.rewrite_file bucket, name, bucket, name, nil, options
until gapi.done
+ sleep 1
options[:token] = gapi.rewrite_token
- gapi = service.rewrite_file bucket, name, bucket, name, options
+ gapi = service.rewrite_file bucket, name, bucket, name, nil, options
end
File.from_gapi gapi.resource, service
end
##
@@ -803,21 +830,45 @@
# Raise an error unless an active service is available.
def ensure_service!
fail "Must have active connection" unless service
end
- def patch_gapi! *attributes
+ def update_gapi! *attributes
attributes.flatten!
return if attributes.empty?
+ update_gapi = gapi_from_attrs attributes
+ return if update_gapi.nil?
+
ensure_service!
- patch_args = Hash[attributes.map do |attr|
+
+ if attributes.include? :storage_class
+ @gapi = rewrite_gapi bucket, name, update_gapi
+ else
+ @gapi = service.patch_file bucket, name, update_gapi
+ end
+ end
+
+ def gapi_from_attrs *attributes
+ attributes.flatten!
+ return nil if attributes.empty?
+ attr_params = Hash[attributes.map do |attr|
[attr, @gapi.send(attr)]
end]
- patch_gapi = Google::Apis::StorageV1::Object.new patch_args
- @gapi = service.patch_file bucket, name, patch_gapi
+ Google::Apis::StorageV1::Object.new attr_params
end
+ def rewrite_gapi bucket, name, update_gapi
+ resp = service.rewrite_file bucket, name, bucket, name, update_gapi
+ until resp.done
+ sleep 1
+ rewrite_options = { token: resp.rewrite_token }
+ resp = service.rewrite_file bucket, name, bucket, name,
+ update_gapi, rewrite_options
+ end
+ resp.resource
+ end
+
def fix_copy_args dest_bucket, dest_path, options = {}
if dest_path.respond_to?(:to_hash) && options.empty?
options = dest_path
dest_path = nil
end
@@ -851,55 +902,51 @@
end
##
# Yielded to a block to accumulate changes for a patch request.
class Updater < File
- # @private Do not allow storage_class to be set in an update call.
- # It cannot be set with PATCH.
- undef :storage_class=
-
# @private
attr_reader :updates
##
# @private Create an Updater object.
def initialize gapi
@updates = []
@gapi = gapi
+ @metadata ||= @gapi.metadata.to_h.dup
end
##
# A hash of custom, user-provided web-safe keys and arbitrary string
# values that will returned with requests for the file as
# "x-goog-meta-" response headers.
def metadata
- # do not freeze metadata
- @metadata ||= @gapi.metadata.to_h.dup
+ @metadata
end
##
# Updates the hash of custom, user-provided web-safe keys and
# arbitrary string values that will returned with requests for the
# file as "x-goog-meta-" response headers.
def metadata= metadata
@metadata = metadata
@gapi.metadata = @metadata
- patch_gapi! :metadata
+ update_gapi! :metadata
end
##
# @private Make sure any metadata changes are saved
def check_for_changed_metadata!
- return if @metadata == @gapi.metadata
+ return if @metadata == @gapi.metadata.to_h
@gapi.metadata = @metadata
- patch_gapi! :metadata
+ update_gapi! :metadata
end
protected
##
# Queue up all the updates instead of making them.
- def patch_gapi! attribute
+ def update_gapi! attribute
@updates << attribute
@updates.uniq!
end
end
end