From c29f67e6620a4e01988001f98e98836f98b55529 Mon Sep 17 00:00:00 2001 From: David Feltell Date: Wed, 12 Jun 2024 15:18:48 +0100 Subject: [PATCH] [Core] Full `file://` syntax support Closes #14. Fully support `file` URLs by making use the OpenAssetIO `FileUrlPathConverter` utility. The utility will throw on non-`file` URLs being provided, maintaining existing behaviour (with a slightly different error message). Confirmed with manual testing. The `FileUrlPathConverter` utility is only available as of OpenAssetIO 1.0.0-beta.2.0. So update README. Signed-off-by: David Feltell --- README.md | 12 ++-- src/resolver.cpp | 61 ++++++------------- .../integration_test_data/bal_library.json | 2 +- .../floors/{floor 1.usd => floor @ 1.usd} | 0 4 files changed, 28 insertions(+), 47 deletions(-) rename tests/resources/integration_test_data/recursive_assetized_resolve/floors/{floor 1.usd => floor @ 1.usd} (100%) diff --git a/README.md b/README.md index 642cb90..3e80a4c 100644 --- a/README.md +++ b/README.md @@ -81,13 +81,15 @@ limitations. ## Dependencies -### [OpenAssetIO](https://github.com/OpenAssetIO/OpenAssetIO/) (1.0.0-alpha.14) +### [OpenAssetIO](https://github.com/OpenAssetIO/OpenAssetIO/) (1.0.0-beta.2.0) -Currently, OpenAssetIO must be built from source to build -`usdOpenAssetIOResolver`. +The OpenAssetIO libary is available pre-built for some common platforms +are available +[here](https://github.com/OpenAssetIO/OpenAssetIO/releases). -The steps to do this can be found -[here.](https://github.com/OpenAssetIO/OpenAssetIO/blob/main/doc/BUILDING.md) +Alternatively, OpenAssetIO can be built from source. The steps to do +this can be found +[here](https://github.com/OpenAssetIO/OpenAssetIO/blob/main/doc/BUILDING.md). ### [USD](https://github.com/PixarAnimationStudios/USD) (22.11) diff --git a/src/resolver.cpp b/src/resolver.cpp index 5340fcc..32d1ed6 100644 --- a/src/resolver.cpp +++ b/src/resolver.cpp @@ -3,6 +3,7 @@ #include "resolver.h" +#include #include #include @@ -20,7 +21,7 @@ #include #include #include -#include +#include #include @@ -35,21 +36,6 @@ TF_DEBUG_CODES(OPENASSETIO_RESOLVER) PXR_NAMESPACE_CLOSE_SCOPE namespace { -/* - * Replaces all occurrences of the search string in the subject with - * the supplied replacement. - */ -void replaceAllInString(std::string &subject, const std::string &search, - const std::string &replace) { - const size_t searchLength = search.length(); - const size_t replaceLength = replace.length(); - size_t pos = 0; - while ((pos = subject.find(search, pos)) != std::string::npos) { - subject.replace(pos, searchLength, replace); - pos += replaceLength; - } -} - /* * OpenAssetIO LoggerInterface implementation * @@ -110,7 +96,7 @@ class UsdOpenAssetIOResolver::Impl { Impl() { logger_ = openassetio::log::SeverityFilter::make(std::make_shared()); - auto managerImplementationFactory = + const auto managerImplementationFactory = openassetio::python::hostApi::createPythonPluginSystemManagerImplementationFactory( logger_); @@ -133,7 +119,7 @@ class UsdOpenAssetIOResolver::Impl { context_ = openassetio::Context::make(); } - [[nodiscard]] std::optional _CreateIdentifier( + [[nodiscard]] std::optional createIdentifier( const std::string &assetPath, [[maybe_unused]] const ArResolvedPath &anchorAssetPath) const { return catchAndLogExceptions( [&]() -> std::optional { @@ -145,10 +131,10 @@ class UsdOpenAssetIOResolver::Impl { TF_FUNC_NAME()); } - [[nodiscard]] std::optional _Resolve(const std::string &assetPath) const { + [[nodiscard]] std::optional resolve(const std::string &assetPath) const { return catchAndLogExceptions( [&]() -> std::optional { - if (auto entityReference = manager_->createEntityReferenceIfValid(assetPath)) { + if (const auto entityReference = manager_->createEntityReferenceIfValid(assetPath)) { return ArResolvedPath{resolveToPath(*entityReference)}; } return std::nullopt; @@ -156,7 +142,7 @@ class UsdOpenAssetIOResolver::Impl { TF_FUNC_NAME()); } - [[nodiscard]] std::optional _CreateIdentifierForNewAsset( + [[nodiscard]] std::optional createIdentifierForNewAsset( const std::string &assetPath, [[maybe_unused]] const ArResolvedPath &anchorAssetPath) const { if (manager_->isEntityReferenceString(assetPath)) { std::string message = "Writes to OpenAssetIO entity references are not currently supported "; @@ -167,7 +153,7 @@ class UsdOpenAssetIOResolver::Impl { return std::nullopt; } - [[nodiscard]] std::optional _ResolveForNewAsset( + [[nodiscard]] std::optional resolveForNewAsset( const std::string &assetPath) const { if (manager_->isEntityReferenceString(assetPath)) { std::string message = "Writes to OpenAssetIO entity references are not currently supported "; @@ -239,27 +225,20 @@ class UsdOpenAssetIOResolver::Impl { const openassetio::trait::TraitsDataPtr traitsData = manager_->resolve( entityReference, {LocatableContentTrait::kId}, ResolveAccess::kRead, context_); - // OpenAssetIO is URL based, but we need a path, so check the - // scheme and decode into a path - - static constexpr std::string_view kFileURLScheme{"file://"}; - static constexpr std::size_t kProtocolSize = kFileURLScheme.size(); - - openassetio::Str url = LocatableContentTrait(traitsData).getLocation(); - if (url.rfind(kFileURLScheme, 0) == openassetio::Str::npos) { - std::string msg = "Only file URLs are supported: "; - msg += url; - throw std::runtime_error(msg); + const std::optional url = LocatableContentTrait(traitsData).getLocation(); + if (!url) { + throw std::invalid_argument{"Entity reference does not have a location: " + + entityReference.toString()}; } - - // TODO(tc): Decode % escape sequences properly - replaceAllInString(url, "%20", " "); - return url.substr(kProtocolSize); + // OpenAssetIO is URL based, but we need a path. Note: will throw if + // the URL is not valid. + return fileUrlPathConverter_.pathFromUrl(*url); } openassetio::log::LoggerInterfacePtr logger_; openassetio::hostApi::ManagerPtr manager_; openassetio::ContextConstPtr context_; + openassetio::utils::FileUrlPathConverter fileUrlPathConverter_; }; UsdOpenAssetIOResolver::UsdOpenAssetIOResolver() : impl_{std::make_unique()} {} @@ -268,24 +247,24 @@ UsdOpenAssetIOResolver::~UsdOpenAssetIOResolver() = default; std::string UsdOpenAssetIOResolver::_CreateIdentifier( const std::string &assetPath, const ArResolvedPath &anchorAssetPath) const { - auto result = impl_->_CreateIdentifier(assetPath, anchorAssetPath); + auto result = impl_->createIdentifier(assetPath, anchorAssetPath); return result ? *result : ArDefaultResolver::_CreateIdentifier(assetPath, anchorAssetPath); } ArResolvedPath UsdOpenAssetIOResolver::_Resolve(const std::string &assetPath) const { - auto result = impl_->_Resolve(assetPath); + auto result = impl_->resolve(assetPath); return result ? *result : ArDefaultResolver::_Resolve(assetPath); } std::string UsdOpenAssetIOResolver::_CreateIdentifierForNewAsset( const std::string &assetPath, const ArResolvedPath &anchorAssetPath) const { - auto result = impl_->_CreateIdentifierForNewAsset(assetPath, anchorAssetPath); + auto result = impl_->createIdentifierForNewAsset(assetPath, anchorAssetPath); return result ? *result : ArDefaultResolver::_CreateIdentifierForNewAsset(assetPath, anchorAssetPath); } ArResolvedPath UsdOpenAssetIOResolver::_ResolveForNewAsset(const std::string &assetPath) const { - auto result = impl_->_ResolveForNewAsset(assetPath); + auto result = impl_->resolveForNewAsset(assetPath); return result ? *result : ArDefaultResolver::_ResolveForNewAsset(assetPath); } diff --git a/tests/resources/integration_test_data/bal_library.json b/tests/resources/integration_test_data/bal_library.json index 5621f02..8103fcd 100644 --- a/tests/resources/integration_test_data/bal_library.json +++ b/tests/resources/integration_test_data/bal_library.json @@ -28,7 +28,7 @@ "traits": { "openassetio-mediacreation:content.LocatableContent": { "location": - "file://${bal_library_dir}/recursive_assetized_resolve/floors/floor%201.usd" + "file://${bal_library_dir}/recursive_assetized_resolve/floors/floor%20%40%201.usd" } } } diff --git a/tests/resources/integration_test_data/recursive_assetized_resolve/floors/floor 1.usd b/tests/resources/integration_test_data/recursive_assetized_resolve/floors/floor @ 1.usd similarity index 100% rename from tests/resources/integration_test_data/recursive_assetized_resolve/floors/floor 1.usd rename to tests/resources/integration_test_data/recursive_assetized_resolve/floors/floor @ 1.usd