2019-12-27 07:44:07 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-10-01 20:41:42 -04:00
# include "PlasticSourceControlProvider.h"
2022-05-16 14:38:52 -04:00
2019-10-01 20:41:42 -04:00
# include "PlasticSourceControlCommand.h"
# include "PlasticSourceControlModule.h"
# include "PlasticSourceControlOperations.h"
2022-05-16 14:38:52 -04:00
# include "PlasticSourceControlSettings.h"
# include "PlasticSourceControlState.h"
2019-10-01 20:41:42 -04:00
# include "PlasticSourceControlUtils.h"
# include "SPlasticSourceControlSettings.h"
2022-05-16 14:38:52 -04:00
# include "ISourceControlModule.h"
2019-10-01 20:41:42 -04:00
# include "Logging/MessageLog.h"
# include "ScopedSourceControlProgress.h"
# include "SourceControlHelpers.h"
# include "SourceControlOperations.h"
# include "Interfaces/IPluginManager.h"
# include "Misc/Paths.h"
# include "HAL/PlatformProcess.h"
# include "Misc/QueuedThreadPool.h"
# define LOCTEXT_NAMESPACE "PlasticSourceControl"
static FName ProviderName ( " Plastic SCM " ) ;
void FPlasticSourceControlProvider : : Init ( bool bForceConnection )
{
// Init() is called multiple times at startup: do not check Plastic SCM each time
2022-05-16 14:38:52 -04:00
if ( ! bPlasticAvailable )
2019-10-01 20:41:42 -04:00
{
const TSharedPtr < IPlugin > Plugin = IPluginManager : : Get ( ) . FindPlugin ( TEXT ( " PlasticSourceControl " ) ) ;
2022-05-16 14:38:52 -04:00
if ( Plugin . IsValid ( ) )
2019-10-01 20:41:42 -04:00
{
2022-05-16 14:38:52 -04:00
PluginVersion = Plugin - > GetDescriptor ( ) . VersionName ;
UE_LOG ( LogSourceControl , Log , TEXT ( " Plastic SCM plugin '%s' " ) , * PluginVersion ) ;
2019-10-01 20:41:42 -04:00
}
CheckPlasticAvailability ( ) ;
2022-05-16 14:38:52 -04:00
// Override the source control logs verbosity level if needed based on settings
FPlasticSourceControlModule & PlasticSourceControl = FModuleManager : : LoadModuleChecked < FPlasticSourceControlModule > ( " PlasticSourceControl " ) ;
if ( PlasticSourceControl . AccessSettings ( ) . GetEnableVerboseLogs ( ) )
{
PlasticSourceControlUtils : : SwitchVerboseLogs ( true ) ;
}
2019-10-01 20:41:42 -04:00
}
2022-06-01 11:26:54 -04:00
if ( bForceConnection & & ! bServerAvailable )
{
// Execute a 'checkconnection' command to set bServerAvailable based on the connectivity of the server
TArray < FString > InfoMessages , ErrorMessages ;
const bool bCommandSuccessful = PlasticSourceControlUtils : : RunCommand ( TEXT ( " checkconnection " ) , TArray < FString > ( ) , TArray < FString > ( ) , EConcurrency : : Synchronous , InfoMessages , ErrorMessages ) ;
bServerAvailable = bCommandSuccessful ;
if ( ! bCommandSuccessful )
{
FMessageLog SourceControlLog ( " SourceControl " ) ;
for ( const FString & ErrorMessage : ErrorMessages )
{
SourceControlLog . Error ( FText : : FromString ( ErrorMessage ) ) ;
}
}
}
2019-10-01 20:41:42 -04:00
}
void FPlasticSourceControlProvider : : CheckPlasticAvailability ( )
{
FPlasticSourceControlModule & PlasticSourceControl = FModuleManager : : LoadModuleChecked < FPlasticSourceControlModule > ( " PlasticSourceControl " ) ;
FString PathToPlasticBinary = PlasticSourceControl . AccessSettings ( ) . GetBinaryPath ( ) ;
2022-05-16 14:38:52 -04:00
if ( PathToPlasticBinary . IsEmpty ( ) )
2019-10-01 20:41:42 -04:00
{
2022-06-01 11:26:54 -04:00
bPlasticAvailable = false ;
2019-10-01 20:41:42 -04:00
// Try to find Plastic binary, and update settings accordingly
PathToPlasticBinary = PlasticSourceControlUtils : : FindPlasticBinaryPath ( ) ;
2022-05-16 14:38:52 -04:00
if ( ! PathToPlasticBinary . IsEmpty ( ) )
2019-10-01 20:41:42 -04:00
{
PlasticSourceControl . AccessSettings ( ) . SetBinaryPath ( PathToPlasticBinary ) ;
}
}
2022-05-16 14:38:52 -04:00
if ( ! PathToPlasticBinary . IsEmpty ( ) )
2019-10-01 20:41:42 -04:00
{
// Find the path to the root Plastic directory (if any, else uses the ProjectDir)
const FString PathToProjectDir = FPaths : : ConvertRelativePathToFull ( FPaths : : ProjectDir ( ) ) ;
bWorkspaceFound = PlasticSourceControlUtils : : FindRootDirectory ( PathToProjectDir , PathToWorkspaceRoot ) ;
// Launch the Plastic SCM cli shell on the background to issue all commands during this session
bPlasticAvailable = PlasticSourceControlUtils : : LaunchBackgroundPlasticShell ( PathToPlasticBinary , PathToWorkspaceRoot ) ;
2022-05-16 14:38:52 -04:00
if ( bPlasticAvailable )
2019-10-01 20:41:42 -04:00
{
PlasticSourceControlUtils : : GetPlasticScmVersion ( PlasticScmVersion ) ;
// Get user name (from the global Plastic SCM client config)
PlasticSourceControlUtils : : GetUserName ( UserName ) ;
2022-05-16 14:38:52 -04:00
// Register Console Commands
PlasticSourceControlConsole . Register ( ) ;
if ( ! bWorkspaceFound )
2019-10-01 20:41:42 -04:00
{
UE_LOG ( LogSourceControl , Warning , TEXT ( " '%s' is not part of a Plastic workspace " ) , * FPaths : : ProjectDir ( ) ) ;
}
}
}
}
void FPlasticSourceControlProvider : : Close ( )
{
// clear the cache
StateCache . Empty ( ) ;
// terminate the background 'cm shell' process and associated pipes
PlasticSourceControlUtils : : Terminate ( ) ;
// Remove all extensions to the "Source Control" menu in the Editor Toolbar
PlasticSourceControlMenu . Unregister ( ) ;
2022-05-16 14:38:52 -04:00
// Unregister Console Commands
PlasticSourceControlConsole . Unregister ( ) ;
2019-10-01 20:41:42 -04:00
bServerAvailable = false ;
bPlasticAvailable = false ;
bWorkspaceFound = false ;
UserName . Empty ( ) ;
}
2022-05-16 14:38:52 -04:00
TSharedRef < FPlasticSourceControlState , ESPMode : : ThreadSafe > FPlasticSourceControlProvider : : GetStateInternal ( const FString & InFilename ) const
2019-10-01 20:41:42 -04:00
{
2022-05-16 14:38:52 -04:00
TSharedRef < FPlasticSourceControlState , ESPMode : : ThreadSafe > * State = StateCache . Find ( InFilename ) ;
if ( State ! = NULL )
2019-10-01 20:41:42 -04:00
{
// found cached item
return ( * State ) ;
}
else
{
// cache an unknown state for this item
2022-05-16 14:38:52 -04:00
TSharedRef < FPlasticSourceControlState , ESPMode : : ThreadSafe > NewState = MakeShareable ( new FPlasticSourceControlState ( FString ( InFilename ) ) ) ;
StateCache . Add ( InFilename , NewState ) ;
2019-10-01 20:41:42 -04:00
return NewState ;
}
}
FText FPlasticSourceControlProvider : : GetStatusText ( ) const
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " PlasticScmVersion " ) , FText : : FromString ( PlasticScmVersion ) ) ;
2022-05-16 14:38:52 -04:00
Args . Add ( TEXT ( " PluginVersion " ) , FText : : FromString ( PluginVersion ) ) ;
2019-10-01 20:41:42 -04:00
Args . Add ( TEXT ( " WorkspacePath " ) , FText : : FromString ( PathToWorkspaceRoot ) ) ;
Args . Add ( TEXT ( " WorkspaceName " ) , FText : : FromString ( WorkspaceName ) ) ;
Args . Add ( TEXT ( " BranchName " ) , FText : : FromString ( BranchName ) ) ;
// Detect special case for a partial checkout (CS:-1 in Gluon mode)!
if ( - 1 ! = ChangesetNumber )
{
Args . Add ( TEXT ( " ChangesetNumber " ) , FText : : FromString ( FString : : Printf ( TEXT ( " %d (standard mode) " ) , ChangesetNumber ) ) ) ;
}
else
{
Args . Add ( TEXT ( " ChangesetNumber " ) , FText : : FromString ( FString : : Printf ( TEXT ( " N/A (Gluon/partial mode) " ) ) ) ) ;
}
Args . Add ( TEXT ( " UserName " ) , FText : : FromString ( UserName ) ) ;
2022-05-16 14:38:52 -04:00
return FText : : Format ( NSLOCTEXT ( " Status " , " Provider: Plastic \n EnabledLabel " , " Plastic SCM {PlasticScmVersion} (plugin v{PluginVersion}) \n Workspace: {WorkspaceName} ({WorkspacePath}) \n {BranchName} \n Changeset: {ChangesetNumber} \n User: {UserName} " ) , Args ) ;
2019-10-01 20:41:42 -04:00
}
2022-06-01 11:26:54 -04:00
/** Quick check if source control is enabled. Specifically, it returns true if a source control provider is set (regardless of whether the provider is available) and false if no provider is set. So all providers except the stub DefaultSourceProvider will return true. */
2019-10-01 20:41:42 -04:00
bool FPlasticSourceControlProvider : : IsEnabled ( ) const
{
2022-06-01 11:26:54 -04:00
return true ;
2019-10-01 20:41:42 -04:00
}
2022-06-01 11:26:54 -04:00
/** Quick check if source control is available for use (return whether the server is available or not) */
2019-10-01 20:41:42 -04:00
bool FPlasticSourceControlProvider : : IsAvailable ( ) const
{
return bServerAvailable ;
}
const FName & FPlasticSourceControlProvider : : GetName ( void ) const
{
return ProviderName ;
}
ECommandResult : : Type FPlasticSourceControlProvider : : GetState ( const TArray < FString > & InFiles , TArray < TSharedRef < ISourceControlState , ESPMode : : ThreadSafe > > & OutState , EStateCacheUsage : : Type InStateCacheUsage )
{
2022-05-16 14:38:52 -04:00
if ( ! IsEnabled ( ) )
2019-10-01 20:41:42 -04:00
{
return ECommandResult : : Failed ;
}
2022-05-16 14:38:52 -04:00
const TArray < FString > AbsoluteFiles = SourceControlHelpers : : AbsoluteFilenames ( InFiles ) ;
2019-10-01 20:41:42 -04:00
2022-05-16 14:38:52 -04:00
if ( InStateCacheUsage = = EStateCacheUsage : : ForceUpdate )
2019-10-01 20:41:42 -04:00
{
UE_LOG ( LogSourceControl , Log , TEXT ( " GetState: ForceUpdate " ) ) ;
Execute ( ISourceControlOperation : : Create < FUpdateStatus > ( ) , AbsoluteFiles ) ;
}
2022-05-16 14:38:52 -04:00
for ( const FString & AbsoluteFile : AbsoluteFiles )
2019-10-01 20:41:42 -04:00
{
2022-05-16 14:38:52 -04:00
OutState . Add ( GetStateInternal ( AbsoluteFile ) ) ;
2019-10-01 20:41:42 -04:00
}
return ECommandResult : : Succeeded ;
}
2021-01-11 14:32:27 -04:00
ECommandResult : : Type FPlasticSourceControlProvider : : GetState ( const TArray < FSourceControlChangelistRef > & InChangelists , TArray < FSourceControlChangelistStateRef > & OutState , EStateCacheUsage : : Type InStateCacheUsage )
{
return ECommandResult : : Failed ;
}
2019-10-01 20:41:42 -04:00
TArray < FSourceControlStateRef > FPlasticSourceControlProvider : : GetCachedStateByPredicate ( TFunctionRef < bool ( const FSourceControlStateRef & ) > Predicate ) const
{
TArray < FSourceControlStateRef > Result ;
2022-05-16 14:38:52 -04:00
for ( const auto & CacheItem : StateCache )
2019-10-01 20:41:42 -04:00
{
FSourceControlStateRef State = CacheItem . Value ;
2022-05-16 14:38:52 -04:00
if ( Predicate ( State ) )
2019-10-01 20:41:42 -04:00
{
Result . Add ( State ) ;
}
}
return Result ;
}
bool FPlasticSourceControlProvider : : RemoveFileFromCache ( const FString & Filename )
{
return StateCache . Remove ( Filename ) > 0 ;
}
FDelegateHandle FPlasticSourceControlProvider : : RegisterSourceControlStateChanged_Handle ( const FSourceControlStateChanged : : FDelegate & SourceControlStateChanged )
{
return OnSourceControlStateChanged . Add ( SourceControlStateChanged ) ;
}
void FPlasticSourceControlProvider : : UnregisterSourceControlStateChanged_Handle ( FDelegateHandle Handle )
{
OnSourceControlStateChanged . Remove ( Handle ) ;
}
2021-01-18 09:42:33 -04:00
ECommandResult : : Type FPlasticSourceControlProvider : : Execute ( const FSourceControlOperationRef & InOperation , FSourceControlChangelistPtr InChangelist , const TArray < FString > & InFiles , EConcurrency : : Type InConcurrency , const FSourceControlOperationComplete & InOperationCompleteDelegate )
2019-10-01 20:41:42 -04:00
{
2022-05-16 14:38:52 -04:00
if ( ! bWorkspaceFound & & ! ( InOperation - > GetName ( ) = = " Connect " ) & & ! ( InOperation - > GetName ( ) = = " MakeWorkspace " ) )
2019-10-01 20:41:42 -04:00
{
UE_LOG ( LogSourceControl , Warning , TEXT ( " '%s': only Connect operation allowed whithout a workspace " ) , * InOperation - > GetName ( ) . ToString ( ) ) ;
return ECommandResult : : Failed ;
}
// Query to see if we allow this operation
TSharedPtr < IPlasticSourceControlWorker , ESPMode : : ThreadSafe > Worker = CreateWorker ( InOperation - > GetName ( ) ) ;
2022-05-16 14:38:52 -04:00
if ( ! Worker . IsValid ( ) )
2019-10-01 20:41:42 -04:00
{
// this operation is unsupported by this source control provider
FFormatNamedArguments Arguments ;
Arguments . Add ( TEXT ( " OperationName " ) , FText : : FromName ( InOperation - > GetName ( ) ) ) ;
Arguments . Add ( TEXT ( " ProviderName " ) , FText : : FromName ( GetName ( ) ) ) ;
FMessageLog ( " SourceControl " ) . Error ( FText : : Format ( LOCTEXT ( " UnsupportedOperation " , " Operation '{OperationName}' not supported by source control provider '{ProviderName}' " ) , Arguments ) ) ;
return ECommandResult : : Failed ;
}
FPlasticSourceControlCommand * Command = new FPlasticSourceControlCommand ( InOperation , Worker . ToSharedRef ( ) ) ;
2022-05-16 14:38:52 -04:00
Command - > Files = SourceControlHelpers : : AbsoluteFilenames ( InFiles ) ;
2019-10-01 20:41:42 -04:00
Command - > OperationCompleteDelegate = InOperationCompleteDelegate ;
// fire off operation
2022-05-16 14:38:52 -04:00
if ( InConcurrency = = EConcurrency : : Synchronous )
2019-10-01 20:41:42 -04:00
{
Command - > bAutoDelete = false ;
UE_LOG ( LogSourceControl , Log , TEXT ( " ExecuteSynchronousCommand: %s " ) , * InOperation - > GetName ( ) . ToString ( ) ) ;
return ExecuteSynchronousCommand ( * Command , InOperation - > GetInProgressString ( ) ) ;
}
else
{
Command - > bAutoDelete = true ;
UE_LOG ( LogSourceControl , Log , TEXT ( " IssueAsynchronousCommand: %s " ) , * InOperation - > GetName ( ) . ToString ( ) ) ;
return IssueCommand ( * Command ) ;
}
}
2021-01-18 09:42:33 -04:00
bool FPlasticSourceControlProvider : : CanCancelOperation ( const FSourceControlOperationRef & InOperation ) const
2019-10-01 20:41:42 -04:00
{
return false ;
}
2021-01-18 09:42:33 -04:00
void FPlasticSourceControlProvider : : CancelOperation ( const FSourceControlOperationRef & InOperation )
2019-10-01 20:41:42 -04:00
{
}
bool FPlasticSourceControlProvider : : UsesLocalReadOnlyState ( ) const
{
return false ; // TODO: use configuration
}
bool FPlasticSourceControlProvider : : UsesChangelists ( ) const
{
return false ; // We don't want to show ChangeList column anymore (Plastic SCM term would be ChangeSet)
}
bool FPlasticSourceControlProvider : : UsesCheckout ( ) const
{
return true ;
}
TSharedPtr < IPlasticSourceControlWorker , ESPMode : : ThreadSafe > FPlasticSourceControlProvider : : CreateWorker ( const FName & InOperationName ) const
{
const FGetPlasticSourceControlWorker * Operation = WorkersMap . Find ( InOperationName ) ;
2022-05-16 14:38:52 -04:00
if ( Operation ! = nullptr )
2019-10-01 20:41:42 -04:00
{
return Operation - > Execute ( ) ;
}
return nullptr ;
}
void FPlasticSourceControlProvider : : RegisterWorker ( const FName & InName , const FGetPlasticSourceControlWorker & InDelegate )
{
WorkersMap . Add ( InName , InDelegate ) ;
}
void FPlasticSourceControlProvider : : OutputCommandMessages ( const FPlasticSourceControlCommand & InCommand ) const
{
FMessageLog SourceControlLog ( " SourceControl " ) ;
2022-06-01 11:26:54 -04:00
for ( const FString & ErrorMessage : InCommand . ErrorMessages )
2019-10-01 20:41:42 -04:00
{
2022-06-01 11:26:54 -04:00
SourceControlLog . Error ( FText : : FromString ( ErrorMessage ) ) ;
2019-10-01 20:41:42 -04:00
}
2022-06-01 11:26:54 -04:00
for ( const FString & InfoMessage : InCommand . InfoMessages )
2019-10-01 20:41:42 -04:00
{
2022-06-01 11:26:54 -04:00
SourceControlLog . Info ( FText : : FromString ( InfoMessage ) ) ;
2019-10-01 20:41:42 -04:00
}
}
void FPlasticSourceControlProvider : : UpdateWorkspaceStatus ( const class FPlasticSourceControlCommand & InCommand )
{
if ( InCommand . Operation - > GetName ( ) = = " Connect " )
{
// Is connection successful?
bServerAvailable = InCommand . bCommandSuccessful ;
2022-05-16 14:38:52 -04:00
bWorkspaceFound = ! InCommand . WorkspaceName . IsEmpty ( ) ;
2019-10-01 20:41:42 -04:00
WorkspaceName = InCommand . WorkspaceName ;
RepositoryName = InCommand . RepositoryName ;
ServerUrl = InCommand . ServerUrl ;
if ( bWorkspaceFound )
{
// Extend the "Source Control" menu in the Editor Toolbar on each successful connection
PlasticSourceControlMenu . Unregister ( ) ; // cleanup for any previous connection
PlasticSourceControlMenu . Register ( ) ;
}
}
else if ( InCommand . bConnectionDropped )
{
// checkconnection failed on UpdateStatus
bServerAvailable = false ;
}
// And for all operations running UpdateStatus, get Changeset and Branch informations:
2022-05-16 14:38:52 -04:00
if ( InCommand . ChangesetNumber ! = 0 )
2019-10-01 20:41:42 -04:00
{
ChangesetNumber = InCommand . ChangesetNumber ;
2022-05-16 14:38:52 -04:00
}
if ( ! InCommand . BranchName . IsEmpty ( ) )
{
2019-10-01 20:41:42 -04:00
BranchName = InCommand . BranchName ;
}
}
void FPlasticSourceControlProvider : : Tick ( )
{
bool bStatesUpdated = false ;
2022-05-16 14:38:52 -04:00
for ( int32 CommandIndex = 0 ; CommandIndex < CommandQueue . Num ( ) ; + + CommandIndex )
2019-10-01 20:41:42 -04:00
{
FPlasticSourceControlCommand & Command = * CommandQueue [ CommandIndex ] ;
2022-05-16 14:38:52 -04:00
if ( Command . bExecuteProcessed )
2019-10-01 20:41:42 -04:00
{
// Remove command from the queue
CommandQueue . RemoveAt ( CommandIndex ) ;
// Update workspace status and connection state on Connect and UpdateStatus operations
UpdateWorkspaceStatus ( Command ) ;
// let command update the states of any files
bStatesUpdated | = Command . Worker - > UpdateStates ( ) ;
// dump any messages to output log
OutputCommandMessages ( Command ) ;
2022-06-01 11:26:54 -04:00
if ( Command . Files . Num ( ) )
{
UE_LOG ( LogSourceControl , Log , TEXT ( " %s of %d files processed in %.3lfs " ) , * Command . Operation - > GetName ( ) . ToString ( ) , Command . Files . Num ( ) , ( FPlatformTime : : Seconds ( ) - Command . StartTimestamp ) ) ;
}
else
{
UE_LOG ( LogSourceControl , Log , TEXT ( " %s processed in %.3lfs " ) , * Command . Operation - > GetName ( ) . ToString ( ) , ( FPlatformTime : : Seconds ( ) - Command . StartTimestamp ) ) ;
}
2022-05-16 14:38:52 -04:00
2019-10-01 20:41:42 -04:00
// run the completion delegate callback if we have one bound
ECommandResult : : Type Result = Command . bCommandSuccessful ? ECommandResult : : Succeeded : ECommandResult : : Failed ;
Command . OperationCompleteDelegate . ExecuteIfBound ( Command . Operation , Result ) ;
// commands that are left in the array during a tick need to be deleted
2022-05-16 14:38:52 -04:00
if ( Command . bAutoDelete )
2019-10-01 20:41:42 -04:00
{
// Only delete commands that are not running 'synchronously'
delete & Command ;
}
// only do one command per tick loop, as we dont want concurrent modification
// of the command queue (which can happen in the completion delegate)
break ;
}
}
2022-05-16 14:38:52 -04:00
if ( bStatesUpdated )
2019-10-01 20:41:42 -04:00
{
OnSourceControlStateChanged . Broadcast ( ) ;
}
}
TArray < TSharedRef < ISourceControlLabel > > FPlasticSourceControlProvider : : GetLabels ( const FString & InMatchingSpec ) const
{
TArray < TSharedRef < ISourceControlLabel > > Tags ;
return Tags ;
}
2021-01-11 14:32:27 -04:00
TArray < FSourceControlChangelistRef > FPlasticSourceControlProvider : : GetChangelists ( EStateCacheUsage : : Type InStateCacheUsage )
{
return TArray < FSourceControlChangelistRef > ( ) ;
}
2019-10-01 20:41:42 -04:00
# if SOURCE_CONTROL_WITH_SLATE
TSharedRef < class SWidget > FPlasticSourceControlProvider : : MakeSettingsWidget ( ) const
{
return SNew ( SPlasticSourceControlSettings ) ;
}
# endif
ECommandResult : : Type FPlasticSourceControlProvider : : ExecuteSynchronousCommand ( FPlasticSourceControlCommand & InCommand , const FText & Task )
{
ECommandResult : : Type Result = ECommandResult : : Failed ;
// Display the progress dialog if a string was provided
{
FScopedSourceControlProgress Progress ( Task ) ;
// Issue the command asynchronously...
IssueCommand ( InCommand ) ;
// ... then wait for its completion (thus making it synchronous)
2022-05-16 14:38:52 -04:00
while ( ! InCommand . bExecuteProcessed )
2019-10-01 20:41:42 -04:00
{
// Tick the command queue and update progress.
Tick ( ) ;
Progress . Tick ( ) ;
// Sleep for a bit so we don't busy-wait so much.
FPlatformProcess : : Sleep ( 0.01f ) ;
}
// always do one more Tick() to make sure the command queue is cleaned up.
Tick ( ) ;
2022-05-16 14:38:52 -04:00
if ( InCommand . bCommandSuccessful )
2019-10-01 20:41:42 -04:00
{
Result = ECommandResult : : Succeeded ;
}
else
{
// TODO If the command failed, inform the user that they need to try again (see Perforce)
//FMessageDialog::Open( EAppMsgType::Ok, LOCTEXT("Plastic_ServerUnresponsive", "Plastic server is unresponsive. Please check your connection and try again.") );
UE_LOG ( LogSourceControl , Error , TEXT ( " Command '%s' Failed! " ) , * InCommand . Operation - > GetName ( ) . ToString ( ) ) ;
}
}
// Delete the command now (asynchronous commands are deleted in the Tick() method)
check ( ! InCommand . bAutoDelete ) ;
// ensure commands that are not auto deleted do not end up in the command queue
if ( CommandQueue . Contains ( & InCommand ) )
{
CommandQueue . Remove ( & InCommand ) ;
}
delete & InCommand ;
return Result ;
}
ECommandResult : : Type FPlasticSourceControlProvider : : IssueCommand ( FPlasticSourceControlCommand & InCommand )
{
2022-05-16 14:38:52 -04:00
if ( GThreadPool ! = nullptr )
2019-10-01 20:41:42 -04:00
{
// Queue this to our worker thread(s) for resolving
GThreadPool - > AddQueuedWork ( & InCommand ) ;
CommandQueue . Add ( & InCommand ) ;
return ECommandResult : : Succeeded ;
}
else
{
return ECommandResult : : Failed ;
}
}
# undef LOCTEXT_NAMESPACE