/// <summary>
 /// Patches the metadata for a storage bucket asynchronously.
 /// </summary>
 /// <param name="bucket">Bucket to update. Must not be null, and must have a populated <c>Name</c> property.</param>
 /// <param name="options">Additional options for the update. May be null, in which case appropriate
 /// defaults will be used.</param>
 /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
 /// <returns>A task representing the asynchronous operation, with a result returning the
 /// <see cref="Bucket"/> representation of the bucket storage bucket.</returns>
 public virtual Task <Bucket> PatchBucketAsync(
     Bucket bucket,
     PatchBucketOptions options          = null,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     throw new NotImplementedException();
 }
        private BucketsResource.PatchRequest CreatePatchBucketRequest(Bucket bucket, PatchBucketOptions options)
        {
            ValidateBucket(bucket, nameof(bucket));
            var request = Service.Buckets.Patch(bucket, bucket.Name);

            options?.ModifyRequest(request);
            return(request);
        }
        /// <inheritdoc />
        public override IDictionary <string, string> ModifyBucketLabels(string bucket, IDictionary <string, string> labels, ModifyBucketLabelsOptions options = null)
        {
            ValidateBucketName(bucket);
            GaxPreconditions.CheckNotNull(labels, nameof(labels));

            int retries    = options?.Retries ?? ModifyBucketLabelsOptions.DefaultRetries;
            var getOptions = new GetBucketOptions {
                IfMetagenerationMatch = options?.IfMetagenerationMatch
            };

            while (true)
            {
                // Outside the catch, as we don't need to retry if *this* fails the precondition.
                // If the bucket originally has the "right" version but then changes before we patch it, we'll end up retrying this
                // part as well, and it will immediately fail.
                var bucketMetadata = GetBucket(bucket, getOptions);
                try
                {
                    var existingLabels = bucketMetadata.Labels ?? new Dictionary <string, string>();

                    var differences = GetDifferences(labels, existingLabels);
                    // If everything's already as we want it to be, we don't need to patch.
                    if (differences.Count != 0)
                    {
                        var patchOptions = new PatchBucketOptions {
                            IfMetagenerationMatch = bucketMetadata.Metageneration
                        };
                        PatchBucket(new Bucket {
                            Name = bucketMetadata.Name, Labels = differences
                        }, patchOptions);
                    }

                    var oldValues = new Dictionary <string, string>();
                    foreach (var entry in labels)
                    {
                        existingLabels.TryGetValue(entry.Key, out string existingValue);
                        oldValues[entry.Key] = existingValue; // May be null
                    }
                    return(oldValues);
                }
                catch (GoogleApiException e) when(retries > 0 && e.HttpStatusCode == HttpStatusCode.PreconditionFailed)
                {
                    retries--;
                    // No delay here: we're only trying to catch the case where another change is made between Get/Patch.
                }
            }
        }
        /// <inheritdoc />
        public override IDictionary <string, string> ClearBucketLabels(string bucket, ModifyBucketLabelsOptions options = null)
        {
            ValidateBucketName(bucket);

            int retries    = options?.Retries ?? ModifyBucketLabelsOptions.DefaultRetries;
            var getOptions = new GetBucketOptions {
                IfMetagenerationMatch = options?.IfMetagenerationMatch
            };

            while (true)
            {
                // Outside the catch, as we don't need to retry if *this* fails the precondition.
                // If the bucket originally has the "right" version but then changes before we patch it, we'll end up retrying this
                // part as well, and it will immediately fail.
                var bucketMetadata = GetBucket(bucket, getOptions);
                try
                {
                    var existingLabels = bucketMetadata.Labels;
                    if (existingLabels == null || existingLabels.Count == 0)
                    {
                        return(new Dictionary <string, string>());
                    }
                    var patchOptions = new PatchBucketOptions {
                        IfMetagenerationMatch = bucketMetadata.Metageneration
                    };

                    var labels = existingLabels.Keys.ToDictionary(key => key, key => (string)null);
                    PatchBucket(new Bucket {
                        Name = bucketMetadata.Name, Labels = labels
                    }, patchOptions);

                    return(existingLabels);
                }
                catch (GoogleApiException e) when(retries > 0 && e.HttpStatusCode == HttpStatusCode.PreconditionFailed)
                {
                    retries--;
                    // No delay here: we're only trying to catch the case where another change is made between Get/Patch.
                }
            }
        }
 /// <inheritdoc />
 public override Task <Bucket> PatchBucketAsync(
     Bucket bucket,
     PatchBucketOptions options          = null,
     CancellationToken cancellationToken = default)
 => CreatePatchBucketRequest(bucket, options).ExecuteAsync(cancellationToken);
 /// <inheritdoc />
 public override Bucket PatchBucket(
     Bucket bucket,
     PatchBucketOptions options = null)
 => CreatePatchBucketRequest(bucket, options).Execute();
 /// <summary>
 /// Patches the metadata for a storage bucket synchronously.
 /// </summary>
 /// <param name="bucket">Bucket to update. Must not be null, and must have a populated <c>Name</c> property.</param>
 /// <param name="options">Additional options for the update. May be null, in which case appropriate
 /// defaults will be used.</param>
 /// <returns>The <see cref="Bucket"/> representation of the updated storage bucket.</returns>
 public virtual Bucket PatchBucket(
     Bucket bucket,
     PatchBucketOptions options = null)
 {
     throw new NotImplementedException();
 }