Added support for CreateIfNotExists and DeleteIfExists (#1282)
* Added support for CreateIfNotExists and DeleteIfExists * Added DataLake * Refined test cases. * Resolve review comments. * Resolve more review comments.
This commit is contained in:
parent
dc8c9182e1
commit
7615a9ee9b
@ -29,6 +29,7 @@ endif()
|
||||
set(
|
||||
AZURE_STORAGE_FILES_DATALAKE_HEADER
|
||||
inc/azure/storage/files/datalake/protocol/datalake_rest_client.hpp
|
||||
inc/azure/storage/files/datalake/datalake_constants.hpp
|
||||
inc/azure/storage/files/datalake/datalake_directory_client.hpp
|
||||
inc/azure/storage/files/datalake/datalake_file_client.hpp
|
||||
inc/azure/storage/files/datalake/datalake_file_system_client.hpp
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Azure { namespace Storage { namespace Files { namespace DataLake { namespace Details {
|
||||
// Error codes:
|
||||
constexpr static const char* ContainerAlreadyExists = "ContainerAlreadyExists";
|
||||
constexpr static const char* ContainerNotFound = "ContainerNotFound";
|
||||
constexpr static const char* DataLakeFilesystemNotFound = "FilesystemNotFound";
|
||||
constexpr static const char* DataLakePathNotFound = "PathNotFound";
|
||||
constexpr static const char* DataLakePathAlreadyExists = "PathAlreadyExists";
|
||||
|
||||
}}}}} // namespace Azure::Storage::Files::DataLake::Details
|
||||
@ -110,6 +110,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
return PathClient::Create(Models::PathResourceType::Directory, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a directory. If it already exists, nothing will happen.
|
||||
* @param options Optional parameters to create the directory the path points to.
|
||||
* @return Azure::Core::Response<Models::CreateDirectoryResult> containing the information of
|
||||
* the created directory
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreateDirectoryResult> CreateIfNotExists(
|
||||
const CreateDirectoryOptions& options = CreateDirectoryOptions()) const
|
||||
{
|
||||
return PathClient::CreateIfNotExists(Models::PathResourceType::Directory, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renames a directory. By default, the destination is overwritten and
|
||||
* if the destination already exists and has a lease the lease is broken.
|
||||
@ -139,6 +152,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
bool recursive,
|
||||
const DeleteDirectoryOptions& options = DeleteDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the directory if it already exists.
|
||||
* @param recursive If "true", all paths beneath the directory will be deleted. If "false" and
|
||||
* the directory is non-empty, an error occurs.
|
||||
* @param options Optional parameters to delete the directory the path points to.
|
||||
* @return Azure::Core::Response<Models::DeleteDirectoryResult> containing the information
|
||||
* returned when deleting the directory.
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> DeleteIfExists(
|
||||
bool recursive,
|
||||
const DeleteDirectoryOptions& options = DeleteDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Sets POSIX access control rights on files and directories under given directory
|
||||
* recursively.
|
||||
|
||||
@ -137,6 +137,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
return PathClient::Create(Models::PathResourceType::File, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a file. If it already exists, it will remain unchanged.
|
||||
* @param options Optional parameters to create the resource the path points to.
|
||||
* @return Azure::Core::Response<Models::CreateFileResult> containing the information returned
|
||||
* when creating the file.
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreateFileResult> CreateIfNotExists(
|
||||
const CreateFileOptions& options = CreateFileOptions()) const
|
||||
{
|
||||
return PathClient::CreateIfNotExists(Models::PathResourceType::File, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Renames a file. By default, the destination is overwritten and
|
||||
* if the destination already exists and has a lease the lease is broken.
|
||||
@ -162,6 +175,15 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Response<Models::DeleteFileResult> Delete(
|
||||
const FileDeleteOptions& options = FileDeleteOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file if it already exists.
|
||||
* @param options Optional parameters to delete the file the path points to.
|
||||
* @return Azure::Core::Response<Models::DeleteFileResult>
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteFileResult> DeleteIfExists(
|
||||
const FileDeleteOptions& options = FileDeleteOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Read the contents of a file. For read operations, range requests are supported.
|
||||
* @param options Optional parameters to read the content from the resource the path points to.
|
||||
|
||||
@ -115,6 +115,16 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Response<Models::CreateFileSystemResult> Create(
|
||||
const CreateFileSystemOptions& options = CreateFileSystemOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Creates the file system if it does not exists.
|
||||
* @param options Optional parameters to create this file system.
|
||||
* @return Azure::Core::Response<Models::CreateFileSystemResult> containing the information of
|
||||
* create a file system. Only valid when successfully created the file system.
|
||||
* @remark This request is sent to blob endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreateFileSystemResult> CreateIfNotExists(
|
||||
const CreateFileSystemOptions& options = CreateFileSystemOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file system.
|
||||
* @param options Optional parameters to delete this file system.
|
||||
@ -125,6 +135,16 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Response<Models::DeleteFileSystemResult> Delete(
|
||||
const DeleteFileSystemOptions& options = DeleteFileSystemOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file system if it exists.
|
||||
* @param options Optional parameters to delete this file system.
|
||||
* @return Azure::Core::Response<Models::DeleteFileSystemResult> containing the information
|
||||
* returned when deleting file systems. Only valid when successfully deleted the file system.
|
||||
* @remark This request is sent to blob endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteFileSystemResult> DeleteIfExists(
|
||||
const DeleteFileSystemOptions& options = DeleteFileSystemOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the metadata of file system.
|
||||
* @param metadata User-defined metadata to be stored with the filesystem. Note that the string
|
||||
|
||||
@ -96,6 +96,19 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Models::PathResourceType type,
|
||||
const CreatePathOptions& options = CreatePathOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Creates a file or directory. By default, the destination is not changed if it already
|
||||
* exists.
|
||||
* @param options Optional parameters to create the resource the path points to.
|
||||
* @return Azure::Core::Response<Models::CreatePathResult> containing the information returned
|
||||
* when creating a path, the information will only be valid when the create operation is
|
||||
* successful.
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreatePathResult> CreateIfNotExists(
|
||||
Models::PathResourceType type,
|
||||
const CreatePathOptions& options = CreatePathOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the resource the path points to.
|
||||
* @param options Optional parameters to delete the reource the path points to.
|
||||
@ -106,6 +119,16 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Response<Models::DeletePathResult> Delete(
|
||||
const DeletePathOptions& options = DeletePathOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the resource the path points to if it exists.
|
||||
* @param options Optional parameters to delete the reource the path points to.
|
||||
* @return Azure::Core::Response<Models::DeletePathResult> which is current empty but preserved
|
||||
* for future usage. The result will only valid if the delete operation is successful.
|
||||
* @remark This request is sent to dfs endpoint.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeletePathResult> DeleteIfExists(
|
||||
const DeletePathOptions& options = DeletePathOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the owner, group, permissions, or access control list for a file or directory.
|
||||
* Note that Hierarchical Namespace must be enabled for the account in order to use
|
||||
|
||||
@ -21,7 +21,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
|
||||
// FileSystemClient models:
|
||||
|
||||
using DeleteFileSystemResult = FileSystemDeleteResult;
|
||||
using ListPathsResult = FileSystemListPathsResult;
|
||||
|
||||
struct GetFileSystemPropertiesResult
|
||||
@ -31,12 +30,28 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
Storage::Metadata Metadata;
|
||||
};
|
||||
|
||||
using CreateFileSystemResult = FileSystemCreateResult;
|
||||
struct CreateFileSystemResult
|
||||
{
|
||||
bool Created = true;
|
||||
std::string ETag;
|
||||
Core::DateTime LastModified;
|
||||
};
|
||||
|
||||
struct DeleteFileSystemResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
};
|
||||
|
||||
using SetFileSystemMetadataResult = FileSystemCreateResult;
|
||||
|
||||
// PathClient models:
|
||||
|
||||
using DeletePathResult = PathDeleteResult;
|
||||
struct DeletePathResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
Azure::Core::Nullable<std::string> ContinuationToken;
|
||||
};
|
||||
|
||||
using AcquirePathLeaseResult = Blobs::Models::AcquireBlobLeaseResult;
|
||||
using RenewPathLeaseResult = Blobs::Models::RenewBlobLeaseResult;
|
||||
using ReleasePathLeaseResult = Blobs::Models::ReleaseBlobLeaseResult;
|
||||
@ -124,6 +139,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
|
||||
struct CreatePathResult
|
||||
{
|
||||
bool Created = true;
|
||||
std::string ETag;
|
||||
Core::DateTime LastModified;
|
||||
Azure::Core::Nullable<int64_t> ContentLength;
|
||||
@ -161,6 +177,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
|
||||
struct DeleteFileResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
};
|
||||
|
||||
struct DownloadFileToResult
|
||||
@ -185,6 +202,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
|
||||
|
||||
using SetDirectoryAccessControlRecursiveResult = PathSetAccessControlRecursiveResult;
|
||||
using CreateDirectoryResult = CreatePathResult;
|
||||
using DeleteDirectoryResult = PathDeleteResult;
|
||||
using DeleteDirectoryResult = DeletePathResult;
|
||||
|
||||
}}}}} // namespace Azure::Storage::Files::DataLake::Models
|
||||
|
||||
@ -177,7 +177,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
auto result = Details::DataLakeRestClient::Path::Create(
|
||||
destinationDfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
// At this point, there is not more exception thrown, meaning the rename is successful.
|
||||
auto ret = Models::RenameDirectoryResult();
|
||||
Models::RenameDirectoryResult ret;
|
||||
ret.ContinuationToken = std::move(result->ContinuationToken);
|
||||
return Azure::Core::Response<Models::RenameDirectoryResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
@ -187,16 +187,24 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
bool recursive,
|
||||
const DeleteDirectoryOptions& options) const
|
||||
{
|
||||
Details::DataLakeRestClient::Path::DeleteOptions protocolLayerOptions;
|
||||
protocolLayerOptions.ContinuationToken = options.ContinuationToken;
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch;
|
||||
protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
|
||||
protocolLayerOptions.RecursiveOptional = recursive;
|
||||
return Details::DataLakeRestClient::Path::Delete(
|
||||
m_dfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
DeletePathOptions deleteOptions;
|
||||
deleteOptions.AccessConditions = options.AccessConditions;
|
||||
deleteOptions.Context = options.Context;
|
||||
deleteOptions.ContinuationToken = options.ContinuationToken;
|
||||
deleteOptions.Recursive = recursive;
|
||||
return PathClient::Delete(deleteOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> DirectoryClient::DeleteIfExists(
|
||||
bool recursive,
|
||||
const DeleteDirectoryOptions& options) const
|
||||
{
|
||||
DeletePathOptions deleteOptions;
|
||||
deleteOptions.AccessConditions = options.AccessConditions;
|
||||
deleteOptions.Context = options.Context;
|
||||
deleteOptions.ContinuationToken = options.ContinuationToken;
|
||||
deleteOptions.Recursive = recursive;
|
||||
return PathClient::DeleteIfExists(deleteOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::SetDirectoryAccessControlRecursiveResult>
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <azure/storage/common/storage_per_retry_policy.hpp>
|
||||
#include <azure/storage/common/storage_retry_policy.hpp>
|
||||
|
||||
#include "azure/storage/files/datalake/datalake_constants.hpp"
|
||||
#include "azure/storage/files/datalake/datalake_utilities.hpp"
|
||||
#include "azure/storage/files/datalake/version.hpp"
|
||||
|
||||
@ -276,7 +277,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
auto result = Details::DataLakeRestClient::Path::Create(
|
||||
destinationDfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
// At this point, there is not more exception thrown, meaning the rename is successful.
|
||||
auto ret = Models::RenameFileResult();
|
||||
Models::RenameFileResult ret;
|
||||
return Azure::Core::Response<Models::RenameFileResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
@ -284,15 +285,25 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Azure::Core::Response<Models::DeleteFileResult> FileClient::Delete(
|
||||
const FileDeleteOptions& options) const
|
||||
{
|
||||
Details::DataLakeRestClient::Path::DeleteOptions protocolLayerOptions;
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
protocolLayerOptions.IfMatch = options.AccessConditions.IfMatch;
|
||||
protocolLayerOptions.IfNoneMatch = options.AccessConditions.IfNoneMatch;
|
||||
protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
|
||||
auto result = Details::DataLakeRestClient::Path::Delete(
|
||||
m_dfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
auto ret = Models::DeleteFileResult();
|
||||
DeletePathOptions deleteOptions;
|
||||
deleteOptions.AccessConditions = options.AccessConditions;
|
||||
deleteOptions.Context = options.Context;
|
||||
auto result = PathClient::Delete(deleteOptions);
|
||||
Models::DeleteFileResult ret;
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeleteFileResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteFileResult> FileClient::DeleteIfExists(
|
||||
const FileDeleteOptions& options) const
|
||||
{
|
||||
DeletePathOptions deleteOptions;
|
||||
deleteOptions.AccessConditions = options.AccessConditions;
|
||||
deleteOptions.Context = options.Context;
|
||||
auto result = PathClient::DeleteIfExists(deleteOptions);
|
||||
Models::DeleteFileResult ret;
|
||||
ret.Deleted = result->Deleted;
|
||||
return Azure::Core::Response<Models::DeleteFileResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <azure/storage/common/storage_per_retry_policy.hpp>
|
||||
#include <azure/storage/common/storage_retry_policy.hpp>
|
||||
|
||||
#include "azure/storage/files/datalake/datalake_constants.hpp"
|
||||
#include "azure/storage/files/datalake/datalake_directory_client.hpp"
|
||||
#include "azure/storage/files/datalake/datalake_file_client.hpp"
|
||||
#include "azure/storage/files/datalake/datalake_path_client.hpp"
|
||||
@ -194,11 +195,32 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
Models::CreateFileSystemResult ret;
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
ret.Created = true;
|
||||
return Azure::Core::Response<Models::CreateFileSystemResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::FileSystemDeleteResult> FileSystemClient::Delete(
|
||||
Azure::Core::Response<Models::CreateFileSystemResult> FileSystemClient::CreateIfNotExists(
|
||||
const CreateFileSystemOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Create(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ContainerAlreadyExists)
|
||||
{
|
||||
Models::CreateFileSystemResult ret;
|
||||
ret.Created = false;
|
||||
return Azure::Core::Response<Models::CreateFileSystemResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteFileSystemResult> FileSystemClient::Delete(
|
||||
const DeleteFileSystemOptions& options) const
|
||||
{
|
||||
Blobs::DeleteBlobContainerOptions blobOptions;
|
||||
@ -207,11 +229,31 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
blobOptions.AccessConditions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
|
||||
blobOptions.AccessConditions.LeaseId = options.AccessConditions.LeaseId;
|
||||
auto result = m_blobContainerClient.Delete(blobOptions);
|
||||
Models::FileSystemDeleteResult ret;
|
||||
return Azure::Core::Response<Models::FileSystemDeleteResult>(
|
||||
Models::DeleteFileSystemResult ret;
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeleteFileSystemResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteFileSystemResult> FileSystemClient::DeleteIfExists(
|
||||
const DeleteFileSystemOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ContainerNotFound)
|
||||
{
|
||||
Models::DeleteFileSystemResult ret;
|
||||
ret.Deleted = false;
|
||||
return Azure::Core::Response<Models::DeleteFileSystemResult>(ret, std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::GetFileSystemPropertiesResult> FileSystemClient::GetProperties(
|
||||
const GetFileSystemPropertiesOptions& options) const
|
||||
{
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <azure/storage/common/storage_per_retry_policy.hpp>
|
||||
#include <azure/storage/common/storage_retry_policy.hpp>
|
||||
|
||||
#include "azure/storage/files/datalake/datalake_constants.hpp"
|
||||
#include "azure/storage/files/datalake/datalake_utilities.hpp"
|
||||
#include "azure/storage/files/datalake/version.hpp"
|
||||
|
||||
@ -248,7 +249,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
protocolLayerOptions.Permissions = options.Permissions;
|
||||
auto result = Details::DataLakeRestClient::Path::Create(
|
||||
m_dfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
auto ret = Models::CreatePathResult();
|
||||
Models::CreatePathResult ret;
|
||||
ret.ETag = std::move(result->ETag.GetValue());
|
||||
ret.LastModified = std::move(result->LastModified.GetValue());
|
||||
ret.ContentLength = std::move(result->ContentLength);
|
||||
@ -256,6 +257,29 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::CreatePathResult> PathClient::CreateIfNotExists(
|
||||
Models::PathResourceType type,
|
||||
const CreatePathOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
auto createOptions = options;
|
||||
createOptions.AccessConditions.IfNoneMatch = ETagWildcard;
|
||||
return Create(type, createOptions);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::DataLakePathAlreadyExists)
|
||||
{
|
||||
Models::CreatePathResult ret;
|
||||
ret.Created = false;
|
||||
return Azure::Core::Response<Models::CreatePathResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeletePathResult> PathClient::Delete(
|
||||
const DeletePathOptions& options) const
|
||||
{
|
||||
@ -267,8 +291,34 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
protocolLayerOptions.IfModifiedSince = options.AccessConditions.IfModifiedSince;
|
||||
protocolLayerOptions.IfUnmodifiedSince = options.AccessConditions.IfUnmodifiedSince;
|
||||
protocolLayerOptions.RecursiveOptional = options.Recursive;
|
||||
return Details::DataLakeRestClient::Path::Delete(
|
||||
auto result = Details::DataLakeRestClient::Path::Delete(
|
||||
m_dfsUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::DeletePathResult ret;
|
||||
ret.ContinuationToken = std::move(result->ContinuationToken);
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeletePathResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeletePathResult> PathClient::DeleteIfExists(
|
||||
const DeletePathOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::DataLakeFilesystemNotFound
|
||||
|| e.ErrorCode == Details::DataLakePathNotFound)
|
||||
{
|
||||
Models::DeletePathResult ret;
|
||||
ret.Deleted = false;
|
||||
return Azure::Core::Response<Models::DeletePathResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::GetPathPropertiesResult> PathClient::GetProperties(
|
||||
@ -332,7 +382,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
|
||||
{
|
||||
acl = Models::Acl::DeserializeAcls(result->Acl.GetValue());
|
||||
}
|
||||
auto ret = Models::GetPathAccessControlResult{};
|
||||
Models::GetPathAccessControlResult ret;
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
if (!acl.HasValue())
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
void DataLakeDirectoryClientTest::SetUpTestSuite()
|
||||
{
|
||||
DataLakeFileSystemClientTest::SetUpTestSuite();
|
||||
m_directoryName = LowercaseRandomString(10);
|
||||
m_directoryName = RandomString(10);
|
||||
m_directoryClient = std::make_shared<Files::DataLake::DirectoryClient>(
|
||||
m_fileSystemClient->GetDirectoryClient(m_directoryName));
|
||||
m_fileSystemClient->GetFileClient(m_directoryName).Create();
|
||||
@ -36,7 +36,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -50,7 +50,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -71,7 +71,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -90,13 +90,12 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
{
|
||||
// Recursive delete works.
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
auto rootDir = LowercaseRandomString();
|
||||
auto rootDir = RandomString();
|
||||
auto rootDirClient = m_fileSystemClient->GetDirectoryClient(rootDir);
|
||||
EXPECT_NO_THROW(rootDirClient.Create());
|
||||
for (int32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
auto client
|
||||
= m_fileSystemClient->GetDirectoryClient(rootDir + "/" + LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(rootDir + "/" + RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -105,6 +104,30 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLakeDirectoryClientTest, CreateDeleteIfExistsDirectory)
|
||||
{
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
bool created = false;
|
||||
bool deleted = false;
|
||||
EXPECT_NO_THROW(created = client.Create()->Created);
|
||||
EXPECT_TRUE(created);
|
||||
EXPECT_NO_THROW(created = client.CreateIfNotExists()->Created);
|
||||
EXPECT_FALSE(created);
|
||||
EXPECT_NO_THROW(deleted = client.Delete(false)->Deleted);
|
||||
EXPECT_TRUE(deleted);
|
||||
EXPECT_NO_THROW(deleted = client.DeleteIfExists(false)->Deleted);
|
||||
EXPECT_FALSE(deleted);
|
||||
}
|
||||
{
|
||||
auto client = Files::DataLake::DirectoryClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString(), RandomString());
|
||||
bool deleted = false;
|
||||
EXPECT_NO_THROW(deleted = client.DeleteIfExists(false)->Deleted);
|
||||
EXPECT_FALSE(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLakeDirectoryClientTest, RenameDirectory)
|
||||
{
|
||||
{
|
||||
@ -112,14 +135,14 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClients;
|
||||
for (int32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClients.emplace_back(std::move(client));
|
||||
}
|
||||
std::vector<std::string> newPaths;
|
||||
for (auto& client : directoryClients)
|
||||
{
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath));
|
||||
newPaths.push_back(newPath);
|
||||
}
|
||||
@ -137,7 +160,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -147,10 +170,10 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
Files::DataLake::RenameDirectoryOptions options1;
|
||||
options1.SourceAccessConditions.IfModifiedSince = response->LastModified;
|
||||
EXPECT_TRUE(IsValidTime(response->LastModified));
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options1), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options1), StorageException);
|
||||
Files::DataLake::RenameDirectoryOptions options2;
|
||||
options2.SourceAccessConditions.IfUnmodifiedSince = response->LastModified;
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options2));
|
||||
EXPECT_NO_THROW(m_fileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -160,7 +183,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -169,10 +192,10 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto response = client.GetProperties();
|
||||
Files::DataLake::RenameDirectoryOptions options1;
|
||||
options1.SourceAccessConditions.IfNoneMatch = response->ETag;
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options1), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options1), StorageException);
|
||||
Files::DataLake::RenameDirectoryOptions options2;
|
||||
options2.SourceAccessConditions.IfMatch = response->ETag;
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options2));
|
||||
EXPECT_NO_THROW(m_fileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -182,7 +205,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
directoryClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -192,7 +215,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
options.DestinationFileSystem = LowercaseRandomString();
|
||||
for (auto& client : directoryClient)
|
||||
{
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options), StorageException);
|
||||
EXPECT_NO_THROW(client.GetProperties());
|
||||
}
|
||||
}
|
||||
@ -207,7 +230,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
options.DestinationFileSystem = newfileSystemName;
|
||||
for (auto& client : directoryClient)
|
||||
{
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options));
|
||||
EXPECT_NO_THROW(newfileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -231,8 +254,8 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
{
|
||||
// Create path with metadata works
|
||||
auto client1 = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client2 = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client1 = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
auto client2 = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
Files::DataLake::CreatePathOptions options1;
|
||||
Files::DataLake::CreatePathOptions options2;
|
||||
options1.Metadata = metadata1;
|
||||
@ -284,7 +307,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::DirectoryClient> directoryClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetDirectoryClient(RandomString());
|
||||
Files::DataLake::CreatePathOptions options;
|
||||
options.HttpHeaders = httpHeader;
|
||||
EXPECT_NO_THROW(client.Create(options));
|
||||
@ -305,9 +328,9 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
TEST_F(DataLakeDirectoryClientTest, DirectorySetAccessControlRecursive)
|
||||
{
|
||||
// Setup directories.
|
||||
auto rootDirectoryName = LowercaseRandomString();
|
||||
auto directoryName1 = LowercaseRandomString();
|
||||
auto directoryName2 = LowercaseRandomString();
|
||||
auto rootDirectoryName = RandomString();
|
||||
auto directoryName1 = RandomString();
|
||||
auto directoryName2 = RandomString();
|
||||
auto rootDirectoryClient = m_fileSystemClient->GetDirectoryClient(rootDirectoryName);
|
||||
rootDirectoryClient.Create();
|
||||
auto directoryClient1
|
||||
@ -346,7 +369,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
{
|
||||
{
|
||||
// Create from connection string validates static creator function and shared key constructor.
|
||||
auto directoryName = LowercaseRandomString(10);
|
||||
auto directoryName = RandomString(10);
|
||||
auto connectionStringClient
|
||||
= Azure::Storage::Files::DataLake::DirectoryClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, directoryName);
|
||||
@ -361,7 +384,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
auto clientSecretClient = Azure::Storage::Files::DataLake::DirectoryClient(
|
||||
Azure::Storage::Files::DataLake::DirectoryClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, LowercaseRandomString(10))
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, RandomString(10))
|
||||
.GetUri(),
|
||||
credential);
|
||||
|
||||
@ -371,7 +394,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
{
|
||||
// Create from Anonymous credential.
|
||||
auto objectName = LowercaseRandomString(10);
|
||||
auto objectName = RandomString(10);
|
||||
auto containerClient = Azure::Storage::Blobs::BlobContainerClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName);
|
||||
Azure::Storage::Blobs::SetBlobContainerAccessPolicyOptions options;
|
||||
|
||||
@ -33,7 +33,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
void DataLakeFileClientTest::SetUpTestSuite()
|
||||
{
|
||||
DataLakeFileSystemClientTest::SetUpTestSuite();
|
||||
m_fileName = LowercaseRandomString(10);
|
||||
m_fileName = RandomString(10);
|
||||
m_fileClient = std::make_shared<Files::DataLake::FileClient>(
|
||||
m_fileSystemClient->GetFileClient(m_fileName));
|
||||
m_fileClient->Create();
|
||||
@ -52,7 +52,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -66,7 +66,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -87,7 +87,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -104,6 +104,30 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLakeFileClientTest, CreateDeleteIfExistsFiles)
|
||||
{
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
bool created = false;
|
||||
bool deleted = false;
|
||||
EXPECT_NO_THROW(created = client.Create()->Created);
|
||||
EXPECT_TRUE(created);
|
||||
EXPECT_NO_THROW(created = client.CreateIfNotExists()->Created);
|
||||
EXPECT_FALSE(created);
|
||||
EXPECT_NO_THROW(deleted = client.Delete()->Deleted);
|
||||
EXPECT_TRUE(deleted);
|
||||
EXPECT_NO_THROW(deleted = client.DeleteIfExists()->Deleted);
|
||||
EXPECT_FALSE(deleted);
|
||||
}
|
||||
{
|
||||
auto client = Files::DataLake::FileClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString(), RandomString());
|
||||
bool deleted = false;
|
||||
EXPECT_NO_THROW(deleted = client.DeleteIfExists()->Deleted);
|
||||
EXPECT_FALSE(deleted);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLakeFileClientTest, RenameFiles)
|
||||
{
|
||||
{
|
||||
@ -111,14 +135,14 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClients;
|
||||
for (int32_t i = 0; i < 5; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClients.emplace_back(std::move(client));
|
||||
}
|
||||
std::vector<std::string> newPaths;
|
||||
for (auto& client : fileClients)
|
||||
{
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath));
|
||||
newPaths.push_back(newPath);
|
||||
}
|
||||
@ -136,7 +160,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -145,10 +169,10 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto response = client.GetProperties();
|
||||
Files::DataLake::RenameFileOptions options1;
|
||||
options1.SourceAccessConditions.IfModifiedSince = response->LastModified;
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options1), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options1), StorageException);
|
||||
Files::DataLake::RenameFileOptions options2;
|
||||
options2.SourceAccessConditions.IfUnmodifiedSince = response->LastModified;
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options2));
|
||||
EXPECT_NO_THROW(m_fileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -158,7 +182,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -167,10 +191,10 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto response = client.GetProperties();
|
||||
Files::DataLake::RenameFileOptions options1;
|
||||
options1.SourceAccessConditions.IfNoneMatch = response->ETag;
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options1), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options1), StorageException);
|
||||
Files::DataLake::RenameFileOptions options2;
|
||||
options2.SourceAccessConditions.IfMatch = response->ETag;
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options2));
|
||||
EXPECT_NO_THROW(m_fileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -180,7 +204,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
fileClient.emplace_back(std::move(client));
|
||||
}
|
||||
@ -190,7 +214,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
options.DestinationFileSystem = LowercaseRandomString();
|
||||
for (auto& client : fileClient)
|
||||
{
|
||||
EXPECT_THROW(client.Rename(LowercaseRandomString(), options), StorageException);
|
||||
EXPECT_THROW(client.Rename(RandomString(), options), StorageException);
|
||||
EXPECT_NO_THROW(client.GetProperties());
|
||||
}
|
||||
}
|
||||
@ -205,7 +229,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
options.DestinationFileSystem = newfileSystemName;
|
||||
for (auto& client : fileClient)
|
||||
{
|
||||
auto newPath = LowercaseRandomString();
|
||||
auto newPath = RandomString();
|
||||
EXPECT_NO_THROW(client.Rename(newPath, options));
|
||||
EXPECT_NO_THROW(newfileSystemClient->GetDirectoryClient(newPath).Delete(false));
|
||||
}
|
||||
@ -229,8 +253,8 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
{
|
||||
// Create path with metadata works
|
||||
auto client1 = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client2 = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client1 = m_fileSystemClient->GetFileClient(RandomString());
|
||||
auto client2 = m_fileSystemClient->GetFileClient(RandomString());
|
||||
Files::DataLake::CreateFileOptions options1;
|
||||
Files::DataLake::CreateFileOptions options2;
|
||||
options1.Metadata = metadata1;
|
||||
@ -280,7 +304,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<Files::DataLake::FileClient> fileClient;
|
||||
for (int32_t i = 0; i < 2; ++i)
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
Files::DataLake::CreateFileOptions options;
|
||||
options.HttpHeaders = httpHeader;
|
||||
EXPECT_NO_THROW(client.Create(options));
|
||||
@ -331,7 +355,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
auto buffer = RandomBuffer(bufferSize);
|
||||
auto bufferStream = std::make_unique<Azure::Core::Http::MemoryBodyStream>(
|
||||
Azure::Core::Http::MemoryBodyStream(buffer));
|
||||
auto newFileName = LowercaseRandomString(10);
|
||||
auto newFileName = RandomString(10);
|
||||
auto newFileClient = std::make_shared<Files::DataLake::FileClient>(
|
||||
m_fileSystemClient->GetFileClient(newFileName));
|
||||
newFileClient->Create();
|
||||
@ -407,13 +431,13 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
TEST_F(DataLakeFileClientTest, ScheduleForDeletion)
|
||||
{
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
EXPECT_NO_THROW(
|
||||
client.ScheduleDeletion(Files::DataLake::ScheduleFileExpiryOriginType::NeverExpire));
|
||||
}
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
Files::DataLake::ScheduleFileDeletionOptions options;
|
||||
EXPECT_THROW(
|
||||
@ -425,7 +449,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
Files::DataLake::ScheduleFileExpiryOriginType::RelativeToNow, options));
|
||||
}
|
||||
{
|
||||
auto client = m_fileSystemClient->GetFileClient(LowercaseRandomString());
|
||||
auto client = m_fileSystemClient->GetFileClient(RandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
Files::DataLake::ScheduleFileDeletionOptions options;
|
||||
EXPECT_THROW(
|
||||
@ -539,7 +563,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
{
|
||||
{
|
||||
// Create from connection string validates static creator function and shared key constructor.
|
||||
auto fileName = LowercaseRandomString(10);
|
||||
auto fileName = RandomString(10);
|
||||
auto connectionStringClient
|
||||
= Azure::Storage::Files::DataLake::FileClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, fileName);
|
||||
@ -554,7 +578,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
auto clientSecretClient = Azure::Storage::Files::DataLake::FileClient(
|
||||
Azure::Storage::Files::DataLake::FileClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, LowercaseRandomString(10))
|
||||
AdlsGen2ConnectionString(), m_fileSystemName, RandomString(10))
|
||||
.GetUri(),
|
||||
credential);
|
||||
|
||||
@ -567,7 +591,7 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
std::vector<uint8_t> blobContent;
|
||||
blobContent.resize(static_cast<std::size_t>(1_MB));
|
||||
RandomBuffer(reinterpret_cast<char*>(&blobContent[0]), blobContent.size());
|
||||
auto objectName = LowercaseRandomString(10);
|
||||
auto objectName = RandomString(10);
|
||||
auto containerClient = Azure::Storage::Blobs::BlobContainerClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), m_fileSystemName);
|
||||
Azure::Storage::Blobs::SetBlobContainerAccessPolicyOptions options;
|
||||
|
||||
@ -130,6 +130,42 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_NO_THROW(client.Delete(options2));
|
||||
}
|
||||
}
|
||||
{
|
||||
// CreateIfNotExists & DeleteIfExists.
|
||||
{
|
||||
auto client = Files::DataLake::FileSystemClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_NO_THROW(client.Delete());
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = Files::DataLake::FileSystemClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_THROW(client.Create(), StorageException);
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = Files::DataLake::FileSystemClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString());
|
||||
auto created = client.Create()->Created;
|
||||
EXPECT_TRUE(created);
|
||||
auto createResult = client.CreateIfNotExists();
|
||||
EXPECT_FALSE(createResult->Created);
|
||||
EXPECT_TRUE(createResult->ETag.empty());
|
||||
EXPECT_EQ(Core::DateTime(), createResult->LastModified);
|
||||
auto deleted = client.Delete()->Deleted;
|
||||
EXPECT_TRUE(deleted);
|
||||
}
|
||||
{
|
||||
auto client = Files::DataLake::FileSystemClient::CreateFromConnectionString(
|
||||
AdlsGen2ConnectionString(), LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DataLakeFileSystemClientTest, FileSystemMetadata)
|
||||
|
||||
@ -21,6 +21,11 @@
|
||||
- Removed `Offset` and `Length` pair in options. They are now represented with `Azure::Core::Http::Range`.
|
||||
- Replace scoped enums that don't support bitwise operations with extensible enum.
|
||||
- `IsServerEncrypted` member in `DownloadFileToResult`, `UploadFileFromResult`, `FileDownloadResult` and `FileGetPropertiesResult` are no longer nullable.
|
||||
- Create APIs for Directory and File now returns `FileShareSmbProperties` that aggregates SMB related properties.
|
||||
|
||||
### New Features
|
||||
|
||||
- Added support for `CreateIfNotExists` for Share and Directory clients, and `DeleteIfExists` for Share, Directory and File clients.
|
||||
|
||||
## 12.0.0-beta.5 (2020-11-13)
|
||||
|
||||
|
||||
@ -105,6 +105,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Response<Models::CreateShareResult> Create(
|
||||
const CreateShareOptions& options = CreateShareOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Creates the file share if it does not exist, nothing will happen if the file share already exists.
|
||||
* @param options Optional parameters to create this file share.
|
||||
* @return Azure::Core::Response<Models::CreateShareResult> containing the information including
|
||||
* the version and modified time of a share if it is successfully created.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreateShareResult> CreateIfNotExists(
|
||||
const CreateShareOptions& options = CreateShareOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file share.
|
||||
* @param options Optional parameters to delete this file share.
|
||||
@ -114,6 +123,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Response<Models::DeleteShareResult> Delete(
|
||||
const DeleteShareOptions& options = DeleteShareOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file share if it exists.
|
||||
* @param options Optional parameters to delete this file share.
|
||||
* @return Azure::Core::Response<Models::ShareDeleteResult> currently empty and reserved for
|
||||
* future usage.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteShareResult> DeleteIfExists(
|
||||
const DeleteShareOptions& options = DeleteShareOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Creates a snapshot for the share.
|
||||
* @param options Optional parameters to create the share snapshot.
|
||||
|
||||
@ -16,6 +16,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
constexpr int64_t c_FileUploadDefaultChunkSize = 4 * 1024 * 1024;
|
||||
constexpr int64_t c_FileDownloadDefaultChunkSize = 4 * 1024 * 1024;
|
||||
constexpr static const char* c_ShareSnapshotQueryParameter = "sharesnapshot";
|
||||
|
||||
// Error codes:
|
||||
constexpr static const char* ParentNotFound = "ParentNotFound";
|
||||
constexpr static const char* ResourceNotFound = "ResourceNotFound";
|
||||
constexpr static const char* ShareAlreadyExists = "ShareAlreadyExists";
|
||||
constexpr static const char* ShareNotFound = "ShareNotFound";
|
||||
constexpr static const char* ResourceAlreadyExists = "ResourceAlreadyExists";
|
||||
} // namespace Details
|
||||
|
||||
}}}} // namespace Azure::Storage::Files::Shares
|
||||
|
||||
@ -101,6 +101,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Response<Models::CreateDirectoryResult> Create(
|
||||
const CreateDirectoryOptions& options = CreateDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Creates the directory if it does not exist.
|
||||
* @param options Optional parameters to create this directory.
|
||||
* @return Azure::Core::Response<Models::CreateDirectoryResult> containing the information
|
||||
* returned when creating the directory if successfully created.
|
||||
*/
|
||||
Azure::Core::Response<Models::CreateDirectoryResult> CreateIfNotExists(
|
||||
const CreateDirectoryOptions& options = CreateDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the directory.
|
||||
* @param options Optional parameters to delete this directory.
|
||||
@ -110,6 +119,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> Delete(
|
||||
const DeleteDirectoryOptions& options = DeleteDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the directory if it exists.
|
||||
* @param options Optional parameters to delete this directory.
|
||||
* @return Azure::Core::Response<Models::DeleteDirectoryResult> containing the information
|
||||
* returned when deleting the directory. Currently empty but preserved for future usage.
|
||||
* Only when the delete operation if successful, the returned information other than 'Deleted'
|
||||
* is valid.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> DeleteIfExists(
|
||||
const DeleteDirectoryOptions& options = DeleteDirectoryOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the properties of the directory.
|
||||
* @param options Optional parameters to get this directory's properties.
|
||||
|
||||
@ -94,6 +94,15 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
Azure::Core::Response<Models::DeleteFileResult> Delete(
|
||||
const DeleteFileOptions& options = DeleteFileOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes the file if it exists.
|
||||
* @param options Optional parameters to delete this file.
|
||||
* @return Azure::Core::Response<DeleteFileResult> containing the information returned when
|
||||
* deleting the file. Only valid when successfully deleted.
|
||||
*/
|
||||
Azure::Core::Response<Models::DeleteFileResult> DeleteIfExists(
|
||||
const DeleteFileOptions& options = DeleteFileOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Open a stream for the file's content, or a range of the file's content that can be
|
||||
* used to download the server end data.
|
||||
|
||||
@ -16,8 +16,17 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { names
|
||||
using GetServicePropertiesResult = StorageServiceProperties;
|
||||
|
||||
// ShareClient models:
|
||||
using CreateShareResult = ShareCreateResult;
|
||||
using DeleteShareResult = ShareDeleteResult;
|
||||
struct CreateShareResult
|
||||
{
|
||||
bool Created = true;
|
||||
std::string ETag;
|
||||
Core::DateTime LastModified;
|
||||
};
|
||||
|
||||
struct DeleteShareResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
};
|
||||
using CreateShareSnapshotResult = ShareCreateSnapshotResult;
|
||||
using GetSharePropertiesResult = ShareGetPropertiesResult;
|
||||
using SetShareQuotaResult = ShareSetQuotaResult;
|
||||
@ -34,8 +43,26 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { names
|
||||
using ChangeShareLeaseResult = ShareChangeLeaseResult;
|
||||
|
||||
// DirectoryClient models:
|
||||
using CreateDirectoryResult = DirectoryCreateResult;
|
||||
using DeleteDirectoryResult = DirectoryDeleteResult;
|
||||
struct CreateDirectoryResult
|
||||
{
|
||||
bool Created = true;
|
||||
std::string ETag;
|
||||
Core::DateTime LastModified;
|
||||
bool IsServerEncrypted = bool();
|
||||
std::string FilePermissionKey;
|
||||
std::string FileAttributes;
|
||||
Core::DateTime FileCreatedOn;
|
||||
Core::DateTime FileLastWrittenOn;
|
||||
Core::DateTime FileChangedOn;
|
||||
std::string FileId;
|
||||
std::string FileParentId;
|
||||
};
|
||||
|
||||
struct DeleteDirectoryResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
};
|
||||
|
||||
using GetDirectoryPropertiesResult = DirectoryGetPropertiesResult;
|
||||
using SetDirectoryPropertiesResult = DirectorySetPropertiesResult;
|
||||
using SetDirectoryMetadataResult = DirectorySetMetadataResult;
|
||||
@ -65,6 +92,27 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { names
|
||||
std::string ContinuationToken;
|
||||
};
|
||||
|
||||
// FileClient models:
|
||||
struct CreateFileResult
|
||||
{
|
||||
bool Created = true;
|
||||
std::string ETag;
|
||||
Core::DateTime LastModified;
|
||||
bool IsServerEncrypted = bool();
|
||||
std::string FilePermissionKey;
|
||||
std::string FileAttributes;
|
||||
Core::DateTime FileCreatedOn;
|
||||
Core::DateTime FileLastWrittenOn;
|
||||
Core::DateTime FileChangedOn;
|
||||
std::string FileId;
|
||||
std::string FileParentId;
|
||||
};
|
||||
|
||||
struct DeleteFileResult
|
||||
{
|
||||
bool Deleted = true;
|
||||
};
|
||||
|
||||
struct FileShareSmbProperties
|
||||
{
|
||||
/**
|
||||
@ -90,9 +138,6 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares { names
|
||||
Azure::Core::Nullable<Core::DateTime> LastWrittenOn;
|
||||
};
|
||||
|
||||
// FileClient models:
|
||||
using CreateFileResult = FileCreateResult;
|
||||
using DeleteFileResult = FileDeleteResult;
|
||||
using DownloadFileResult = FileDownloadResult;
|
||||
using StartCopyFileResult = FileStartCopyResult;
|
||||
using AbortCopyFileResult = FileAbortCopyResult;
|
||||
|
||||
@ -129,8 +129,34 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
auto protocolLayerOptions = Details::ShareRestClient::Share::CreateOptions();
|
||||
protocolLayerOptions.Metadata = options.Metadata;
|
||||
protocolLayerOptions.ShareQuota = options.ShareQuotaInGiB;
|
||||
return Details::ShareRestClient::Share::Create(
|
||||
auto result = Details::ShareRestClient::Share::Create(
|
||||
m_shareUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::CreateShareResult ret;
|
||||
ret.Created = true;
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
return Azure::Core::Response<Models::CreateShareResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::CreateShareResult> ShareClient::CreateIfNotExists(
|
||||
const CreateShareOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Create(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ShareAlreadyExists)
|
||||
{
|
||||
Models::CreateShareResult ret;
|
||||
ret.Created = false;
|
||||
return Azure::Core::Response<Models::CreateShareResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteShareResult> ShareClient::Delete(
|
||||
@ -141,8 +167,32 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.XMsDeleteSnapshots = Models::DeleteSnapshotsOptionType::Include;
|
||||
}
|
||||
return Details::ShareRestClient::Share::Delete(
|
||||
auto result = Details::ShareRestClient::Share::Delete(
|
||||
m_shareUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::DeleteShareResult ret;
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeleteShareResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteShareResult> ShareClient::DeleteIfExists(
|
||||
const DeleteShareOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ShareNotFound)
|
||||
{
|
||||
Models::DeleteShareResult ret;
|
||||
ret.Deleted = false;
|
||||
return Azure::Core::Response<Models::DeleteShareResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::CreateShareSnapshotResult> ShareClient::CreateSnapshot(
|
||||
|
||||
@ -167,16 +167,77 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.FilePermission = std::string(c_FileInheritPermission);
|
||||
}
|
||||
return Details::ShareRestClient::Directory::Create(
|
||||
auto result = Details::ShareRestClient::Directory::Create(
|
||||
m_shareDirectoryUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::CreateDirectoryResult ret;
|
||||
ret.Created = true;
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.FileAttributes = result->FileAttributes;
|
||||
ret.FileCreatedOn = std::move(result->FileCreatedOn);
|
||||
ret.FileLastWrittenOn = std::move(result->FileLastWrittenOn);
|
||||
ret.FilePermissionKey = std::move(result->FilePermissionKey);
|
||||
ret.FileChangedOn = std::move(result->FileChangedOn);
|
||||
ret.FileId = std::move(result->FileId);
|
||||
ret.FileParentId = std::move(result->FileParentId);
|
||||
ret.IsServerEncrypted = result->IsServerEncrypted;
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
|
||||
return Azure::Core::Response<Models::CreateDirectoryResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::CreateDirectoryResult> ShareDirectoryClient::CreateIfNotExists(
|
||||
const CreateDirectoryOptions& options) const
|
||||
|
||||
{
|
||||
try
|
||||
{
|
||||
return Create(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ResourceAlreadyExists)
|
||||
{
|
||||
Models::CreateDirectoryResult ret;
|
||||
ret.Created = false;
|
||||
return Azure::Core::Response<Models::CreateDirectoryResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> ShareDirectoryClient::Delete(
|
||||
const DeleteDirectoryOptions& options) const
|
||||
{
|
||||
auto protocolLayerOptions = Details::ShareRestClient::Directory::DeleteOptions();
|
||||
return Details::ShareRestClient::Directory::Delete(
|
||||
auto result = Details::ShareRestClient::Directory::Delete(
|
||||
m_shareDirectoryUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::DeleteDirectoryResult ret;
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeleteDirectoryResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteDirectoryResult> ShareDirectoryClient::DeleteIfExists(
|
||||
const DeleteDirectoryOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ShareNotFound || e.ErrorCode == Details::ParentNotFound
|
||||
|| e.ErrorCode == Details::ResourceNotFound)
|
||||
{
|
||||
Models::DeleteDirectoryResult ret;
|
||||
ret.Deleted = false;
|
||||
return Azure::Core::Response<Models::DeleteDirectoryResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::GetDirectoryPropertiesResult> ShareDirectoryClient::GetProperties(
|
||||
@ -266,7 +327,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::ListDirectoryHandlesSinglePageResult>
|
||||
ShareDirectoryClient::ListHandlesSinglePage(const ListDirectoryHandlesSinglePageOptions& options) const
|
||||
ShareDirectoryClient::ListHandlesSinglePage(
|
||||
const ListDirectoryHandlesSinglePageOptions& options) const
|
||||
{
|
||||
auto protocolLayerOptions = Details::ShareRestClient::Directory::ListHandlesOptions();
|
||||
protocolLayerOptions.ContinuationToken = options.ContinuationToken;
|
||||
|
||||
@ -185,8 +185,23 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
protocolLayerOptions.ContentMd5 = options.HttpHeaders.ContentHash;
|
||||
}
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
return Details::ShareRestClient::File::Create(
|
||||
auto result = Details::ShareRestClient::File::Create(
|
||||
m_shareFileUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::CreateFileResult ret;
|
||||
ret.Created = true;
|
||||
ret.ETag = std::move(result->ETag);
|
||||
ret.FileAttributes = result->FileAttributes;
|
||||
ret.FileCreatedOn = std::move(result->FileCreatedOn);
|
||||
ret.FileLastWrittenOn = std::move(result->FileLastWrittenOn);
|
||||
ret.FilePermissionKey = std::move(result->FilePermissionKey);
|
||||
ret.FileChangedOn = std::move(result->FileChangedOn);
|
||||
ret.FileId = std::move(result->FileId);
|
||||
ret.FileParentId = std::move(result->FileParentId);
|
||||
ret.IsServerEncrypted = result->IsServerEncrypted;
|
||||
ret.LastModified = std::move(result->LastModified);
|
||||
|
||||
return Azure::Core::Response<Models::CreateFileResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteFileResult> ShareFileClient::Delete(
|
||||
@ -194,8 +209,33 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
auto protocolLayerOptions = Details::ShareRestClient::File::DeleteOptions();
|
||||
protocolLayerOptions.LeaseIdOptional = options.AccessConditions.LeaseId;
|
||||
return Details::ShareRestClient::File::Delete(
|
||||
auto result = Details::ShareRestClient::File::Delete(
|
||||
m_shareFileUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
Models::DeleteFileResult ret;
|
||||
ret.Deleted = true;
|
||||
return Azure::Core::Response<Models::DeleteFileResult>(
|
||||
std::move(ret), result.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DeleteFileResult> ShareFileClient::DeleteIfExists(
|
||||
const DeleteFileOptions& options) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return Delete(options);
|
||||
}
|
||||
catch (StorageException& e)
|
||||
{
|
||||
if (e.ErrorCode == Details::ShareNotFound || e.ErrorCode == Details::ParentNotFound
|
||||
|| e.ErrorCode == Details::ResourceNotFound)
|
||||
{
|
||||
Models::DeleteFileResult ret;
|
||||
ret.Deleted = false;
|
||||
return Azure::Core::Response<Models::DeleteFileResult>(
|
||||
std::move(ret), std::move(e.RawResponse));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::DownloadFileResult> ShareFileClient::Download(
|
||||
@ -208,7 +248,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.Range = std::string("bytes=")
|
||||
+ std::to_string(options.Range.GetValue().Offset) + std::string("-")
|
||||
+ std::to_string(options.Range.GetValue().Offset + options.Range.GetValue().Length.GetValue() - 1);
|
||||
+ std::to_string(options.Range.GetValue().Offset
|
||||
+ options.Range.GetValue().Length.GetValue() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -472,12 +513,13 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
{
|
||||
protocolLayerOptions.XMsRange = std::string("bytes=")
|
||||
+ std::to_string(options.Range.GetValue().Offset) + std::string("-")
|
||||
+ std::to_string(options.Range.GetValue().Offset + options.Range.GetValue().Length.GetValue() - 1);
|
||||
+ std::to_string(options.Range.GetValue().Offset
|
||||
+ options.Range.GetValue().Length.GetValue() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
protocolLayerOptions.XMsRange
|
||||
= std::string("bytes=") + std::to_string(options.Range.GetValue().Offset) + std::string("-");
|
||||
protocolLayerOptions.XMsRange = std::string("bytes=")
|
||||
+ std::to_string(options.Range.GetValue().Offset) + std::string("-");
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,8 +529,8 @@ namespace Azure { namespace Storage { namespace Files { namespace Shares {
|
||||
m_shareFileUri, *m_pipeline, options.Context, protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<Models::ListFileHandlesSinglePageResult> ShareFileClient::ListHandlesSinglePage(
|
||||
const ListFileHandlesSinglePageOptions& options) const
|
||||
Azure::Core::Response<Models::ListFileHandlesSinglePageResult>
|
||||
ShareFileClient::ListHandlesSinglePage(const ListFileHandlesSinglePageOptions& options) const
|
||||
{
|
||||
auto protocolLayerOptions = Details::ShareRestClient::File::ListHandlesOptions();
|
||||
protocolLayerOptions.ContinuationToken = options.ContinuationToken;
|
||||
|
||||
@ -72,6 +72,42 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_NO_THROW(client.Delete());
|
||||
}
|
||||
}
|
||||
{
|
||||
// CreateIfNotExists & DeleteIfExists.
|
||||
{
|
||||
auto client = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_NO_THROW(client.Delete());
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_THROW(client.Create(), StorageException);
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
auto created = client.Create()->Created;
|
||||
EXPECT_TRUE(created);
|
||||
auto createResult = client.CreateIfNotExists();
|
||||
EXPECT_FALSE(createResult->Created);
|
||||
EXPECT_TRUE(createResult->ETag.empty());
|
||||
EXPECT_EQ(Core::DateTime(), createResult->LastModified);
|
||||
auto deleted = client.Delete()->Deleted;
|
||||
EXPECT_TRUE(deleted);
|
||||
}
|
||||
{
|
||||
auto client = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FileShareClientTest, ShareMetadata)
|
||||
|
||||
@ -100,6 +100,57 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_THROW(client.Create(), StorageException);
|
||||
}
|
||||
}
|
||||
{
|
||||
// CreateIfNotExists & DeleteIfExists.
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetSubShareDirectoryClient(
|
||||
LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.Create());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_NO_THROW(client.Delete());
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetSubShareDirectoryClient(
|
||||
LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.CreateIfNotExists());
|
||||
EXPECT_THROW(client.Create(), StorageException);
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetSubShareDirectoryClient(
|
||||
LowercaseRandomString());
|
||||
auto created = client.Create()->Created;
|
||||
EXPECT_TRUE(created);
|
||||
auto createResult = client.CreateIfNotExists();
|
||||
EXPECT_FALSE(createResult->Created);
|
||||
EXPECT_TRUE(createResult->ETag.empty());
|
||||
EXPECT_EQ(Core::DateTime(), createResult->LastModified);
|
||||
auto deleted = client.Delete()->Deleted;
|
||||
EXPECT_TRUE(deleted);
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetSubShareDirectoryClient(
|
||||
LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
{
|
||||
auto shareClient = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
auto client = shareClient.GetRootShareDirectoryClient().GetSubShareDirectoryClient(
|
||||
LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient()
|
||||
.GetSubShareDirectoryClient(LowercaseRandomString())
|
||||
.GetSubShareDirectoryClient(LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FileShareDirectoryClientTest, DirectoryMetadata)
|
||||
|
||||
@ -69,6 +69,37 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
EXPECT_NO_THROW(client.Create(1024));
|
||||
}
|
||||
}
|
||||
{
|
||||
// DeleteIfExists.
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetShareFileClient(
|
||||
LowercaseRandomString());
|
||||
EXPECT_NO_THROW(client.Create(1024));
|
||||
EXPECT_NO_THROW(client.Delete());
|
||||
EXPECT_NO_THROW(client.DeleteIfExists());
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetShareFileClient(
|
||||
LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
{
|
||||
auto shareClient = Files::Shares::ShareClient::CreateFromConnectionString(
|
||||
StandardStorageConnectionString(), LowercaseRandomString());
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient().GetShareFileClient(
|
||||
LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
{
|
||||
auto client = m_shareClient->GetRootShareDirectoryClient()
|
||||
.GetSubShareDirectoryClient(LowercaseRandomString())
|
||||
.GetShareFileClient(LowercaseRandomString());
|
||||
auto deleteResult = client.DeleteIfExists();
|
||||
EXPECT_FALSE(deleteResult->Deleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(FileShareFileClientTest, FileMetadata)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user