Google Cloud Storage C++ Client  1.40.2
A C++ Client Library for Google Cloud Storage
client.h
Go to the documentation of this file.
1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H
17 
18 #include "google/cloud/storage/hmac_key_metadata.h"
19 #include "google/cloud/storage/internal/logging_client.h"
20 #include "google/cloud/storage/internal/parameter_pack_validation.h"
21 #include "google/cloud/storage/internal/policy_document_request.h"
22 #include "google/cloud/storage/internal/retry_client.h"
23 #include "google/cloud/storage/internal/signed_url_requests.h"
24 #include "google/cloud/storage/internal/tuple_filter.h"
25 #include "google/cloud/storage/list_buckets_reader.h"
26 #include "google/cloud/storage/list_hmac_keys_reader.h"
27 #include "google/cloud/storage/list_objects_and_prefixes_reader.h"
28 #include "google/cloud/storage/list_objects_reader.h"
29 #include "google/cloud/storage/notification_event_type.h"
30 #include "google/cloud/storage/notification_payload_format.h"
31 #include "google/cloud/storage/oauth2/google_credentials.h"
32 #include "google/cloud/storage/object_rewriter.h"
33 #include "google/cloud/storage/object_stream.h"
34 #include "google/cloud/storage/retry_policy.h"
35 #include "google/cloud/storage/upload_options.h"
36 #include "google/cloud/storage/version.h"
37 #include "google/cloud/internal/throw_delegate.h"
38 #include "google/cloud/status.h"
39 #include "google/cloud/status_or.h"
40 #include "absl/meta/type_traits.h"
41 #include <string>
42 #include <type_traits>
43 #include <vector>
44 
45 namespace google {
46 namespace cloud {
47 namespace storage {
49 namespace internal {
50 class NonResumableParallelUploadState;
51 class ResumableParallelUploadState;
52 struct ClientImplDetails;
53 } // namespace internal
54 /**
55  * The Google Cloud Storage (GCS) Client.
56  *
57  * This is the main class to interact with GCS. It provides member functions to
58  * invoke all the APIs in the service.
59  *
60  * @par Performance
61  * Creating an object of this type is a relatively low-cost operation.
62  * Connections to the service are created on demand. Copy-assignment and
63  * copy-construction are also relatively low-cost operations, they should be
64  * comparable to copying a few shared pointers. The first request (or any
65  * request that requires a new connection) incurs the cost of creating the
66  * connection and authenticating with the service. Note that the library may
67  * need to perform other bookkeeping operations that may impact performance.
68  * For example, access tokens need to be refreshed from time to time, and this
69  * may impact the performance of some operations.
70  *
71  * @par Connection Pool
72  * By default this class uses HTTPS to communicate with the service. Creating a
73  * new HTTPS session is relatively expensive, as it must go through the TCP/IP
74  * and SSL handshakes. To minimize this overhead the class maintains a
75  * connection pool to the service. After each request completes the connection
76  * is returned to the pool, and reused in future requests. Note that for
77  * downloads (implemented by the ReadObject() member function) the connection
78  * remains in use until the download completes. Therefore, having multiple
79  * downloads open at the same time requires multiple connections.
80  *
81  * The application can limit the maximum size of this connection pool using
82  * `storage::ConnectionPoolSizeOption`. If returning a connection to the pool
83  * would make the pool larger than this limit then the oldest connection in the
84  * pool is closed (recall that all connections in the pool are inactive). Note
85  * that this is the maximum size of the pool, the client library does not create
86  * connections until needed.
87  *
88  * Note that the application may (at times) use more connections than the
89  * maximum size of the pool. For example if N downloads are in progress the
90  * library may need N connections, even if the the pool size is smaller.
91  *
92  * Two clients that compare equal share the same connection pool. Two clients
93  * created with the default constructor or with the constructor from a
94  * `google::cloud::Options` are never equal and do not share connection pools.
95  * Clients created via copy (or move) construction compare equal and share the
96  * connection pool.
97  *
98  * @par Thread-safety
99  * Instances of this class created via copy-construction or copy-assignment
100  * share the underlying pool of connections. Access to these copies via multiple
101  * threads is guaranteed to work. Two threads operating on the same instance of
102  * this class is not guaranteed to work.
103  *
104  * @par Credentials
105  * The default approach for creating a Client uses Google Application Default
106  * Credentials (ADCs). Note that a default-constructed client uses the ADCs:
107  *
108  * @snippet storage_client_initialization_samples.cc default-client
109  *
110  * Finding or loading the ADCs can fail. This will result in run-time errors
111  * when making requests.
112  *
113  * If you prefer to explicitly load the ADCs use:
114  *
115  * @snippet storage_client_initialization_samples.cc explicit-adcs
116  *
117  * To load a service account credentials key file use:
118  *
119  * @snippet storage_client_initialization_samples.cc service-account-keyfile
120  *
121  * Other credential types are available, including:
122  *
123  * - `google::cloud::MakeInsecureCredentials()` for anonymous access to public
124  * GCS buckets or objects.
125  * - `google::cloud::MakeAccessTokenCredentials()` to use an access token
126  * obtained through any out-of-band mechanism.
127  * - `google::cloud::MakeImpersonateServiceAccountCredentials()` to use the IAM
128  * credentials service and [impersonate a service account].
129  * - `google::cloud::MakeServiceAccountCredentials()` to use a service account
130  * key file.
131  *
132  * [impersonate service account]:
133  * https://cloud.google.com/iam/docs/impersonating-service-accounts
134  *
135  * @par Error Handling
136  * This class uses `StatusOr<T>` to report errors. When an operation fails to
137  * perform its work the returned `StatusOr<T>` contains the error details. If
138  * the `ok()` member function in the `StatusOr<T>` returns `true` then it
139  * contains the expected result. Please consult the [`StatusOr<T>`
140  * documentation](#google::cloud::StatusOr) for more details.
141  *
142  * @code
143  * namespace gcs = google::cloud::storage;
144  * gcs::Client client = ...;
145  * google::cloud::StatusOr<gcs::BucketMetadata> bucket_metadata =
146  * client.GetBucketMetadata("my-bucket");
147  *
148  * if (!bucket_metadata) {
149  * std::cerr << "Error getting metadata for my-bucket: "
150  * << bucket_metadata.status() << "\n";
151  * return;
152  * }
153  *
154  * // Use bucket_metadata as a smart pointer here, e.g.:
155  * std::cout << "The generation for " << bucket_metadata->name() " is "
156  * << bucket_metadata->generation() << "\n";
157  * @endcode
158  *
159  * In addition, the @ref index "main page" contains examples using `StatusOr<T>`
160  * to handle errors.
161  *
162  * @par Optional Parameters
163  * Most of the member functions in this class can receive optional parameters
164  * to modify their behavior. For example, the default when reading multi-version
165  * objects is to retrieve the latest version:
166  *
167  * @code
168  * auto stream = gcs.ReadObject("my-bucket", "my-object");
169  * @endcode
170  *
171  * Some applications may want to retrieve specific versions, in this case
172  * just provide the `Generation` option:
173  *
174  * @code
175  * auto stream = gcs.ReadObject(
176  * "my-bucket", "my-object", gcs::Generation(generation));
177  * @endcode
178  *
179  * Each function documents the types accepted as optional parameters. These
180  * options can be specified in any order. Specifying an option that is not
181  * applicable to a member function results in a compile-time error.
182  *
183  * @par Retry, Backoff, and Idempotency Policies
184  *
185  * The library automatically retries requests that fail with transient errors,
186  * and follows the
187  * [recommended
188  * practice](https://cloud.google.com/storage/docs/exponential-backoff) to
189  * backoff between retries.
190  *
191  * The default policies are to continue retrying for up to 15 minutes, and to
192  * use truncated (at 5 minutes) exponential backoff, doubling the maximum
193  * backoff period between retries. Likewise, the idempotency policy is
194  * configured to retry all operations.
195  *
196  * The application can override these policies when constructing objects of this
197  * class. The documentation for the constructors show examples of this in
198  * action.
199  *
200  * @see https://cloud.google.com/storage/ for an overview of GCS.
201  *
202  * @see https://cloud.google.com/storage/docs/key-terms for an introduction of
203  * the key terms used in GCS.
204  *
205  * @see https://cloud.google.com/storage/docs/json_api/ for an overview of the
206  * underlying API.
207  *
208  * @see https://cloud.google.com/docs/authentication/production for details
209  * about Application Default %Credentials.
210  *
211  * @see #google::cloud::StatusOr.
212  *
213  * @see `LimitedTimeRetryPolicy` and `LimitedErrorCountRetryPolicy` for
214  * alternative retry policies.
215  *
216  * @see `ExponentialBackoffPolicy` to configure different parameters for the
217  * exponential backoff policy.
218  *
219  * @see `AlwaysRetryIdempotencyPolicy` and `StrictIdempotencyPolicy` for
220  * alternative idempotency policies.
221  */
222 class Client {
223  public:
224  /**
225  * Build a new client.
226  *
227  * @param opts the configuration parameters for the `Client`.
228  *
229  * @see #ClientOptionList for a list of useful options.
230  *
231  * @par Idempotency Policy Example
232  * @snippet storage_object_samples.cc insert object strict idempotency
233  *
234  * @par Modified Retry Policy Example
235  * @snippet storage_object_samples.cc insert object modified retry
236  *
237  * @par Change Credentials Example
238  * @snippet storage_client_initialization_samples.cc service-account-keyfile
239  */
240  explicit Client(Options opts = {});
241 
242  /**
243  * Creates the default client type given the options.
244  *
245  * @param options the client options, these are used to control credentials,
246  * buffer sizes, etc.
247  * @param policies the client policies, these control the behavior of the
248  * client, for example, how to backoff when an operation needs to be
249  * retried, or what operations cannot be retried because they are not
250  * idempotent.
251  *
252  * @deprecated use the constructor from `google::cloud::Options` instead.
253  */
254  template <typename... Policies>
255  explicit Client(ClientOptions options, Policies&&... policies)
256  : Client(InternalOnly{}, internal::ApplyPolicies(
257  internal::MakeOptions(std::move(options)),
258  std::forward<Policies>(policies)...)) {}
259 
260  /**
261  * Creates the default client type given the credentials and policies.
262  *
263  * @param credentials a set of credentials to initialize the `ClientOptions`.
264  * @param policies the client policies, these control the behavior of the
265  * client, for example, how to backoff when an operation needs to be
266  * retried, or what operations cannot be retried because they are not
267  * idempotent.
268  *
269  * @deprecated use the constructor from `google::cloud::Options` instead.
270  */
271  template <typename... Policies>
272  explicit Client(std::shared_ptr<oauth2::Credentials> credentials,
273  Policies&&... policies)
274  : Client(InternalOnly{},
275  internal::ApplyPolicies(
276  internal::DefaultOptions(std::move(credentials), {}),
277  std::forward<Policies>(policies)...)) {}
278 
279  /**
280  * Create a Client using ClientOptions::CreateDefaultClientOptions().
281  *
282  * @deprecated use the constructor from `google::cloud::Options` instead.
283  */
284  static StatusOr<Client> CreateDefaultClient();
285 
286  /// Builds a client and maybe override the retry, idempotency, and/or backoff
287  /// policies.
288  /// @deprecated This was intended only for test code, applications should not
289  /// use it.
290  template <typename... Policies>
291 #if !defined(_MSC_VER) || _MSC_VER >= 1920
292  GOOGLE_CLOUD_CPP_DEPRECATED(
293  "applications should not need this."
294  " Please use the constructors from ClientOptions instead."
295  " For mocking, please use testing::ClientFromMock() instead."
296  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
297  " if you have a use-case not covered by these.")
298 #endif // _MSC_VER
299  // NOLINTNEXTLINE(performance-unnecessary-value-param)
300  explicit Client(std::shared_ptr<internal::RawClient> client,
301  Policies&&... policies)
302  : Client(InternalOnlyNoDecorations{},
303  CreateDefaultInternalClient(
304  internal::ApplyPolicies(
305  internal::DefaultOptions(
306  client->client_options().credentials(), {}),
307  std::forward<Policies>(policies)...),
308  client)) {
309  }
310 
311  /// Define a tag to disable automatic decorations of the RawClient.
312  struct NoDecorations {};
313 
314  /// Builds a client with a specific RawClient, without decorations.
315  /// @deprecated This was intended only for test code, applications should not
316  /// use it.
317  GOOGLE_CLOUD_CPP_DEPRECATED(
318  "applications should not need this."
319  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
320  " if you do.")
321  explicit Client(std::shared_ptr<internal::RawClient> client, NoDecorations)
322  : Client(InternalOnlyNoDecorations{}, std::move(client)) {}
323 
324  //@{
325  // @name Equality
326  friend bool operator==(Client const& a, Client const& b) {
327  return a.raw_client_ == b.raw_client_;
328  }
329  friend bool operator!=(Client const& a, Client const& b) { return !(a == b); }
330  //@}
331 
332  /// Access the underlying `RawClient`.
333  /// @deprecated Only intended for implementors, do not use.
334  GOOGLE_CLOUD_CPP_DEPRECATED(
335  "applications should not need this."
336  " Please file a bug at https://github.com/googleapis/google-cloud-cpp"
337  " if you do.")
338  std::shared_ptr<internal::RawClient> raw_client() const {
339  return raw_client_;
340  }
341 
342  //@{
343  /**
344  * @name Bucket operations.
345  *
346  * Buckets are the basic containers that hold your data. Everything that you
347  * store in GCS must be contained in a bucket. You can use buckets to organize
348  * your data and control access to your data, but unlike directories and
349  * folders, you cannot nest buckets.
350  *
351  * @see https://cloud.google.com/storage/docs/key-terms#buckets for more
352  * information about GCS buckets.
353  */
354  /**
355  * Fetches the list of buckets for a given project.
356  *
357  * @param project_id the project to query.
358  * @param options a list of optional query parameters and/or request headers.
359  * Valid types for this operation include `MaxResults`, `Prefix`,
360  * `UserProject`, and `Projection`.
361  *
362  * @par Idempotency
363  * This is a read-only operation and is always idempotent.
364  *
365  * @par Example
366  * @snippet storage_bucket_samples.cc list buckets for project
367  */
368  template <typename... Options>
369  ListBucketsReader ListBucketsForProject(std::string const& project_id,
370  Options&&... options) {
371  internal::ListBucketsRequest request(project_id);
372  request.set_multiple_options(std::forward<Options>(options)...);
373  auto client = raw_client_;
374  return google::cloud::internal::MakePaginationRange<ListBucketsReader>(
375  request,
376  [client](internal::ListBucketsRequest const& r) {
377  return client->ListBuckets(r);
378  },
379  [](internal::ListBucketsResponse r) { return std::move(r.items); });
380  }
381 
382  /**
383  * Fetches the list of buckets for the default project.
384  *
385  * The default project is required to be configured in the `ClientOptions`
386  * used to construct this object. If the application does not set the project
387  * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
388  * used. If neither the environment variable is set, nor a value is set
389  * explicitly by the application, the returned `ListBucketsReader` will
390  * return an error status when used.
391  *
392  * @param options a list of optional query parameters and/or request headers.
393  * Valid types for this operation include `MaxResults`, `Prefix`,
394  * `UserProject`, and `Projection`.
395  *
396  * @par Idempotency
397  * This is a read-only operation and is always idempotent.
398  *
399  * @par Example
400  * @snippet storage_bucket_samples.cc list buckets
401  */
402  template <typename... Options>
403  ListBucketsReader ListBuckets(Options&&... options) {
404  auto const& project_id = raw_client_->client_options().project_id();
405  return ListBucketsForProject(project_id, std::forward<Options>(options)...);
406  }
407 
408  /**
409  * Creates a new Google Cloud Storage bucket using the default project. If
410  * the default project is not configured the server will reject the request,
411  * and this function returns the error status.
412  *
413  * @param bucket_name the name of the new bucket.
414  * @param metadata the metadata for the new Bucket. The `name` field is
415  * ignored in favor of @p bucket_name.
416  * @param options a list of optional query parameters and/or request headers.
417  * Valid types for this operation include `PredefinedAcl`,
418  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
419  *
420  * @par Idempotency
421  * This operation is always idempotent. It fails if the bucket already exists.
422  *
423  * @par Example
424  * @snippet storage_bucket_samples.cc create bucket
425  *
426  * @see Before enabling Uniform Bucket Level Access please review the
427  * [feature documentation][ubla-link], as well as
428  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
429  *
430  * [ubla-link]:
431  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
432  * [ubla-should-link]:
433  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
434  */
435  template <typename... Options>
436  StatusOr<BucketMetadata> CreateBucket(std::string bucket_name,
437  BucketMetadata metadata,
438  Options&&... options) {
439  auto const& project_id = raw_client_->client_options().project_id();
440  return CreateBucketForProject(std::move(bucket_name), project_id,
441  std::move(metadata),
442  std::forward<Options>(options)...);
443  }
444 
445  /**
446  * Creates a new Google Cloud Storage Bucket in a given project.
447  *
448  * @param bucket_name the name of the new bucket.
449  * @param project_id the id of the project that will host the new bucket.
450  * @param metadata the metadata for the new Bucket. The `name` field is
451  * ignored in favor of @p bucket_name.
452  * @param options a list of optional query parameters and/or request headers.
453  * Valid types for this operation include `PredefinedAcl`,
454  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
455  *
456  * @par Idempotency
457  * This operation is always idempotent. It fails if the bucket already exists.
458  *
459  * @par Example
460  * @snippet storage_bucket_samples.cc create bucket for project
461  *
462  * @see Before enabling Uniform Bucket Level Access please review the
463  * [feature documentation][ubla-link], as well as
464  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
465  *
466  * [ubla-link]:
467  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
468  * [ubla-should-link]:
469  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
470  */
471  template <typename... Options>
472  StatusOr<BucketMetadata> CreateBucketForProject(std::string bucket_name,
473  std::string project_id,
474  BucketMetadata metadata,
475  Options&&... options) {
476  metadata.set_name(std::move(bucket_name));
477  internal::CreateBucketRequest request(std::move(project_id),
478  std::move(metadata));
479  request.set_multiple_options(std::forward<Options>(options)...);
480  return raw_client_->CreateBucket(request);
481  }
482 
483  /**
484  * Fetches the bucket metadata.
485  *
486  * @param bucket_name query metadata information about this bucket.
487  * @param options a list of optional query parameters and/or request headers.
488  * Valid types for this operation include `IfMetagenerationMatch`,
489  * `IfMetagenerationNotMatch`, `UserProject`, and `Projection`.
490  *
491  * @par Idempotency
492  * This is a read-only operation and is always idempotent.
493  *
494  * @par Example
495  * @snippet storage_bucket_samples.cc get bucket metadata
496  */
497  template <typename... Options>
498  StatusOr<BucketMetadata> GetBucketMetadata(std::string const& bucket_name,
499  Options&&... options) {
500  internal::GetBucketMetadataRequest request(bucket_name);
501  request.set_multiple_options(std::forward<Options>(options)...);
502  return raw_client_->GetBucketMetadata(request);
503  }
504 
505  /**
506  * Deletes a Google Cloud Storage Bucket.
507  *
508  * @param bucket_name the bucket to be deleted.
509  * @param options a list of optional query parameters and/or request headers.
510  * Valid types for this operation include `IfMetagenerationMatch`,
511  * `IfMetagenerationNotMatch`, and `UserProject`.
512  *
513  * @par Idempotency
514  * This operation is only idempotent if restricted by pre-conditions, in this
515  * case, `IfMetagenerationMatch`.
516  *
517  * @par Example
518  * @snippet storage_bucket_samples.cc delete bucket
519  */
520  template <typename... Options>
521  Status DeleteBucket(std::string const& bucket_name, Options&&... options) {
522  internal::DeleteBucketRequest request(bucket_name);
523  request.set_multiple_options(std::forward<Options>(options)...);
524  return raw_client_->DeleteBucket(request).status();
525  }
526 
527  /**
528  * Updates the metadata in a Google Cloud Storage Bucket.
529  *
530  * A `Buckets: update` request changes *all* the writeable attributes of a
531  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
532  * the attributes included in the request. This function creates a
533  * `Buckets: update` request to change the writable attributes in
534  * `BucketMetadata`.
535  *
536  * @param bucket_name the name of the new bucket.
537  * @param metadata the new metadata for the Bucket. The `name` field is
538  * ignored in favor of @p bucket_name.
539  * @param options a list of optional query parameters and/or request headers.
540  * Valid types for this operation include `IfMetagenerationMatch`,
541  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
542  * `PredefinedDefaultObjectAcl`, `Projection`, and `UserProject`.
543  *
544  * @par Idempotency
545  * This operation is only idempotent if restricted by pre-conditions, in this
546  * case,`IfMetagenerationMatch`.
547  *
548  * @par Example
549  * @snippet storage_bucket_samples.cc update bucket
550  *
551  * @see Before enabling Uniform Bucket Level Access please review the
552  * [feature documentation][ubla-link], as well as
553  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
554  *
555  * [ubla-link]:
556  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
557  * [ubla-should-link]:
558  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
559  */
560  template <typename... Options>
561  StatusOr<BucketMetadata> UpdateBucket(std::string bucket_name,
562  BucketMetadata metadata,
563  Options&&... options) {
564  metadata.set_name(std::move(bucket_name));
565  internal::UpdateBucketRequest request(std::move(metadata));
566  request.set_multiple_options(std::forward<Options>(options)...);
567  return raw_client_->UpdateBucket(request);
568  }
569 
570  /**
571  * Computes the difference between two BucketMetadata objects and patches a
572  * bucket based on that difference.
573  *
574  * A `Buckets: update` request changes *all* the writeable attributes of a
575  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
576  * the attributes included in the request.
577  *
578  * This function creates a patch request to change the writeable attributes in
579  * @p original to the values in @p updated. Non-writeable attributes are
580  * ignored, and attributes not present in @p updated are removed. Typically
581  * this function is used after the application obtained a value with
582  * `GetBucketMetadata` and has modified these parameters.
583  *
584  * @param bucket_name the bucket to be updated.
585  * @param original the initial value of the bucket metadata.
586  * @param updated the updated value for the bucket metadata.
587  * @param options a list of optional query parameters and/or request headers.
588  * Valid types for this operation include `IfMetagenerationMatch`,
589  * `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
590  *
591  * @par Idempotency
592  * This operation is only idempotent if restricted by pre-conditions, in this
593  * case, `IfMetagenerationMatch`.
594  *
595  * @par Example
596  * @snippet storage_bucket_samples.cc patch bucket storage class
597  *
598  * @see Before enabling Uniform Bucket Level Access please review the
599  * [feature documentation][ubla-link], as well as
600  * ["Should you use uniform bucket-level access?"][ubla-should-link].
601  *
602  * [ubla-link]:
603  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
604  * [ubla-should-link]:
605  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
606  */
607  template <typename... Options>
608  StatusOr<BucketMetadata> PatchBucket(std::string bucket_name,
609  BucketMetadata const& original,
610  BucketMetadata const& updated,
611  Options&&... options) {
612  internal::PatchBucketRequest request(std::move(bucket_name), original,
613  updated);
614  request.set_multiple_options(std::forward<Options>(options)...);
615  return raw_client_->PatchBucket(request);
616  }
617 
618  /**
619  * Patches the metadata in a Google Cloud Storage Bucket given a desired set
620  * changes.
621  *
622  * A `Buckets: update` request changes *all* the writeable attributes of a
623  * bucket, in contrast, a `Buckets: patch` request only changes the subset of
624  * the attributes included in the request. This function creates a patch
625  * request based on the given `BucketMetadataPatchBuilder` which represents
626  * the desired set of changes.
627  *
628  * @param bucket_name the bucket to be updated.
629  * @param builder the set of updates to perform in the Bucket.
630  * @param options a list of optional query parameters and/or request headers.
631  * Valid types for this operation include `IfMetagenerationMatch`,
632  * `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
633  *
634  * @par Idempotency
635  * This operation is only idempotent if restricted by pre-conditions, in this
636  * case, `IfMetagenerationMatch`.
637  *
638  * @par Example
639  * @snippet storage_bucket_samples.cc patch bucket storage class with builder
640  *
641  * @see Before enabling Uniform Bucket Level Access please review the
642  * [feature documentation][ubla-link], as well as
643  * ["Should you use uniform bucket-level access ?"][ubla-should-link].
644  *
645  * [ubla-link]:
646  * https://cloud.google.com/storage/docs/uniform-bucket-level-access
647  * [ubla-should-link]:
648  * https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
649  */
650  template <typename... Options>
652  std::string bucket_name, BucketMetadataPatchBuilder const& builder,
653  Options&&... options) {
654  internal::PatchBucketRequest request(std::move(bucket_name), builder);
655  request.set_multiple_options(std::forward<Options>(options)...);
656  return raw_client_->PatchBucket(request);
657  }
658 
659  /**
660  * Fetches the native
661  * [IAM policy](@ref google::cloud::storage::NativeIamPolicy) for a Bucket.
662  *
663  * Google Cloud Identity & Access Management (IAM) lets administrators
664  * authorize who can take action on specific resources, including Google
665  * Cloud Storage Buckets. This operation allows you to query the IAM policies
666  * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
667  * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
668  * documentation describes
669  * [the
670  * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
671  * between legacy Bucket ACLs and IAM policies.
672  *
673  * Consult
674  * [the
675  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
676  * for a more detailed description of IAM policies and their use in
677  * Google Cloud Storage.
678  *
679  * @param bucket_name query metadata information about this bucket.
680  * @param options a list of optional query parameters and/or request headers.
681  * Valid types for this operation include `UserProject`.
682  *
683  * @par Idempotency
684  * This is a read-only operation and is always idempotent.
685  *
686  * @par Example
687  * @snippet storage_bucket_iam_samples.cc native get bucket iam policy
688  *
689  * @see #google::cloud::storage::NativeIamPolicy for details about the
690  * `NativeIamPolicy` class.
691  */
692  template <typename... Options>
694  std::string const& bucket_name, Options&&... options) {
695  internal::GetBucketIamPolicyRequest request(bucket_name);
696  request.set_multiple_options(std::forward<Options>(options)...);
697  return raw_client_->GetNativeBucketIamPolicy(request);
698  }
699 
700  /**
701  * Sets the native
702  * [IAM Policy](@ref google::cloud::storage::NativeIamPolicy) for a Bucket.
703  *
704  * Google Cloud Identity & Access Management (IAM) lets administrators
705  * authorize who can take action on specific resources, including Google
706  * Cloud Storage Buckets. This operation allows you to set the IAM policies
707  * for a Bucket. IAM policies are a superset of the Bucket ACL, changes
708  * to the Bucket ACL are reflected in the IAM policy, and vice-versa. The
709  * documentation describes
710  * [the
711  * mapping](https://cloud.google.com/storage/docs/access-control/iam#acls)
712  * between legacy Bucket ACLs and IAM policies.
713  *
714  * Consult
715  * [the
716  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
717  * for a more detailed description of IAM policies their use in
718  * Google Cloud Storage.
719  *
720  * @note The server rejects requests where the ETag value of the policy does
721  * not match the current ETag. Effectively this means that applications must
722  * use `GetNativeBucketIamPolicy()` to fetch the current value and ETag
723  * before calling `SetNativeBucketIamPolicy()`. Applications should use
724  * optimistic concurrency control techniques to retry changes in case some
725  * other application modified the IAM policy between the
726  * `GetNativeBucketIamPolicy` and `SetNativeBucketIamPolicy` calls.
727  *
728  * @param bucket_name query metadata information about this bucket.
729  * @param iam_policy the new IAM policy.
730  * @param options a list of optional query parameters and/or request headers.
731  * Valid types for this operation include `UserProject`.
732  *
733  * @par Idempotency
734  * This operation is only idempotent if restricted by pre-conditions, in this
735  * case, `IfMetagenerationMatch`.
736  *
737  * @par Example: adding a new member
738  * @snippet storage_bucket_iam_samples.cc native add bucket iam member
739  *
740  * @par Example: removing a IAM member
741  * @snippet storage_bucket_iam_samples.cc native remove bucket iam member
742  *
743  * @see #google::cloud::storage::NativeIamPolicy for details about the
744  * `NativeIamPolicy` class.
745  */
746  template <typename... Options>
748  std::string const& bucket_name, NativeIamPolicy const& iam_policy,
749  Options&&... options) {
750  internal::SetNativeBucketIamPolicyRequest request(bucket_name, iam_policy);
751  request.set_multiple_options(std::forward<Options>(options)...);
752  return raw_client_->SetNativeBucketIamPolicy(request);
753  }
754 
755  /**
756  * Tests the IAM permissions of the caller against a Bucket.
757  *
758  * Google Cloud Identity & Access Management (IAM) lets administrators
759  * authorize who can take action on specific resources, including Google
760  * Cloud Storage Buckets. This operation tests the permissions of the caller
761  * for a Bucket. You must provide a list of permissions, this API will return
762  * the subset of those permissions that the current caller has in the given
763  * Bucket.
764  *
765  * Consult
766  * [the
767  * documentation](https://cloud.google.com/storage/docs/access-control/iam)
768  * for a more detailed description of IAM policies their use in
769  * Google Cloud Storage.
770  *
771  * @param bucket_name query metadata information about this bucket.
772  * @param permissions the list of permissions to check.
773  * @param options a list of optional query parameters and/or request headers.
774  * Valid types for this operation include `UserProject`.
775  *
776  * @par Idempotency
777  * This is a read-only operation and is always idempotent.
778  *
779  * @par Example
780  * @snippet storage_bucket_iam_samples.cc test bucket iam permissions
781  */
782  template <typename... Options>
783  StatusOr<std::vector<std::string>> TestBucketIamPermissions(
784  std::string bucket_name, std::vector<std::string> permissions,
785  Options&&... options) {
786  internal::TestBucketIamPermissionsRequest request(std::move(bucket_name),
787  std::move(permissions));
788  request.set_multiple_options(std::forward<Options>(options)...);
789  auto result = raw_client_->TestBucketIamPermissions(request);
790  if (!result) {
791  return std::move(result).status();
792  }
793  return std::move(result.value().permissions);
794  }
795 
796  /**
797  * Locks the retention policy for a bucket.
798  *
799  * @warning Locking a retention policy is an irreversible action. Once locked,
800  * you must delete the entire bucket in order to "remove" the bucket's
801  * retention policy. However, before you can delete the bucket, you must
802  * be able to delete all the objects in the bucket, which itself is only
803  * possible if all the objects have reached the retention period set by
804  * the retention policy.
805  *
806  * The [Bucket Lock
807  * feature](https://cloud.google.com/storage/docs/bucket-lock) allows you to
808  * configure a data retention policy for a Cloud Storage bucket that governs
809  * how long objects in the bucket must be retained. The feature also allows
810  * you to lock the data retention policy, permanently preventing the policy
811  * from being reduced or removed.
812  *
813  * @param bucket_name the name of the bucket.
814  * @param metageneration the expected value of the metageneration on the
815  * bucket. The request will fail if the metageneration does not match the
816  * current value.
817  * @param options a list of optional query parameters and/or request headers.
818  * Valid types for this operation include `UserProject`.
819  *
820  * @par Idempotency
821  * This operation is always idempotent because the `metageneration` parameter
822  * is always required, and it acts as a pre-condition on the operation.
823  *
824  * @par Example: lock the retention policy
825  * @snippet storage_retention_policy_samples.cc lock retention policy
826  *
827  * @par Example: get the current retention policy
828  * @snippet storage_retention_policy_samples.cc get retention policy
829  *
830  * @par Example: set the current retention policy
831  * @snippet storage_retention_policy_samples.cc set retention policy
832  *
833  * @par Example: remove the retention policy
834  * @snippet storage_retention_policy_samples.cc remove retention policy
835  *
836  * @see https://cloud.google.com/storage/docs/bucket-lock for a description of
837  * the Bucket Lock feature.
838  *
839  * @see https://cloud.google.com/storage/docs/using-bucket-lock for examples
840  * of how to use the Bucket Lock and retention policy features.
841  */
842  template <typename... Options>
844  std::string const& bucket_name, std::uint64_t metageneration,
845  Options&&... options) {
846  internal::LockBucketRetentionPolicyRequest request(bucket_name,
847  metageneration);
848  request.set_multiple_options(std::forward<Options>(options)...);
849  return raw_client_->LockBucketRetentionPolicy(request);
850  }
851  //@}
852 
853  //@{
854  /**
855  * @name Object operations
856  *
857  * Objects are the individual pieces of data that you store in GCS. Objects
858  * have two components: *object data* and *object metadata*. Object data
859  * (sometimes referred to as *media*) is typically a file that you want
860  * to store in GCS. Object metadata is information that describe various
861  * object qualities.
862  *
863  * @see https://cloud.google.com/storage/docs/key-terms#objects for more
864  * information about GCS objects.
865  */
866  /**
867  * Creates an object given its name and contents.
868  *
869  * @param bucket_name the name of the bucket that will contain the object.
870  * @param object_name the name of the object to be created.
871  * @param contents the contents (media) for the new object.
872  * @param options a list of optional query parameters and/or request headers.
873  * Valid types for this operation include `ContentEncoding`,
874  * `ContentType`, `Crc32cChecksumValue`, `DisableCrc32cChecksum`,
875  * `DisableMD5Hash`, `EncryptionKey`, `IfGenerationMatch`,
876  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
877  * `IfMetagenerationNotMatch`, `KmsKeyName`, `MD5HashValue`,
878  * `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
879  *
880  * @par Idempotency
881  * This operation is only idempotent if restricted by pre-conditions, in this
882  * case, `IfGenerationMatch`.
883  *
884  * @par Example
885  * @snippet storage_object_samples.cc insert object
886  *
887  * @par Example
888  * @snippet storage_object_samples.cc insert object multipart
889  */
890  template <typename... Options>
891  StatusOr<ObjectMetadata> InsertObject(std::string const& bucket_name,
892  std::string const& object_name,
893  std::string contents,
894  Options&&... options) {
895  internal::InsertObjectMediaRequest request(bucket_name, object_name,
896  std::move(contents));
897  request.set_multiple_options(std::forward<Options>(options)...);
898  return raw_client_->InsertObjectMedia(request);
899  }
900 
901  /**
902  * Copies an existing object.
903  *
904  * Use `CopyObject` to copy between objects in the same location and storage
905  * class. Copying objects across locations or storage classes can fail for
906  * large objects and retrying the operation will not succeed.
907  *
908  * @note Prefer using `RewriteObject()` to copy objects, `RewriteObject()` can
909  * copy objects to different locations, with different storage class,
910  * and/or with different encryption keys.
911  *
912  * @param source_bucket_name the name of the bucket that contains the object
913  * to be copied.
914  * @param source_object_name the name of the object to copy.
915  * @param destination_bucket_name the name of the bucket that will contain the
916  * new object.
917  * @param destination_object_name the name of the new object.
918  * @param options a list of optional query parameters and/or request headers.
919  * Valid types for this operation include `DestinationKmsKeyName`,
920  * `DestinationPredefinedAcl`,`EncryptionKey`,`IfGenerationMatch`,
921  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
922  * `IfMetagenerationNotMatch`, `IfSourceGenerationMatch`,
923  * `IfSourceGenerationNotMatch`, `IfSourceMetagenerationMatch`,
924  * `IfSourceMetagenerationNotMatch`, `Projection`, `SourceGeneration`,
925  * `SourceEncryptionKey`, `UserProject`, and `WithObjectMetadata`.
926  *
927  * @par Idempotency
928  * This operation is only idempotent if restricted by pre-conditions, in this
929  * case, `IfGenerationMatch`.
930  *
931  * @par Example
932  * @snippet storage_object_samples.cc copy object
933  *
934  * @par Example: copy an encrypted object
935  * @snippet storage_object_csek_samples.cc copy encrypted object
936  *
937  * @see https://cloud.google.com/storage/docs/json_api/v1/objects/copy for
938  * a full description of the advantages of `Objects: rewrite` over
939  * `Objects: copy`.
940  */
941  template <typename... Options>
942  StatusOr<ObjectMetadata> CopyObject(std::string source_bucket_name,
943  std::string source_object_name,
944  std::string destination_bucket_name,
945  std::string destination_object_name,
946  Options&&... options) {
947  internal::CopyObjectRequest request(
948  std::move(source_bucket_name), std::move(source_object_name),
949  std::move(destination_bucket_name), std::move(destination_object_name));
950  request.set_multiple_options(std::forward<Options>(options)...);
951  return raw_client_->CopyObject(request);
952  }
953 
954  /**
955  * Fetches the object metadata.
956  *
957  * @param bucket_name the bucket containing the object.
958  * @param object_name the object name.
959  * @param options a list of optional query parameters and/or request headers.
960  * Valid types for this operation include `Generation`,
961  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
962  * `IfMetagenerationNotMatch`, `Projection`, and `UserProject`.
963  *
964  * @par Idempotency
965  * This is a read-only operation and is always idempotent.
966  *
967  * @par Example
968  * @snippet storage_object_samples.cc get object metadata
969  */
970  template <typename... Options>
971  StatusOr<ObjectMetadata> GetObjectMetadata(std::string const& bucket_name,
972  std::string const& object_name,
973  Options&&... options) {
974  internal::GetObjectMetadataRequest request(bucket_name, object_name);
975  request.set_multiple_options(std::forward<Options>(options)...);
976  return raw_client_->GetObjectMetadata(request);
977  }
978 
979  /**
980  * Lists the objects in a bucket.
981  *
982  * @param bucket_name the name of the bucket to list.
983  * @param options a list of optional query parameters and/or request headers.
984  * Valid types for this operation include
985  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `UserProject`,
986  * `Projection`, `Prefix`, `Delimiter`, `IncludeTrailingDelimiter`,
987  * `StartOffset`, `EndOffset`, and `Versions`.
988  *
989  * @par Idempotency
990  * This is a read-only operation and is always idempotent.
991  *
992  * @par Example
993  * @snippet storage_object_samples.cc list objects
994  */
995  template <typename... Options>
996  ListObjectsReader ListObjects(std::string const& bucket_name,
997  Options&&... options) {
998  internal::ListObjectsRequest request(bucket_name);
999  request.set_multiple_options(std::forward<Options>(options)...);
1000  auto client = raw_client_;
1001  return google::cloud::internal::MakePaginationRange<ListObjectsReader>(
1002  request,
1003  [client](internal::ListObjectsRequest const& r) {
1004  return client->ListObjects(r);
1005  },
1006  [](internal::ListObjectsResponse r) { return std::move(r.items); });
1007  }
1008 
1009  /**
1010  * Lists the objects and prefixes in a bucket.
1011  *
1012  * @param bucket_name the name of the bucket to list.
1013  * @param options a list of optional query parameters and/or request headers.
1014  * Valid types for this operation include
1015  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `UserProject`,
1016  * `Projection`, `Prefix`, `Delimiter`, `IncludeTrailingDelimiter`,
1017  * `StartOffset`, `EndOffset`, and `Versions`.
1018  *
1019  * @par Idempotency
1020  * This is a read-only operation and is always idempotent.
1021  *
1022  * @par Example
1023  * @snippet storage_object_samples.cc list objects and prefixes
1024  */
1025  template <typename... Options>
1026  ListObjectsAndPrefixesReader ListObjectsAndPrefixes(
1027  std::string const& bucket_name, Options&&... options) {
1028  internal::ListObjectsRequest request(bucket_name);
1029  request.set_multiple_options(std::forward<Options>(options)...);
1030  auto client = raw_client_;
1031  return google::cloud::internal::MakePaginationRange<
1032  ListObjectsAndPrefixesReader>(
1033  request,
1034  [client](internal::ListObjectsRequest const& r) {
1035  return client->ListObjects(r);
1036  },
1037  [](internal::ListObjectsResponse r) {
1038  std::vector<ObjectOrPrefix> result;
1039  for (auto& item : r.items) {
1040  result.emplace_back(std::move(item));
1041  }
1042  for (auto& prefix : r.prefixes) {
1043  result.emplace_back(std::move(prefix));
1044  }
1045  internal::SortObjectsAndPrefixes(result);
1046  return result;
1047  });
1048  }
1049 
1050  /**
1051  * Reads the contents of an object.
1052  *
1053  * Returns an object derived from `std::istream` which can be used to read the
1054  * contents of the GCS blob. The application should check the `badbit` (e.g.
1055  * by calling `stream.bad()`) on the returned object to detect if there was
1056  * an error reading from the blob. If `badbit` is set, the application can
1057  * check the `status()` variable to get details about the failure.
1058  * Applications can also set the exception mask on the returned stream, in
1059  * which case an exception is thrown if an error is detected.
1060  *
1061  * @param bucket_name the name of the bucket that contains the object.
1062  * @param object_name the name of the object to be read.
1063  * @param options a list of optional query parameters and/or request headers.
1064  * Valid types for this operation include `DisableCrc32cChecksum`,
1065  * `DisableMD5Hash`, `IfGenerationMatch`, `EncryptionKey`, `Generation`,
1066  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1067  * `IfMetagenerationNotMatch`, `ReadFromOffset`, `ReadRange`, `ReadLast`,
1068  * `UserProject`, and `AcceptEncoding`.
1069  *
1070  * @par Idempotency
1071  * This is a read-only operation and is always idempotent.
1072  *
1073  * @par Example
1074  * @snippet storage_object_samples.cc read object
1075  *
1076  * @par Example: read only a sub-range in the object.
1077  * @snippet storage_object_samples.cc read object range
1078  *
1079  * @par Example: read a object encrypted with a CSEK.
1080  * @snippet storage_object_csek_samples.cc read encrypted object
1081  *
1082  * @par Example: disable decompressive transcoding.
1083  * @snippet storage_object_samples.cc read object gzip
1084  */
1085  template <typename... Options>
1086  ObjectReadStream ReadObject(std::string const& bucket_name,
1087  std::string const& object_name,
1088  Options&&... options) {
1089  struct HasReadRange
1090  : public absl::disjunction<std::is_same<ReadRange, Options>...> {};
1091  struct HasReadFromOffset
1092  : public absl::disjunction<std::is_same<ReadFromOffset, Options>...> {};
1093  struct HasReadLast
1094  : public absl::disjunction<std::is_same<ReadLast, Options>...> {};
1095 
1096  struct HasIncompatibleRangeOptions
1097  : public std::integral_constant<bool, HasReadLast::value &&
1098  (HasReadFromOffset::value ||
1099  HasReadRange::value)> {};
1100 
1101  static_assert(!HasIncompatibleRangeOptions::value,
1102  "Cannot set ReadLast option with either ReadFromOffset or "
1103  "ReadRange.");
1104 
1105  internal::ReadObjectRangeRequest request(bucket_name, object_name);
1106  request.set_multiple_options(std::forward<Options>(options)...);
1107  return ReadObjectImpl(request);
1108  }
1109 
1110  /**
1111  * Writes contents into an object.
1112  *
1113  * This creates a `std::ostream` object to upload contents. The application
1114  * can use either the regular `operator<<()`, or `std::ostream::write()` to
1115  * upload data.
1116  *
1117  * This function always uses [resumable uploads][resumable-link]. The
1118  * application can provide a `#RestoreResumableUploadSession()` option to
1119  * resume a previously created upload. The returned object has accessors to
1120  * query the session id and the next byte expected by GCS.
1121  *
1122  * @note When resuming uploads it is the application's responsibility to save
1123  * the session id to restart the upload later. Likewise, it is the
1124  * application's responsibility to query the next expected byte and send
1125  * the remaining data without gaps or duplications.
1126  *
1127  * For small uploads we recommend using `InsertObject`, consult
1128  * [the documentation][how-to-upload-link] for details.
1129  *
1130  * If the application does not provide a `#RestoreResumableUploadSession()`
1131  * option, or it provides the `#NewResumableUploadSession()` option then a new
1132  * resumable upload session is created.
1133  *
1134  * More information about buffering and recommendations around performance in
1135  * the `ObjectWriteStream` class documentation.
1136  *
1137  * @param bucket_name the name of the bucket that contains the object.
1138  * @param object_name the name of the object to be read.
1139  * @param options a list of optional query parameters and/or request headers.
1140  * Valid types for this operation include `ContentEncoding`, `ContentType`,
1141  * `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1142  * `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1143  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1144  * `MD5HashValue`, `PredefinedAcl`, `Projection`,
1145  * `UseResumableUploadSession`, `UserProject`, `WithObjectMetadata`,
1146  * `UploadContentLength`, `AutoFinalize`, and `UploadBufferSize`.
1147  *
1148  * @par Idempotency
1149  * This operation is only idempotent if restricted by pre-conditions, in this
1150  * case, `IfGenerationMatch`.
1151  *
1152  * @par Example
1153  * @snippet storage_object_samples.cc write object
1154  *
1155  * @par Example: write an object with a CMEK.
1156  * @snippet storage_object_cmek_samples.cc write object with kms key
1157  *
1158  * @par Example: starting a resumable upload.
1159  * @snippet storage_object_resumable_write_samples.cc start resumable upload
1160  *
1161  * @par Example: resuming a resumable upload.
1162  * @snippet storage_object_resumable_write_samples.cc resume resumable upload
1163  *
1164  * @see [Resumable Uploads][resumable-link] for more information about
1165  * resumable uploads.
1166  *
1167  * [resumable-link]: https://cloud.google.com/storage/docs/resumable-uploads
1168  * [how-to-upload-link]:
1169  * https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload
1170  */
1171  template <typename... Options>
1172  ObjectWriteStream WriteObject(std::string const& bucket_name,
1173  std::string const& object_name,
1174  Options&&... options) {
1175  internal::ResumableUploadRequest request(bucket_name, object_name);
1176  request.set_multiple_options(std::forward<Options>(options)...);
1177  return WriteObjectImpl(request);
1178  }
1179 
1180  /**
1181  * Uploads a file to an object.
1182  *
1183  * @note
1184  * Only regular files are supported. If you need to upload the results of
1185  * reading a device, Named Pipe, FIFO, or other type of file system object
1186  * that is **not** a regular file then `WriteObject()` is probably a better
1187  * alternative.
1188  *
1189  * @param file_name the name of the file to be uploaded.
1190  * @param bucket_name the name of the bucket that contains the object.
1191  * @param object_name the name of the object to be read.
1192  * @param options a list of optional query parameters and/or request headers.
1193  * Valid types for this operation include `ContentEncoding`, `ContentType`,
1194  * `Crc32cChecksumValue`, `DisableCrc32cChecksum`, `DisableMD5Hash`,
1195  * `EncryptionKey`, `IfGenerationMatch`, `IfGenerationNotMatch`,
1196  * `IfMetagenerationMatch`, `IfMetagenerationNotMatch`, `KmsKeyName`,
1197  * `MD5HashValue`, `PredefinedAcl`, `Projection`, `UserProject`,
1198  * `UploadFromOffset`, `UploadLimit` and `WithObjectMetadata`.
1199  *
1200  * @par Idempotency
1201  * This operation is only idempotent if restricted by pre-conditions, in this
1202  * case, `IfGenerationMatch`.
1203  *
1204  * @par Example
1205  * @snippet storage_object_file_transfer_samples.cc upload file
1206  *
1207  * @par Example: manually selecting a resumable upload
1208  * @snippet storage_object_file_transfer_samples.cc upload file resumable
1209  */
1210  template <typename... Options>
1211  StatusOr<ObjectMetadata> UploadFile(std::string const& file_name,
1212  std::string const& bucket_name,
1213  std::string const& object_name,
1214  Options&&... options) {
1215  // Determine, at compile time, which version of UploadFileImpl we should
1216  // call. This needs to be done at compile time because ObjectInsertMedia
1217  // does not support (nor should it support) the UseResumableUploadSession
1218  // option.
1219  using HasUseResumableUpload =
1220  absl::disjunction<std::is_same<UseResumableUploadSession, Options>...>;
1221  return UploadFileImpl(file_name, bucket_name, object_name,
1222  HasUseResumableUpload{},
1223  std::forward<Options>(options)...);
1224  }
1225 
1226  /**
1227  * Cancel a resumable upload.
1228  *
1229  * @param upload_session_url the url of the upload session. Returned by
1230  * `ObjectWriteStream::resumable_session_id`.
1231  * @param options a list of optional query parameters and/or request headers.
1232  * Valid types for this operation include `UserProject`.
1233  *
1234  * @par Idempotency
1235  * This operation is always idempotent because it only acts on a specific
1236  * `upload_session_url`.
1237  */
1238  template <typename... Options>
1239  Status DeleteResumableUpload(std::string const& upload_session_url,
1240  Options&&... options) {
1241  internal::DeleteResumableUploadRequest request(upload_session_url);
1242  request.set_multiple_options(std::forward<Options>(options)...);
1243  return raw_client_->DeleteResumableUpload(request).status();
1244  }
1245 
1246  /**
1247  * Downloads a Cloud Storage object to a file.
1248  *
1249  * @param bucket_name the name of the bucket that contains the object.
1250  * @param object_name the name of the object to be downloaded.
1251  * @param file_name the name of the destination file that will have the object
1252  * media.
1253  * @param options a list of optional query parameters and/or request headers.
1254  * Valid types for this operation include `IfGenerationMatch`,
1255  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1256  * `IfMetagenerationNotMatch`, `Generation`, `ReadFromOffset`, `ReadRange`,
1257  * and `UserProject`.
1258  *
1259  * @par Idempotency
1260  * This is a read-only operation and is always idempotent.
1261  *
1262  * @par Example
1263  * @snippet storage_object_file_transfer_samples.cc download file
1264  */
1265  template <typename... Options>
1266  Status DownloadToFile(std::string const& bucket_name,
1267  std::string const& object_name,
1268  std::string const& file_name, Options&&... options) {
1269  internal::ReadObjectRangeRequest request(bucket_name, object_name);
1270  request.set_multiple_options(std::forward<Options>(options)...);
1271  return DownloadFileImpl(request, file_name);
1272  }
1273 
1274  /**
1275  * Deletes an object.
1276  *
1277  * @param bucket_name the name of the bucket that contains the object.
1278  * @param object_name the name of the object to be deleted.
1279  * @param options a list of optional query parameters and/or request headers.
1280  * Valid types for this operation include `Generation`,
1281  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1282  * `IfMetagenerationNotMatch`, and `UserProject`.
1283  *
1284  * @par Idempotency
1285  * This operation is only idempotent if:
1286  * - restricted by pre-conditions, in this case, `IfGenerationMatch`
1287  * - or, if it applies to only one object version via `Generation`.
1288  *
1289  * @par Example
1290  * @snippet storage_object_samples.cc delete object
1291  */
1292  template <typename... Options>
1293  Status DeleteObject(std::string const& bucket_name,
1294  std::string const& object_name, Options&&... options) {
1295  internal::DeleteObjectRequest request(bucket_name, object_name);
1296  request.set_multiple_options(std::forward<Options>(options)...);
1297  return raw_client_->DeleteObject(request).status();
1298  }
1299 
1300  /**
1301  * Updates the metadata in a Google Cloud Storage Object.
1302  *
1303  * @param bucket_name the name of the bucket that contains the object.
1304  * @param object_name the name of the object.
1305  * @param metadata the new metadata for the Object. Only the writeable fields
1306  * accepted by the `Objects: update` API are used, all other fields are
1307  * ignored. In particular, note that `bucket` and `name` are ignored in
1308  * favor of @p bucket_name and @p object_name.
1309  * @param options a list of optional query parameters and/or request headers.
1310  * Valid types for this operation include `Generation`,
1311  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1312  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
1313  * `Projection`, and `UserProject`.
1314  *
1315  * @par Idempotency
1316  * This operation is only idempotent if restricted by pre-conditions, in this
1317  * case, `IfMetagenerationMatch`.
1318  *
1319  * @par Example
1320  * @snippet storage_object_samples.cc update object metadata
1321  */
1322  template <typename... Options>
1323  StatusOr<ObjectMetadata> UpdateObject(std::string bucket_name,
1324  std::string object_name,
1325  ObjectMetadata metadata,
1326  Options&&... options) {
1327  internal::UpdateObjectRequest request(
1328  std::move(bucket_name), std::move(object_name), std::move(metadata));
1329  request.set_multiple_options(std::forward<Options>(options)...);
1330  return raw_client_->UpdateObject(request);
1331  }
1332 
1333  /**
1334  * Patches the metadata in a Google Cloud Storage Object.
1335  *
1336  * This function creates a patch request to change the writeable attributes in
1337  * @p original to the values in @p updated. Non-writeable attributes are
1338  * ignored, and attributes not present in @p updated are removed. Typically
1339  * this function is used after the application obtained a value with
1340  * `GetObjectMetadata` and has modified these parameters.
1341  *
1342  * @param bucket_name the bucket that contains the object to be updated.
1343  * @param object_name the object to be updated.
1344  * @param original the initial value of the object metadata.
1345  * @param updated the updated value for the object metadata.
1346  * @param options a list of optional query parameters and/or request headers.
1347  * Valid types for this operation include `Generation`,
1348  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1349  * `IfMetagenerationNotMatch`, `PredefinedAcl`,
1350  * `Projection`, and `UserProject`.
1351  *
1352  * @par Idempotency
1353  * This operation is only idempotent if restricted by pre-conditions, in this
1354  * case, `IfMetagenerationMatch`.
1355  *
1356  * @par Example
1357  * @snippet storage_object_samples.cc patch object delete metadata
1358  */
1359  template <typename... Options>
1360  StatusOr<ObjectMetadata> PatchObject(std::string bucket_name,
1361  std::string object_name,
1362  ObjectMetadata const& original,
1363  ObjectMetadata const& updated,
1364  Options&&... options) {
1365  internal::PatchObjectRequest request(
1366  std::move(bucket_name), std::move(object_name), original, updated);
1367  request.set_multiple_options(std::forward<Options>(options)...);
1368  return raw_client_->PatchObject(request);
1369  }
1370 
1371  /**
1372  * Patches the metadata in a Google Cloud Storage Object.
1373  *
1374  * This function creates a patch request based on the given @p builder.
1375  * Typically this function is used when the application needs to set an
1376  * object's metadata fields regardless of their previous value (i.e. when
1377  * calling GetObjectMetadata first is not necessary).
1378  *
1379  * @param bucket_name the bucket that contains the object to be updated.
1380  * @param object_name the object to be updated.
1381  * @param builder the set of updates to perform in the Object metadata.
1382  * @param options a list of optional query parameters and/or request headers.
1383  * Valid types for this operation include `Generation`,
1384  * `IfGenerationMatch`, `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1385  * `IfMetagenerationNotMatch`, `PredefinedAcl`, `EncryptionKey`,
1386  * `Projection`, and `UserProject`.
1387  *
1388  * @par Idempotency
1389  * This operation is only idempotent if restricted by pre-conditions, in this
1390  * case, `IfMetagenerationMatch`.
1391  *
1392  * @par Example
1393  * @snippet storage_object_samples.cc patch object content type
1394  */
1395  template <typename... Options>
1397  std::string bucket_name, std::string object_name,
1398  ObjectMetadataPatchBuilder const& builder, Options&&... options) {
1399  internal::PatchObjectRequest request(std::move(bucket_name),
1400  std::move(object_name), builder);
1401  request.set_multiple_options(std::forward<Options>(options)...);
1402  return raw_client_->PatchObject(request);
1403  }
1404 
1405  /**
1406  * Composes existing objects into a new object in the same bucket.
1407  *
1408  * @param bucket_name the name of the bucket used for source object and
1409  * destination object.
1410  * @param source_objects objects used to compose `destination_object_name`.
1411  * @param destination_object_name the composed object name.
1412  * @param options a list of optional query parameters and/or request headers.
1413  * Valid types for this operation include
1414  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1415  * `IfMetagenerationMatch`, `KmsKeyName`, `UserProject`, and
1416  * `WithObjectMetadata`.
1417  *
1418  * @par Idempotency
1419  * This operation is only idempotent if restricted by pre-conditions, in this
1420  * case, `IfGenerationMatch`.
1421  *
1422  * @par Example
1423  * @snippet storage_object_samples.cc compose object
1424  *
1425  * @par Example: using encrypted objects with CSEK
1426  * @snippet storage_object_csek_samples.cc compose object csek
1427  */
1428  template <typename... Options>
1430  std::string bucket_name, std::vector<ComposeSourceObject> source_objects,
1431  std::string destination_object_name, Options&&... options) {
1432  internal::ComposeObjectRequest request(std::move(bucket_name),
1433  std::move(source_objects),
1434  std::move(destination_object_name));
1435  request.set_multiple_options(std::forward<Options>(options)...);
1436  return raw_client_->ComposeObject(request);
1437  }
1438 
1439  /**
1440  * Creates an `ObjectRewriter` to copy the source object.
1441  *
1442  * Applications use this function to reliably copy objects across [location
1443  * boundaries](https://cloud.google.com/storage/docs/locations), and to
1444  * rewrite objects with different encryption keys. The operation returns a
1445  * `ObjectRewriter`, which the application can use to initiate the copy and to
1446  * iterate if the copy requires more than one call to complete.
1447  *
1448  * @note Application developers should be aware that rewriting large objects
1449  * may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1450  * may be required to completely rewrite an object.
1451  *
1452  * @param source_bucket_name the name of the bucket containing the source
1453  * object.
1454  * @param source_object_name the name of the source object.
1455  * @param destination_bucket_name where the destination object will be
1456  * located.
1457  * @param destination_object_name what to name the destination object.
1458  * @param options a list of optional query parameters and/or request headers.
1459  * Valid types for this operation include `DestinationKmsKeyName`,
1460  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1461  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1462  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1463  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1464  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1465  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1466  *
1467  * @par Idempotency
1468  * This operation is only idempotent if restricted by pre-conditions, in this
1469  * case, `IfGenerationMatch`.
1470  *
1471  * @par Example
1472  * @snippet storage_object_rewrite_samples.cc rewrite object non blocking
1473  *
1474  * @par Example
1475  * @snippet storage_object_rewrite_samples.cc rewrite object resume
1476  */
1477  template <typename... Options>
1478  ObjectRewriter RewriteObject(std::string source_bucket_name,
1479  std::string source_object_name,
1480  std::string destination_bucket_name,
1481  std::string destination_object_name,
1482  Options&&... options) {
1483  return ResumeRewriteObject(
1484  std::move(source_bucket_name), std::move(source_object_name),
1485  std::move(destination_bucket_name), std::move(destination_object_name),
1486  std::string{}, std::forward<Options>(options)...);
1487  }
1488 
1489  /**
1490  * Creates an `ObjectRewriter` to resume a previously created rewrite.
1491  *
1492  * Applications use this function to resume a rewrite operation, possibly
1493  * created with `RewriteObject()`. Rewrite can reliably copy objects across
1494  * location boundaries, and can rewrite objects with different encryption
1495  * keys. For large objects this operation can take a long time, thus
1496  * applications should consider checkpointing the rewrite token (accessible in
1497  * the `ObjectRewriter`) and restarting the operation in the event the program
1498  * is terminated.
1499  *
1500  * @note Application developers should be aware that rewriting large objects
1501  * may take multiple hours. Multiple calls to `ObjectRewriter::Iterate()`
1502  * may be required to completely rewrite an object.
1503  *
1504  * @param source_bucket_name the name of the bucket containing the source
1505  * object.
1506  * @param source_object_name the name of the source object.
1507  * @param destination_bucket_name where the destination object will be
1508  * located.
1509  * @param destination_object_name what to name the destination object.
1510  * @param rewrite_token the token from a previous successful rewrite
1511  * iteration. Can be the empty string, in which case this starts a new
1512  * rewrite operation.
1513  * @param options a list of optional query parameters and/or request headers.
1514  * Valid types for this operation include `DestinationKmsKeyName`,
1515  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1516  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1517  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1518  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1519  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1520  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1521  *
1522  * @par Idempotency
1523  * This operation is only idempotent if restricted by pre-conditions, in this
1524  * case, `IfGenerationMatch`.
1525  *
1526  * @par Example
1527  * @snippet storage_object_rewrite_samples.cc rewrite object resume
1528  */
1529  template <typename... Options>
1530  ObjectRewriter ResumeRewriteObject(std::string source_bucket_name,
1531  std::string source_object_name,
1532  std::string destination_bucket_name,
1533  std::string destination_object_name,
1534  std::string rewrite_token,
1535  Options&&... options) {
1536  internal::RewriteObjectRequest request(
1537  std::move(source_bucket_name), std::move(source_object_name),
1538  std::move(destination_bucket_name), std::move(destination_object_name),
1539  std::move(rewrite_token));
1540  request.set_multiple_options(std::forward<Options>(options)...);
1541  return ObjectRewriter(raw_client_, std::move(request));
1542  }
1543 
1544  /**
1545  * Rewrites the object, blocking until the rewrite completes, and returns the
1546  * resulting `ObjectMetadata`.
1547  *
1548  * Applications use this function to reliably copy objects across [location
1549  * boundaries](https://cloud.google.com/storage/docs/locations), and to
1550  * rewrite objects with different encryption keys. The operation blocks until
1551  * the rewrite completes, and returns the resulting `ObjectMetadata`.
1552  *
1553  * @note Application developers should be aware that rewriting large objects
1554  * may take multiple hours. In such cases the application should consider
1555  * using `RewriteObject()` or `ResumeRewriteObject()`.
1556  *
1557  * @param source_bucket_name the name of the bucket containing the source
1558  * object.
1559  * @param source_object_name the name of the source object.
1560  * @param destination_bucket_name where the destination object will be
1561  * located.
1562  * @param destination_object_name what to name the destination object.
1563  * @param options a list of optional query parameters and/or request headers.
1564  * Valid types for this operation include `DestinationKmsKeyName`,
1565  * `DestinationPredefinedAcl`, `EncryptionKey`, `IfGenerationMatch`,
1566  * `IfGenerationNotMatch`, `IfMetagenerationMatch`,
1567  * `IfSourceGenerationMatch`, `IfSourceGenerationNotMatch`,
1568  * `IfSourceMetagenerationMatch`, `IfSourceMetagenerationNotMatch`,
1569  * `MaxBytesRewrittenPerCall`, `Projection`, `SourceEncryptionKey`,
1570  * `SourceGeneration`, `UserProject`, and `WithObjectMetadata`.
1571  *
1572  * @return The metadata of the newly created object.
1573  *
1574  * @par Idempotency
1575  * This operation is only idempotent if restricted by pre-conditions, in this
1576  * case, `IfGenerationMatch`.
1577  *
1578  * @par Example
1579  * @snippet storage_object_rewrite_samples.cc rewrite object
1580  *
1581  * @par Example: using rewrite object to rotate the encryption key
1582  * @snippet storage_object_csek_samples.cc rotate encryption key
1583  *
1584  * @par Example: using rewrite object to rename an object
1585  * @snippet storage_object_rewrite_samples.cc rename object
1586  */
1587  template <typename... Options>
1589  std::string source_bucket_name, std::string source_object_name,
1590  std::string destination_bucket_name, std::string destination_object_name,
1591  Options&&... options) {
1592  return ResumeRewriteObject(std::move(source_bucket_name),
1593  std::move(source_object_name),
1594  std::move(destination_bucket_name),
1595  std::move(destination_object_name),
1596  std::string{}, std::forward<Options>(options)...)
1597  .Result();
1598  }
1599  //@}
1600 
1601  //@{
1602  /**
1603  * @name Bucket Access Control List operations.
1604  *
1605  * You can control who has access to your GCS buckets and objects as
1606  * well as what level of access they have.
1607  *
1608  * @note In most cases, you should use IAM permissions instead of ACLs to
1609  * control access to buckets.
1610  *
1611  * @note All buckets are owned by the project owners group. Project owners
1612  * are granted `OWNER` permissions to all buckets inside their project.
1613  * Bucket and object ownership cannot be changed by modifying ACLs.
1614  *
1615  * @note When you apply a new ACL to a bucket, GCS adds `OWNER` permission to
1616  * the bucket if you omit the grants. You cannot remove the project owners
1617  * group from a bucket ACL. Attempts to do so will appear to succeed, but
1618  * the service will add the project owners group into the new ACL before
1619  * applying it.
1620  *
1621  * @see https://cloud.google.com/storage/docs/access-control/ for more
1622  * information about access control in GCS.
1623  *
1624  * @see
1625  * https://cloud.google.com/storage/docs/access-control/lists#defaultbuckets
1626  * for more details about the default owners for a bucket.
1627  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1628  * the format of the @p entity parameters.
1629  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1630  * for the format of the @p role parameters.
1631  */
1632  /**
1633  * Retrieves the list of `BucketAccessControl` items for a bucket.
1634  *
1635  * @param bucket_name the name of the bucket.
1636  * @param options a list of optional query parameters and/or request headers.
1637  * Valid types for this operation include `UserProject`.
1638  *
1639  * @par Idempotency
1640  * This is a read-only operation and is always idempotent.
1641  *
1642  * @par Example
1643  * @snippet storage_bucket_acl_samples.cc list bucket acl
1644  */
1645  template <typename... Options>
1646  StatusOr<std::vector<BucketAccessControl>> ListBucketAcl(
1647  std::string const& bucket_name, Options&&... options) {
1648  internal::ListBucketAclRequest request(bucket_name);
1649  request.set_multiple_options(std::forward<Options>(options)...);
1650  auto items = raw_client_->ListBucketAcl(request);
1651  if (!items) {
1652  return std::move(items).status();
1653  }
1654  return std::move(items.value().items);
1655  }
1656 
1657  /**
1658  * Creates a new entry in a bucket ACL.
1659  *
1660  * @param bucket_name the name of the bucket.
1661  * @param entity the name of the entity added to the ACL.
1662  * @param role the role of the entity.
1663  * @param options a list of optional query parameters and/or request headers.
1664  * Valid types for this operation include `UserProject`.
1665  *
1666  * @par Idempotency
1667  * This operation is only idempotent if restricted by pre-conditions. There
1668  * are no pre-conditions for this operation that can make it idempotent.
1669  *
1670  * @par Example
1671  * @snippet storage_bucket_acl_samples.cc create bucket acl
1672  *
1673  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1674  * the format of the @p entity parameter.
1675  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1676  * for the format of the @p role parameter.
1677  */
1678  template <typename... Options>
1679  StatusOr<BucketAccessControl> CreateBucketAcl(std::string const& bucket_name,
1680  std::string const& entity,
1681  std::string const& role,
1682  Options&&... options) {
1683  internal::CreateBucketAclRequest request(bucket_name, entity, role);
1684  request.set_multiple_options(std::forward<Options>(options)...);
1685  return raw_client_->CreateBucketAcl(request);
1686  }
1687 
1688  /**
1689  * Deletes an entry from a bucket ACL.
1690  *
1691  * @param bucket_name the name of the bucket.
1692  * @param entity the name of the entity added to the ACL.
1693  * @param options a list of optional query parameters and/or request headers.
1694  * Valid types for this operation include `UserProject`.
1695  *
1696  * @par Idempotency
1697  * This operation is only idempotent if restricted by pre-conditions. There
1698  * are no pre-conditions for this operation that can make it idempotent.
1699  *
1700  * @par Example
1701  * @snippet storage_bucket_acl_samples.cc delete bucket acl
1702  *
1703  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1704  * the format of the @p entity parameter.
1705  */
1706  template <typename... Options>
1707  Status DeleteBucketAcl(std::string const& bucket_name,
1708  std::string const& entity, Options&&... options) {
1709  internal::DeleteBucketAclRequest request(bucket_name, entity);
1710  request.set_multiple_options(std::forward<Options>(options)...);
1711  return raw_client_->DeleteBucketAcl(request).status();
1712  }
1713 
1714  /**
1715  * Gets the value of an existing bucket ACL.
1716  *
1717  * @param bucket_name the name of the bucket to query.
1718  * @param entity the name of the entity to query.
1719  * @param options a list of optional query parameters and/or request headers.
1720  * Valid types for this operation include `UserProject`.
1721  *
1722  * @par Idempotency
1723  * This is a read-only operation and is always idempotent.
1724  *
1725  * @par Example
1726  * @snippet storage_bucket_acl_samples.cc get bucket acl
1727  *
1728  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1729  * the format of the @p entity parameter.
1730  */
1731  template <typename... Options>
1732  StatusOr<BucketAccessControl> GetBucketAcl(std::string const& bucket_name,
1733  std::string const& entity,
1734  Options&&... options) {
1735  internal::GetBucketAclRequest request(bucket_name, entity);
1736  request.set_multiple_options(std::forward<Options>(options)...);
1737  return raw_client_->GetBucketAcl(request);
1738  }
1739 
1740  /**
1741  * Updates the value of an existing bucket ACL.
1742  *
1743  * @note
1744  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1745  * the same functionality. The only field that can be modified by either API
1746  * is `role`, and it may only be set to a new value (it cannot be removed).
1747  * The API is offered for consistency with the other resource types where
1748  * Patch and Update APIs have different semantics.
1749  *
1750  * @param bucket_name the name of the bucket.
1751  * @param acl the new ACL value. Note that only the writable values of the ACL
1752  * will be modified by the server.
1753  * @param options a list of optional query parameters and/or request headers.
1754  * Valid types for this operation include `UserProject`.
1755  *
1756  * @par Idempotency
1757  * This operation is only idempotent if restricted by pre-conditions. There
1758  * are no pre-conditions for this operation that can make it idempotent.
1759  *
1760  * @par Example
1761  * @snippet storage_bucket_acl_samples.cc update bucket acl
1762  *
1763  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1764  * for additional details on what fields are writeable.
1765  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1766  * the format of the @p entity parameter.
1767  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1768  * for the format of the @p role parameter.
1769  */
1770  template <typename... Options>
1771  StatusOr<BucketAccessControl> UpdateBucketAcl(std::string const& bucket_name,
1772  BucketAccessControl const& acl,
1773  Options&&... options) {
1774  internal::UpdateBucketAclRequest request(bucket_name, acl.entity(),
1775  acl.role());
1776  request.set_multiple_options(std::forward<Options>(options)...);
1777  return raw_client_->UpdateBucketAcl(request);
1778  }
1779 
1780  /**
1781  * Patches the value of an existing bucket ACL.
1782  *
1783  * Computes the delta between a previous value for an BucketAccessControl and
1784  * the new value for an BucketAccessControl and apply that delta.
1785  *
1786  * @note
1787  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1788  * the same functionality. The only field that can be modified by either API
1789  * is `role`, and it may only be set to a new value (it cannot be removed).
1790  * The API is offered for consistency with the other resource types where
1791  * Patch and Update APIs have different semantics.
1792  *
1793  * @param bucket_name the name of the bucket.
1794  * @param entity the identifier for the user, group, service account, or
1795  * predefined set of actors holding the permission.
1796  * @param original_acl the original ACL value.
1797  * @param new_acl the new ACL value. Note that only changes on writeable
1798  * fields will be accepted by the server.
1799  * @param options a list of optional query parameters and/or request headers.
1800  * Valid types for this operation include `UserProject`, and the standard
1801  * options available to all operations.
1802  *
1803  * @par Idempotency
1804  * This operation is only idempotent if restricted by pre-conditions. There
1805  * are no pre-conditions for this operation that can make it idempotent.
1806  *
1807  * @par Example
1808  * @snippet storage_bucket_acl_samples.cc patch bucket acl
1809  *
1810  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1811  * for additional details on what fields are writeable.
1812  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1813  * the format of the @p entity parameters.
1814  */
1815  template <typename... Options>
1817  std::string const& bucket_name, std::string const& entity,
1818  BucketAccessControl const& original_acl,
1819  BucketAccessControl const& new_acl, Options&&... options) {
1820  internal::PatchBucketAclRequest request(bucket_name, entity, original_acl,
1821  new_acl);
1822  request.set_multiple_options(std::forward<Options>(options)...);
1823  return raw_client_->PatchBucketAcl(request);
1824  }
1825 
1826  /**
1827  * Patches the value of an existing bucket ACL.
1828  *
1829  * This API allows the application to patch an BucketAccessControl without
1830  * having to read the current value.
1831  *
1832  * @note
1833  * For changing BucketAccessControl, the Patch and Update APIs basically offer
1834  * the same functionality. The only field that can be modified by either API
1835  * is `role`, and it may only be set to a new value (it cannot be removed).
1836  * The API is offered for consistency with the other resource types where
1837  * Patch and Update APIs have different semantics.
1838  *
1839  * @param bucket_name the name of the bucket.
1840  * @param entity the identifier for the user, group, service account, or
1841  * predefined set of actors holding the permission.
1842  * @param builder a builder ready to create the patch.
1843  * @param options a list of optional query parameters and/or request
1844  * headers. Valid types for this operation include `Generation`,
1845  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
1846  *
1847  * @par Idempotency
1848  * This operation is only idempotent if restricted by pre-conditions. There
1849  * are no pre-conditions for this operation that can make it idempotent.
1850  *
1851  * @par Example
1852  * @snippet storage_bucket_acl_samples.cc patch bucket acl no-read
1853  *
1854  * @see https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls
1855  * for additional details on what fields are writeable.
1856  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1857  * the format of the @p entity parameters.
1858  */
1859  template <typename... Options>
1861  std::string const& bucket_name, std::string const& entity,
1862  BucketAccessControlPatchBuilder const& builder, Options&&... options) {
1863  internal::PatchBucketAclRequest request(bucket_name, entity, builder);
1864  request.set_multiple_options(std::forward<Options>(options)...);
1865  return raw_client_->PatchBucketAcl(request);
1866  }
1867  //@}
1868 
1869  //@{
1870  /**
1871  * @name Object Access Control List operations.
1872  *
1873  * You can control who has access to your GCS buckets and objects as
1874  * well as what level of access they have.
1875  *
1876  * @note When you upload (create) an object the entity that uploads the object
1877  * is listed as the object owner. This can be a user or a service account,
1878  * depending on what credentials are used to authenticate with GCS.
1879  * Object ownership cannot be changed by modifying ACLs. You can change
1880  * object ownership only by overwriting the object while authenticated as
1881  * the desired owner.
1882  *
1883  * @note When you apply a new ACL to an object, GCS adds `OWNER` permission to
1884  * the object if you omit the grants.
1885  *
1886  * @see https://cloud.google.com/storage/docs/access-control/ for more
1887  * information about access control in GCS.
1888  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1889  * the format of the @p entity parameters.
1890  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1891  * for the format of the @p role parameters.
1892  */
1893  /**
1894  * Retrieves the list of ObjectAccessControl items for an object.
1895  *
1896  * @param bucket_name the name of the bucket that contains the object.
1897  * @param object_name the name of the object to be deleted.
1898  * @param options a list of optional query parameters and/or request headers.
1899  * Valid types for this operation include `Generation`, and `UserProject`.
1900  *
1901  * @par Idempotency
1902  * This is a read-only operation and is always idempotent.
1903  *
1904  * @par Example
1905  * @snippet storage_object_acl_samples.cc list object acl
1906  */
1907  template <typename... Options>
1908  StatusOr<std::vector<ObjectAccessControl>> ListObjectAcl(
1909  std::string const& bucket_name, std::string const& object_name,
1910  Options&&... options) {
1911  internal::ListObjectAclRequest request(bucket_name, object_name);
1912  request.set_multiple_options(std::forward<Options>(options)...);
1913  auto result = raw_client_->ListObjectAcl(request);
1914  if (!result) {
1915  return std::move(result).status();
1916  }
1917  return std::move(result.value().items);
1918  }
1919 
1920  /**
1921  * Creates a new entry in the object ACL.
1922  *
1923  * @param bucket_name the name of the bucket that contains the object.
1924  * @param object_name the name of the object.
1925  * @param entity the name of the entity added to the ACL.
1926  * @param role the role of the entity.
1927  * @param options a list of optional query parameters and/or request headers.
1928  * Valid types for this operation include `Generation`, and `UserProject`.
1929  *
1930  * @par Idempotency
1931  * This operation is only idempotent if restricted by pre-conditions. There
1932  * are no pre-conditions for this operation that can make it idempotent.
1933  *
1934  * @par Example
1935  * @snippet storage_object_acl_samples.cc create object acl
1936  *
1937  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1938  * the format of the @p entity parameter.
1939  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
1940  * for the format of the @p role parameter.
1941  */
1942  template <typename... Options>
1943  StatusOr<ObjectAccessControl> CreateObjectAcl(std::string const& bucket_name,
1944  std::string const& object_name,
1945  std::string const& entity,
1946  std::string const& role,
1947  Options&&... options) {
1948  internal::CreateObjectAclRequest request(bucket_name, object_name, entity,
1949  role);
1950  request.set_multiple_options(std::forward<Options>(options)...);
1951  return raw_client_->CreateObjectAcl(request);
1952  }
1953 
1954  /**
1955  * Deletes one access control entry in one object.
1956  *
1957  * @param bucket_name the name of the bucket that contains the object.
1958  * @param object_name the name of the object to be deleted.
1959  * @param entity the name of the entity (user, team, group) to be removed from
1960  * the Object's ACL.
1961  * @param options a list of optional query parameters and/or request headers.
1962  * Valid types for this operation include `Generation`, and `UserProject`.
1963  *
1964  * @par Idempotency
1965  * This operation is only idempotent if restricted by pre-conditions. There
1966  * are no pre-conditions for this operation that can make it idempotent.
1967  *
1968  * @par Example
1969  * @snippet storage_object_acl_samples.cc delete object acl
1970  *
1971  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1972  * the format of the @p entity parameters.
1973  */
1974  template <typename... Options>
1975  Status DeleteObjectAcl(std::string const& bucket_name,
1976  std::string const& object_name,
1977  std::string const& entity, Options&&... options) {
1978  internal::DeleteObjectAclRequest request(bucket_name, object_name, entity);
1979  request.set_multiple_options(std::forward<Options>(options)...);
1980  return raw_client_->DeleteObjectAcl(request).status();
1981  }
1982 
1983  /**
1984  * Gets the value of an existing object ACL.
1985  *
1986  * @param bucket_name the name of the bucket that contains the object.
1987  * @param object_name the name of the object.
1988  * @param entity the name of the entity added to the ACL.
1989  * @param options a list of optional query parameters and/or request headers.
1990  * Valid types for this operation include `Generation`, and `UserProject`.
1991  *
1992  * @par Idempotency
1993  * This is a read-only operation and is always idempotent.
1994  *
1995  * @par Example
1996  * @snippet storage_object_acl_samples.cc print file acl for user
1997  *
1998  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
1999  * the format of the @p entity parameters.
2000  */
2001  template <typename... Options>
2002  StatusOr<ObjectAccessControl> GetObjectAcl(std::string const& bucket_name,
2003  std::string const& object_name,
2004  std::string const& entity,
2005  Options&&... options) {
2006  internal::GetObjectAclRequest request(bucket_name, object_name, entity);
2007  request.set_multiple_options(std::forward<Options>(options)...);
2008  return raw_client_->GetObjectAcl(request);
2009  }
2010 
2011  /**
2012  * Updates the value of an existing object ACL.
2013  *
2014  * @note
2015  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2016  * the same functionality. The only field that can be modified by either API
2017  * is `role`, and it may only be set to a new value (it cannot be removed).
2018  * The API is offered for consistency with the other resource types where
2019  * Patch and Update APIs have different semantics.
2020  *
2021  * @param bucket_name the name of the bucket that contains the object.
2022  * @param object_name the name of the object.
2023  * @param acl the new ACL value. Note that only the writable values of the ACL
2024  * will be modified by the server.
2025  * @param options a list of optional query parameters and/or request
2026  * Valid types for this operation include `Generation`, and `UserProject`.
2027  *
2028  * @par Idempotency
2029  * This operation is only idempotent if restricted by pre-conditions. There
2030  * are no pre-conditions for this operation that can make it idempotent.
2031  *
2032  * @par Example
2033  * @snippet storage_object_acl_samples.cc update object acl
2034  *
2035  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2036  * the format of the @p entity parameters.
2037  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2038  * for additional details on what fields are writeable.
2039  */
2040  template <typename... Options>
2041  StatusOr<ObjectAccessControl> UpdateObjectAcl(std::string const& bucket_name,
2042  std::string const& object_name,
2043  ObjectAccessControl const& acl,
2044  Options&&... options) {
2045  internal::UpdateObjectAclRequest request(bucket_name, object_name,
2046  acl.entity(), acl.role());
2047  request.set_multiple_options(std::forward<Options>(options)...);
2048  return raw_client_->UpdateObjectAcl(request);
2049  }
2050 
2051  /**
2052  * Patches the value of an existing object ACL.
2053  *
2054  * Compute the delta between a previous value for an ObjectAccessControl and
2055  * the new value for an ObjectAccessControl and apply that delta.
2056  *
2057  * @note
2058  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2059  * the same functionality. The only field that can be modified by either API
2060  * is `role`, and it may only be set to a new value (it cannot be removed).
2061  * The API is offered for consistency with the other resource types where
2062  * Patch and Update APIs have different semantics.
2063  *
2064  * @param bucket_name the name of the bucket that contains the object.
2065  * @param object_name the name of the object.
2066  * @param entity the identifier for the user, group, service account, or
2067  * predefined set of actors holding the permission.
2068  * @param original_acl the original ACL value.
2069  * @param new_acl the new ACL value. Note that only changes on writeable
2070  * fields will be accepted by the server.
2071  * @param options a list of optional query parameters and/or request
2072  * headers. Valid types for this operation include `Generation`,
2073  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2074  *
2075  * @par Idempotency
2076  * This operation is only idempotent if restricted by pre-conditions. There
2077  * are no pre-conditions for this operation that can make it idempotent.
2078  *
2079  * @par Example
2080  * @snippet storage_object_acl_samples.cc patch object acl
2081  *
2082  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2083  * the format of the @p entity parameters.
2084  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2085  * for additional details on what fields are writeable.
2086  */
2087  template <typename... Options>
2089  std::string const& bucket_name, std::string const& object_name,
2090  std::string const& entity, ObjectAccessControl const& original_acl,
2091  ObjectAccessControl const& new_acl, Options&&... options) {
2092  internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2093  original_acl, new_acl);
2094  request.set_multiple_options(std::forward<Options>(options)...);
2095  return raw_client_->PatchObjectAcl(request);
2096  }
2097 
2098  /**
2099  * Patches the value of an existing object ACL.
2100  *
2101  * This API allows the application to patch an ObjectAccessControl without
2102  * having to read the current value.
2103  *
2104  * @note
2105  * For changing ObjectAccessControl, the Patch and Update APIs basically offer
2106  * the same functionality. The only field that can be modified by either API
2107  * is `role`, and it may only be set to a new value (it cannot be removed).
2108  * The API is offered for consistency with the other resource types where
2109  * Patch and Update APIs have different semantics.
2110  *
2111  * @param bucket_name the name of the bucket that contains the object.
2112  * @param object_name the name of the object.
2113  * @param entity the identifier for the user, group, service account, or
2114  * predefined set of actors holding the permission.
2115  * @param builder a builder ready to create the patch.
2116  * @param options a list of optional query parameters and/or request
2117  * headers. Valid types for this operation include `Generation`,
2118  * `UserProject`, `IfMatchEtag`, and `IfNoneMatchEtag`.
2119  *
2120  * @par Idempotency
2121  * This operation is only idempotent if restricted by pre-conditions. There
2122  * are no pre-conditions for this operation that can make it idempotent.
2123  *
2124  * @par Example
2125  * @snippet storage_object_acl_samples.cc patch object acl no-read
2126  *
2127  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2128  * the format of the @p entity parameters.
2129  * @see https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls
2130  * for additional details on what fields are writeable.
2131  */
2132  template <typename... Options>
2134  std::string const& bucket_name, std::string const& object_name,
2135  std::string const& entity, ObjectAccessControlPatchBuilder const& builder,
2136  Options&&... options) {
2137  internal::PatchObjectAclRequest request(bucket_name, object_name, entity,
2138  builder);
2139  request.set_multiple_options(std::forward<Options>(options)...);
2140  return raw_client_->PatchObjectAcl(request);
2141  }
2142  //@}
2143 
2144  //@{
2145  /**
2146  * @name Bucket Default Object Access Control List operations.
2147  *
2148  * When you upload an object to GCS without specifying an ACL, the object is
2149  * created with the Default Object ACL for its bucket. These operations are
2150  * used to query and modify the Default Object ACL of a bucket.
2151  *
2152  * @see
2153  * https://cloud.google.com/storage/docs/access-control/lists#defaultobjects
2154  * for more information on default object ACLs.
2155  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2156  * the format of the @p entity parameters.
2157  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2158  * for the format of the @p role parameters.
2159  */
2160  /**
2161  * Retrieves the default object ACL for a bucket as a vector of
2162  * `ObjectAccessControl` items.
2163  *
2164  * The default object ACL sets the ACL for any object created in the bucket,
2165  * unless a different ACL is specified when the object is created.
2166  *
2167  * @param bucket_name the name of the bucket.
2168  * @param options a list of optional query parameters and/or request headers.
2169  * Valid types for this operation include `IfMetagenerationMatch`,
2170  * `IfMetagenerationNotMatch` and `UserProject`.
2171  *
2172  * @par Idempotency
2173  * This is a read-only operation and is always idempotent.
2174  *
2175  * @par Example
2176  * @snippet storage_default_object_acl_samples.cc list default object acl
2177  *
2178  * @see
2179  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2180  */
2181  template <typename... Options>
2183  std::string const& bucket_name, Options&&... options) {
2184  internal::ListDefaultObjectAclRequest request(bucket_name);
2185  request.set_multiple_options(std::forward<Options>(options)...);
2186  auto response = raw_client_->ListDefaultObjectAcl(request);
2187  if (!response) {
2188  return std::move(response).status();
2189  }
2190  return std::move(response.value().items);
2191  }
2192 
2193  /**
2194  * Creates a new entry in the default object ACL for a bucket.
2195  *
2196  * The default object ACL sets the ACL for any object created in the bucket,
2197  * unless a different ACL is specified when the object is created.
2198  *
2199  * @param bucket_name the name of the bucket.
2200  * @param entity the name of the entity added to the ACL.
2201  * @param role the role of the entity.
2202  * @param options a list of optional query parameters and/or request headers.
2203  * Valid types for this operation include `UserProject`.
2204  *
2205  * @par Idempotency
2206  * This operation is only idempotent if restricted by pre-conditions. There
2207  * are no pre-conditions for this operation that can make it idempotent.
2208  *
2209  * @par Example
2210  * @snippet storage_default_object_acl_samples.cc create default object acl
2211  *
2212  * @see
2213  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2214  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2215  * the format of the @p entity parameter.
2216  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2217  * for the format of the @p role parameter.
2218  */
2219  template <typename... Options>
2221  std::string const& bucket_name, std::string const& entity,
2222  std::string const& role, Options&&... options) {
2223  internal::CreateDefaultObjectAclRequest request(bucket_name, entity, role);
2224  request.set_multiple_options(std::forward<Options>(options)...);
2225  return raw_client_->CreateDefaultObjectAcl(request);
2226  }
2227 
2228  /**
2229  * Deletes an entry from the default object ACL in a bucket.
2230  *
2231  * The default object ACL sets the ACL for any object created in the bucket,
2232  * unless a different ACL is specified when the object is created.
2233  *
2234  * @param bucket_name the name of the bucket.
2235  * @param entity the name of the entity added to the ACL.
2236  * @param options a list of optional query parameters and/or request headers.
2237  * Valid types for this operation include `UserProject`.
2238  *
2239  * @par Idempotency
2240  * This operation is only idempotent if restricted by pre-conditions. There
2241  * are no pre-conditions for this operation that can make it idempotent.
2242  *
2243  * @par Example
2244  * @snippet storage_default_object_acl_samples.cc delete default object acl
2245  *
2246  * @see
2247  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2248  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2249  * the format of the @p entity parameter.
2250  */
2251  template <typename... Options>
2252  Status DeleteDefaultObjectAcl(std::string const& bucket_name,
2253  std::string const& entity,
2254  Options&&... options) {
2255  internal::DeleteDefaultObjectAclRequest request(bucket_name, entity);
2256  request.set_multiple_options(std::forward<Options>(options)...);
2257  return raw_client_->DeleteDefaultObjectAcl(request).status();
2258  }
2259 
2260  /**
2261  * Gets the value of a default object ACL in a bucket.
2262  *
2263  * The default object ACL sets the ACL for any object created in the bucket,
2264  * unless a different ACL is specified when the object is created.
2265  *
2266  * @param bucket_name the name of the bucket.
2267  * @param entity the name of the entity.
2268  * @param options a list of optional query parameters and/or request headers.
2269  * Valid types for this operation include `UserProject`.
2270  *
2271  * @par Idempotency
2272  * This is a read-only operation and is always idempotent.
2273  *
2274  * @par Example
2275  * @snippet storage_default_object_acl_samples.cc get default object acl
2276  *
2277  * @see
2278  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2279  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2280  * the format of the @p entity parameter.
2281  */
2282  template <typename... Options>
2284  std::string const& bucket_name, std::string const& entity,
2285  Options&&... options) {
2286  internal::GetDefaultObjectAclRequest request(bucket_name, entity);
2287  request.set_multiple_options(std::forward<Options>(options)...);
2288  return raw_client_->GetDefaultObjectAcl(request);
2289  }
2290 
2291  /**
2292  * Updates the value of an existing default object ACL.
2293  *
2294  * The default object ACL sets the ACL for any object created in the bucket,
2295  * unless a different ACL is specified when the object is created.
2296  *
2297  * @note
2298  * For changing default object access controls, the Patch and Update APIs
2299  * basically offer the same functionality. The only field that can be modified
2300  * by either API is `role`, and it may only be set to a new value (it cannot
2301  * be removed). The API is offered for consistency with the other resource
2302  * types where Patch and Update APIs have different semantics.
2303  *
2304  * @param bucket_name the name of the bucket.
2305  * @param acl the new ACL value. Note that only the writable values of the ACL
2306  * will be modified by the server.
2307  * @param options a list of optional query parameters and/or request
2308  * Valid types for this operation include `UserProject`.
2309  *
2310  * @par Idempotency
2311  * This operation is only idempotent if restricted by pre-conditions. There
2312  * are no pre-conditions for this operation that can make it idempotent.
2313  *
2314  * @par Example
2315  * @snippet storage_default_object_acl_samples.cc update default object acl
2316  *
2317  * @see
2318  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2319  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2320  * the format of the @p entity parameter.
2321  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2322  * for the format of the @p role parameter.
2323  */
2324  template <typename... Options>
2326  std::string const& bucket_name, ObjectAccessControl const& acl,
2327  Options&&... options) {
2328  internal::UpdateDefaultObjectAclRequest request(bucket_name, acl.entity(),
2329  acl.role());
2330  request.set_multiple_options(std::forward<Options>(options)...);
2331  return raw_client_->UpdateDefaultObjectAcl(request);
2332  }
2333 
2334  /**
2335  * Patches the value of an existing default object ACL.
2336  *
2337  * Compute the delta between a previous and new values for a default object
2338  * access control, and apply that delta.
2339  *
2340  * @note
2341  * For changing default object access controls, the Patch and Update APIs
2342  * basically offer the same functionality. The only field that can be modified
2343  * by either API is `role`, and it may only be set to a new value (it cannot
2344  * be removed). The API is offered for consistency with the other resource
2345  * types where Patch and Update APIs have different semantics.
2346  *
2347  * @param bucket_name the name of the bucket.
2348  * @param entity the identifier for the user, group, service account, or
2349  * predefined set of actors holding the permission.
2350  * @param original_acl the original ACL value.
2351  * @param new_acl the new ACL value. Note that only changes on writeable
2352  * fields will be accepted by the server.
2353  * @param options a list of optional query parameters and/or request
2354  * headers. Valid types for this operation include `UserProject`, as well
2355  * as the standard parameters, such as `IfMatchEtag`, and
2356  * `IfNoneMatchEtag`.
2357  *
2358  * @par Idempotency
2359  * This operation is only idempotent if restricted by pre-conditions. There
2360  * are no pre-conditions for this operation that can make it idempotent.
2361  *
2362  * @par Example
2363  * @snippet storage_default_object_acl_samples.cc patch default object acl
2364  *
2365  * @see
2366  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2367  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2368  * the format of the @p entity parameter.
2369  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2370  * for the format of the @p role parameter.
2371  */
2372  template <typename... Options>
2374  std::string const& bucket_name, std::string const& entity,
2375  ObjectAccessControl const& original_acl,
2376  ObjectAccessControl const& new_acl, Options&&... options) {
2377  internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2378  original_acl, new_acl);
2379  request.set_multiple_options(std::forward<Options>(options)...);
2380  return raw_client_->PatchDefaultObjectAcl(request);
2381  }
2382 
2383  /**
2384  * Patches the value of an existing default object ACL.
2385  *
2386  * This API allows the application to patch an ObjectAccessControl without
2387  * having to read the current value.
2388  *
2389  * @note
2390  * For changing default object access controls, the Patch and Update APIs
2391  * basically offer the same functionality. The only field that can be modified
2392  * by either API is `role`, and it may only be set to a new value (it cannot
2393  * be removed). The API is offered for consistency with the other resource
2394  * types where Patch and Update APIs have different semantics.
2395  *
2396  * @param bucket_name the name of the bucket.
2397  * @param entity the identifier for the user, group, service account, or
2398  * predefined set of actors holding the permission.
2399  * @param builder a builder ready to create the patch.
2400  * @param options a list of optional query parameters and/or request
2401  * headers. Valid types for this operation include `UserProject`, as well
2402  * as the standard parameters, such as `IfMatchEtag`, and
2403  * `IfNoneMatchEtag`.
2404  *
2405  * @par Idempotency
2406  * This operation is only idempotent if restricted by pre-conditions. There
2407  * are no pre-conditions for this operation that can make it idempotent.
2408  *
2409  * @par Example
2410  * @snippet storage_default_object_acl_samples.cc patch default object acl
2411  * no-read
2412  *
2413  * @see
2414  * https://cloud.google.com/storage/docs/access-control/create-manage-lists#defaultobjects
2415  * @see https://cloud.google.com/storage/docs/access-control/lists#scopes for
2416  * the format of the @p entity parameter.
2417  * @see https://cloud.google.com/storage/docs/access-control/lists#permissions
2418  * for the format of the @p role parameter.
2419  */
2420  template <typename... Options>
2422  std::string const& bucket_name, std::string const& entity,
2423  ObjectAccessControlPatchBuilder const& builder, Options&&... options) {
2424  internal::PatchDefaultObjectAclRequest request(bucket_name, entity,
2425  builder);
2426  request.set_multiple_options(std::forward<Options>(options)...);
2427  return raw_client_->PatchDefaultObjectAcl(request);
2428  }
2429  //@}
2430 
2431  //@{
2432  /**
2433  * @name Service account operations.
2434  *
2435  * Service accounts allow applications to authenticate and access GCP
2436  * resources and services. When acting on your behalf, GCS uses such a service
2437  * account. GCS creates one service account per project. These operations
2438  * allow you to query the GCS service account for a project.
2439  *
2440  * @see https://cloud.google.com/storage/docs/projects#service-accounts for
2441  * more information on service accounts.
2442  */
2443  /**
2444  * Gets the GCS service account for a given project.
2445  *
2446  * A service account is a special Google account that belongs to your
2447  * application, virtual machine, or to a Google service when acting on your
2448  * behalf. This API allows you to discover the GCS service account for the
2449  * @p project_id project.
2450  *
2451  * @param project_id the project to query.
2452  * @param options a list of optional query parameters and/or request headers.
2453  * Valid types for this operation include `UserProject`.
2454  *
2455  * @par Idempotency
2456  * This is a read-only operation and is always idempotent.
2457  *
2458  * @par Example
2459  * @snippet storage_service_account_samples.cc get service account for project
2460  *
2461  * @see https://cloud.google.com/iam/docs/service-accounts for general
2462  * information on Google Cloud Platform service accounts.
2463  */
2464  template <typename... Options>
2466  std::string const& project_id, Options&&... options) {
2467  internal::GetProjectServiceAccountRequest request(project_id);
2468  request.set_multiple_options(std::forward<Options>(options)...);
2469  return raw_client_->GetServiceAccount(request);
2470  }
2471 
2472  /**
2473  * Gets the GCS service account for the default project.
2474  *
2475  * A service account is a special Google account that belongs to your
2476  * application, virtual machine, or to a Google service when acting on your
2477  * behalf. This API allows you to discover the GCS service account for the
2478  * default project associated with this object.
2479  *
2480  * The default project is required to be configured in the `ClientOptions`
2481  * used to construct this object. If the application does not set the project
2482  * id in the `ClientOptions`, the value of the `GOOGLE_CLOUD_PROJECT` is
2483  * used. If neither the environment variable is set, nor a value is set
2484  * explicitly by the application, the server will reject the request and this
2485  * function will return the error status.
2486  *
2487  * @param options a list of optional query parameters and/or request headers.
2488  * Valid types for this operation include `UserProject`.
2489  *
2490  * @par Idempotency
2491  * This is a read-only operation and is always idempotent.
2492  *
2493  * @par Example
2494  * @snippet storage_service_account_samples.cc get service account
2495  *
2496  * @see https://cloud.google.com/iam/docs/service-accounts for general
2497  * information on Google Cloud Platform service accounts.
2498  */
2499  template <typename... Options>
2500  StatusOr<ServiceAccount> GetServiceAccount(Options&&... options) {
2501  auto const& project_id = raw_client_->client_options().project_id();
2502  return GetServiceAccountForProject(project_id,
2503  std::forward<Options>(options)...);
2504  }
2505 
2506  /**
2507  * List the available HMAC keys.
2508  *
2509  * @warning This GCS feature is not GA, it is subject to change without
2510  * notice.
2511  *
2512  * @param options a list of optional query parameters and/or request headers.
2513  * In addition to the options common to all requests, this operation
2514  * accepts `Deleted` `MaxResults`, `OverrideDefaultProject`,
2515  * `ServiceAccountFilter`, and `UserProject`.
2516  *
2517  * @return A range to iterate over the available HMAC keys.
2518  *
2519  * @par Idempotency
2520  * This is a read-only operation and is always idempotent.
2521  *
2522  * @par Example
2523  * @snippet storage_service_account_samples.cc list hmac keys
2524  *
2525  * @par Example
2526  * @snippet storage_service_account_samples.cc list hmac keys service account
2527  *
2528  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2529  * general information on using HMAC keys for Google Cloud Platform
2530  * service accounts authentication.
2531  *
2532  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2533  * for a detailed description on how to use the feature.
2534  */
2535  template <typename... Options>
2536  ListHmacKeysReader ListHmacKeys(Options&&... options) {
2537  auto const& project_id = raw_client_->client_options().project_id();
2538  internal::ListHmacKeysRequest request(project_id);
2539  request.set_multiple_options(std::forward<Options>(options)...);
2540  auto client = raw_client_;
2541  return google::cloud::internal::MakePaginationRange<ListHmacKeysReader>(
2542  request,
2543  [client](internal::ListHmacKeysRequest const& r) {
2544  return client->ListHmacKeys(r);
2545  },
2546  [](internal::ListHmacKeysResponse r) { return std::move(r.items); });
2547  }
2548 
2549  /**
2550  * Create a new HMAC key.
2551  *
2552  * @warning This GCS feature is not GA, it is subject to change without
2553  * notice.
2554  *
2555  * @param service_account the service account email where you want to create
2556  * the new HMAC key.
2557  * @param options a list of optional query parameters and/or request headers.
2558  * In addition to the options common to all requests, this operation
2559  * accepts `OverrideDefaultProject`.
2560  *
2561  * @return This operation returns the new HMAC key metadata *and* the HMAC key
2562  * secret (encoded as a base64 string). This is the only request that
2563  * returns the secret.
2564  *
2565  * @par Idempotency
2566  * This operation is not idempotent. Retrying the operation will create a new
2567  * key each time.
2568  *
2569  * @par Example
2570  * @snippet storage_service_account_samples.cc create hmac key
2571  *
2572  * @par Example
2573  * @snippet storage_service_account_samples.cc create hmac key project
2574  *
2575  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2576  * general information on using HMAC keys for Google Cloud Platform
2577  * service accounts authentication.
2578  *
2579  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2580  * for a detailed description on how to use the feature.
2581  */
2582  template <typename... Options>
2583  StatusOr<std::pair<HmacKeyMetadata, std::string>> CreateHmacKey(
2584  std::string service_account, Options&&... options) {
2585  auto const& project_id = raw_client_->client_options().project_id();
2586  internal::CreateHmacKeyRequest request(project_id,
2587  std::move(service_account));
2588  request.set_multiple_options(std::forward<Options>(options)...);
2589  auto result = raw_client_->CreateHmacKey(request);
2590  if (!result) {
2591  return result.status();
2592  }
2593  return std::make_pair(std::move(result->metadata),
2594  std::move(result->secret));
2595  }
2596 
2597  /**
2598  * Delete a HMAC key in a given project.
2599  *
2600  * @warning This GCS feature is not GA, it is subject to change without
2601  * notice.
2602  *
2603  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2604  * HMAC key is assigned an `access_id()` attribute at creation time.
2605  * @param options a list of optional query parameters and/or request headers.
2606  * In addition to the options common to all requests, this operation
2607  * accepts `OverrideDefaultProject`.
2608  *
2609  * @return This operation returns the new HMAC key metadata.
2610  *
2611  * @par Idempotency
2612  * This operation is always idempotent. An access id identifies a single HMAC
2613  * key, calling the operation multiple times can succeed only once.
2614  *
2615  * @par Example
2616  * @snippet storage_service_account_samples.cc delete hmac key
2617  *
2618  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2619  * general information on using HMAC keys for Google Cloud Platform
2620  * service accounts authentication.
2621  *
2622  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2623  * for a detailed description on how to use the feature.
2624  */
2625  template <typename... Options>
2626  Status DeleteHmacKey(std::string access_id, Options&&... options) {
2627  auto const& project_id = raw_client_->client_options().project_id();
2628  internal::DeleteHmacKeyRequest request(project_id, std::move(access_id));
2629  request.set_multiple_options(std::forward<Options>(options)...);
2630  return raw_client_->DeleteHmacKey(request).status();
2631  }
2632 
2633  /**
2634  * Get an existing HMAC key in a given project.
2635  *
2636  * @warning This GCS feature is not GA, it is subject to change without
2637  * notice.
2638  *
2639  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2640  * HMAC key is assigned an `access_id()` attribute at creation time.
2641  * @param options a list of optional query parameters and/or request headers.
2642  * In addition to the options common to all requests, this operation
2643  * accepts `OverrideDefaultProject`.
2644  *
2645  * @return This operation returns the new HMAC key metadata.
2646  *
2647  * @par Idempotency
2648  * This is a read-only operation and therefore it is always idempotent.
2649  *
2650  * @par Example
2651  * @snippet storage_service_account_samples.cc get hmac key
2652  *
2653  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2654  * general information on using HMAC keys for Google Cloud Platform
2655  * service accounts authentication.
2656  *
2657  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2658  * for a detailed description on how to use the feature.
2659  */
2660  template <typename... Options>
2661  StatusOr<HmacKeyMetadata> GetHmacKey(std::string access_id,
2662  Options&&... options) {
2663  auto const& project_id = raw_client_->client_options().project_id();
2664  internal::GetHmacKeyRequest request(project_id, std::move(access_id));
2665  request.set_multiple_options(std::forward<Options>(options)...);
2666  return raw_client_->GetHmacKey(request);
2667  }
2668 
2669  /**
2670  * Update an existing HMAC key in a given project.
2671  *
2672  * @warning This GCS feature is not GA, it is subject to change without
2673  * notice.
2674  *
2675  * @param access_id the HMAC key `access_id()` that you want to delete. Each
2676  * HMAC key is assigned an `access_id()` attribute at creation time.
2677  * @param resource the desired changes to the HMAC key resource. Only the
2678  * `state` field may be changed. The `etag` field may be set but it is
2679  * only used as a pre-condition, the application cannot set the `etag`.
2680  * @param options a list of optional query parameters and/or request headers.
2681  * In addition to the options common to all requests, this operation
2682  * accepts `OverrideDefaultProject`.
2683  *
2684  * @return This operation returns the new HMAC key metadata.
2685  *
2686  * @par Idempotency
2687  * This operation is only idempotent if the `etag` attribute in @p resource
2688  * is set, or if the `IfMatchEtag` option is set.
2689  *
2690  * @par Example
2691  * @snippet storage_service_account_samples.cc update hmac key
2692  *
2693  * @see https://cloud.google.com/storage/docs/authentication/hmackeys for
2694  * general information on using HMAC keys for Google Cloud Platform
2695  * service accounts authentication.
2696  *
2697  * @see https://cloud.google.com/storage/docs/authentication/managing-hmackeys
2698  * for a detailed description on how to use the feature.
2699  */
2700  template <typename... Options>
2701  StatusOr<HmacKeyMetadata> UpdateHmacKey(std::string access_id,
2702  HmacKeyMetadata resource,
2703  Options&&... options) {
2704  auto const& project_id = raw_client_->client_options().project_id();
2705  internal::UpdateHmacKeyRequest request(project_id, std::move(access_id),
2706  std::move(resource));
2707  request.set_multiple_options(std::forward<Options>(options)...);
2708  return raw_client_->UpdateHmacKey(request);
2709  }
2710  //@}
2711 
2712  //@{
2713  /// @name Signed URL support operations.
2714  /**
2715  * Create a V2 signed URL for the given parameters.
2716  *
2717  * @note By default URLs created with this function expire after 7 days.
2718  *
2719  * @note The application must ensure that any URL created with this function
2720  * is a valid request via the XML API. For example, the options for
2721  * bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2722  * not all sub-resources are valid for objects. Likewise, only a single
2723  * sub-resource may be retrieved in each request.
2724  *
2725  * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2726  * `PUT`, `HEAD`, etc. are valid values.
2727  * @param bucket_name the name of the bucket.
2728  * @param object_name the name of the object, note that the object may not
2729  * exist for signed URLs that upload new objects. Use an empty string for
2730  * requests that only affect a bucket.
2731  * @param options a list of optional parameters for the signed URL, this
2732  * include: `ExpirationTime`, `MD5HashValue`, `ContentType`,
2733  * `SigningAccount`, `SigningAccountDelegates`,
2734  * `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2735  * `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2736  * option has any effect.
2737  *
2738  * @par Helper Functions
2739  *
2740  * The following functions create a `AddSubResourceOption` with less
2741  * opportunities for typos in the sub-resource name: `WithAcl()`,
2742  * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2743  * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2744  * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2745  *
2746  * Likewise, the following helper functions can create properly formatted
2747  * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2748  * `WithGenerationMarker()`, `WithMarker()`,
2749  * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2750  * `WithUserProject()`.
2751  *
2752  * @return the signed URL.
2753  *
2754  * @par Example
2755  * @snippet storage_signed_url_v2_samples.cc sign url v2
2756  *
2757  * @par Example
2758  * @snippet storage_signed_url_v2_samples.cc create put signed url v2
2759  *
2760  * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2761  * a general description of signed URLs and how they can be used.
2762  *
2763  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2764  * description of the XML API.
2765  */
2766  template <typename... Options>
2767  StatusOr<std::string> CreateV2SignedUrl(std::string verb,
2768  std::string bucket_name,
2769  std::string object_name,
2770  Options&&... options) {
2771  internal::V2SignUrlRequest request(std::move(verb), std::move(bucket_name),
2772  std::move(object_name));
2773  request.set_multiple_options(std::forward<Options>(options)...);
2774  return SignUrlV2(request);
2775  }
2776 
2777  /**
2778  * Create a V4 signed URL for the given parameters.
2779  *
2780  * @note By default URLs created with this function expire after 7 days.
2781  *
2782  * @note The application must ensure that any URL created with this function
2783  * is a valid request via the XML API. For example, the options for
2784  * bucket requests may include a sub-resource (e.g. `WithBilling()`) but
2785  * not all sub-resources are valid for objects. Likewise, only a single
2786  * sub-resource may be retrieved in each request.
2787  *
2788  * @param verb the operation allowed through this signed URL, `GET`, `POST`,
2789  * `PUT`, `HEAD`, etc. are valid values.
2790  * @param bucket_name the name of the bucket.
2791  * @param object_name the name of the object, note that the object may not
2792  * exist for signed URLs that upload new objects. Use an empty string for
2793  * requests that only affect a bucket.
2794  * @param options a list of optional parameters for the signed URL, this
2795  * include: `SignedUrlTimestamp`, `SignedUrlDuration`, `MD5HashValue`,
2796  * `ContentType`, `SigningAccount`, `SigningAccountDelegates`,
2797  * `AddExtensionHeaderOption`, `AddQueryParameterOption`, and
2798  * `AddSubResourceOption`. Note that only the last `AddSubResourceOption`
2799  * option has any effect.
2800  *
2801  * @par Helper Functions
2802  *
2803  * The following functions create a `AddSubResourceOption` with less
2804  * opportunities for typos in the sub-resource name: `WithAcl()`,
2805  * `WithBilling()`, `WithCompose()`, `WithCors()`, `WithEncryption()`,
2806  * `WithEncryptionConfig()`, `WithLifecycle()`, `WithLocation()`,
2807  * `WithLogging()`, `WithStorageClass()`, and `WithTagging()`.
2808  *
2809  * Likewise, the following helper functions can create properly formatted
2810  * `AddExtensionHeaderOption` objects: `WithGeneration()`,
2811  * `WithGenerationMarker()`, `WithMarker()`,
2812  * `WithResponseContentDisposition()`, `WithResponseContentType()`, and
2813  * `WithUserProject()`.
2814  *
2815  * @return the signed URL.
2816  *
2817  * @par Example
2818  * @snippet storage_signed_url_v4_samples.cc sign url v4
2819  *
2820  * @par Example
2821  * @snippet storage_signed_url_v4_samples.cc create put signed url v4
2822  *
2823  * @see https://cloud.google.com/storage/docs/access-control/signed-urls for
2824  * a general description of signed URLs and how they can be used.
2825  *
2826  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2827  * description of the XML API.
2828  */
2829  template <typename... Options>
2830  StatusOr<std::string> CreateV4SignedUrl(std::string verb,
2831  std::string bucket_name,
2832  std::string object_name,
2833  Options&&... options) {
2834  internal::V4SignUrlRequest request(std::move(verb), std::move(bucket_name),
2835  std::move(object_name));
2836  request.set_multiple_options(std::forward<Options>(options)...);
2837  return SignUrlV4(std::move(request));
2838  }
2839  //@}
2840 
2841  /**
2842  * Create a signed policy document.
2843  *
2844  * @note The application must ensure that any document created with this
2845  * function contains valid conditions. This function does not do any error
2846  * checking, e.g. that a `ExactMatchObject()` condition contains two
2847  * elements. Using the provided helper functions can prevent errors.
2848  *
2849  * @note It is the application's responsibility to construct a POST request
2850  * based on the value returned by this function. For example, a web
2851  * application can create a HTML form containing these fields, the result of
2852  * which is a POST request to GCS.
2853  *
2854  * @param document the policy document.
2855  * @param options a list of optional parameters, this includes:
2856  * `SigningAccount`, and `SigningAccountDelegates`.
2857  *
2858  * @par Helper Functions
2859  * The following functions create a `PolicyDocumentCondition` with less
2860  * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2861  * `ExactMatch()`, `ContentLengthRange()`.
2862  *
2863  * @par Example
2864  * @snippet storage_policy_doc_samples.cc create signed policy document
2865  *
2866  * @see
2867  * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2868  * for a general description of policy documents and how they can be used.
2869  *
2870  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2871  * description of the XML API.
2872  */
2873  template <typename... Options>
2875  PolicyDocument document, Options&&... options) {
2876  internal::PolicyDocumentRequest request(std::move(document));
2877  request.set_multiple_options(std::forward<Options>(options)...);
2878  return SignPolicyDocument(request);
2879  }
2880 
2881  /**
2882  * Create a signed V4 policy document.
2883  *
2884  * @note The application must ensure that any document created with this
2885  * function contains valid conditions. This function does not do any error
2886  * checking, e.g. that a `ExactMatchObject()` condition contains two
2887  * elements. Using the provided helper functions can prevent errors.
2888  *
2889  * @note It is the application's responsibility to construct a POST request
2890  * based on the value returned by this function. For example, a web
2891  * application can create a HTML form containing these fields, the result of
2892  * which is a POST request to GCS.
2893  *
2894  * @param document the policy document.
2895  * @param options a list of optional parameters, this includes:
2896  * `AddExtensionFieldOption`, `BucketBoundHostname`, `PredefinedAcl`,
2897  * `Scheme`, `SigningAccountDelegates`, `SigningAccount`, `VirtualHostname`
2898  *
2899  * @par Helper Functions
2900  * The following functions create a `PolicyDocumentCondition` with less
2901  * opportunities for typos: `StartsWith()`, `ExactMatchObject()`,
2902  * `ExactMatch()`, `ContentLengthRange()`.
2903  *
2904  * @par Example
2905  * @snippet storage_policy_doc_samples.cc create signed policy document v4
2906  *
2907  * @see
2908  * https://cloud.google.com/storage/docs/xml-api/post-object#policydocument
2909  * for a general description of policy documents and how they can be used.
2910  *
2911  * @see https://cloud.google.com/storage/docs/xml-api/overview for a detailed
2912  * description of the XML API.
2913  */
2914  template <typename... Options>
2916  PolicyDocumentV4 document, Options&&... options) {
2917  internal::PolicyDocumentV4Request request(std::move(document));
2918  request.set_multiple_options(std::forward<Options>(options)...);
2919  return SignPolicyDocumentV4(std::move(request));
2920  }
2921 
2922  //@{
2923  /**
2924  * @name Pub/Sub operations.
2925  *
2926  * Cloud Pub/Sub Notifications sends information about changes to objects in
2927  * your buckets to Cloud Pub/Sub, where the information is added to a Cloud
2928  * Pub/Sub topic of your choice in the form of messages.
2929  *
2930  * @see https://cloud.google.com/storage/docs/pubsub-notifications for more
2931  * information about Cloud Pub/Sub in the context of GCS.
2932  */
2933  /**
2934  * Retrieves the list of Notifications for a Bucket.
2935  *
2936  * Cloud Pub/Sub Notifications sends information about changes to objects
2937  * in your buckets to Google Cloud Pub/Sub service.
2938  *
2939  * @param bucket_name the name of the bucket.
2940  * @param options a list of optional query parameters and/or request headers.
2941  * Valid types for this operation include `UserProject`.
2942  *
2943  * @par Idempotency
2944  * This is a read-only operation and is always idempotent.
2945  *
2946  * @par Example
2947  * @snippet storage_notification_samples.cc list notifications
2948  */
2949  template <typename... Options>
2950  StatusOr<std::vector<NotificationMetadata>> ListNotifications(
2951  std::string const& bucket_name, Options&&... options) {
2952  internal::ListNotificationsRequest request(bucket_name);
2953  request.set_multiple_options(std::forward<Options>(options)...);
2954  auto result = raw_client_->ListNotifications(request);
2955  if (!result) {
2956  return std::move(result).status();
2957  }
2958  return std::move(result.value().items);
2959  }
2960 
2961  /**
2962  * Creates a new notification config for a Bucket.
2963  *
2964  * Cloud Pub/Sub Notifications send information about changes to objects
2965  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
2966  * notifications per Bucket, with different topics and filtering options.
2967  *
2968  * @param bucket_name the name of the bucket.
2969  * @param topic_name the Google Cloud Pub/Sub topic that will receive the
2970  * notifications. This requires the full name of the topic, i.e.:
2971  * `projects/<PROJECT_ID>/topics/<TOPIC_ID>`.
2972  * @param metadata define any optional parameters for the notification, such
2973  * as the list of event types, or any custom attributes.
2974  * @param options a list of optional query parameters and/or request headers.
2975  * Valid types for this operation include `UserProject`.
2976  *
2977  * @par Idempotency
2978  * This operation is only idempotent if restricted by pre-conditions. There
2979  * are no pre-conditions for this operation that can make it idempotent.
2980  *
2981  * @par Example
2982  * @snippet storage_notification_samples.cc create notification
2983  *
2984  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
2985  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
2986  *
2987  * @see https://cloud.google.com/pubsub/ for general information on Google
2988  * Cloud Pub/Sub service.
2989  */
2990  template <typename... Options>
2992  std::string const& bucket_name, std::string const& topic_name,
2993  NotificationMetadata metadata, Options&&... options) {
2994  return CreateNotification(bucket_name, topic_name,
2995  payload_format::JsonApiV1(), std::move(metadata),
2996  std::forward<Options>(options)...);
2997  }
2998 
2999  /**
3000  * Creates a new notification config for a Bucket.
3001  *
3002  * Cloud Pub/Sub Notifications send information about changes to objects
3003  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3004  * notifications per Bucket, with different topics and filtering options.
3005  *
3006  * @param bucket_name the name of the bucket.
3007  * @param topic_name the Google Cloud Pub/Sub topic that will receive the
3008  * notifications. This requires the full name of the topic, i.e.:
3009  * `projects/<PROJECT_ID>/topics/<TOPIC_ID>`.
3010  * @param payload_format how will the data be formatted in the notifications,
3011  * consider using the helpers in the `payload_format` namespace, or
3012  * specify one of the valid formats defined in:
3013  * https://cloud.google.com/storage/docs/json_api/v1/notifications
3014  * @param metadata define any optional parameters for the notification, such
3015  * as the list of event types, or any custom attributes.
3016  * @param options a list of optional query parameters and/or request headers.
3017  * Valid types for this operation include `UserProject`.
3018  *
3019  * @par Idempotency
3020  * This operation is only idempotent if restricted by pre-conditions. There
3021  * are no pre-conditions for this operation that can make it idempotent.
3022  *
3023  * @par Example
3024  * @snippet storage_notification_samples.cc create notification
3025  *
3026  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3027  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3028  *
3029  * @see https://cloud.google.com/pubsub/ for general information on Google
3030  * Cloud Pub/Sub service.
3031  */
3032  template <typename... Options>
3034  std::string const& bucket_name, std::string const& topic_name,
3035  std::string const& payload_format, NotificationMetadata metadata,
3036  Options&&... options) {
3037  metadata.set_topic(topic_name).set_payload_format(payload_format);
3038  internal::CreateNotificationRequest request(bucket_name, metadata);
3039  request.set_multiple_options(std::forward<Options>(options)...);
3040  return raw_client_->CreateNotification(request);
3041  }
3042 
3043  /**
3044  * Gets the details about a notification config in a given Bucket.
3045  *
3046  * Cloud Pub/Sub Notifications sends information about changes to objects
3047  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3048  * notifications per Bucket, with different topics and filtering options. This
3049  * function fetches the detailed information for a given notification config.
3050  *
3051  * @param bucket_name the name of the bucket.
3052  * @param notification_id the id of the notification config.
3053  * @param options a list of optional query parameters and/or request headers.
3054  * Valid types for this operation include `UserProject`.
3055  *
3056  * @par Idempotency
3057  * This is a read-only operation and is always idempotent.
3058  *
3059  * @par Example
3060  * @snippet storage_notification_samples.cc get notification
3061  *
3062  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3063  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3064  *
3065  * @see https://cloud.google.com/pubsub/ for general information on Google
3066  * Cloud Pub/Sub service.
3067  */
3068  template <typename... Options>
3070  std::string const& bucket_name, std::string const& notification_id,
3071  Options&&... options) {
3072  internal::GetNotificationRequest request(bucket_name, notification_id);
3073  request.set_multiple_options(std::forward<Options>(options)...);
3074  return raw_client_->GetNotification(request);
3075  }
3076 
3077  /**
3078  * Delete an existing notification config in a given Bucket.
3079  *
3080  * Cloud Pub/Sub Notifications sends information about changes to objects
3081  * in your buckets to Google Cloud Pub/Sub service. You can create multiple
3082  * notifications per Bucket, with different topics and filtering options. This
3083  * function deletes one of the notification configs.
3084  *
3085  * @param bucket_name the name of the bucket.
3086  * @param notification_id the id of the notification config.
3087  * @param options a list of optional query parameters and/or request headers.
3088  * Valid types for this operation include `UserProject`.
3089  *
3090  * @par Idempotency
3091  * This operation is always idempotent because it only acts on a specific
3092  * `notification_id`, the state after calling this function multiple times is
3093  * to delete that notification. New notifications get different ids.
3094  *
3095  * @par Example
3096  * @snippet storage_notification_samples.cc delete notification
3097  *
3098  * @see https://cloud.google.com/storage/docs/pubsub-notifications for general
3099  * information on Cloud Pub/Sub Notifications for Google Cloud Storage.
3100  *
3101  * @see https://cloud.google.com/pubsub/ for general information on Google
3102  * Cloud Pub/Sub service.
3103  */
3104  template <typename... Options>
3105  Status DeleteNotification(std::string const& bucket_name,
3106  std::string const& notification_id,
3107  Options&&... options) {
3108  internal::DeleteNotificationRequest request(bucket_name, notification_id);
3109  request.set_multiple_options(std::forward<Options>(options)...);
3110  return std::move(raw_client_->DeleteNotification(request)).status();
3111  }
3112  //@}
3113 
3114  private:
3115  friend class internal::NonResumableParallelUploadState;
3116  friend class internal::ResumableParallelUploadState;
3117  friend internal::ClientImplDetails;
3118 
3119  struct InternalOnly {};
3120  struct InternalOnlyNoDecorations {};
3121 
3122  Client(InternalOnly, Options const& opts)
3123  : raw_client_(CreateDefaultInternalClient(opts)) {}
3124  Client(InternalOnlyNoDecorations, std::shared_ptr<internal::RawClient> c)
3125  : raw_client_(std::move(c)) {}
3126 
3127  static std::shared_ptr<internal::RawClient> CreateDefaultInternalClient(
3128  Options const& opts, std::shared_ptr<internal::RawClient> client);
3129  static std::shared_ptr<internal::RawClient> CreateDefaultInternalClient(
3130  Options const& opts);
3131 
3132  ObjectReadStream ReadObjectImpl(
3133  internal::ReadObjectRangeRequest const& request);
3134 
3135  ObjectWriteStream WriteObjectImpl(
3136  internal::ResumableUploadRequest const& request);
3137 
3138  // The version of UploadFile() where UseResumableUploadSession is one of the
3139  // options. Note how this does not use InsertObjectMedia at all.
3140  template <typename... Options>
3141  StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3142  std::string const& bucket_name,
3143  std::string const& object_name,
3144  std::true_type,
3145  Options&&... options) {
3146  internal::ResumableUploadRequest request(bucket_name, object_name);
3147  request.set_multiple_options(std::forward<Options>(options)...);
3148  return UploadFileResumable(file_name, std::move(request));
3149  }
3150 
3151  // The version of UploadFile() where UseResumableUploadSession is *not* one of
3152  // the options. In this case we can use InsertObjectMediaRequest because it
3153  // is safe.
3154  template <typename... Options>
3155  StatusOr<ObjectMetadata> UploadFileImpl(std::string const& file_name,
3156  std::string const& bucket_name,
3157  std::string const& object_name,
3158  std::false_type,
3159  Options&&... options) {
3160  std::size_t file_size = 0;
3161  if (UseSimpleUpload(file_name, file_size)) {
3162  internal::InsertObjectMediaRequest request(bucket_name, object_name,
3163  std::string{});
3164  request.set_multiple_options(std::forward<Options>(options)...);
3165  return UploadFileSimple(file_name, file_size, request);
3166  }
3167  internal::ResumableUploadRequest request(bucket_name, object_name);
3168  request.set_multiple_options(std::forward<Options>(options)...);
3169  return UploadFileResumable(file_name, std::move(request));
3170  }
3171 
3172  bool UseSimpleUpload(std::string const& file_name, std::size_t& size) const;
3173 
3174  StatusOr<ObjectMetadata> UploadFileSimple(
3175  std::string const& file_name, std::size_t file_size,
3176  internal::InsertObjectMediaRequest request);
3177 
3178  StatusOr<ObjectMetadata> UploadFileResumable(
3179  std::string const& file_name, internal::ResumableUploadRequest request);
3180 
3181  StatusOr<ObjectMetadata> UploadStreamResumable(
3182  std::istream& source,
3183  internal::ResumableUploadRequest const& request) const;
3184 
3185  Status DownloadFileImpl(internal::ReadObjectRangeRequest const& request,
3186  std::string const& file_name);
3187 
3188  /// Determine the email used to sign a blob.
3189  std::string SigningEmail(SigningAccount const& signing_account) const;
3190 
3191  /// Represents the result of signing a blob, including the key used in the
3192  /// signature.
3193  struct SignBlobResponseRaw {
3194  std::string key_id;
3195  std::vector<std::uint8_t> signed_blob;
3196  };
3197 
3198  /// Sign a blob.
3199  StatusOr<SignBlobResponseRaw> SignBlobImpl(
3200  SigningAccount const& signing_account, std::string const& string_to_sign);
3201 
3202  StatusOr<std::string> SignUrlV2(internal::V2SignUrlRequest const& request);
3203  StatusOr<std::string> SignUrlV4(internal::V4SignUrlRequest request);
3204 
3205  StatusOr<PolicyDocumentResult> SignPolicyDocument(
3206  internal::PolicyDocumentRequest const& request);
3207  StatusOr<PolicyDocumentV4Result> SignPolicyDocumentV4(
3208  internal::PolicyDocumentV4Request request);
3209 
3210  std::shared_ptr<internal::RawClient> raw_client_;
3211 };
3212 
3213 /**
3214  * Create a random prefix for object names.
3215  *
3216  * This is useful for operations which require a unique prefix for temporary
3217  * files.
3218  *
3219  * This is a helper function and it doesn't communicate with GCS, so there is a
3220  * very small chance that names generated this way aren't unique. The chance
3221  * should be small enough to fit any error budget.
3222  *
3223  * Given the same `prefix`, the randomly generated names will have the same
3224  * length.
3225  *
3226  * @param prefix the prefix of the prefix to be created.
3227  * @return the random prefix name
3228  */
3229 std::string CreateRandomPrefixName(std::string const& prefix = "");
3230 
3231 namespace internal {
3232 struct ClientImplDetails {
3233  static std::shared_ptr<RawClient> GetRawClient(Client& c) {
3234  return c.raw_client_;
3235  }
3236 
3237  static StatusOr<ObjectMetadata> UploadStreamResumable(
3238  Client& client, std::istream& source,
3239  internal::ResumableUploadRequest const& request) {
3240  return client.UploadStreamResumable(source, request);
3241  }
3242  template <typename... Policies>
3243 
3244  static Client CreateClient(std::shared_ptr<internal::RawClient> c,
3245  Policies&&... p) {
3246  auto opts =
3247  internal::ApplyPolicies(internal::MakeOptions(c->client_options()),
3248  std::forward<Policies>(p)...);
3249  return Client(Client::InternalOnlyNoDecorations{},
3250  Client::CreateDefaultInternalClient(opts, std::move(c)));
3251  }
3252 
3253  static Client CreateWithoutDecorations(
3254  std::shared_ptr<internal::RawClient> c) {
3255  return Client(Client::InternalOnlyNoDecorations{}, std::move(c));
3256  }
3257 };
3258 
3259 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3260 struct DeleteApplyHelper {
3261  template <typename... Options>
3262  Status operator()(Options... options) const {
3263  return client.DeleteObject(bucket_name, object_name, Generation(generation),
3264  std::move(options)...);
3265  }
3266 
3267  Client& client;
3268  std::string bucket_name;
3269  std::string object_name;
3270  std::int64_t generation;
3271 };
3272 
3273 // Just a wrapper to allow for using in `google::cloud::internal::apply`.
3274 struct InsertObjectApplyHelper {
3275  template <typename... Options>
3276  StatusOr<ObjectMetadata> operator()(Options... options) const {
3277  return client.InsertObject(bucket_name, object_name, std::move(contents),
3278  std::move(options)...);
3279  }
3280 
3281  Client& client;
3282  std::string const& bucket_name;
3283  std::string const& object_name;
3284  std::string contents;
3285 };
3286 
3287 /**
3288  * Create a "marker" object to ensure that two tasks cannot share a prefix.
3289  *
3290  * @param client the client on which to perform the operation.
3291  * @param bucket_name the name of the bucket that will contain the object.
3292  * @param prefix the prefix of the objects to be deleted.
3293  * @param options a list of optional query parameters and/or request headers.
3294  * Valid types for this operation include `EncryptionKey` `KmsKeyName`,
3295  * `PredefinedAcl`, `Projection`, `UserProject`, and `WithObjectMetadata`.
3296  * Contrary to the public API, invalid options will be silently ignored
3297  * for ease of use.
3298  * @return the metadata of the marker
3299  */
3300 template <typename... Options>
3301 StatusOr<ObjectMetadata> LockPrefix(Client& client,
3302  std::string const& bucket_name,
3303  std::string const& prefix,
3304  Options&&... options) {
3305  return google::cloud::internal::apply(
3306  internal::InsertObjectApplyHelper{client, bucket_name, prefix, ""},
3307  std::tuple_cat(
3308  std::make_tuple(IfGenerationMatch(0)),
3309  internal::StaticTupleFilter<
3310  internal::Among<EncryptionKey, KmsKeyName, PredefinedAcl,
3311  Projection, UserProject>::TPred>(
3312  std::forward_as_tuple(std::forward<Options>(options)...))));
3313 }
3314 
3315 } // namespace internal
3316 
3317 /**
3318  * Delete objects whose names match a given prefix
3319  *
3320  * @param client the client on which to perform the operation.
3321  * @param bucket_name the name of the bucket that will contain the object.
3322  * @param prefix the prefix of the objects to be deleted.
3323  * @param options a list of optional query parameters and/or request headers.
3324  * Valid types for this operation include `QuotaUser`, `UserIp`,
3325  * `UserProject` and `Versions`.
3326  */
3327 template <typename... Options>
3328 Status DeleteByPrefix(Client& client, std::string const& bucket_name,
3329  std::string const& prefix, Options&&... options) {
3330  using internal::NotAmong;
3331  using internal::StaticTupleFilter;
3332 
3333  auto all_options = std::tie(options...);
3334 
3335  static_assert(
3336  std::tuple_size<
3337  decltype(StaticTupleFilter<
3338  NotAmong<QuotaUser, UserIp, UserProject, Versions>::TPred>(
3339  all_options))>::value == 0,
3340  "This functions accepts only options of type QuotaUser, UserIp, "
3341  "UserProject or Versions.");
3342  auto status = Status{};
3343  for (auto& object :
3344  client.ListObjects(bucket_name, Projection::NoAcl(), Prefix(prefix),
3345  std::forward<Options>(options)...)) {
3346  if (!object) return std::move(object).status();
3347  auto del = google::cloud::internal::apply(
3348  internal::DeleteApplyHelper{client, object->bucket(), object->name(),
3349  object->generation()},
3350  StaticTupleFilter<NotAmong<Versions>::TPred>(all_options));
3351  // We ignore kNotFound because we are trying to delete the object anyway.
3352  if (del.ok() || status.code() == StatusCode::kNotFound) continue;
3353  status = std::move(del);
3354  }
3355  return status;
3356 }
3357 
3358 namespace internal {
3359 
3360 // Just a wrapper to allow for use in `google::cloud::internal::apply`.
3361 struct ComposeApplyHelper {
3362  template <typename... Options>
3363  StatusOr<ObjectMetadata> operator()(Options... options) const {
3364  return client.ComposeObject(
3365  std::move(bucket_name), std::move(source_objects),
3366  std::move(destination_object_name), std::move(options)...);
3367  }
3368 
3369  Client& client;
3370  std::string bucket_name;
3371  std::vector<ComposeSourceObject> source_objects;
3372  std::string destination_object_name;
3373 };
3374 
3375 // A helper to defer deletion of temporary GCS objects.
3376 class ScopedDeleter {
3377  public:
3378  // The actual deletion depends on local's types in a very non-trivial way,
3379  // so we abstract this away by providing the function to delete one object.
3380  explicit ScopedDeleter(std::function<Status(std::string, std::int64_t)> df);
3381  ScopedDeleter(ScopedDeleter const&) = delete;
3382  ScopedDeleter& operator=(ScopedDeleter const&) = delete;
3383  ~ScopedDeleter();
3384 
3385  /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3386  void Add(ObjectMetadata const& object);
3387 
3388  /// Defer object's deletion to this objects destruction (or ExecuteDelete())
3389  void Add(std::string object_name, std::int64_t generation);
3390 
3391  /// Execute all the deferred deletions now.
3392  Status ExecuteDelete();
3393 
3394  void Enable(bool enable) { enabled_ = enable; }
3395 
3396  private:
3397  bool enabled_ = true;
3398  std::function<Status(std::string, std::int64_t)> delete_fun_;
3399  std::vector<std::pair<std::string, std::int64_t>> object_list_;
3400 };
3401 
3402 } // namespace internal
3403 
3404 /**
3405  * Compose existing objects into a new object in the same bucket.
3406  *
3407  * Contrary to `Client::ComposeObject`, this function doesn't have a limit on
3408  * the number of source objects.
3409  *
3410  * The implementation may need to perform multiple Client::ComposeObject calls
3411  * to create intermediate, temporary objects which are then further composed.
3412  * Due to the lack of atomicity of this series of operations, stray temporary
3413  * objects might be left over if there are transient failures. In order to allow
3414  * the user to easily control for such situations, the user is expected to
3415  * provide a unique @p prefix parameter, which will become the prefix of all the
3416  * temporary objects created by this function. Once this function finishes, the
3417  * user may safely remove all objects with the provided prefix (e.g. via
3418  * DeleteByPrefix()). We recommend using CreateRandomPrefixName() for selecting
3419  * a random prefix within a bucket.
3420  *
3421  * @param client the client on which to perform the operations needed by this
3422  * function
3423  * @param bucket_name the name of the bucket used for source object and
3424  * destination object.
3425  * @param source_objects objects used to compose `destination_object_name`.
3426  * @param destination_object_name the composed object name.
3427  * @param prefix prefix for temporary objects created by this function; there
3428  * should not be any objects with this prefix; in order to avoid race
3429  * conditions, this function will create an object with this name
3430  * @param ignore_cleanup_failures if the composition succeeds but cleanup of
3431  * temporary objects fails, depending on this parameter either a success
3432  * will be returned (`true`) or the relevant cleanup error (`false`)
3433  * @param options a list of optional query parameters and/or request headers.
3434  * Valid types for this operation include `DestinationPredefinedAcl`,
3435  * `EncryptionKey`, `IfGenerationMatch`, `IfMetagenerationMatch`
3436  * `KmsKeyName`, `QuotaUser`, `UserIp`, `UserProject` and
3437  * `WithObjectMetadata`.
3438  *
3439  * @par Idempotency
3440  * This operation is not idempotent. While each request performed by this
3441  * function is retried based on the client policies, the operation itself stops
3442  * on the first request that fails.
3443  *
3444  * @par Example
3445  * @snippet storage_object_samples.cc compose object from many
3446  */
3447 template <typename... Options>
3449  Client& client, std::string const& bucket_name,
3450  std::vector<ComposeSourceObject> source_objects, std::string const& prefix,
3451  std::string destination_object_name, bool ignore_cleanup_failures,
3452  Options&&... options) {
3453  using internal::Among;
3454  using internal::NotAmong;
3455  using internal::StaticTupleFilter;
3456  std::size_t const max_num_objects = 32;
3457 
3458  if (source_objects.empty()) {
3460  "ComposeMany requires at least one source object.");
3461  }
3462 
3463  auto all_options = std::make_tuple(options...);
3464 
3465  // TODO(#3247): this list of type should somehow be generated
3466  static_assert(
3467  std::tuple_size<
3468  decltype(StaticTupleFilter<
3471  KmsKeyName, QuotaUser, UserIp, UserProject,
3472  WithObjectMetadata>::TPred>(all_options))>::value ==
3473  0,
3474  "This functions accepts only options of type DestinationPredefinedAcl, "
3475  "EncryptionKey, IfGenerationMatch, IfMetagenerationMatch, KmsKeyName, "
3476  "QuotaUser, UserIp, UserProject or WithObjectMetadata.");
3477 
3478  internal::ScopedDeleter deleter(
3479  [&](std::string const& object_name, std::int64_t generation) {
3480  return google::cloud::internal::apply(
3481  internal::DeleteApplyHelper{client, bucket_name, object_name,
3482  generation},
3483  StaticTupleFilter<Among<QuotaUser, UserProject, UserIp>::TPred>(
3484  all_options));
3485  });
3486 
3487  auto lock = internal::LockPrefix(client, bucket_name, prefix, "",
3488  std::make_tuple(options...));
3489  if (!lock) {
3490  return Status(
3491  lock.status().code(),
3492  "Failed to lock prefix for ComposeMany: " + lock.status().message());
3493  }
3494  deleter.Add(*lock);
3495 
3496  std::size_t num_tmp_objects = 0;
3497  auto tmpobject_name_gen = [&num_tmp_objects, &prefix] {
3498  return prefix + ".compose-tmp-" + std::to_string(num_tmp_objects++);
3499  };
3500 
3501  auto to_source_objects = [](std::vector<ObjectMetadata> objects) {
3502  std::vector<ComposeSourceObject> sources(objects.size());
3503  std::transform(objects.begin(), objects.end(), sources.begin(),
3504  [](ObjectMetadata const& m) {
3505  return ComposeSourceObject{m.name(), m.generation(), {}};
3506  });
3507  return sources;
3508  };
3509 
3510  auto composer = [&](std::vector<ComposeSourceObject> compose_range,
3511  bool is_final) -> StatusOr<ObjectMetadata> {
3512  if (is_final) {
3513  return google::cloud::internal::apply(
3514  internal::ComposeApplyHelper{client, bucket_name,
3515  std::move(compose_range),
3516  std::move(destination_object_name)},
3517  all_options);
3518  }
3519  return google::cloud::internal::apply(
3520  internal::ComposeApplyHelper{client, bucket_name,
3521  std::move(compose_range),
3522  tmpobject_name_gen()},
3523  StaticTupleFilter<
3524  NotAmong<IfGenerationMatch, IfMetagenerationMatch>::TPred>(
3525  all_options));
3526  };
3527 
3528  auto reduce = [&](std::vector<ComposeSourceObject> source_objects)
3529  -> StatusOr<std::vector<ObjectMetadata>> {
3530  std::vector<ObjectMetadata> objects;
3531  for (auto range_begin = source_objects.begin();
3532  range_begin != source_objects.end();) {
3533  std::size_t range_size = std::min<std::size_t>(
3534  std::distance(range_begin, source_objects.end()), max_num_objects);
3535  auto range_end = std::next(range_begin, range_size);
3536  std::vector<ComposeSourceObject> compose_range(range_size);
3537  std::move(range_begin, range_end, compose_range.begin());
3538 
3539  bool const is_final_composition =
3540  source_objects.size() <= max_num_objects;
3541  auto object = composer(std::move(compose_range), is_final_composition);
3542  if (!object) {
3543  return std::move(object).status();
3544  }
3545  objects.push_back(*std::move(object));
3546  if (!is_final_composition) {
3547  deleter.Add(objects.back());
3548  }
3549  range_begin = range_end;
3550  }
3551  return objects;
3552  };
3553 
3554  StatusOr<ObjectMetadata> result;
3555  do {
3556  StatusOr<std::vector<ObjectMetadata>> objects = reduce(source_objects);
3557  if (!objects) {
3558  return objects.status();
3559  }
3560  if (objects->size() == 1) {
3561  if (!ignore_cleanup_failures) {
3562  auto delete_status = deleter.ExecuteDelete();
3563  if (!delete_status.ok()) {
3564  return delete_status;
3565  }
3566  }
3567  result = std::move((*objects)[0]);
3568  break;
3569  }
3570  source_objects = to_source_objects(*std::move(objects));
3571  } while (source_objects.size() > 1);
3572  return result;
3573 }
3574 
3576 } // namespace storage
3577 } // namespace cloud
3578 } // namespace google
3579 
3580 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_STORAGE_CLIENT_H