Update the FileIO Aliases (#4186)
* Update the FileIOAlias naming to make the cache, project root and engine root paths more clear The alias of `@root@`, `@assets@`, and `@projectplatformcache@` has been collapsed to `@projectproductassets@` The alias of `@devroot@` and `@engroot@` has been collapsed to `@engroot@` The alias of `@devassets@` and `@projectroot@` has been collapsed to `@projectroot@` Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated use of devassets and devroot properties in python Those properties now use projectroot and engroot Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updating the alias @engroot@ alias path comment in each platform specific LocalFileIO_*.cpp file Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed hardcoded size of 9 for the product asset alias. The ResolvePath function now just appends the @projectproductassets@ alias with the input path Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Remove duplicate @projectproductassets@ check in ProcessFileTreeRequest Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fix for typos in Hydra python test Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated LocalFileIO::Copy call on Windows to use the Unicode aware CopyFileW API Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the AWSMetreicsGemAllocatorFixture to properly suppress asset cache write errors for Test file creation. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed unneeded call to set the @projectproductasstes@ alias at the bottom of the AssetSeedManagerTest SetUp Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added a deprecated alias map to the FileIO System When a deprecated alias is accessed, the FileIO System logs an AZ_Error and indicates the alias that should be used Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated python test scripts to use the projectroot binding Retrieving the AutomatedTesting project path based on "<devroot>/AutomatedTesting" has been removed. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated references to devroot and devgame within the codebase The GetAbsoluteDevGameFolderPath functions has been replaced with direct call to AZ::Utils::GetProjectPath The GetAbsoluteDevRootFolderPath functions has been replaced with direct calls to AZ::Utils::GetEnginePath Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated <engroot>/AutomatedTesting references to projectroot Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Replaced references that assumes the project path is <engroot>/AutomatedTesting with <projectroot> in the AutomatedTesting python test Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Correct casing in emfxworkspace file Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed newly added AppendPathParts function Removed the Path constructors which accepts a PathIterable instance The PathIterable isn't safe to return to a user of the Path class as it might be referencing temporary paths supplied via PathView arguments Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed unused parameter warning Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Undid change to the LexicallyProximate function to set the path result to the base path. It needs to return the *this path if the pathResult is empty Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Moved the LocalFileIO ConvertToAbsolutePath implementations to AZ::Utils Fixed the ConvertToAbsolutePath implementation for Unix platforms to use a buffer that is size PATH_MAX(4096 on all our supported Unix platforms). Because the buffer before was AZ::IO::MaxPathLength which as a size of 1024, this was resulting in the Unix `realpath` function smashing the stack when it converts a path to an absolute path that is longer than 1024 characters Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the EditorCore.Tests to attach the AZ Environment to the EditorCore shared library that is statically loaded on launch. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed for DeprecatedAlaisesKeyVisitor Visit function causing the non string_view overloads being hidden causing a hidden base class function warning Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Changed the AWSMetricsGemMock to use a temporary for writing test assets Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the LocalFileIO::ResolvePath function to use HasRootPath to determine if a path starts with a root path such as "D:", "D:/" or "/" IsAbsolute was not the corect check as the path of "D:" is a relative path. To be absolute according to the Windows the path must have a root directory. i.e "D:/" or "D:\" Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed absolute path comment from LocalFile_UnixLike.cpp and LocalFile_Android.cpp FindFiles implementations Updated the ConvertToAlias to supply an AZ::IO::FixedMaxPath Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Replaced usage of the @projectproductassets@ alias with @engroot@ when referring to the LmbrCentral source folder in the CopyDependencyBuilderTest and the SeedBuilderTests Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the ScriptCanvas Upgrade Tool to output backed up files to the Project User Path instead of the engine root Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed whitespacing issues in Application.cpp Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Remove unnecessary creation of a FixedMaxPath in the UpgradeTool.cpp Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Modified testSeedFolder variable in the SeedBuilderTests to use the @engroot@ alias instead of @projectproductassets@/.. alias when referring to the LmbrCentral Gem source path Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated references to the Project Asset Cache in the PythonTests. Those tests no longer use the logic `azlmbr.paths.projectroot / "Cache" / "pc"` to retrieve a path to the cache root but instead the `azlmbr.paths.projectproductassets` constant Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed the FileIO Deprecated Alias test on Windows Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removing @projectsourceassets@ alias, as it is only used once. Updated the PhysX EditorSystemComponent.cpp to query the ProjectPath form the SettingsRegistry. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Replaced @projectproductassets@ alias with @products@ Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Rollback changes to the PhysX EditorSystemComponent.cpp The changes to use the ProjectPath from the SettingsRegistry has been implemented in PR #4497 Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
643bd84739
commit
f648cb1fd8
@@ -148,7 +148,7 @@ namespace AZ
|
||||
virtual AZ::u64 ModificationTime(HandleType fileHandle) = 0;
|
||||
virtual AZ::u64 ModificationTime(const char* filePath) = 0;
|
||||
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
/// Get the size of the file. Returns Success if we report size.
|
||||
virtual Result Size(const char* filePath, AZ::u64& size) = 0;
|
||||
virtual Result Size(HandleType fileHandle, AZ::u64& size) = 0;
|
||||
|
||||
@@ -198,7 +198,7 @@ namespace AZ
|
||||
/// note: the callback will contain the full concatenated path (filePath + slash + fileName)
|
||||
/// not just the individual file name found.
|
||||
/// note: if the file path of the found file corresponds to a registered ALIAS, the longest matching alias will be returned
|
||||
/// so expect return values like @assets@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// so expect return values like @products@/textures/mytexture.dds instead of a full path. This is so that fileIO works over remote connections.
|
||||
/// note: if rootPath is specified the implementation has the option of substituting it for the current directory
|
||||
/// as would be the case on a file server.
|
||||
typedef AZStd::function<bool(const char*)> FindFilesCallbackType;
|
||||
@@ -206,13 +206,18 @@ namespace AZ
|
||||
|
||||
// Alias system
|
||||
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @root@, etc.
|
||||
/// SetAlias - Adds an alias to the path resolution system, e.g. @user@, @products@, etc.
|
||||
virtual void SetAlias(const char* alias, const char* path) = 0;
|
||||
/// ClearAlias - Removes an alias from the path resolution system
|
||||
virtual void ClearAlias(const char* alias) = 0;
|
||||
/// GetAlias - Returns the destination path for a given alias, or nullptr if the alias does not exist
|
||||
virtual const char* GetAlias(const char* alias) const = 0;
|
||||
|
||||
/// SetDeprecateAlias - Adds a deprecated alias with path resolution which points to a new alias
|
||||
/// When the DeprecatedAlias is used an Error is logged and the alias is resolved to the path
|
||||
/// specified by the new alais
|
||||
virtual void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) = 0;
|
||||
|
||||
/// Shorten the given path if it contains an alias. it will always pick the longest alias match.
|
||||
/// note that it re-uses the buffer, since the data can only get smaller and we don't want to internally allocate memory if we
|
||||
/// can avoid it.
|
||||
@@ -230,8 +235,8 @@ namespace AZ
|
||||
|
||||
//! ResolvePath - Replaces any aliases in path with their values and stores the result in resolvedPath,
|
||||
//! also ensures that the path is absolute
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @assets@ is used
|
||||
//! which has the effect of making the path relative to the @assets@/ folder
|
||||
//! NOTE: If the path does not start with an alias then the resolved value of the @products@ is used
|
||||
//! which has the effect of making the path relative to the @products@/ folder
|
||||
//! returns true if path was resolved, false otherwise
|
||||
//! note that all of the above file-finding and opening functions automatically resolve the path before operating
|
||||
//! so you should not need to call this except in very exceptional circumstances where you absolutely need to
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace AZ::IO
|
||||
// These functions can't be called after a request has been queued.
|
||||
//
|
||||
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to read a file.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -62,9 +62,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param outputBuffer The buffer that will hold the loaded data. This must be able to at least hold "size" number of bytes.
|
||||
//! @param outputBufferSize The size of the buffer that will hold the loaded data. This must be equal or larger than "size" number of bytes.
|
||||
//! @param readSize The number of bytes to read from the file at the relative path.
|
||||
@@ -84,8 +84,8 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! Creates a request to the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -106,9 +106,9 @@ namespace AZ::IO
|
||||
IStreamerTypes::Priority priority = IStreamerTypes::s_priorityMedium,
|
||||
size_t offset = 0) = 0;
|
||||
|
||||
//! Sets a request to the read command.
|
||||
//! Sets a request to the read command.
|
||||
//! @param request The request that will store the read command.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to load. This can include aliases such as @products@.
|
||||
//! @param allocator The allocator used to reserve and release memory for the read request. Memory allocated this way will
|
||||
//! be automatically freed when there are no more references to the FileRequestPtr. To avoid this, use GetReadRequestResult
|
||||
//! to claim the pointer and use the provided allocator to release the memory at a later point.
|
||||
@@ -138,7 +138,7 @@ namespace AZ::IO
|
||||
//! @result A smart pointer to the newly created request with the cancel command.
|
||||
virtual FileRequestPtr Cancel(FileRequestPtr target) = 0;
|
||||
|
||||
//! Sets a request to the cancel command.
|
||||
//! Sets a request to the cancel command.
|
||||
//! When this request completes it's not guaranteed to have canceled the target request. Not all requests can be canceled and requests
|
||||
//! that already processing may complete. It's recommended to let the target request handle the completion of the request as normal
|
||||
//! and handle cancellation by checking the status on the target request is set to IStreamerTypes::RequestStatus::Canceled.
|
||||
@@ -177,7 +177,7 @@ namespace AZ::IO
|
||||
//! DestroyDedicatedCache is called. Typical use of a dedicated cache is for files that have their own compression
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to create a dedicated cache.
|
||||
virtual FileRequestPtr CreateDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -186,25 +186,25 @@ namespace AZ::IO
|
||||
//! and are periodically visited to read a section, e.g. streaming video play or streaming audio banks. This
|
||||
//! request will fail if there are no nodes in Streamer's stack that deal with dedicated caches.
|
||||
//! @param request The request that will store the command to create a dedicated cache.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file to receive a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& CreateDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to destroy a dedicated cache.
|
||||
virtual FileRequestPtr DestroyDedicatedCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Destroy a dedicated cache created by CreateDedicatedCache. See CreateDedicatedCache for more details.
|
||||
//! @param request The request that will store the command to destroy a dedicated cache.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that got a dedicated cache. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& DestroyDedicatedCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
//! Clears a file from all caches in use by Streamer.
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A smart pointer to the newly created request with the command to flush a file from all caches.
|
||||
virtual FileRequestPtr FlushCache(AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -212,7 +212,7 @@ namespace AZ::IO
|
||||
//! Flushing the cache will cause the streaming stack to pause processing until it's idle before issuing the flush and resuming
|
||||
//! processing. This can result in a noticeable interruption.
|
||||
//! @param request The request that will store the command to flush a file from all caches.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @assets@.
|
||||
//! @param relativePath Relative path to the file that will be cleared from all caches. This can include aliases such as @products@.
|
||||
//! @return A reference to the provided request.
|
||||
virtual FileRequestPtr& FlushCache(FileRequestPtr& request, AZStd::string_view relativePath) = 0;
|
||||
|
||||
@@ -334,7 +334,7 @@ namespace AZ::IO
|
||||
//
|
||||
|
||||
//! Collect statistics from all the components that make up Streamer.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! This is thread safe in the sense that it won't crash.
|
||||
//! Data is collected lockless from involved threads and might be slightly
|
||||
//! out of date in some cases.
|
||||
//! @param statistics The container where statistics will be added to.
|
||||
|
||||
@@ -98,6 +98,11 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const noexcept;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// decomposition
|
||||
//! Given a windows path of "C:\O3DE\foo\bar\name.txt" and a posix path of
|
||||
//! "/O3DE/foo/bar/name.txt"
|
||||
@@ -178,7 +183,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -238,7 +243,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
@@ -253,24 +258,23 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
friend class BasicPath;
|
||||
friend struct AZStd::hash<PathView>;
|
||||
|
||||
template <typename PathResultType>
|
||||
static constexpr void MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base);
|
||||
|
||||
struct PathIterable;
|
||||
|
||||
static constexpr void MakeRelativeTo(PathIterable& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept;
|
||||
|
||||
//! Returns a structure that provides a view of the path parts which can be used for iteration
|
||||
//! Only the path parts that correspond to creating an normalized path is returned
|
||||
//! This function is useful for returning a "view" into a normalized path without the need
|
||||
//! to allocate memory for the heap
|
||||
static constexpr PathIterable GetNormalPathParts(const AZ::IO::PathView& path) noexcept;
|
||||
// joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
// If the input path is absolute it will replace the current PathIterable otherwise
|
||||
// the input path will be appended to the Path Iterable structure
|
||||
// For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
// If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
// If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
// If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
// If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
//! joins the input path to the Path Iterable structure using similiar logic to Path::Append
|
||||
//! If the input path is absolute it will replace the current PathIterable otherwise
|
||||
//! the input path will be appended to the Path Iterable structure
|
||||
//! For example a PathIterable with parts = ['C:', '/', 'foo']
|
||||
//! If the path input = 'bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar']
|
||||
//! If the path input = 'C:/bar', then the new PathIterable parts = [C:', '/', 'bar']
|
||||
//! If the path input = 'C:bar', then the new PathIterable parts = [C:', '/', 'foo', 'bar' ]
|
||||
//! If the path input = 'D:bar', then the new PathIterable parts = [D:, 'bar' ]
|
||||
static constexpr void AppendNormalPathParts(PathIterable& pathIterableResult, const AZ::IO::PathView& path) noexcept;
|
||||
|
||||
constexpr int ComparePathView(const PathView& other) const;
|
||||
@@ -325,32 +329,32 @@ namespace AZ::IO
|
||||
constexpr BasicPath(BasicPath&& other) = default;
|
||||
|
||||
// Conversion constructor for other types of BasicPath instantiations
|
||||
constexpr BasicPath(const PathView& other);
|
||||
constexpr BasicPath(const PathView& other) noexcept;
|
||||
|
||||
// String constructors
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const string_type& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const string_type& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by moving the pathString to its internal string
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(string_type&& pathString) noexcept;
|
||||
//! Constructs a Path by copying the pathString to its internal string
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(string_type&& pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(AZStd::string_view src) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a string_view
|
||||
//! The preferred separators it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(AZStd::string_view src, const char preferredSeparator) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator is to the OS default path separator
|
||||
constexpr BasicPath(const value_type* pathString) noexcept;
|
||||
//! Constructs a Path by constructing it's internal out of a value_type*
|
||||
//! The preferred separator it set to the parameter
|
||||
//! The preferred separator is set to the parameter
|
||||
constexpr BasicPath(const value_type* pathString, const char preferredSeparator) noexcept;
|
||||
//! Constructs a empty Path with the preferred separator set to the parameter
|
||||
explicit constexpr BasicPath(const char preferredSeparator) noexcept;
|
||||
@@ -371,7 +375,7 @@ namespace AZ::IO
|
||||
constexpr BasicPath& operator=(BasicPath&& other) = default;
|
||||
|
||||
// conversion assignment operator
|
||||
constexpr BasicPath& operator=(const PathView& pathView);
|
||||
constexpr BasicPath& operator=(const PathView& pathView) noexcept;
|
||||
constexpr BasicPath& operator=(const string_type& str) noexcept;
|
||||
constexpr BasicPath& operator=(string_type&& str) noexcept;
|
||||
constexpr BasicPath& operator=(AZStd::string_view str) noexcept;
|
||||
@@ -477,6 +481,12 @@ namespace AZ::IO
|
||||
//! made from the internal string
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathString() const;
|
||||
|
||||
// as_posix
|
||||
//! Replicates the behavior of the Python pathlib as_posix method
|
||||
//! by replacing the Windows Path Separator with the Posix Path Seperator
|
||||
AZStd::string StringAsPosix() const;
|
||||
constexpr AZStd::fixed_string<MaxPathLength> FixedMaxPathStringAsPosix() const noexcept;
|
||||
|
||||
// compare
|
||||
//! Performs a compare of each of the path parts for equivalence
|
||||
//! Each part of the path is compare using string comparison
|
||||
@@ -574,7 +584,7 @@ namespace AZ::IO
|
||||
//! Normalizes a path in a purely lexical manner.
|
||||
//! # Path separators are converted to their preferred path separator
|
||||
//! # Path parts of "." are collapsed to nothing empty
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! # Paths parts of ".." are removed if there is a preceding directory
|
||||
//! The preceding directory is also removed
|
||||
//! # Runs of Two or more path separators are collapsed into one path separator
|
||||
//! unless the path begins with two path separators
|
||||
@@ -616,7 +626,7 @@ namespace AZ::IO
|
||||
|
||||
// iterators
|
||||
//! Returns an iterator to the beginning of the path that can be used to traverse the path
|
||||
//! according to the following
|
||||
//! according to the following
|
||||
//! 1. Root name - (0 or 1)
|
||||
//! 2. Root directory - (0 or 1)
|
||||
//! 3. Filename - (0 or more)
|
||||
|
||||
@@ -240,6 +240,14 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
constexpr AZStd::fixed_string<MaxPathLength> PathView::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
// decomposition
|
||||
constexpr auto PathView::RootName() const -> PathView
|
||||
{
|
||||
@@ -473,8 +481,7 @@ namespace AZ::IO
|
||||
return lhs.Compare(rhs) >= 0;
|
||||
}
|
||||
|
||||
template <typename PathResultType>
|
||||
constexpr void PathView::MakeRelativeTo(PathResultType& pathResult, const AZ::IO::PathView& path, const AZ::IO::PathView& base)
|
||||
constexpr void PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView& path, const AZ::IO::PathView& base) noexcept
|
||||
{
|
||||
const bool exactCaseCompare = path.m_preferred_separator == PosixPathSeparator
|
||||
|| base.m_preferred_separator == PosixPathSeparator;
|
||||
@@ -492,13 +499,11 @@ namespace AZ::IO
|
||||
if (int res = Internal::ComparePathSegment(*pathParser, *pathParserBase, exactCaseCompare);
|
||||
res != 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,7 +517,6 @@ namespace AZ::IO
|
||||
}
|
||||
if (CheckIterMismatchAtBase())
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -530,7 +534,7 @@ namespace AZ::IO
|
||||
// If there is no mismatch, return ".".
|
||||
if (!pathParser && !pathParserBase)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,27 +543,25 @@ namespace AZ::IO
|
||||
int elemCount = parser::DetermineLexicalElementCount(pathParserBase);
|
||||
if (elemCount < 0)
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{};
|
||||
return;
|
||||
}
|
||||
|
||||
// if elemCount == 0 and (pathParser == end() || pathParser->empty()), returns path("."); otherwise
|
||||
if (elemCount == 0 && (pathParser.AtEnd() || *pathParser == ""))
|
||||
{
|
||||
pathResult.m_path = AZStd::string_view{ "." };
|
||||
pathIterable.emplace_back(".", parser::PathPartKind::PK_Dot);
|
||||
return;
|
||||
}
|
||||
|
||||
// return a path constructed with 'n' dot-dot elements, followed by the
|
||||
// elements of '*this' after the mismatch.
|
||||
pathResult = PathResultType(path.m_preferred_separator);
|
||||
while (elemCount--)
|
||||
{
|
||||
pathResult /= "..";
|
||||
pathIterable.emplace_back("..", parser::PathPartKind::PK_DotDot);
|
||||
}
|
||||
for (; pathParser; ++pathParser)
|
||||
{
|
||||
pathResult /= *pathParser;
|
||||
pathIterable.emplace_back(*pathParser, parser::ClassifyPathPart(pathParser));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,7 +675,7 @@ namespace AZ::IO
|
||||
// Basic Path implementation
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other)
|
||||
constexpr BasicPath<StringType>::BasicPath(const PathView& other) noexcept
|
||||
: m_path(other.m_path)
|
||||
, m_preferred_separator(other.m_preferred_separator) {}
|
||||
|
||||
@@ -726,6 +728,7 @@ namespace AZ::IO
|
||||
: m_path(first, last)
|
||||
, m_preferred_separator(preferredSeparator) {}
|
||||
|
||||
|
||||
template <typename StringType>
|
||||
constexpr BasicPath<StringType>::operator PathView() const noexcept
|
||||
{
|
||||
@@ -733,7 +736,7 @@ namespace AZ::IO
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) -> BasicPath&
|
||||
constexpr auto BasicPath<StringType>::operator=(const PathView& other) noexcept -> BasicPath&
|
||||
{
|
||||
m_path = other.m_path;
|
||||
m_preferred_separator = other.m_preferred_separator;
|
||||
@@ -974,13 +977,13 @@ namespace AZ::IO
|
||||
template <typename StringType>
|
||||
constexpr auto BasicPath<StringType>::MakePreferred() -> BasicPath&
|
||||
{
|
||||
if (m_preferred_separator != '/')
|
||||
if (m_preferred_separator != PosixPathSeparator)
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '/', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), PosixPathSeparator, m_preferred_separator);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZStd::replace(m_path.begin(), m_path.end(), '\\', m_preferred_separator);
|
||||
AZStd::replace(m_path.begin(), m_path.end(), WindowsPathSeparator, m_preferred_separator);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1033,6 +1036,24 @@ namespace AZ::IO
|
||||
return AZStd::fixed_string<MaxPathLength>(m_path.begin(), m_path.end());
|
||||
}
|
||||
|
||||
// as_posix
|
||||
// Returns a copy of the path with the path separators converted to PosixPathSeparator
|
||||
template <typename StringType>
|
||||
AZStd::string BasicPath<StringType>::StringAsPosix() const
|
||||
{
|
||||
AZStd::string resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr AZStd::fixed_string<MaxPathLength> BasicPath<StringType>::FixedMaxPathStringAsPosix() const noexcept
|
||||
{
|
||||
AZStd::fixed_string<MaxPathLength> resultPath(m_path.begin(), m_path.end());
|
||||
AZStd::replace(resultPath.begin(), resultPath.end(), WindowsPathSeparator, PosixPathSeparator);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
constexpr void BasicPath<StringType>::swap(BasicPath& rhs) noexcept
|
||||
{
|
||||
@@ -1234,6 +1255,7 @@ namespace AZ::IO
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1241,7 +1263,13 @@ namespace AZ::IO
|
||||
constexpr auto BasicPath<StringType>::LexicallyRelative(const PathView& base) const -> BasicPath
|
||||
{
|
||||
BasicPath pathResult(m_preferred_separator);
|
||||
static_cast<PathView>(*this).MakeRelativeTo(pathResult, *this, base);
|
||||
PathView::PathIterable pathIterable;
|
||||
PathView::MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
@@ -1355,7 +1383,7 @@ namespace AZ::IO
|
||||
return !basePathParts.empty() || !thisPathParts.IsAbsolute();
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyNormal() const
|
||||
constexpr auto PathView::LexicallyNormal() const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
PathIterable pathIterable = GetNormalPathParts(*this);
|
||||
@@ -1367,21 +1395,28 @@ namespace AZ::IO
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyRelative(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyRelative(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath pathResult(m_preferred_separator);
|
||||
MakeRelativeTo(pathResult, *this, base);
|
||||
PathIterable pathIterable;
|
||||
MakeRelativeTo(pathIterable, *this, base);
|
||||
for ([[maybe_unused]] auto [pathPartView, pathPartKind] : pathIterable)
|
||||
{
|
||||
pathResult /= pathPartView;
|
||||
}
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
|
||||
constexpr FixedMaxPath PathView::LexicallyProximate(const PathView& base) const
|
||||
constexpr auto PathView::LexicallyProximate(const PathView& base) const -> FixedMaxPath
|
||||
{
|
||||
FixedMaxPath result = LexicallyRelative(base);
|
||||
if (result.empty())
|
||||
FixedMaxPath pathResult = LexicallyRelative(base);
|
||||
if (pathResult.empty())
|
||||
{
|
||||
return FixedMaxPath(*this);
|
||||
}
|
||||
return result;
|
||||
|
||||
return pathResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ namespace AZ::IO
|
||||
|
||||
constexpr void clear() noexcept;
|
||||
|
||||
friend constexpr auto PathView::GetNormalPathParts(const AZ::IO::PathView&) noexcept -> PathIterable;
|
||||
friend constexpr auto PathView::AppendNormalPathParts(PathIterable& pathIterable, const AZ::IO::PathView&) noexcept -> void;
|
||||
friend constexpr auto PathView::MakeRelativeTo(PathIterable& pathIterable, const AZ::IO::PathView&, const AZ::IO::PathView&) noexcept -> void;
|
||||
PartKindArray m_parts{};
|
||||
size_t m_size{};
|
||||
};
|
||||
|
||||
@@ -546,7 +546,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetExecutableDirectory();
|
||||
registry.Set(FilePathKey_BinaryFolder, path.LexicallyNormal().Native());
|
||||
|
||||
// Engine root folder - corresponds to the @engroot@ and @devroot@ aliases
|
||||
// Engine root folder - corresponds to the @engroot@ and @engroot@ aliases
|
||||
AZ::IO::FixedMaxPath engineRoot = FindEngineRoot(registry);
|
||||
registry.Set(FilePathKey_EngineRootFolder, engineRoot.LexicallyNormal().Native());
|
||||
|
||||
@@ -570,7 +570,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
assetPlatform = AZ::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
}
|
||||
|
||||
// Project path - corresponds to the @devassets@ alias
|
||||
// Project path - corresponds to the @projectroot@ alias
|
||||
// NOTE: Here we append to engineRoot, but if projectPathValue is absolute then engineRoot is discarded.
|
||||
path = engineRoot / projectPathValue;
|
||||
|
||||
@@ -662,7 +662,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache: root - same as the @root@ alias, this is the starting path for cache files.
|
||||
// Cache: root - same as the @products@ alias, this is the starting path for cache files.
|
||||
path = normalizedProjectPath / "Cache";
|
||||
registry.Set(FilePathKey_CacheProjectRootFolder, path.LexicallyNormal().Native());
|
||||
path /= assetPlatform;
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ
|
||||
MOCK_METHOD2(SetAlias, void(const char* alias, const char* path));
|
||||
MOCK_METHOD1(ClearAlias, void(const char* alias));
|
||||
MOCK_CONST_METHOD1(GetAlias, const char*(const char* alias));
|
||||
MOCK_METHOD2(SetDeprecatedAlias, void(AZStd::string_view, AZStd::string_view));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, AZStd::optional<AZ::u64>(char* inOutBuffer, AZ::u64 bufferLength));
|
||||
MOCK_CONST_METHOD2(ConvertToAlias, bool(AZ::IO::FixedMaxPath& aliasPath, const AZ::IO::PathView& path));
|
||||
MOCK_CONST_METHOD3(ResolvePath, bool(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize));
|
||||
|
||||
@@ -51,6 +51,20 @@ namespace AZ::Utils
|
||||
return executableDirectory;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (ConvertToAbsolutePath(srcPath.c_str(), absolutePath.data(), absolutePath.capacity()))
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath()
|
||||
{
|
||||
AZ::IO::FixedMaxPath o3deManifestPath = GetO3deManifestDirectory();
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace AZ
|
||||
// Attempts the supplied path to an absolute path.
|
||||
//! Returns nullopt if path cannot be converted to an absolute path
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path);
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 absolutePathMaxSize);
|
||||
|
||||
//! Save a string to a file. Otherwise returns a failure with error message.
|
||||
AZ::Outcome<void, AZStd::string> WriteFile(AZStd::string_view content, AZStd::string_view filePath);
|
||||
|
||||
@@ -60,23 +60,34 @@ namespace AZ
|
||||
return writeStorage ? AZStd::make_optional<AZ::IO::FixedMaxPathString>(writeStorage) : AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
if (AZ::Android::Utils::IsApkPath(srcPath.c_str()))
|
||||
if (AZ::Android::Utils::IsApkPath(path))
|
||||
{
|
||||
return srcPath;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,23 +47,32 @@ namespace AZ
|
||||
AZ::IO::FixedMaxPath path{pass->pw_dir};
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
|
||||
if (char* result = realpath(srcPath.c_str(), absolutePath.data()); result)
|
||||
#ifdef PATH_MAX
|
||||
static constexpr size_t UnixMaxPathLength = PATH_MAX;
|
||||
#else
|
||||
// Fallback to 4096 if the PATH_MAX macro isn't defined on the Unix System
|
||||
static constexpr size_t UnixMaxPathLength = 4096;
|
||||
#endif
|
||||
if (!AZ::IO::PathView(path).IsAbsolute())
|
||||
{
|
||||
// Fix the size value of the fixed string by calculating the c-string length using char traits
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
return absolutePath;
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
char absolutePathBuffer[UnixMaxPathLength];
|
||||
if (const char* result = realpath(path, absolutePathBuffer); result != nullptr)
|
||||
{
|
||||
azstrcpy(absolutePath, maxLength, absolutePathBuffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return AZ::IO::PathView(absolutePath).IsAbsolute();
|
||||
}
|
||||
} // namespace Utils
|
||||
} // namespace AZ
|
||||
|
||||
@@ -67,19 +67,12 @@ namespace AZ
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::IO::FixedMaxPathString> ConvertToAbsolutePath(AZStd::string_view path)
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength)
|
||||
{
|
||||
AZ::IO::FixedMaxPathString absolutePath;
|
||||
AZ::IO::FixedMaxPathString srcPath{ path };
|
||||
char* result = _fullpath(absolutePath.data(), srcPath.c_str(), absolutePath.capacity());
|
||||
// Force update of the fixed_string size() value
|
||||
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
|
||||
if (result)
|
||||
{
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
char* result = _fullpath(absolutePath, path, maxLength);
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +426,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetDeprecatedAlias(AZStd::string_view, AZStd::string_view) override
|
||||
{
|
||||
}
|
||||
|
||||
void ClearAlias(const char* ) override { }
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64) const override
|
||||
|
||||
@@ -698,7 +698,7 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
using PathViewLexicallyProximateFixture = PathLexicallyFixture<PathViewLexicallyProximateParams>;
|
||||
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPathIfNot)
|
||||
TEST_P(PathViewLexicallyProximateFixture, LexicallyProximate_ReturnsRelativePathIfNotEmptyOrTestPath)
|
||||
{
|
||||
const auto& testParams = GetParam();
|
||||
AZ::IO::PathView testPath(testParams.m_testPathString, testParams.m_preferredSeparator);
|
||||
|
||||
@@ -77,11 +77,15 @@
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
|
||||
namespace ApplicationInternal
|
||||
{
|
||||
static constexpr const char s_prefabSystemKey[] = "/Amazon/Preferences/EnablePrefabSystem";
|
||||
static constexpr const char s_prefabWipSystemKey[] = "/Amazon/Preferences/EnablePrefabSystemWipFeatures";
|
||||
static constexpr const char s_legacySlicesAssertKey[] = "/Amazon/Preferences/ShouldAssertForLegacySlicesUsage";
|
||||
static constexpr const char* DeprecatedFileIOAliasesRoot = "/O3DE/AzCore/FileIO/DeprecatedAliases";
|
||||
static constexpr const char* DeprecatedFileIOAliasesOldAliasKey = "OldAlias";
|
||||
static constexpr const char* DeprecatedFileIOAliasesNewAliasKey = "NewAlias";
|
||||
}
|
||||
|
||||
Application::Application()
|
||||
@@ -563,6 +567,68 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
struct DeprecatedAliasesKeyVisitor
|
||||
: AZ::SettingsRegistryInterface::Visitor
|
||||
{
|
||||
using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse;
|
||||
using VisitAction = AZ::SettingsRegistryInterface::VisitAction;
|
||||
using Type = AZ::SettingsRegistryInterface::Type;
|
||||
|
||||
using AZ::SettingsRegistryInterface::Visitor::Visit;
|
||||
|
||||
VisitResponse Traverse(AZStd::string_view path, AZStd::string_view,
|
||||
VisitAction action, Type type) override
|
||||
{
|
||||
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = path;
|
||||
}
|
||||
|
||||
// Strip off last path segment from json path and check if is a child element of the array
|
||||
if (AZ::StringFunc::TokenizeLast(path, '/');
|
||||
m_parentArrayPath == path)
|
||||
{
|
||||
m_aliases.emplace_back();
|
||||
}
|
||||
}
|
||||
else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
|
||||
{
|
||||
if (type == AZ::SettingsRegistryInterface::Type::Array)
|
||||
{
|
||||
m_parentArrayPath = AZStd::string{};
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::SettingsRegistryInterface::VisitResponse::Continue;
|
||||
}
|
||||
|
||||
void Visit(AZStd::string_view, AZStd::string_view valueName, Type, AZStd::string_view value) override
|
||||
{
|
||||
if (!m_aliases.empty())
|
||||
{
|
||||
if (valueName == ApplicationInternal::DeprecatedFileIOAliasesOldAliasKey)
|
||||
{
|
||||
m_aliases.back().m_oldAlias = value;
|
||||
}
|
||||
else if (valueName == ApplicationInternal::DeprecatedFileIOAliasesNewAliasKey)
|
||||
{
|
||||
m_aliases.back().m_newAlias = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AliasPair
|
||||
{
|
||||
AZStd::string m_oldAlias;
|
||||
AZStd::string m_newAlias;
|
||||
};
|
||||
AZStd::vector<AliasPair> m_aliases;
|
||||
|
||||
private:
|
||||
AZStd::string m_parentArrayPath;
|
||||
};
|
||||
|
||||
static void CreateUserCache(const AZ::IO::FixedMaxPath& cacheUserPath, AZ::IO::FileIOBase& fileIoBase)
|
||||
{
|
||||
@@ -610,9 +676,8 @@ namespace AzFramework
|
||||
|
||||
void Application::SetFileIOAliases()
|
||||
{
|
||||
if (m_archiveFileIO)
|
||||
if (auto fileIoBase = m_archiveFileIO.get(); fileIoBase)
|
||||
{
|
||||
auto fileIoBase = m_archiveFileIO.get();
|
||||
// Set up the default file aliases based on the settings registry
|
||||
fileIoBase->SetAlias("@engroot@", GetEngineRoot());
|
||||
fileIoBase->SetAlias("@projectroot@", GetEngineRoot());
|
||||
@@ -620,29 +685,20 @@ namespace AzFramework
|
||||
|
||||
{
|
||||
AZ::IO::FixedMaxPath pathAliases;
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@projectcache@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectplatformcache@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@root@", pathAliases.c_str()); // Deprecated Use @projectplatformcache@
|
||||
fileIoBase->SetAlias("@products@", pathAliases.c_str());
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder))
|
||||
{
|
||||
fileIoBase->SetAlias("@engroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@devroot@", pathAliases.c_str()); // Deprecated - Use @engroot@
|
||||
}
|
||||
pathAliases.clear();
|
||||
if (m_settingsRegistry->Get(pathAliases.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
|
||||
{
|
||||
fileIoBase->SetAlias("@devassets@", pathAliases.c_str()); // Deprecated - Use @projectsourceassets@
|
||||
fileIoBase->SetAlias("@projectroot@", pathAliases.c_str());
|
||||
fileIoBase->SetAlias("@projectsourceassets@", (pathAliases / "Assets").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +719,15 @@ namespace AzFramework
|
||||
}
|
||||
fileIoBase->SetAlias("@log@", projectLogPath.c_str());
|
||||
fileIoBase->CreatePath(projectLogPath.c_str());
|
||||
|
||||
DeprecatedAliasesKeyVisitor visitor;
|
||||
if (m_settingsRegistry->Visit(visitor, ApplicationInternal::DeprecatedFileIOAliasesRoot))
|
||||
{
|
||||
for (const auto& [oldAlias, newAlias] : visitor.m_aliases)
|
||||
{
|
||||
fileIoBase->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ namespace AZ::IO
|
||||
|
||||
if (AZ::IO::FixedMaxPath pathBindRoot; !AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, szBindRoot))
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@assets@");
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->ResolvePath(pathBindRoot, "@products@");
|
||||
desc.m_pathBindRoot = pathBindRoot.LexicallyNormal().String();
|
||||
}
|
||||
else
|
||||
@@ -1807,9 +1807,9 @@ namespace AZ::IO
|
||||
if (m_eRecordFileOpenList != IArchive::RFOM_Disabled)
|
||||
{
|
||||
// we only want to record ASSET access
|
||||
// assets are identified as files that are relative to the resolved @assets@ alias path
|
||||
// assets are identified as files that are relative to the resolved @products@ alias path
|
||||
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
|
||||
const char* aliasValue = fileIoBase->GetAlias("@assets@");
|
||||
const char* aliasValue = fileIoBase->GetAlias("@products@");
|
||||
|
||||
if (AZ::IO::FixedMaxPath resolvedFilePath;
|
||||
fileIoBase->ResolvePath(resolvedFilePath, szFilename)
|
||||
|
||||
@@ -546,6 +546,16 @@ namespace AZ::IO
|
||||
realUnderlyingFileIO->GetAlias(alias);
|
||||
}
|
||||
|
||||
void ArchiveFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
FileIOBase* realUnderlyingFileIO = FileIOBase::GetDirectInstance();
|
||||
if (!realUnderlyingFileIO)
|
||||
{
|
||||
return;
|
||||
}
|
||||
realUnderlyingFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> ArchiveFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
if ((!inOutBuffer) || (bufferLength == 0))
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ::IO
|
||||
IO::Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace AZ::IO
|
||||
{
|
||||
// filter out the stuff which does not match.
|
||||
|
||||
// the problem here is that szDir might be something like "@assets@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@assets@" or "@assets@/levels/mylevel"
|
||||
// the problem here is that szDir might be something like "@products@/levels/*"
|
||||
// but our archive might be mounted at the root, or at some other folder at like "@products@" or "@products@/levels/mylevel"
|
||||
// so there's really no way to filter out opening the pack and looking at the files inside.
|
||||
// however, the bind root is not part of the inner zip entry name either
|
||||
// and the ZipDir::FindFile actually expects just the chopped off piece.
|
||||
@@ -202,22 +202,22 @@ namespace AZ::IO
|
||||
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\" <--- mount point
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\" <--- mount point
|
||||
// ~~~~~~~~~~~ Common part
|
||||
// "levels\\*" <---- remainder that is not in common
|
||||
// "" <--- mount point remainder. In this case, we should scan the contents of the pak for the remainder
|
||||
|
||||
// Example:
|
||||
// "@assets@\\levels\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// ~~~~~~~~~~~~~~~~~~ common part
|
||||
// "*" <---- remainder that is not in common
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
// example:
|
||||
// "@assets@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@assets@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "@products@\\levels\\otherlevel\\*" <--- szDir
|
||||
// "@products@\\levels\\mylevel\\" <--- mount point (its level.pak)
|
||||
// "otherlevel\\*" <---- remainder
|
||||
// "mylevel\\" <--- mount point remainder.
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace AZ::IO
|
||||
// which means we may search inside the pack.
|
||||
ScanInZip(it->pZip.get(), sourcePathRemainder.Native());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace AZ::IO::Internal
|
||||
}
|
||||
|
||||
AZStd::smatch matches;
|
||||
const AZStd::regex lodRegex("@assets@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
const AZStd::regex lodRegex("@products@\\\\(.*)_lod[0-9]+(\\.cgfm?)");
|
||||
if (!AZStd::regex_match(szPath, matches, lodRegex) || matches.size() != 3)
|
||||
{
|
||||
// The current file is not a valid LOD file
|
||||
|
||||
@@ -725,7 +725,7 @@ namespace AzFramework
|
||||
|
||||
if (!info.m_relativePath.empty())
|
||||
{
|
||||
const char* devAssetRoot = fileIO->GetAlias("@devassets@");
|
||||
const char* devAssetRoot = fileIO->GetAlias("@projectroot@");
|
||||
if (devAssetRoot)
|
||||
{
|
||||
AZ::Data::AssetStreamInfo streamInfo;
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzFramework
|
||||
|
||||
AZ::IO::Path& gemAbsPath = gemInfo.m_absoluteSourcePaths.emplace_back(value);
|
||||
// Resolve any file aliases first - Do not use ResolvePath() as that assumes
|
||||
// any relative path is underneath the @assets@ alias
|
||||
// any relative path is underneath the @products@ alias
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
AZ::IO::FixedMaxPath replacedAliasPath;
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
#include <AzCore/std/containers/fixed_unordered_set.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string_view.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <cctype>
|
||||
|
||||
namespace AZ
|
||||
@@ -292,7 +294,7 @@ namespace AZ
|
||||
void LocalFileIO::CheckInvalidWrite([[maybe_unused]] const char* path)
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* assetAliasPath = GetAlias("@products@");
|
||||
if (path && assetAliasPath)
|
||||
{
|
||||
const AZ::IO::PathView pathView(path);
|
||||
@@ -478,17 +480,15 @@ namespace AZ
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsAbsolutePath(path))
|
||||
if (AZ::IO::PathView(path).HasRootPath())
|
||||
{
|
||||
size_t pathLen = strlen(path);
|
||||
if (pathLen + 1 < resolvedPathSize)
|
||||
{
|
||||
azstrncpy(resolvedPath, resolvedPathSize, path, pathLen + 1);
|
||||
|
||||
//see if the absolute path uses @assets@ or @root@, if it does lowercase the relative part
|
||||
[[maybe_unused]] bool lowercasePath = LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@assets@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@root@"))
|
||||
|| LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@projectplatformcache@"));
|
||||
//see if the absolute path matches the resolved value of @products@, if it does lowercase the relative part
|
||||
LowerIfBeginsWith(resolvedPath, resolvedPathSize, GetAlias("@products@"));
|
||||
|
||||
ToUnixSlashes(resolvedPath, resolvedPathSize);
|
||||
return true;
|
||||
@@ -499,34 +499,39 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
char rootedPathBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
constexpr AZStd::string_view productAssetAlias = "@products@";
|
||||
// Add plus one for the path separator: <alias>/<path>
|
||||
constexpr size_t MaxPathSizeWithProductAssetAlias = AZ::IO::MaxPathLength + productAssetAlias.size() + 1;
|
||||
using RootedPathString = AZStd::fixed_string<MaxPathSizeWithProductAssetAlias>;
|
||||
RootedPathString rootedPathBuffer;
|
||||
const char* rootedPath = path;
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @assets@
|
||||
// if the path does not begin with an alias, then it is assumed to begin with @products@
|
||||
if (path[0] != '@')
|
||||
{
|
||||
if (GetAlias("@assets@"))
|
||||
if (GetAlias("@products@"))
|
||||
{
|
||||
const int rootLength = 9;// strlen("@assets@/")
|
||||
azstrncpy(rootedPathBuffer, AZ_MAX_PATH_LEN, "@assets@/", rootLength);
|
||||
size_t pathLen = strlen(path);
|
||||
size_t rootedPathBufferlength = rootLength + pathLen + 1;// +1 for null terminator
|
||||
if (rootedPathBufferlength > resolvedPathSize)
|
||||
|
||||
if (const size_t requiredSize = productAssetAlias.size() + strlen(path) + 1;
|
||||
requiredSize > rootedPathBuffer.capacity())
|
||||
{
|
||||
AZ_Assert(rootedPathBufferlength < resolvedPathSize, "Constructed path length is wrong:%s", rootedPathBuffer);//path constructed is wrong
|
||||
size_t remainingSize = resolvedPathSize - rootLength - 1;// - 1 for null terminator
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN, path, remainingSize);
|
||||
rootedPathBuffer[resolvedPathSize - 1] = '\0';
|
||||
AZ_Error("FileIO", false, "Prepending the %.*s alias to the input path results in a path longer than the"
|
||||
" AZ::IO::MaxPathLength + the alias size of %zu. The size of the potential failed path is %zu",
|
||||
AZ_STRING_ARG(productAssetAlias), rootedPathBuffer.capacity(), requiredSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
azstrncpy(rootedPathBuffer + rootLength, AZ_MAX_PATH_LEN - rootLength, path, pathLen + 1);
|
||||
rootedPathBuffer = RootedPathString::format("%.*s/%s", AZ_STRING_ARG(productAssetAlias), path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertToAbsolutePath(path, rootedPathBuffer, AZ_MAX_PATH_LEN);
|
||||
if (ConvertToAbsolutePath(path, rootedPathBuffer.data(), rootedPathBuffer.capacity()))
|
||||
{
|
||||
// Recalculate the internal string length
|
||||
rootedPathBuffer.resize_no_construct(AZStd::char_traits<char>::length(rootedPathBuffer.data()));
|
||||
}
|
||||
}
|
||||
rootedPath = rootedPathBuffer;
|
||||
rootedPath = rootedPathBuffer.c_str();
|
||||
}
|
||||
|
||||
if (ResolveAliases(rootedPath, resolvedPath, resolvedPathSize))
|
||||
@@ -561,11 +566,57 @@ namespace AZ
|
||||
|
||||
const char* LocalFileIO::GetAlias(const char* key) const
|
||||
{
|
||||
const auto it = m_aliases.find(key);
|
||||
if (it != m_aliases.end())
|
||||
if (const auto it = m_aliases.find(key); it != m_aliases.end())
|
||||
{
|
||||
return it->second.c_str();
|
||||
}
|
||||
else if (const auto deprecatedIt = m_deprecatedAliases.find(key);
|
||||
deprecatedIt != m_deprecatedAliases.end())
|
||||
{
|
||||
AZ_Error("FileIO", false, R"(Alias "%s" is deprecated. Please use alias "%s" instead)",
|
||||
key, deprecatedIt->second.c_str());
|
||||
AZStd::string_view aliasValue = deprecatedIt->second;
|
||||
// Contains the list of aliases resolved so far
|
||||
// If max_size is hit, than an error is logged and nullptr is returned
|
||||
using VisitedAliasSet = AZStd::fixed_unordered_set<AZStd::string_view, 8, 8>;
|
||||
VisitedAliasSet visitedAliasSet;
|
||||
while (aliasValue.starts_with("@"))
|
||||
{
|
||||
if (visitedAliasSet.contains(aliasValue))
|
||||
{
|
||||
AZ_Error("FileIO", false, "Cycle found with for alias %.*s when trying to resolve deprecated alias %s",
|
||||
AZ_STRING_ARG(aliasValue), key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(visitedAliasSet.size() == visitedAliasSet.max_size())
|
||||
{
|
||||
AZ_Error("FileIO", false, "Unable to resolve path to deprecated alias %s within %zu steps",
|
||||
key, visitedAliasSet.max_size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Add the current alias value to the visited set
|
||||
visitedAliasSet.emplace(aliasValue);
|
||||
|
||||
// Check if the alias value corresponds to another alias
|
||||
if (auto resolvedIter = m_aliases.find(aliasValue); resolvedIter != m_aliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else if (resolvedIter = m_deprecatedAliases.find(aliasValue);
|
||||
resolvedIter != m_deprecatedAliases.end())
|
||||
{
|
||||
aliasValue = resolvedIter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return aliasValue.data();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -574,6 +625,11 @@ namespace AZ
|
||||
m_aliases.erase(key);
|
||||
}
|
||||
|
||||
void LocalFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
m_deprecatedAliases[oldAlias] = newAlias;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> LocalFileIO::ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const
|
||||
{
|
||||
size_t longestMatch = 0;
|
||||
@@ -675,7 +731,9 @@ namespace AZ
|
||||
: string_view_pair{};
|
||||
|
||||
size_t requiredResolvedPathSize = pathView.size() - aliasKey.size() + aliasValue.size() + 1;
|
||||
AZ_Assert(path != resolvedPath && resolvedPathSize >= requiredResolvedPathSize, "Resolved path is incorrect");
|
||||
AZ_Assert(path != resolvedPath, "ResolveAliases does not support inplace update of the path");
|
||||
AZ_Assert(resolvedPathSize >= requiredResolvedPathSize, "Resolved path size %llu not large enough. It needs to be %zu",
|
||||
resolvedPathSize, requiredResolvedPathSize);
|
||||
// we assert above, but we also need to properly handle the case when the resolvedPath buffer size
|
||||
// is too small to copy the source into.
|
||||
if (path == resolvedPath || (resolvedPathSize < requiredResolvedPathSize))
|
||||
@@ -699,13 +757,9 @@ namespace AZ
|
||||
resolvedPath[resolvedPathLen] = '\0';
|
||||
|
||||
// If the path started with one of the "asset cache" path aliases, lowercase the path
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* rootAliasPath = GetAlias("@root@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@projectplatformcache@");
|
||||
const char* projectPlatformCacheAliasPath = GetAlias("@products@");
|
||||
|
||||
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
|
||||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
|
||||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
|
||||
const bool lowercasePath = projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath);
|
||||
|
||||
if (lowercasePath)
|
||||
{
|
||||
@@ -822,5 +876,10 @@ namespace AZ
|
||||
|
||||
return pathStr + "/";
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
return AZ::Utils::ConvertToAbsolutePath(path, absolutePath, maxLength);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -71,7 +73,7 @@ namespace AZ
|
||||
|
||||
bool GetFilename(HandleType fileHandle, char* filename, AZ::u64 filenameSize) const override;
|
||||
bool ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const;
|
||||
|
||||
|
||||
private:
|
||||
SystemFile* GetFilePointerFromHandle(HandleType fileHandle);
|
||||
|
||||
@@ -79,7 +81,6 @@ namespace AZ
|
||||
|
||||
AZStd::optional<AZ::u64> ConvertToAliasBuffer(char* outBuffer, AZ::u64 outBufferLength, AZStd::string_view inBuffer) const;
|
||||
bool ResolveAliases(const char* path, char* resolvedPath, AZ::u64 resolvedPathSize) const;
|
||||
bool IsAbsolutePath(const char* path) const;
|
||||
|
||||
bool LowerIfBeginsWith(char* inOutBuffer, AZ::u64 bufferLen, const char* alias) const;
|
||||
|
||||
@@ -91,6 +92,7 @@ namespace AZ
|
||||
AZStd::atomic<HandleType> m_nextHandle;
|
||||
AZStd::unordered_map<HandleType, SystemFile> m_openFiles;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_aliases;
|
||||
AZStd::unordered_map<AZStd::string, AZStd::string> m_deprecatedAliases;
|
||||
|
||||
void CheckInvalidWrite(const char* path);
|
||||
};
|
||||
|
||||
@@ -49,14 +49,14 @@ namespace AZ
|
||||
s_IOLog.append(m_name);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
void Append(const char* line)
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u ", m_fileOperation));
|
||||
s_IOLog.append(line);
|
||||
s_IOLog.append("\r\n");
|
||||
}
|
||||
|
||||
|
||||
~LogCall()
|
||||
{
|
||||
s_IOLog.append(AZStd::string::format("%u End ", m_fileOperation));
|
||||
@@ -251,7 +251,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size request failed. return Error", filePath).c_str());
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
|
||||
size = response.m_size;
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("NetworkFileIO::Size(filePath=%s) size=%u. return Success", filePath, size).c_str());
|
||||
return ResultCode::Success;
|
||||
@@ -793,6 +793,12 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ClearAlias(alias=%s)", alias?alias:"nullptr").c_str());
|
||||
}
|
||||
|
||||
void NetworkFileIO::SetDeprecatedAlias([[maybe_unused]] AZStd::string_view oldAlias, [[maybe_unused]] AZStd::string_view newAlias)
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::SetDeprecatedAlias(oldAlias=%.*s, newAlias=%.*s)",
|
||||
AZ_STRING_ARG(oldAlias), AZ_STRING_ARG(newAlias)).c_str());
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> NetworkFileIO::ConvertToAlias(char* inOutBuffer, [[maybe_unused]] AZ::u64 bufferLength) const
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("NetworkFileIO()::ConvertToAlias(inOutBuffer=%s, bufferLength=%u)", inOutBuffer?inOutBuffer:"nullptr", bufferLength).c_str());
|
||||
@@ -927,7 +933,7 @@ namespace AZ
|
||||
{
|
||||
m_cacheLookaheadPos = filePosition - CacheStartFilePosition();
|
||||
}
|
||||
|
||||
|
||||
void RemoteFileCache::SyncCheck()
|
||||
{
|
||||
#ifdef REMOTEFILEIO_SYNC_CHECK
|
||||
@@ -955,7 +961,7 @@ namespace AZ
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle);
|
||||
REMOTEFILE_LOG_APPEND(AZStd::string::format("RemoteFileCache::SyncCheck(m_fileHandle=%u) tell request failed.", m_fileHandle).c_str());
|
||||
}
|
||||
|
||||
|
||||
if (responce.m_offset != m_filePosition)
|
||||
{
|
||||
AZ_TracePrintf(RemoteFileCacheChannel, "RemoteFileCache::SyncCheck(m_fileHandle=%u) failed!!! m_filePosition=%u tell=%u", m_fileHandle, m_filePosition, responce.m_offset);
|
||||
@@ -1028,7 +1034,7 @@ namespace AZ
|
||||
{
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Close(fileHandle=%u)", fileHandle).c_str());
|
||||
Result returnValue = NetworkFileIO::Close(fileHandle);
|
||||
|
||||
|
||||
if (returnValue == ResultCode::Success)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
@@ -1160,7 +1166,7 @@ namespace AZ
|
||||
REMOTEFILE_LOG_CALL(AZStd::string::format("RemoteFileIO()::Read(fileHandle=%u, buffer=OUT, size=%u, failOnFewerThanSizeBytesRead=%s, bytesRead=OUT)", fileHandle, size, failOnFewerThanSizeBytesRead ? "True" : "False").c_str());
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_remoteFileCacheGuard);
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
|
||||
|
||||
AZ::u64 remainingBytesToRead = size;
|
||||
AZ::u64 bytesReadFromCache = 0;
|
||||
AZ::u64 remainingBytesInCache = cache.RemainingBytes();
|
||||
@@ -1263,7 +1269,7 @@ namespace AZ
|
||||
RemoteFileCache& cache = GetCache(fileHandle);
|
||||
if (cache.m_cacheLookaheadBuffer.size() && cache.RemainingBytes())
|
||||
{
|
||||
// find out where we are
|
||||
// find out where we are
|
||||
AZ::u64 seekPosition = cache.CacheFilePosition();
|
||||
|
||||
// note, seeks are predicted, and do not ask for a response.
|
||||
@@ -1361,6 +1367,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteFileIO::SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
if (m_excludedFileIO)
|
||||
{
|
||||
m_excludedFileIO->SetDeprecatedAlias(oldAlias, newAlias);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::u64> RemoteFileIO::ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const
|
||||
{
|
||||
return m_excludedFileIO ? m_excludedFileIO->ConvertToAlias(inOutBuffer, bufferLength) : strlen(inOutBuffer);
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace AZ
|
||||
Result FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback) override;
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
@@ -194,6 +195,7 @@ namespace AZ
|
||||
void SetAlias(const char* alias, const char* path) override;
|
||||
const char* GetAlias(const char* alias) const override;
|
||||
void ClearAlias(const char* alias) override;
|
||||
void SetDeprecatedAlias(AZStd::string_view oldAlias, AZStd::string_view newAlias) override;
|
||||
AZStd::optional<AZ::u64> ConvertToAlias(char* inOutBuffer, AZ::u64 bufferLength) const override;
|
||||
bool ConvertToAlias(AZ::IO::FixedMaxPath& convertedPath, const AZ::IO::PathView& path) const override;
|
||||
using FileIOBase::ConvertToAlias;
|
||||
|
||||
+13
-49
@@ -13,7 +13,6 @@
|
||||
#include <AzCore/Android/Utils.h>
|
||||
#include <AzCore/IO/IOUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
#include <android/api-level.h>
|
||||
@@ -42,10 +41,10 @@ namespace AZ
|
||||
{
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourcePath[AZ_MAX_PATH_LEN];
|
||||
char resolvedDestPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ_MAX_PATH_LEN);
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedSourcePath[AZ::IO::MaxPathLength];
|
||||
char resolvedDestPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ::IO::MaxPathLength);
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ::IO::MaxPathLength);
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(sourceFilePath) || AZ::Android::Utils::IsApkPath(destinationFilePath))
|
||||
{
|
||||
@@ -77,18 +76,17 @@ namespace AZ
|
||||
{
|
||||
ANDROID_IO_PROFILE_SECTION_ARGS("FindFiles:%s", filePath);
|
||||
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
AZStd::string pathWithoutSlash = RemoveTrailingSlash(resolvedPath);
|
||||
bool isInAPK = AZ::Android::Utils::IsApkPath(pathWithoutSlash.c_str());
|
||||
|
||||
AZ::IO::FixedMaxPath tempBuffer;
|
||||
if (isInAPK)
|
||||
{
|
||||
AZ::IO::FixedMaxPath strippedPath = AZ::Android::Utils::StripApkPrefix(pathWithoutSlash.c_str());
|
||||
|
||||
char tempBuffer[AZ_MAX_PATH_LEN] = {0};
|
||||
|
||||
AZ::Android::APKFileHandler::ParseDirectory(strippedPath.c_str(), [&](const char* name)
|
||||
{
|
||||
AZStd::string_view filenameView = name;
|
||||
@@ -98,10 +96,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += name;
|
||||
// if aliased, de-alias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -115,10 +112,6 @@ namespace AZ
|
||||
|
||||
if (dir != nullptr)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
|
||||
// clear the errno state so we can distinguish between errors and end of stream
|
||||
errno = 0;
|
||||
struct dirent* entry = readdir(dir);
|
||||
@@ -133,10 +126,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += entry->d_name;
|
||||
// if aliased, de-alias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -163,8 +155,8 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::CreatePath(const char* filePath)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength];
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
if (AZ::Android::Utils::IsApkPath(resolvedPath))
|
||||
{
|
||||
@@ -201,33 +193,5 @@ namespace AZ
|
||||
mkdir(pathBuffer.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
return IsDirectory(resolvedPath) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
return path && path[0] == '/';
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
if (AZ::Android::Utils::IsApkPath(path))
|
||||
{
|
||||
azstrncpy(absolutePath, maxLength, path, maxLength);
|
||||
return true;
|
||||
}
|
||||
AZ_Assert(maxLength >= AZ_MAX_PATH_LEN, "Path length is larger than AZ_MAX_PATH_LEN");
|
||||
if (!IsAbsolutePath(path))
|
||||
{
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
const char* result = realpath(path, absolutePath);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return IsAbsolutePath(absolutePath);
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
|
||||
+12
-38
@@ -10,7 +10,7 @@
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/functional.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -19,11 +19,11 @@ namespace AZ
|
||||
{
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourceFilePath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(sourceFilePath, resolvedSourceFilePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedSourceFilePath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(sourceFilePath, resolvedSourceFilePath, AZ::IO::MaxPathLength);
|
||||
|
||||
char resolvedDestinationFilePath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(destinationFilePath, resolvedDestinationFilePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedDestinationFilePath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(destinationFilePath, resolvedDestinationFilePath, AZ::IO::MaxPathLength);
|
||||
|
||||
// Use standard C++ method of file copy.
|
||||
{
|
||||
@@ -45,17 +45,15 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::FindFiles(const char* filePath, const char* filter, FindFilesCallbackType callback)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
AZStd::string withoutSlash = RemoveTrailingSlash(resolvedPath);
|
||||
DIR* dir = opendir(withoutSlash.c_str());
|
||||
|
||||
if (dir != nullptr)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FixedMaxPath tempBuffer;
|
||||
|
||||
errno = 0;
|
||||
struct dirent* entry = readdir(dir);
|
||||
@@ -70,10 +68,9 @@ namespace AZ
|
||||
AZStd::string foundFilePath = CheckForTrailingSlash(resolvedPath);
|
||||
foundFilePath += entry->d_name;
|
||||
// if aliased, dealias!
|
||||
azstrcpy(tempBuffer, AZ_MAX_PATH_LEN, foundFilePath.c_str());
|
||||
ConvertToAlias(tempBuffer, AZ_MAX_PATH_LEN);
|
||||
ConvertToAlias(tempBuffer, AZ::IO::PathView{ foundFilePath });
|
||||
|
||||
if (!callback(tempBuffer))
|
||||
if (!callback(tempBuffer.c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -92,8 +89,8 @@ namespace AZ
|
||||
|
||||
Result LocalFileIO::CreatePath(const char* filePath)
|
||||
{
|
||||
char resolvedPath[AZ_MAX_PATH_LEN] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ_MAX_PATH_LEN);
|
||||
char resolvedPath[AZ::IO::MaxPathLength] = {0};
|
||||
ResolvePath(filePath, resolvedPath, AZ::IO::MaxPathLength);
|
||||
|
||||
// create all paths up to that directory.
|
||||
// its not an error if the path exists.
|
||||
@@ -125,28 +122,5 @@ namespace AZ
|
||||
mkdir(buf.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
return IsDirectory(resolvedPath) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
return path && path[0] == '/';
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
AZ_Assert(maxLength >= AZ_MAX_PATH_LEN, "Path length is larger than AZ_MAX_PATH_LEN");
|
||||
if (!IsAbsolutePath(path))
|
||||
{
|
||||
// note that realpath fails if the path does not exist and actually changes the return value
|
||||
// to be the actual place that FAILED, which we don't want.
|
||||
// if we fail, we'd prefer to fall through and at least use the original path.
|
||||
const char* result = realpath(path, absolutePath);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
azstrcpy(absolutePath, maxLength, path);
|
||||
return IsAbsolutePath(absolutePath);
|
||||
}
|
||||
} // namespace IO
|
||||
} // namespace AZ
|
||||
|
||||
+1
-32
@@ -47,7 +47,7 @@ namespace AZ
|
||||
|
||||
if (hFind != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// because the absolute path might actually be SHORTER than the alias ("c:/r/dev" -> "@devroot@"), we need to
|
||||
// because the absolute path might actually be SHORTER than the alias ("D:/o3de" -> "@engroot@"), we need to
|
||||
// use a static buffer here.
|
||||
char tempBuffer[AZ_MAX_PATH_LEN];
|
||||
do
|
||||
@@ -133,36 +133,5 @@ namespace AZ
|
||||
|
||||
return SystemFile::CreateDir(buf.c_str()) ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
|
||||
bool LocalFileIO::ConvertToAbsolutePath(const char* path, char* absolutePath, AZ::u64 maxLength) const
|
||||
{
|
||||
char* result = _fullpath(absolutePath, path, maxLength);
|
||||
size_t len = ::strlen(absolutePath);
|
||||
if (len > 0)
|
||||
{
|
||||
// strip trailing slash
|
||||
if (absolutePath[len - 1] == '/' || absolutePath[len - 1] == '\\')
|
||||
{
|
||||
absolutePath[len - 1] = 0;
|
||||
}
|
||||
|
||||
// For some reason, at least on windows, _fullpath returns a lowercase drive letter even though other systems like Qt, use upper case.
|
||||
if (len > 2)
|
||||
{
|
||||
if (absolutePath[1] == ':')
|
||||
{
|
||||
absolutePath[0] = (char)toupper(absolutePath[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
bool LocalFileIO::IsAbsolutePath(const char* path) const
|
||||
{
|
||||
char drive[16] = { 0 };
|
||||
_splitpath_s(path, drive, 16, nullptr, 0, nullptr, 0, nullptr, 0);
|
||||
return strlen(drive) > 0;
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
|
||||
+15
-17
@@ -7,26 +7,24 @@
|
||||
*/
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/IO/SystemFile.h>
|
||||
|
||||
namespace AZ
|
||||
namespace AZ::IO
|
||||
{
|
||||
namespace IO
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
AZ::IO::FixedMaxPath resolvedSourcePath;
|
||||
ResolvePath(resolvedSourcePath, sourceFilePath);
|
||||
AZ::IO::FixedMaxPath resolvedDestPath;
|
||||
ResolvePath(resolvedDestPath, destinationFilePath);
|
||||
|
||||
Result LocalFileIO::Copy(const char* sourceFilePath, const char* destinationFilePath)
|
||||
{
|
||||
char resolvedSourcePath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(sourceFilePath, resolvedSourcePath, AZ_MAX_PATH_LEN);
|
||||
char resolvedDestPath[AZ_MAX_PATH_LEN];
|
||||
ResolvePath(destinationFilePath, resolvedDestPath, AZ_MAX_PATH_LEN);
|
||||
AZStd::fixed_wstring<AZ::IO::MaxPathLength> resolvedSourcePathW;
|
||||
AZStd::fixed_wstring<AZ::IO::MaxPathLength> resolvedDestPathW;
|
||||
AZStd::to_wstring(resolvedSourcePathW, resolvedSourcePath.Native());
|
||||
AZStd::to_wstring(resolvedDestPathW, resolvedDestPath.Native());
|
||||
|
||||
if (::CopyFileA(resolvedSourcePath, resolvedDestPath, false) == 0)
|
||||
{
|
||||
return ResultCode::Error;
|
||||
}
|
||||
|
||||
return ResultCode::Success;
|
||||
}
|
||||
} // namespace IO
|
||||
}//namespace AZ
|
||||
return ::CopyFileW(resolvedSourcePathW.c_str(), resolvedDestPathW.c_str(), false) != 0 ? ResultCode::Success : ResultCode::Error;
|
||||
}
|
||||
}//namespace AZ::IO
|
||||
|
||||
@@ -26,7 +26,7 @@ protected:
|
||||
}
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", m_tempDirectory.GetDirectory());
|
||||
fileIoBase->SetAlias("@products@", m_tempDirectory.GetDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace UnitTest
|
||||
|
||||
m_application->Start({});
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
}
|
||||
@@ -262,7 +262,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withSubfolders.c_str()));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", testArchivePath_withSubfolders.c_str()));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", testArchivePath_withSubfolders.c_str()));
|
||||
|
||||
EXPECT_TRUE(archive->IsFileExist(fileInArchiveFile));
|
||||
}
|
||||
@@ -353,7 +353,7 @@ namespace UnitTest
|
||||
// and be able to IMMEDIATELY
|
||||
// * read the file in the subfolder
|
||||
// * enumerate the folders (including that subfolder) even though they are 'virtual', not real folders on physical media
|
||||
// * all of the above even though the mount point for the archive is @assets@ wheras the physical pack lives in @usercache@
|
||||
// * all of the above even though the mount point for the archive is @products@ wheras the physical pack lives in @usercache@
|
||||
// finally, we're going to repeat the above test but with files mounted with subfolders
|
||||
// so for example, the pack will contain levelinfo.xml at the root of it
|
||||
// but it will be mounted at a subfolder (levels/mylevel).
|
||||
@@ -388,7 +388,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withSubfolders));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", testArchivePath_withSubfolders));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", testArchivePath_withSubfolders));
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(archive->IsFileExist("levels\\mylevel\\levelinfo.xml"));
|
||||
EXPECT_TRUE(archive->IsFileExist("levels//mylevel//levelinfo.xml"));
|
||||
@@ -484,7 +484,7 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(testArchivePath_withMountPoint));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@\\uniquename\\mylevel2", testArchivePath_withMountPoint));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@\\uniquename\\mylevel2", testArchivePath_withMountPoint));
|
||||
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(archive->IsFileExist("uniquename\\mylevel2\\levelinfo.xml"));
|
||||
@@ -543,7 +543,7 @@ namespace UnitTest
|
||||
archive->ClosePack(testArchivePath_withMountPoint);
|
||||
|
||||
// --- test to make sure that when you iterate only the first component is found, so bury it deep and ask for the root
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@\\uniquename\\mylevel2\\mylevel3\\mylevel4", testArchivePath_withMountPoint));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@\\uniquename\\mylevel2\\mylevel3\\mylevel4", testArchivePath_withMountPoint));
|
||||
|
||||
found_mylevel_folder = false;
|
||||
handle = archive->FindFirst("uniquename\\*");
|
||||
@@ -574,9 +574,9 @@ namespace UnitTest
|
||||
found_mylevel_folder = false;
|
||||
|
||||
// now make sure no red herrings appear
|
||||
// for example, if a file is mounted at "@assets@\\uniquename\\mylevel2\\mylevel3\\mylevel4"
|
||||
// and the file "@assets@\\somethingelse" is requested it should not be found
|
||||
// in addition if the file "@assets@\\uniquename\\mylevel3" is requested it should not be found
|
||||
// for example, if a file is mounted at "@products@\\uniquename\\mylevel2\\mylevel3\\mylevel4"
|
||||
// and the file "@products@\\somethingelse" is requested it should not be found
|
||||
// in addition if the file "@products@\\uniquename\\mylevel3" is requested it should not be found
|
||||
handle = archive->FindFirst("somethingelse\\*");
|
||||
EXPECT_FALSE(static_cast<bool>(handle));
|
||||
|
||||
@@ -610,7 +610,7 @@ namespace UnitTest
|
||||
cpfio.Remove(genericArchiveFileName);
|
||||
|
||||
// create the asset alias directory
|
||||
cpfio.CreatePath("@assets@");
|
||||
cpfio.CreatePath("@products@");
|
||||
|
||||
// create generic file
|
||||
|
||||
@@ -635,11 +635,11 @@ namespace UnitTest
|
||||
pArchive.reset();
|
||||
EXPECT_TRUE(IsPackValid(genericArchiveFileName));
|
||||
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", genericArchiveFileName));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", genericArchiveFileName));
|
||||
|
||||
// ---- BARRAGE OF TESTS
|
||||
EXPECT_TRUE(cpfio.Exists("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@assets@/testfile.xml")); // this should be hte same file
|
||||
EXPECT_TRUE(cpfio.Exists("@products@/testfile.xml")); // this should be hte same file
|
||||
EXPECT_TRUE(!cpfio.Exists("@log@/testfile.xml"));
|
||||
EXPECT_TRUE(!cpfio.Exists("@usercache@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
@@ -685,9 +685,9 @@ namespace UnitTest
|
||||
EXPECT_EQ(ResultCode::Success, cpfio.Close(normalFileHandle));
|
||||
|
||||
EXPECT_TRUE(!cpfio.IsDirectory("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsDirectory("@assets@"));
|
||||
EXPECT_TRUE(cpfio.IsDirectory("@products@"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("@assets@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.IsReadOnly("@products@/testfile.xml"));
|
||||
EXPECT_TRUE(!cpfio.IsReadOnly("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
|
||||
|
||||
@@ -714,10 +714,10 @@ namespace UnitTest
|
||||
|
||||
// find files test.
|
||||
AZ::IO::FixedMaxPath resolvedTestFilePath;
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedTestFilePath, AZ::IO::PathView("@assets@/testfile.xml")));
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedTestFilePath, AZ::IO::PathView("@products@/testfile.xml")));
|
||||
bool foundIt = false;
|
||||
// note that this file exists only in the archive.
|
||||
cpfio.FindFiles("@assets@", "*.xml", [&foundIt, &cpfio, &resolvedTestFilePath](const char* foundName)
|
||||
cpfio.FindFiles("@products@", "*.xml", [&foundIt, &cpfio, &resolvedTestFilePath](const char* foundName)
|
||||
{
|
||||
AZ::IO::FixedMaxPath resolvedFoundPath;
|
||||
EXPECT_TRUE(cpfio.ResolvePath(resolvedFoundPath, AZ::IO::PathView(foundName)));
|
||||
@@ -734,10 +734,10 @@ namespace UnitTest
|
||||
|
||||
|
||||
// The following test is disabled because it will trigger an AZ_ERROR which will affect the outcome of this entire test
|
||||
// EXPECT_NE(ResultCode::Success, cpfio.Remove("@assets@/testfile.xml")); // may not delete archive files
|
||||
// EXPECT_NE(ResultCode::Success, cpfio.Remove("@products@/testfile.xml")); // may not delete archive files
|
||||
|
||||
// make sure it works with and without alias:
|
||||
EXPECT_TRUE(cpfio.Exists("@assets@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("@products@/testfile.xml"));
|
||||
EXPECT_TRUE(cpfio.Exists("testfile.xml"));
|
||||
|
||||
EXPECT_TRUE(cpfio.Exists("@log@/unittesttemp/realfileforunittest.xml"));
|
||||
@@ -788,22 +788,22 @@ namespace UnitTest
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
// change its actual location:
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@assets@/foundit.dat"));
|
||||
EXPECT_TRUE(archive->OpenPack("@products@", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous location!
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/notfoundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat"));
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
|
||||
// try sub-folders
|
||||
EXPECT_TRUE(archive->OpenPack("@assets@/mystuff", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@assets@/mystuff/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_TRUE(archive->OpenPack("@products@/mystuff", realNameBuf));
|
||||
EXPECT_TRUE(archive->IsFileExist("@products@/mystuff/foundit.dat"));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@usercache@/foundit.dat")); // do not find it in the previous locations!
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@assets@/mystuff/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/foundit.dat", AZ::IO::IArchive::eFileLocation_OnDisk));
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/notfoundit.dat")); // non-existent file
|
||||
EXPECT_FALSE(archive->IsFileExist("@products@/mystuff/notfoundit.dat")); // non-existent file
|
||||
EXPECT_TRUE(archive->ClosePack(realNameBuf));
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ namespace UnitTest
|
||||
AZ::IO::FileIOBase* ioBase = AZ::IO::FileIOBase::GetInstance();
|
||||
ASSERT_NE(nullptr, ioBase);
|
||||
|
||||
const char* assetsPath = ioBase->GetAlias("@assets@");
|
||||
const char* assetsPath = ioBase->GetAlias("@products@");
|
||||
ASSERT_NE(nullptr, assetsPath);
|
||||
|
||||
auto stringToAdd = AZ::IO::Path(assetsPath) / "textures" / "test.dds";
|
||||
@@ -872,7 +872,7 @@ namespace UnitTest
|
||||
// it normalizes the string, so the slashes flip and everything is lowercased.
|
||||
AZ::IO::FixedMaxPath resolvedAddedPath;
|
||||
AZ::IO::FixedMaxPath resolvedResourcePath;
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedAddedPath, "@assets@/textures/test.dds"));
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedAddedPath, "@products@/textures/test.dds"));
|
||||
EXPECT_TRUE(ioBase->ReplaceAlias(resolvedResourcePath, reslist->GetFirst()));
|
||||
EXPECT_EQ(resolvedAddedPath, resolvedResourcePath);
|
||||
reslist->Clear();
|
||||
|
||||
@@ -802,6 +802,51 @@ namespace UnitTest
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
TEST_F(AliasTest, GetAlias_LogsError_WhenAccessingDeprecatedAlias_Succeeds)
|
||||
{
|
||||
AZ::IO::LocalFileIO local;
|
||||
|
||||
AZ::IO::FixedMaxPathString aliasFolder;
|
||||
EXPECT_TRUE(local.ConvertToAbsolutePath("/temp", aliasFolder.data(), aliasFolder.capacity()));
|
||||
aliasFolder.resize_no_construct(AZStd::char_traits<char>::length(aliasFolder.data()));
|
||||
|
||||
local.SetAlias("@test@", aliasFolder.c_str());
|
||||
local.SetDeprecatedAlias("@deprecated@", "@test@");
|
||||
local.SetDeprecatedAlias("@deprecatednonexistent@", "@nonexistent@");
|
||||
local.SetDeprecatedAlias("@deprecatedsecond@", "@deprecated@");
|
||||
local.SetDeprecatedAlias("@deprecatednonaliaspath@", aliasFolder);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
const char* testAlias = local.GetAlias("@test@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(0);
|
||||
|
||||
// Validate that accessing Deprecated Alias results in AZ_Error
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecated@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatednonexistent@");
|
||||
EXPECT_EQ(nullptr, testAlias);
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatedsecond@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
|
||||
AZ_TEST_START_TRACE_SUPPRESSION;
|
||||
testAlias = local.GetAlias("@deprecatednonaliaspath@");
|
||||
ASSERT_NE(nullptr, testAlias);
|
||||
EXPECT_EQ(AZ::IO::PathView(aliasFolder), AZ::IO::PathView(testAlias));
|
||||
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
|
||||
}
|
||||
|
||||
class SmartMoveTests
|
||||
: public FolderFixture
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace UnitTest
|
||||
|
||||
const char DummyFile[] = "dummy.txt";
|
||||
const char AnotherDummyFile[] = "Foo/Dummy.txt";
|
||||
|
||||
|
||||
const char DummyPattern[] = R"(^(.+)_([a-z]+)\..+$)";
|
||||
const char MatchingPatternFile[] = "Foo/dummy_abc.txt";
|
||||
const char NonMatchingPatternFile[] = "Foo/dummy_a8c.txt";
|
||||
@@ -75,7 +75,7 @@ namespace UnitTest
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsFixture::SetUp();
|
||||
@@ -89,7 +89,7 @@ namespace UnitTest
|
||||
const char* testAssetRoot = m_tempDirectory.GetDirectory();
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace UnitTest
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr);
|
||||
AZ::IO::FileIOBase::SetInstance(m_data->m_localFileIO.get());
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", testAssetRoot);
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", testAssetRoot);
|
||||
|
||||
m_data->m_excludeFileQueryManager = AZStd::make_unique<FileTagQueryManagerTest>(FileTagType::Exclude);
|
||||
m_data->m_includeFileQueryManager = AZStd::make_unique<FileTagQueryManagerTest>(FileTagType::Include);
|
||||
@@ -114,7 +114,7 @@ namespace UnitTest
|
||||
|
||||
AZStd::vector<AZStd::string> includedWildcardTags = { DummyFileTags[DummyFileTagIndex::GIdx] };
|
||||
EXPECT_TRUE(m_data->m_fileTagManager.AddFilePatternTags(DummyWildcard, FilePatternType::Wildcard, FileTagType::Include, includedWildcardTags).IsSuccess());
|
||||
|
||||
|
||||
AzFramework::StringFunc::Path::Join(testAssetRoot, AZStd::string::format("%s.%s", ExcludeFile, FileTagAsset::Extension()).c_str(), m_data->m_excludeFile);
|
||||
|
||||
AzFramework::StringFunc::Path::Join(testAssetRoot, AZStd::string::format("%s.%s", IncludeFile, FileTagAsset::Extension()).c_str(), m_data->m_includeFile);
|
||||
@@ -184,7 +184,7 @@ namespace UnitTest
|
||||
TEST_F(FileTagTest, FileTags_QueryByAbsoluteFilePath_Valid)
|
||||
{
|
||||
AZStd::string absoluteDummyFilePath = DummyFile;
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@assets@", absoluteDummyFilePath.c_str(), absoluteDummyFilePath));
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@products@", absoluteDummyFilePath.c_str(), absoluteDummyFilePath));
|
||||
|
||||
AZStd::set<AZStd::string> tags = m_data->m_excludeFileQueryManager->GetTags(absoluteDummyFilePath);
|
||||
|
||||
@@ -196,7 +196,7 @@ namespace UnitTest
|
||||
ASSERT_EQ(tags.size(), 0);
|
||||
|
||||
AZStd::string absoluteAnotherDummyFilePath = AnotherDummyFile;
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@assets@", absoluteAnotherDummyFilePath.c_str(), absoluteAnotherDummyFilePath));
|
||||
EXPECT_TRUE(AzFramework::StringFunc::AssetDatabasePath::Join("@products@", absoluteAnotherDummyFilePath.c_str(), absoluteAnotherDummyFilePath));
|
||||
|
||||
tags = m_data->m_includeFileQueryManager->GetTags(absoluteAnotherDummyFilePath);
|
||||
ASSERT_EQ(tags.size(), 2);
|
||||
@@ -213,7 +213,7 @@ namespace UnitTest
|
||||
|
||||
// Set the customized alias
|
||||
AZStd::string customizedAliasFilePath;
|
||||
const char* assetsAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@assets@");
|
||||
const char* assetsAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@products@");
|
||||
AzFramework::StringFunc::AssetDatabasePath::Join(assetsAlias, "foo", customizedAliasFilePath);
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@customizedalias@", customizedAliasFilePath.c_str());
|
||||
|
||||
@@ -305,7 +305,7 @@ namespace UnitTest
|
||||
|
||||
m_data->m_excludeFileQueryManager->ClearData();
|
||||
EXPECT_TRUE(m_data->m_excludeFileQueryManager->Load(m_data->m_excludeFile));
|
||||
|
||||
|
||||
AZStd::set<AZStd::string> outputTags = m_data->m_excludeFileQueryManager->GetTags(MatchingWildcardFile);
|
||||
|
||||
EXPECT_EQ(outputTags.size(), 2);
|
||||
|
||||
@@ -6,81 +6,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/ObjectStream.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzTest/Utils.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
class FileIOBaseRAII
|
||||
{
|
||||
public:
|
||||
FileIOBaseRAII(AZ::IO::FileIOBase& fileIO)
|
||||
: m_prevFileIO(AZ::IO::FileIOBase::GetInstance())
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(&fileIO);
|
||||
}
|
||||
|
||||
~FileIOBaseRAII()
|
||||
{
|
||||
AZ::IO::FileIOBase::SetInstance(m_prevFileIO);
|
||||
}
|
||||
private:
|
||||
AZ::IO::FileIOBase* m_prevFileIO;
|
||||
};
|
||||
|
||||
class GenAppDescriptors
|
||||
: public AllocatorsTestFixture
|
||||
{
|
||||
public:
|
||||
|
||||
void run()
|
||||
{
|
||||
struct Config
|
||||
{
|
||||
const char* platformName;
|
||||
const char* configName;
|
||||
const char* libSuffix;
|
||||
};
|
||||
|
||||
ComponentApplication app;
|
||||
|
||||
SerializeContext serializeContext;
|
||||
AZ::ComponentApplication::Descriptor::Reflect(&serializeContext, &app);
|
||||
AZ::Entity::Reflect(&serializeContext);
|
||||
DynamicModuleDescriptor::Reflect(&serializeContext);
|
||||
|
||||
AZ::Entity dummySystemEntity(AZ::SystemEntityId, "SystemEntity");
|
||||
|
||||
const Config config = {"Platform", "Config", "libSuffix"};
|
||||
|
||||
AZ::ComponentApplication::Descriptor descriptor;
|
||||
|
||||
if (config.libSuffix && config.libSuffix[0])
|
||||
{
|
||||
FakePopulateModules(descriptor, config.libSuffix);
|
||||
}
|
||||
|
||||
const AZStd::string filename = AZStd::string::format("LYConfig_%s%s.xml", config.platformName, config.configName);
|
||||
|
||||
IO::FileIOStream stream(filename.c_str(), IO::OpenMode::ModeWrite);
|
||||
ObjectStream* objStream = ObjectStream::Create(&stream, serializeContext, ObjectStream::ST_XML);
|
||||
bool descWriteOk = objStream->WriteClass(&descriptor);
|
||||
(void)descWriteOk;
|
||||
AZ_Warning("ComponentApplication", descWriteOk, "Failed to write memory descriptor to application descriptor file %s!", filename.c_str());
|
||||
bool entityWriteOk = objStream->WriteClass(&dummySystemEntity);
|
||||
(void)entityWriteOk;
|
||||
AZ_Warning("ComponentApplication", entityWriteOk, "Failed to write system entity to application descriptor file %s!", filename.c_str());
|
||||
bool flushOk = objStream->Finalize();
|
||||
(void)flushOk;
|
||||
AZ_Warning("ComponentApplication", flushOk, "Failed finalizing application descriptor file %s!", filename.c_str());
|
||||
|
||||
}
|
||||
|
||||
void FakePopulateModules(AZ::ComponentApplication::Descriptor& desc, const char* libSuffix)
|
||||
{
|
||||
static const char* modules[] =
|
||||
@@ -100,10 +38,44 @@ namespace UnitTest
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(GenAppDescriptors, Test)
|
||||
TEST_F(GenAppDescriptors, WriteDescriptor_ToXML_Succeeds)
|
||||
{
|
||||
AZ::IO::LocalFileIO fileIO;
|
||||
FileIOBaseRAII restoreFileIOScope(fileIO);
|
||||
run();
|
||||
struct Config
|
||||
{
|
||||
const char* platformName;
|
||||
const char* configName;
|
||||
const char* libSuffix;
|
||||
};
|
||||
|
||||
AzFramework::Application app;
|
||||
|
||||
AZ::SerializeContext serializeContext;
|
||||
AZ::ComponentApplication::Descriptor::Reflect(&serializeContext, &app);
|
||||
AZ::Entity::Reflect(&serializeContext);
|
||||
AZ::DynamicModuleDescriptor::Reflect(&serializeContext);
|
||||
|
||||
AZ::Entity dummySystemEntity(AZ::SystemEntityId, "SystemEntity");
|
||||
|
||||
const Config config = {"Platform", "Config", "libSuffix"};
|
||||
|
||||
AZ::ComponentApplication::Descriptor descriptor;
|
||||
|
||||
if (config.libSuffix && config.libSuffix[0])
|
||||
{
|
||||
FakePopulateModules(descriptor, config.libSuffix);
|
||||
}
|
||||
|
||||
AZ::Test::ScopedAutoTempDirectory tempDirectory;
|
||||
const auto filename = AZ::IO::Path(tempDirectory.GetDirectory()) /
|
||||
AZStd::string::format("LYConfig_%s%s.xml", config.platformName, config.configName);
|
||||
|
||||
AZ::IO::FileIOStream stream(filename.c_str(), AZ::IO::OpenMode::ModeWrite);
|
||||
auto objStream = AZ::ObjectStream::Create(&stream, serializeContext, AZ::ObjectStream::ST_XML);
|
||||
const bool descWriteOk = objStream->WriteClass(&descriptor);
|
||||
EXPECT_TRUE(descWriteOk) << "Failed to write memory descriptor to application descriptor file " << filename.c_str() << "!";
|
||||
const bool entityWriteOk = objStream->WriteClass(&dummySystemEntity);
|
||||
EXPECT_TRUE(entityWriteOk) << "Failed to write system entity to application descriptor file " << filename.c_str() << "!";
|
||||
const bool flushOk = objStream->Finalize();
|
||||
EXPECT_TRUE(flushOk) << "Failed finalizing application descriptor file " << filename.c_str() << "!";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +38,12 @@ namespace AzGameFramework
|
||||
{
|
||||
// fall back to checking Project Cache Root.
|
||||
enginePakPath /= "engine.pak";
|
||||
enginePakOpened = m_archive->OpenPack("@projectproductassets@", enginePakPath.Native());
|
||||
enginePakOpened = m_archive->OpenPack("@products@", enginePakPath.Native());
|
||||
}
|
||||
if (!enginePakOpened)
|
||||
{
|
||||
enginePakPath = AZ::IO::FixedMaxPath(AZ::Utils::GetExecutableDirectory()) / "engine.pak";
|
||||
m_archive->OpenPack("@projectproductassets@", enginePakPath.Native());
|
||||
m_archive->OpenPack("@products@", enginePakPath.Native());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace AzNetworking
|
||||
if (AZ::IO::FileIOBase::GetInstance() != nullptr)
|
||||
{
|
||||
char buffer[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@assets@/", buffer, sizeof(buffer));
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@products@/", buffer, sizeof(buffer));
|
||||
assetDir = AZStd::string(buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,14 +47,6 @@ namespace AzToolsFramework
|
||||
|
||||
//! Retrieve the absolute path for the Asset Database Location
|
||||
virtual bool GetAbsoluteAssetDatabaseLocation(AZStd::string& /*result*/) { return false; }
|
||||
|
||||
//! Retrieve the absolute folder path to the current game's source assets (the ones that go into source control)
|
||||
//! This may include the current mod path, if a mod is being edited by the editor
|
||||
virtual const char* GetAbsoluteDevGameFolderPath() = 0;
|
||||
|
||||
//! Retrieve the absolute folder path to the current developer root ('dev'), which contains source artifacts
|
||||
//! and is generally checked into source control.
|
||||
virtual const char* GetAbsoluteDevRootFolderPath() = 0;
|
||||
|
||||
/// Convert a full source path like "c:\\dev\\gamename\\blah\\test.tga" into a relative product path.
|
||||
/// asset paths never mention their alias and are relative to the asset cache root
|
||||
|
||||
@@ -354,26 +354,6 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
const char* AssetSystemComponent::GetAbsoluteDevGameFolderPath()
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (fileIO)
|
||||
{
|
||||
return fileIO->GetAlias("@devassets@");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* AssetSystemComponent::GetAbsoluteDevRootFolderPath()
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
if (fileIO)
|
||||
{
|
||||
return fileIO->GetAlias("@devroot@");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void AssetSystemComponent::OnSystemTick()
|
||||
{
|
||||
AssetSystemBus::ExecuteQueuedEvents();
|
||||
|
||||
@@ -56,8 +56,6 @@ namespace AzToolsFramework
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzToolsFramework::AssetSystemRequestBus::Handler overrides
|
||||
bool GetAbsoluteAssetDatabaseLocation(AZStd::string& result) override;
|
||||
const char* GetAbsoluteDevGameFolderPath() override;
|
||||
const char* GetAbsoluteDevRootFolderPath() override;
|
||||
bool GetRelativeProductPathFromFullSourceOrProductPath(const AZStd::string& fullPath, AZStd::string& outputPath) override;
|
||||
bool GenerateRelativeSourcePath(
|
||||
const AZStd::string& sourcePath, AZStd::string& outputPath, AZStd::string& watchFolder) override;
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace AzToolsFramework
|
||||
AssetEditorWidgetUserSettings::AssetEditorWidgetUserSettings()
|
||||
{
|
||||
char assetRoot[AZ_MAX_PATH_LEN] = { 0 };
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@devassets@", assetRoot, AZ_MAX_PATH_LEN);
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath("@projectroot@", assetRoot, AZ_MAX_PATH_LEN);
|
||||
|
||||
m_lastSavePath = assetRoot;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AzToolsFramework
|
||||
// the TraceContextLogFormatter.
|
||||
//
|
||||
// Usage example:
|
||||
// const char* gameFolder = m_context.pRC->GetSystemEnvironment()->pFileIO->GetAlias("@devassets@");
|
||||
// const char* gameFolder = m_context.pRC->GetSystemEnvironment()->pFileIO->GetAlias("@projectroot@");
|
||||
// AZ_TraceContext("Game folder", gameFolder);
|
||||
//
|
||||
// for (int i=0; i<subMeshCount; ++i)
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace AzToolsFramework
|
||||
StringFunc::Path::Join(resolveBuffer, "log", logDirectory);
|
||||
fileIO->SetAlias("@log@", logDirectory.c_str());
|
||||
|
||||
fileIO->CreatePath("@root@");
|
||||
fileIO->CreatePath("@products@");
|
||||
fileIO->CreatePath("@user@");
|
||||
fileIO->CreatePath("@log@");
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
@@ -78,13 +79,9 @@ namespace AzToolsFramework
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(entitiesAndDescendants,
|
||||
&AzToolsFramework::ToolsApplicationRequestBus::Events::GatherEntitiesAndAllDescendents, AzToolsFramework::EntityIdList{ entityId });
|
||||
|
||||
// Retrieve the game folder so we can use that as a root with the passed in relative path
|
||||
const char* gameFolder = nullptr;
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gameFolder, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetAbsoluteDevGameFolderPath);
|
||||
|
||||
// Join our relative path with the game folder to get a full path to the desired asset
|
||||
AZStd::string assetFullPath;
|
||||
AzFramework::StringFunc::Path::Join(gameFolder, assetPath, assetFullPath);
|
||||
AZ::IO::FixedMaxPath assetFullPath = AZ::Utils::GetProjectPath();
|
||||
assetFullPath /= assetPath;
|
||||
|
||||
// Call SliceUtilities::MakeNewSlice with all user input prompts disabled
|
||||
bool success = AzToolsFramework::SliceUtilities::MakeNewSlice(entitiesAndDescendants,
|
||||
|
||||
@@ -718,7 +718,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (!fullPathFound)
|
||||
{
|
||||
assetFullPath = AZStd::string::format("@devassets@/%s", sliceAssetPath.c_str());
|
||||
assetFullPath = AZStd::string::format("@projectroot@/%s", sliceAssetPath.c_str());
|
||||
}
|
||||
|
||||
return Commit(assetFullPath.c_str(), preSaveCallback, postSaveCallback, sliceCommitFlags);
|
||||
@@ -1020,13 +1020,13 @@ namespace AzToolsFramework
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(fileIO, "File IO is not initialized.");
|
||||
|
||||
AZStd::string devAssetPath = fileIO->GetAlias("@devassets@");
|
||||
AZStd::string devAssetPath = fileIO->GetAlias("@projectroot@");
|
||||
AZStd::string userPath = fileIO->GetAlias("@user@");
|
||||
AZStd::string tempPath = fullPath;
|
||||
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, devAssetPath);
|
||||
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, userPath);
|
||||
EBUS_EVENT(AzFramework::ApplicationRequests::Bus, NormalizePath, tempPath);
|
||||
AzFramework::StringFunc::Replace(tempPath, "@devassets@", devAssetPath.c_str());
|
||||
AzFramework::StringFunc::Replace(tempPath, "@projectroot@", devAssetPath.c_str());
|
||||
AzFramework::StringFunc::Replace(tempPath, devAssetPath.c_str(), userPath.c_str());
|
||||
tempPath.append(".slicetemp");
|
||||
|
||||
|
||||
+2
-2
@@ -378,11 +378,11 @@ namespace AzToolsFramework
|
||||
// If this layer is being loaded, it won't have a level save dependency yet, so clear that flag.
|
||||
m_mustSaveLevelWhenLayerSaves = false;
|
||||
QString fullPathName = levelPakFile;
|
||||
if (fullPathName.contains("@devassets@"))
|
||||
if (fullPathName.contains("@projectroot@"))
|
||||
{
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
// Resolving the path through resolvepath would normalize and lowcase it, and in this case, we don't want that.
|
||||
fullPathName.replace("@devassets@", fileIO->GetAlias("@devassets@"));
|
||||
fullPathName.replace("@projectroot@", fileIO->GetAlias("@projectroot@"));
|
||||
}
|
||||
|
||||
QFileInfo fileNameInfo(fullPathName);
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ namespace AzToolsFramework
|
||||
// temporarily null after QFileDialogs close, which we need in order to
|
||||
// be able to parent our message dialogs properly
|
||||
QWidget* activeWindow = QApplication::activeWindow();
|
||||
const AZStd::string prefabFilesPath = "@devassets@/Prefabs";
|
||||
const AZStd::string prefabFilesPath = "@projectroot@/Prefabs";
|
||||
|
||||
// Remove Level entity if it's part of the list
|
||||
|
||||
|
||||
@@ -131,13 +131,13 @@ namespace UnitTest
|
||||
m_app.reset(aznew ToolsTestApplication("ArchiveComponentTest"));
|
||||
m_app->Start(AzFramework::Application::Descriptor());
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
if (auto fileIoBase = AZ::IO::FileIOBase::GetInstance(); fileIoBase != nullptr)
|
||||
{
|
||||
fileIoBase->SetAlias("@assets@", m_tempDir.GetDirectory());
|
||||
fileIoBase->SetAlias("@products@", m_tempDir.GetDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ namespace // anonymous
|
||||
|
||||
bool Search(const AzToolsFramework::AssetFileInfoList& assetList, const AZ::Data::AssetId& assetId)
|
||||
{
|
||||
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
|
||||
[&](AzToolsFramework::AssetFileInfo fileInfo)
|
||||
{
|
||||
return fileInfo.m_assetId == assetId;
|
||||
return AZStd::find_if(assetList.m_fileInfoList.begin(), assetList.m_fileInfoList.end(),
|
||||
[&](AzToolsFramework::AssetFileInfo fileInfo)
|
||||
{
|
||||
return fileInfo.m_assetId == assetId;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -74,11 +74,11 @@ namespace UnitTest
|
||||
|
||||
m_application->Start(AzFramework::Application::Descriptor());
|
||||
|
||||
// By default @assets@ is setup to include the platform at the end. But this test is going to
|
||||
// By default @products@ is setup to include the platform at the end. But this test is going to
|
||||
// loop over platforms and it will be included as part of the relative path of the file.
|
||||
// So the asset folder for these tests have to point to the cache project root folder, which
|
||||
// doesn't include the platform.
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
|
||||
|
||||
for (int idx = 0; idx < s_totalAssets; idx++)
|
||||
{
|
||||
@@ -158,17 +158,17 @@ namespace UnitTest
|
||||
m_assetRegistry->RegisterAssetDependency(assets[5], AZ::Data::ProductDependency(assets[6], 0));
|
||||
m_assetRegistry->RegisterAssetDependency(assets[6], AZ::Data::ProductDependency(assets[7], 0));
|
||||
|
||||
// asset8 -> asset6
|
||||
// asset8 -> asset6
|
||||
m_assetRegistry->RegisterAssetDependency(assets[8], AZ::Data::ProductDependency(assets[6], 0));
|
||||
|
||||
// asset10 -> asset11
|
||||
// asset10 -> asset11
|
||||
m_assetRegistry->RegisterAssetDependency(assets[10], AZ::Data::ProductDependency(assets[11], 0));
|
||||
|
||||
// asset11 -> asset10
|
||||
// asset11 -> asset10
|
||||
m_assetRegistry->RegisterAssetDependency(assets[11], AZ::Data::ProductDependency(assets[10], 0));
|
||||
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
@@ -203,10 +203,6 @@ namespace UnitTest
|
||||
|
||||
const AZStd::string engroot = AZ::Test::GetEngineRootPath();
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@engroot@", engroot.c_str());
|
||||
|
||||
AZ::IO::Path assetRoot(AZ::Utils::GetProjectPath());
|
||||
assetRoot /= "Cache";
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@root@", assetRoot.c_str());
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
@@ -219,7 +215,7 @@ namespace UnitTest
|
||||
delete m_application;
|
||||
}
|
||||
|
||||
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
|
||||
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
|
||||
{
|
||||
auto foundIter = m_assetRegistry->m_assetIdToInfo.find(id);
|
||||
if (foundIter != m_assetRegistry->m_assetIdToInfo.end())
|
||||
@@ -540,7 +536,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(Search(assetList, assets[7]));
|
||||
EXPECT_TRUE(Search(assetList, assets[8]));
|
||||
|
||||
// Removing the android flag from the asset should still produce the same result
|
||||
// Removing the android flag from the asset should still produce the same result
|
||||
m_assetSeedManager->RemoveSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
|
||||
|
||||
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::PC);
|
||||
@@ -564,7 +560,7 @@ namespace UnitTest
|
||||
EXPECT_TRUE(Search(assetList, assets[3]));
|
||||
EXPECT_TRUE(Search(assetList, assets[4]));
|
||||
|
||||
// Adding the android flag again to the asset
|
||||
// Adding the android flag again to the asset
|
||||
m_assetSeedManager->AddSeedAsset(assets[8], AzFramework::PlatformFlags::Platform_ANDROID);
|
||||
assetList = m_assetSeedManager->GetDependencyList(AzFramework::PlatformId::ANDROID_ID);
|
||||
|
||||
@@ -624,7 +620,7 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(assetList1.m_fileInfoList[0].m_assetId, assetList2.m_fileInfoList[0].m_assetId);
|
||||
EXPECT_GE(assetList2.m_fileInfoList[0].m_modificationTime, assetList1.m_fileInfoList[0].m_modificationTime); // file mod time should change
|
||||
|
||||
|
||||
// file hash should not change
|
||||
for (int idx = 0; idx < 5; idx++)
|
||||
{
|
||||
@@ -680,7 +676,7 @@ namespace UnitTest
|
||||
m_assetSeedManager->AddSeedAsset(assets[validFileIndex], AzFramework::PlatformFlags::Platform_PC, m_assetsPath[invalidFileIndex]);
|
||||
|
||||
const AzFramework::AssetSeedList& oldSeedList = m_assetSeedManager->GetAssetSeedList();
|
||||
|
||||
|
||||
for (const auto& seedInfo : oldSeedList)
|
||||
{
|
||||
if (seedInfo.m_assetId == assets[validFileIndex])
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace UnitTests
|
||||
{
|
||||
public:
|
||||
MOCK_METHOD1(GetAbsoluteAssetDatabaseLocation, bool(AZStd::string&));
|
||||
MOCK_METHOD0(GetAbsoluteDevGameFolderPath, const char* ());
|
||||
MOCK_METHOD0(GetAbsoluteDevRootFolderPath, const char* ());
|
||||
MOCK_METHOD2(GetRelativeProductPathFromFullSourceOrProductPath, bool(const AZStd::string& fullPath, AZStd::string& relativeProductPath));
|
||||
MOCK_METHOD3(GenerateRelativeSourcePath,
|
||||
bool(const AZStd::string& sourcePath, AZStd::string& relativePath, AZStd::string& watchFolder));
|
||||
|
||||
@@ -181,8 +181,8 @@ namespace UnitTest
|
||||
|
||||
const char* dir = m_componentApplication->GetExecutableFolder();
|
||||
|
||||
m_localFileIO.SetAlias("@assets@", dir);
|
||||
m_localFileIO.SetAlias("@devassets@", dir);
|
||||
m_localFileIO.SetAlias("@products@", dir);
|
||||
m_localFileIO.SetAlias("@projectroot@", dir);
|
||||
}
|
||||
|
||||
void Destroy()
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
#include <Utils/Utils.h>
|
||||
|
||||
namespace
|
||||
namespace
|
||||
{
|
||||
static const int s_totalAssets = 12;
|
||||
}
|
||||
@@ -53,15 +53,15 @@ namespace UnitTest
|
||||
|
||||
m_application->Start(AzFramework::Application::Descriptor());
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
|
||||
// By default @assets@ is setup to include the platform at the end. But this test is going to
|
||||
// By default @products@ is setup to include the platform at the end. But this test is going to
|
||||
// loop over all platforms and it will be included as part of the relative path of the file.
|
||||
// So the asset folder for these tests have to point to the cache project root folder, which
|
||||
// doesn't include the platform.
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@assets@", cacheProjectRootFolder.c_str());
|
||||
AZ::IO::FileIOBase::GetInstance()->SetAlias("@products@", cacheProjectRootFolder.c_str());
|
||||
|
||||
for (int platformNum = AzFramework::PlatformId::PC; platformNum < AzFramework::PlatformId::NumPlatformIds; ++platformNum)
|
||||
{
|
||||
|
||||
-2
@@ -142,8 +142,6 @@ namespace UnitTest
|
||||
/*
|
||||
* AssetSystemRequestBus
|
||||
*/
|
||||
const char* GetAbsoluteDevGameFolderPath() override { return ""; }
|
||||
const char* GetAbsoluteDevRootFolderPath() override { return ""; }
|
||||
bool GetRelativeProductPathFromFullSourceOrProductPath([[maybe_unused]] const AZStd::string& fullPath, [[maybe_unused]] AZStd::string& relativeProductPath) override { return false; }
|
||||
bool GenerateRelativeSourcePath(
|
||||
[[maybe_unused]] const AZStd::string& sourcePath, [[maybe_unused]] AZStd::string& relativePath,
|
||||
|
||||
Reference in New Issue
Block a user