Files
UnrealEngineUWP/Engine/Source/Developer/SourceControl/Private/SourceControlOperations.cpp
paul chipchase 14b6c6fc6a Allow the caller to decide if FUpdateStatus will check for directy paths based on the path itself (terminating in a seperator) or if the file system should be used instead.
#rb Patrick.Laflamme
#jira UE-145721
#rnx
#preflight 622f0358752729a2ad448e16

- The problem we have is if a p4 depot path is used when requesting filestates (to see if the file exists in p4 for example) it will be treated as a networkpath due to it starting with // so calling the filesystem to check if it is a directory or not can get very expensive.
- Other operations just check the end of the path for '/' or '\' which is what this operation used to do, but that was changed at some point to check the file system, presumably to fix another problem and as we don't really know how 3rd party code is using this system we cannot just change the behavior without risking breaking existing code bases.
- This fix allows the caller to opt in to the old behavior of just checking the end of the path to determine if it is a directory or not.
- This fix is not very good, future work for a better fix will be tracked in the attached jira.

[CL 19371141 by paul chipchase in ue5-main branch]
2022-03-14 05:25:55 -04:00

73 lines
2.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SourceControlOperations.h"
#include "Containers/StringView.h"
#include "HAL/FileManager.h"
#include "ISourceControlModule.h"
#include "Misc/PathViews.h"
#include "Misc/Paths.h"
bool FUpdateStatus::IsDirectoryPath(const FString& Path) const
{
// Problem:
// We need to be able to work out if a path if a directory or not as some source
// control implementations will need to append wildcards to the path if it is
// a directory in order for it to function correctly.
//
// Strictly speaking the only way we can tell the difference between a file path
// and a directory path is to check with the file system.
// However some source control implementations let us reference files on the server
// and do not require us to have them on the users machine. This means checking with
// the file system does not give an accurate result and can end up being very
// slow if the file system interprets the path as a UNC path and tries to resolve it.
//
// Ideally we would let the caller clearly mark if the path is for a file or a
// directory but this would require a large overhaul of the source control API.
// We cannot change the existing behavior as it is very likely that 3rd party code is
// relying on it.
//
// Solution:
// As a 'temporary' solution, the caller can set bSetRequireDirPathEndWithSeparator
// to true. When it is true we will assume that all directory paths end with a
// separator. Although we tend to not terminate directory paths with a separator in the
// engine, this will allow us an opt in to the new behavior until more substantial API
// changes can be made.
if (bSetRequireDirPathEndWithSeparator)
{
return Path.EndsWith(TEXT("/")) || Path.EndsWith(TEXT("\\"));
}
else
{
return IFileManager::Get().DirectoryExists(*Path);
}
}
FDownloadFile::FDownloadFile(FStringView InTargetDirectory, EVerbosity InVerbosity)
: Verbosity(InVerbosity)
, TargetDirectory(InTargetDirectory)
{
FPaths::NormalizeDirectoryName(TargetDirectory);
// Due to the asynchronous nature of the source control api, it might be some time before
// the TargetDirectory is actually used. So we do a validation pass on it now to try and
// give errors close to the point that they were created. The caller is still free to try
// and use the FDownloadFile but with an invalid path it probably won't work.
FText Reason;
if (!FPaths::ValidatePath(TargetDirectory, &Reason))
{
UE_LOG(LogSourceControl, Error, TEXT("Path '%s' passed to FDownloadFile is invalid due to: %s"),
*TargetDirectory, *Reason.ToString());
}
}
FCreateWorkspace::FCreateWorkspace(FStringView InWorkspaceName, FStringView InWorkspaceRoot)
: WorkspaceName(InWorkspaceName)
{
TStringBuilder<512> AbsoluteWorkspaceName;
FPathViews::ToAbsolutePath(InWorkspaceRoot, AbsoluteWorkspaceName);
WorkspaceRoot = AbsoluteWorkspaceName.ToString();
}