diff --git a/.toys/batch-review-legacy.rb b/.toys/batch-review-legacy.rb index 8801147607e9..69a043a4e7ed 100644 --- a/.toys/batch-review-legacy.rb +++ b/.toys/batch-review-legacy.rb @@ -41,7 +41,7 @@ /\.release-please-manifest\.json$/, /\/CHANGELOG\.md$/, /\/version\.rb$/, - /\/snippets\/snippet_metadata_[\w\.]+\.json$/, + /\/snippets\/snippet_metadata_[\w.]+\.json$/, ], }, "releases-wrappers" => { @@ -62,7 +62,7 @@ /\.release-please-manifest\.json$/, /\/CHANGELOG\.md$/, /\/version\.rb$/, - /\/snippets\/snippet_metadata_[\w\.]+\.json$/, + /\/snippets\/snippet_metadata_[\w.]+\.json$/, ], }, }.freeze diff --git a/.toys/batch-review.rb b/.toys/batch-review.rb index b97d8ad5fc04..31edb28afba1 100644 --- a/.toys/batch-review.rb +++ b/.toys/batch-review.rb @@ -31,7 +31,7 @@ batch_reviewer.define_preset "releases", based_on: :basic_releases do |preset| preset.message << :pr_title_number preset.diff_expectations.expect name: "snippet metadata" do |expect| - expect.change_type(:changed).path_pattern(/\/snippets\/snippet_metadata_[\w\.]+\.json$/) + expect.change_type(:changed).path_pattern(/\/snippets\/snippet_metadata_[\w.]+\.json$/) end preset.diff_expectations.expect name: "repo metadata" do |expect| expect.change_type(:changed).path_pattern(/\/\.repo-metadata\.json$/) diff --git a/google-cloud-storage/lib/google/cloud/storage/bucket.rb b/google-cloud-storage/lib/google/cloud/storage/bucket.rb index ca8461354bb7..885f729d4500 100644 --- a/google-cloud-storage/lib/google/cloud/storage/bucket.rb +++ b/google-cloud-storage/lib/google/cloud/storage/bucket.rb @@ -717,6 +717,30 @@ def default_kms_key= new_default_kms_key patch_gapi! :encryption end + ## + # Restart resumable upload + # @param [String, ::File] file Path of the file on the filesystem to + # upload. Can be a File object, or File-like object such as StringIO. + # @param [String] upload_id Unique Id of a resumable upload + # + # @return [Google::Apis::StorageV1::Object, Boolean] + # The object metadata on success, or 'false' request is not completed. + # + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # + # bucket = storage.bucket "my-bucket" + # bucket.restart_resumable_upload file, upload_id + + def restart_resumable_upload file, upload_id + ensure_service! + ensure_io_or_file_exists! file + raise ArgumentError, "Upload Id missing" unless upload_id + service.restart_resumable_upload name, file, upload_id + end + ## # The period of time (in seconds) that files in the bucket must be # retained, and cannot be deleted, overwritten, or archived. @@ -1410,6 +1434,27 @@ def delete if_metageneration_match: nil, if_metageneration_not_match: nil user_project: user_project end + ## + # Delete resumable upload + # @param [String] upload_id Unique Id of a resumable upload + # + # @return [Boolean] Returns `true` if the resumable upload was deleted, + # 'false' if the request is not completed. + # + # @example + # require "google/cloud/storage" + # + # storage = Google::Cloud::Storage.new + # + # bucket = storage.bucket "my-bucket" + # bucket.delete_resumable_upload upload_id + + def delete_resumable_upload upload_id + ensure_service! + raise ArgumentError, "Upload Id missing" unless upload_id + service.delete_resumable_upload name, upload_id + end + ## # Retrieves a list of files matching the criteria. # diff --git a/google-cloud-storage/lib/google/cloud/storage/service.rb b/google-cloud-storage/lib/google/cloud/storage/service.rb index d9adf2acff65..4d3fcaf07c09 100644 --- a/google-cloud-storage/lib/google/cloud/storage/service.rb +++ b/google-cloud-storage/lib/google/cloud/storage/service.rb @@ -696,6 +696,18 @@ def delete_file bucket_name, end end + def restart_resumable_upload bucket_name, source, upload_id, options: {} + execute do + service.restart_resumable_upload bucket_name, source, upload_id, options: options + end + end + + def delete_resumable_upload bucket_name, upload_id, options: {} + execute do + service.delete_resumable_upload bucket_name, upload_id, options: options + end + end + ## # Restore soft deleted bucket def restore_bucket bucket_name, diff --git a/google-cloud-storage/test/google/cloud/storage/bucket_test.rb b/google-cloud-storage/test/google/cloud/storage/bucket_test.rb index 203e423467e5..cc45518f2903 100644 --- a/google-cloud-storage/test/google/cloud/storage/bucket_test.rb +++ b/google-cloud-storage/test/google/cloud/storage/bucket_test.rb @@ -1408,6 +1408,112 @@ end end + it "restarts a resumable upload with upload_id" do + new_file_name = random_file_path + upload_id = "TEST_ID" + + Tempfile.open ["google-cloud", ".txt"] do |tmpfile| + tmpfile.write "Hello world" + tmpfile.rewind + mock = Minitest::Mock.new + expected_return_value = create_file_gapi(bucket.name, new_file_name) + mock.expect :restart_resumable_upload, expected_return_value, + [bucket.name, tmpfile, upload_id], + **resumable_upload_args(options: {}) + bucket.service.mocked_service = mock + returned_value= bucket.restart_resumable_upload tmpfile, upload_id + assert_equal expected_return_value, returned_value + mock.verify + end + end + + it "raises ArgumentError if anyone or both arguments are not provided to restart_resumable_upload" do + upload_id = "TEST_ID" + + Tempfile.open ["google-cloud", ".txt"] do |tmpfile| + tmpfile.write "Hello world" + tmpfile.rewind + error = _ { bucket.restart_resumable_upload }.must_raise ArgumentError + assert_match "wrong number of arguments", error.message + + error = _ { bucket.restart_resumable_upload upload_id }.must_raise ArgumentError + assert_match "wrong number of arguments", error.message + + error = _ { bucket.restart_resumable_upload tmpfile }.must_raise ArgumentError + assert_match "wrong number of arguments", error.message + end + end + + it "raises ArgumentError if upload_id as nil is provided to restart_resumable_upload" do + upload_id = nil + + Tempfile.open ["google-cloud", ".txt"] do |tmpfile| + tmpfile.write "Hello world" + tmpfile.rewind + error = _ { bucket.restart_resumable_upload tmpfile, upload_id }.must_raise ArgumentError + assert_match "Upload Id missing", error.message + end + end + + it "returns false if restart_resumable_upload is provided wrong upload_id" do + new_file_name = random_file_path + upload_id = "wrong_TEST_ID" + + Tempfile.open ["google-cloud", ".txt"] do |tmpfile| + tmpfile.write "Hello world" + tmpfile.rewind + mock = Minitest::Mock.new + expected_return_value = false + mock.expect :restart_resumable_upload, expected_return_value, + [bucket.name, tmpfile, upload_id], + **resumable_upload_args(options: {}) + bucket.service.mocked_service = mock + returned_value= bucket.restart_resumable_upload tmpfile, upload_id + assert_equal expected_return_value, returned_value + mock.verify + end + end + + + it "deletes a resumable upload with upload_id" do + upload_id = "TEST_ID" + + mock = Minitest::Mock.new + expected_return_value = true + mock.expect :delete_resumable_upload, expected_return_value, + [bucket.name, upload_id], + **resumable_upload_args(options: {}) + bucket.service.mocked_service = mock + returned_value = bucket.delete_resumable_upload upload_id + assert_equal expected_return_value, returned_value + mock.verify + end + + it "returns false if delete_resumable_upload is provided wrong upload_id" do + upload_id = "wrong_TEST_ID" + + mock = Minitest::Mock.new + expected_return_value = false + mock.expect :delete_resumable_upload, expected_return_value, + [bucket.name, upload_id], + **resumable_upload_args(options: {}) + bucket.service.mocked_service = mock + returned_value = bucket.delete_resumable_upload upload_id + assert_equal expected_return_value, returned_value + mock.verify + end + + it "raises ArgumentError if upload_id is not provided to delete_resumable_upload" do + error = _ { bucket.delete_resumable_upload }.must_raise ArgumentError + assert_match "wrong number of arguments", error.message + end + + it "raises ArgumentError if upload_id as nil is provided to delete_resumable_upload" do + upload_id = nil + error = _ { bucket.delete_resumable_upload upload_id }.must_raise ArgumentError + assert_match "Upload Id missing", error.message + end + def create_file_gapi bucket=nil, name = nil Google::Apis::StorageV1::Object.from_json random_file_hash(bucket, name).to_json end diff --git a/google-cloud-storage/test/helper.rb b/google-cloud-storage/test/helper.rb index 5d37f92feb26..09644b957b7a 100644 --- a/google-cloud-storage/test/helper.rb +++ b/google-cloud-storage/test/helper.rb @@ -391,6 +391,12 @@ def insert_object_args name: nil, } end + def resumable_upload_args options: {} + { + options: options + } + end + def get_object_args generation: nil, if_generation_match: nil, if_generation_not_match: nil,