You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb Luc.Eygasier, Sebastien.Lussier #rnx #preflight 622895d331133a23da78a4ca ### Misc - FPerforceSourceControlRevision, FPerforceConnection and FPerforceSourceControlLabel now own a reference to their FPerforceSourceControlProvider and accesses the connection settings from that rather than via the module singleton. - FPerforceSourceControlCommand now accesses the connection settings by finding the FPerforceSourceControlProvider that the given IPerforceSourceControlWorker references. - FPerforceSourceControlProvider now owns it's own FPerforceSourceControlSettings rather than accessing a shared one owned by the module. - Marked a number of derived classes as final. ### FPerforceConnection - ::EnsureValidConnection can now work without a valid client (although most commands will require a client to run, things like p4 print does not). -- Due to this change we might not catch cases where the the system cannot connect to source control as the user is not logged in as this would get caught when we checked the workspace by calling ::TestConnection. -- To get around this ::EnsureValidConnection will now call "p4 login -s" via the newly added TestLoginConnection. - Renamed ::TestConnection to ::TestClientConnection as we are really testing the connection to the specified workspace. - There does seem to be some inconsistency in the logging, depending how a perforce source control provider first creates its connection as in some cases FPerforceConnection::EnsureValidConnection gets called first and in other cases FPerforceConnection::EstablishConnection is called. We should unify these paths but this change list is already so large I am opting to postpone this to it's own work item. ### FPerforceSourceControlModule - Removed all of the singleton style accessors so that classes inside of the module can no longer assume that there is only one FPerforceSourceControlProvider. Updated the documentation to match. - Since there is no reason for classes in the module to need to access FPerforceSourceControlModule, ::Get has been removed - The responsibility to register all of the worker creation delegates has been moved to IPerforceSourceControlWorker so that all source control providers can share them. - ::GetProvider has been removed, if a class inside the module needs access to a provider then a reference to it's provider will be given to it at construction time. - ::SetLastError, ::AccessSettings and ::SaveSettings are now called directly on FPerforceSourceControlSettings ### FPerforceSourceControlSettings - This class now takes the name of the system that owns it as a parameter in the constructor -- The name will be used to identify where to store the settings in the config file, unless the name is blank in which case the pre-existing default location will be used. - This will allow for multiple source control providers to store their connection info. ### SPerforceSourceControlSettings - Moved FGetWorkspaces from SPerforceSourceControlSettings.h to its own header file to reduce the number of places that need to include the slate headers. - Move the fwd declares to the top of the header base don recent coding standards discussions. - Instead of accessing the source control provider via FPerforceSourceControlModule the dialog is now given a pointer to one when constructed. -- This pointer is assumed to always be valid and should be a reference if the slate system supported it. ### PerforceSourceControlOperations - IPerforceSourceControlWorker now takes a reference to the owning FPerforceSourceControlProvider in it's constructor. All derived workers have been updated to this. - Moved the registering of worker creation delegates from the module cpp to a new static method IPerforceSourceControlWorker::RegisterWorkers -- This should make it easier to find when adding a new worker and allows source control providers to share the same map of delegates rather than duplicating it. -- This means we also need a new static method IPerforceSourceControlWorker::CreateWorker for instantiating new workers based on the given name. ### FSourceControlInitSettings - This is a new class that is used to set up a newly created source control provider. - The settings are expected to be given in the same way you would override settings via the cmdline. The existing perforce cmdline code has been updated to use this class. - This still has the downside that the calling code needs to know the type of source control provider, but I don't really see a good way around this unless we refactor the entire API to be feature based. [CL 19318801 by paul chipchase in ue5-main branch]
551 lines
17 KiB
C++
551 lines
17 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SourceControlModule.h"
|
|
#include "Features/IModularFeatures.h"
|
|
#include "SSourceControlLogin.h"
|
|
#include "SourceControlOperations.h"
|
|
#include "SourceControlHelpers.h"
|
|
#include "SourceControlAssetDataCache.h"
|
|
#include "Misc/Paths.h"
|
|
|
|
#if SOURCE_CONTROL_WITH_SLATE
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "Widgets/SWindow.h"
|
|
#include "Widgets/Layout/SBox.h"
|
|
#include "Framework/Docking/TabManager.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#endif
|
|
|
|
#if WITH_UNREAL_DEVELOPER_TOOLS
|
|
#include "MessageLogModule.h"
|
|
#endif
|
|
|
|
#if WITH_EDITOR
|
|
#include "Runtime/Engine/Public/EngineAnalytics.h"
|
|
#include "Runtime/Analytics/Analytics/Public/Interfaces/IAnalyticsProvider.h"
|
|
#endif
|
|
|
|
DEFINE_LOG_CATEGORY(LogSourceControl);
|
|
|
|
#define LOCTEXT_NAMESPACE "SourceControl"
|
|
|
|
static const FName SourceControlFeatureName("SourceControl");
|
|
|
|
namespace SourceControlConstants
|
|
{
|
|
/** The maximum number of file/directory status requests we should dispatch in a tick */
|
|
const int32 MaxStatusDispatchesPerTick = 64;
|
|
|
|
/** The interval at which we refresh a file's state */
|
|
const FTimespan StateRefreshInterval = FTimespan::FromMinutes(5.0);
|
|
}
|
|
|
|
FSourceControlModule::FSourceControlModule()
|
|
: CurrentSourceControlProvider(NULL)
|
|
, bTemporarilyDisabled(false)
|
|
{
|
|
}
|
|
|
|
void FSourceControlModule::StartupModule()
|
|
{
|
|
// load our settings
|
|
SourceControlSettings.LoadSettings();
|
|
|
|
// Register to check for source control features
|
|
IModularFeatures::Get().OnModularFeatureRegistered().AddRaw(this, &FSourceControlModule::HandleModularFeatureRegistered);
|
|
IModularFeatures::Get().OnModularFeatureUnregistered().AddRaw(this, &FSourceControlModule::HandleModularFeatureUnregistered);
|
|
|
|
// bind default provider to editor
|
|
IModularFeatures::Get().RegisterModularFeature( SourceControlFeatureName, &DefaultSourceControlProvider );
|
|
|
|
#if WITH_UNREAL_DEVELOPER_TOOLS
|
|
// create a message log for source control to use
|
|
FMessageLogModule& MessageLogModule = FModuleManager::LoadModuleChecked<FMessageLogModule>("MessageLog");
|
|
MessageLogModule.RegisterLogListing("SourceControl", LOCTEXT("SourceControlLogLabel", "Source Control"));
|
|
#endif
|
|
|
|
AssetDataCache.Startup();
|
|
}
|
|
|
|
void FSourceControlModule::ShutdownModule()
|
|
{
|
|
AssetDataCache.Shutdown();
|
|
// close the current provider
|
|
GetProvider().Close();
|
|
|
|
#if WITH_UNREAL_DEVELOPER_TOOLS
|
|
// unregister message log
|
|
if(FModuleManager::Get().IsModuleLoaded("MessageLog"))
|
|
{
|
|
FMessageLogModule& MessageLogModule = FModuleManager::LoadModuleChecked<FMessageLogModule>("MessageLog");
|
|
MessageLogModule.UnregisterLogListing("SourceControl");
|
|
}
|
|
#endif
|
|
|
|
// unbind default provider from editor
|
|
IModularFeatures::Get().UnregisterModularFeature( SourceControlFeatureName, &DefaultSourceControlProvider );
|
|
|
|
// we don't care about modular features any more
|
|
IModularFeatures::Get().OnModularFeatureRegistered().RemoveAll(this);
|
|
IModularFeatures::Get().OnModularFeatureUnregistered().RemoveAll(this);
|
|
}
|
|
|
|
void FSourceControlModule::SaveSettings()
|
|
{
|
|
SourceControlSettings.SaveSettings();
|
|
}
|
|
|
|
void FSourceControlModule::ShowLoginDialog(const FSourceControlLoginClosed& InOnSourceControlLoginClosed, ELoginWindowMode::Type InLoginWindowMode, EOnLoginWindowStartup::Type InOnLoginWindowStartup)
|
|
{
|
|
#if SOURCE_CONTROL_WITH_SLATE
|
|
// Avoid continue running tasks while the dialog is displayed. Any change in textboxes could affect the connection status.
|
|
AssetDataCache.OnSourceControlDialogShown();
|
|
|
|
// Get Active Provider Name
|
|
ActiveProviderName = GetProvider().GetName().ToString();
|
|
|
|
// if we are showing a modal version of the dialog & a modeless version already exists, we must destroy the modeless dialog first
|
|
if(InLoginWindowMode == ELoginWindowMode::Modal && SourceControlLoginPtr.IsValid())
|
|
{
|
|
// unhook the delegate so it doesn't fire in this case
|
|
SourceControlLoginWindowPtr->SetOnWindowClosed(FOnWindowClosed());
|
|
SourceControlLoginWindowPtr->RequestDestroyWindow();
|
|
SourceControlLoginWindowPtr = NULL;
|
|
SourceControlLoginPtr = NULL;
|
|
}
|
|
|
|
if(SourceControlLoginWindowPtr.IsValid())
|
|
{
|
|
SourceControlLoginWindowPtr->BringToFront();
|
|
}
|
|
else
|
|
{
|
|
// set provider to 'none'.
|
|
// When we open the window, we turn off the fact that source control is available, this solves issues that are present with
|
|
// being a three state modeless system (Accepted settings, disabled, and not yet decided).
|
|
if(InOnLoginWindowStartup == EOnLoginWindowStartup::ResetProviderToNone)
|
|
{
|
|
SetProvider("None");
|
|
}
|
|
|
|
// temporarily disable access to source control features
|
|
bTemporarilyDisabled = true;
|
|
|
|
// Create the window
|
|
SourceControlLoginWindowPtr = SNew(SWindow)
|
|
.Title( LOCTEXT("SourceControlLoginTitle", "Source Control Login") )
|
|
.HasCloseButton(true)
|
|
.SupportsMaximize(false)
|
|
.SupportsMinimize(false)
|
|
.SizingRule( ESizingRule::Autosized );
|
|
|
|
// Set the closed callback
|
|
SourceControlLoginWindowPtr->SetOnWindowClosed(FOnWindowClosed::CreateRaw(this, &FSourceControlModule::OnSourceControlDialogClosed));
|
|
|
|
// Setup the content for the created login window.
|
|
SourceControlLoginWindowPtr->SetContent(
|
|
SAssignNew(SourceControlLoginPtr, SSourceControlLogin)
|
|
.ParentWindow(SourceControlLoginWindowPtr)
|
|
.OnSourceControlLoginClosed(InOnSourceControlLoginClosed)
|
|
);
|
|
|
|
TSharedPtr<SWindow> RootWindow = FGlobalTabmanager::Get()->GetRootWindow();
|
|
if(RootWindow.IsValid())
|
|
{
|
|
if(InLoginWindowMode == ELoginWindowMode::Modal)
|
|
{
|
|
FSlateApplication::Get().AddModalWindow(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow);
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindowAsNativeChild(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow.ToSharedRef());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(InLoginWindowMode == ELoginWindowMode::Modal)
|
|
{
|
|
FSlateApplication::Get().AddModalWindow(SourceControlLoginWindowPtr.ToSharedRef(), RootWindow);
|
|
}
|
|
else
|
|
{
|
|
FSlateApplication::Get().AddWindow(SourceControlLoginWindowPtr.ToSharedRef());
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
STUBBED("FSourceControlModule::ShowLoginDialog - no Slate");
|
|
#endif // SOURCE_CONTROL_WITH_SLATE
|
|
}
|
|
|
|
void FSourceControlModule::OnSourceControlDialogClosed(const TSharedRef<SWindow>& InWindow)
|
|
{
|
|
SourceControlLoginWindowPtr = NULL;
|
|
SourceControlLoginPtr = NULL;
|
|
bTemporarilyDisabled = false;
|
|
|
|
#if WITH_EDITOR
|
|
FString NewProvider = CurrentSourceControlProvider->GetName().ToString();
|
|
if( FEngineAnalytics::IsAvailable() && !ActiveProviderName.Equals( NewProvider, ESearchCase::IgnoreCase ))
|
|
{
|
|
FEngineAnalytics::GetProvider().RecordEvent( TEXT( "Editor.Usage.SourceControl" ), TEXT( "Provider" ), NewProvider );
|
|
ActiveProviderName = NewProvider;
|
|
}
|
|
#endif
|
|
|
|
AssetDataCache.OnSourceControlDialogClosed();
|
|
}
|
|
|
|
void FSourceControlModule::InitializeSourceControlProviders()
|
|
{
|
|
int32 SourceControlCount = IModularFeatures::Get().GetModularFeatureImplementationCount(SourceControlFeatureName);
|
|
if( SourceControlCount > 0 )
|
|
{
|
|
FString PreferredSourceControlProvider = SourceControlSettings.GetProvider();
|
|
TArray<ISourceControlProvider*> Providers = IModularFeatures::Get().GetModularFeatureImplementations<ISourceControlProvider>(SourceControlFeatureName);
|
|
for(auto It(Providers.CreateIterator()); It; It++)
|
|
{
|
|
ISourceControlProvider* Provider = *It;
|
|
if(PreferredSourceControlProvider == Provider->GetName().ToString())
|
|
{
|
|
CurrentSourceControlProvider = Provider;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// no provider found of this name, default to the first one
|
|
if( CurrentSourceControlProvider == NULL )
|
|
{
|
|
CurrentSourceControlProvider = &DefaultSourceControlProvider;
|
|
}
|
|
}
|
|
|
|
check(CurrentSourceControlProvider);
|
|
|
|
CurrentSourceControlProvider->Init(false); // Don't force a connection here, as its synchronous. Let the user establish a connection.
|
|
}
|
|
|
|
void FSourceControlModule::GetProviderNames(TArray<FName>& OutProviderNames)
|
|
{
|
|
OutProviderNames.Reset();
|
|
|
|
int32 ProviderCount = GetNumSourceControlProviders();
|
|
for ( int32 ProviderIndex = 0; ProviderIndex < ProviderCount; ProviderIndex++ )
|
|
{
|
|
FName ProviderName = GetSourceControlProviderName(ProviderIndex);
|
|
OutProviderNames.Add(ProviderName);
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::Tick()
|
|
{
|
|
if( CurrentSourceControlProvider != nullptr )
|
|
{
|
|
ISourceControlProvider& Provider = GetProvider();
|
|
|
|
// tick the provider, so any operation results can be read back
|
|
Provider.Tick();
|
|
|
|
AssetDataCache.Tick();
|
|
|
|
// don't allow background status updates when temporarily disabled for login
|
|
if(!bTemporarilyDisabled)
|
|
{
|
|
// check for any pending dispatches
|
|
if(PendingStatusUpdateFiles.Num() > 0)
|
|
{
|
|
// grab a batch of files
|
|
TArray<FString> FilesToDispatch;
|
|
for(auto Iter(PendingStatusUpdateFiles.CreateConstIterator()); Iter; Iter++)
|
|
{
|
|
if(FilesToDispatch.Num() >= SourceControlConstants::MaxStatusDispatchesPerTick)
|
|
{
|
|
break;
|
|
}
|
|
FilesToDispatch.Add(*Iter);
|
|
}
|
|
|
|
if(FilesToDispatch.Num() > 0)
|
|
{
|
|
// remove the files we are dispatching so we don't try again
|
|
PendingStatusUpdateFiles.RemoveAt(0, FilesToDispatch.Num());
|
|
|
|
// dispatch update
|
|
Provider.Execute(ISourceControlOperation::Create<FUpdateStatus>(), FilesToDispatch, EConcurrency::Asynchronous);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::QueueStatusUpdate(const TArray<UPackage*>& InPackages)
|
|
{
|
|
if(IsEnabled())
|
|
{
|
|
for(auto It(InPackages.CreateConstIterator()); It; It++)
|
|
{
|
|
QueueStatusUpdate(*It);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::QueueStatusUpdate(const TArray<FString>& InFilenames)
|
|
{
|
|
if(IsEnabled())
|
|
{
|
|
for(auto It(InFilenames.CreateConstIterator()); It; It++)
|
|
{
|
|
QueueStatusUpdate(*It);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::QueueStatusUpdate(UPackage* InPackage)
|
|
{
|
|
if(IsEnabled())
|
|
{
|
|
QueueStatusUpdate(SourceControlHelpers::PackageFilename(InPackage));
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::QueueStatusUpdate(const FString& InFilename)
|
|
{
|
|
if(IsEnabled())
|
|
{
|
|
TSharedPtr<ISourceControlState, ESPMode::ThreadSafe> SourceControlState = GetProvider().GetState(InFilename, EStateCacheUsage::Use);
|
|
if(SourceControlState.IsValid())
|
|
{
|
|
FTimespan TimeSinceLastUpdate = FDateTime::Now() - SourceControlState->GetTimeStamp();
|
|
if(TimeSinceLastUpdate > SourceControlConstants::StateRefreshInterval)
|
|
{
|
|
PendingStatusUpdateFiles.AddUnique(InFilename);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FSourceControlModule::IsEnabled() const
|
|
{
|
|
return !bTemporarilyDisabled && GetProvider().IsEnabled();
|
|
}
|
|
|
|
ISourceControlProvider& FSourceControlModule::GetProvider() const
|
|
{
|
|
return *CurrentSourceControlProvider;
|
|
}
|
|
|
|
TUniquePtr<ISourceControlProvider> FSourceControlModule::CreateProvider(const FName& ProviderName, const FStringView& OwnerName, const FSourceControlInitSettings& InitialSettings) const
|
|
{
|
|
TArray<ISourceControlProvider*> Providers = IModularFeatures::Get().GetModularFeatureImplementations<ISourceControlProvider>(SourceControlFeatureName);
|
|
for (const ISourceControlProvider* DefaultProvider : Providers)
|
|
{
|
|
if (DefaultProvider->GetName() == ProviderName)
|
|
{
|
|
return DefaultProvider->Create(OwnerName, InitialSettings);
|
|
}
|
|
}
|
|
|
|
// Provider was not found
|
|
return TUniquePtr<ISourceControlProvider>();
|
|
}
|
|
|
|
FSourceControlAssetDataCache& FSourceControlModule::GetAssetDataCache()
|
|
{
|
|
return AssetDataCache;
|
|
}
|
|
|
|
void FSourceControlModule::SetProvider( const FName& InName )
|
|
{
|
|
TArray<ISourceControlProvider*> Providers = IModularFeatures::Get().GetModularFeatureImplementations<ISourceControlProvider>(SourceControlFeatureName);
|
|
for(auto It(Providers.CreateIterator()); It; It++)
|
|
{
|
|
ISourceControlProvider* Provider = *It;
|
|
if(InName == Provider->GetName())
|
|
{
|
|
SetCurrentSourceControlProvider(*Provider);
|
|
return;
|
|
}
|
|
}
|
|
|
|
UE_LOG(LogSourceControl, Fatal, TEXT("Tried to set unknown source control provider: %s"), *InName.ToString());
|
|
}
|
|
|
|
void FSourceControlModule::ClearCurrentSourceControlProvider()
|
|
{
|
|
if( !CurrentSourceControlProvider || CurrentSourceControlProvider != &DefaultSourceControlProvider )
|
|
{
|
|
ISourceControlProvider* OldSourceControlProvider = CurrentSourceControlProvider;
|
|
if (CurrentSourceControlProvider)
|
|
{
|
|
CurrentSourceControlProvider->Close();
|
|
}
|
|
|
|
CurrentSourceControlProvider = &DefaultSourceControlProvider;
|
|
|
|
if (OldSourceControlProvider)
|
|
{
|
|
OnSourceControlProviderChanged.Broadcast(*OldSourceControlProvider, *CurrentSourceControlProvider);
|
|
}
|
|
}
|
|
}
|
|
|
|
int32 FSourceControlModule::GetNumSourceControlProviders()
|
|
{
|
|
return IModularFeatures::Get().GetModularFeatureImplementationCount(SourceControlFeatureName);
|
|
}
|
|
|
|
void FSourceControlModule::SetCurrentSourceControlProvider(int32 ProviderIndex)
|
|
{
|
|
TArray<ISourceControlProvider*> Providers = IModularFeatures::Get().GetModularFeatureImplementations<ISourceControlProvider>(SourceControlFeatureName);
|
|
check(Providers.IsValidIndex(ProviderIndex));
|
|
SetCurrentSourceControlProvider(*Providers[ProviderIndex]);
|
|
}
|
|
|
|
void FSourceControlModule::SetCurrentSourceControlProvider(ISourceControlProvider& InProvider)
|
|
{
|
|
// see if we are switching or not
|
|
if(&InProvider == CurrentSourceControlProvider)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ClearCurrentSourceControlProvider();
|
|
|
|
ISourceControlProvider* OldSourceControlProvider = CurrentSourceControlProvider;
|
|
|
|
CurrentSourceControlProvider = &InProvider;
|
|
CurrentSourceControlProvider->Init(false); // Don't force a connection here, as its synchronous. Let the user establish a connection.
|
|
|
|
SourceControlSettings.SetProvider(CurrentSourceControlProvider->GetName().ToString());
|
|
|
|
SaveSettings();
|
|
|
|
if (OldSourceControlProvider)
|
|
{
|
|
OnSourceControlProviderChanged.Broadcast(*OldSourceControlProvider, *CurrentSourceControlProvider);
|
|
}
|
|
}
|
|
|
|
FName FSourceControlModule::GetSourceControlProviderName(int32 ProviderIndex)
|
|
{
|
|
TArray<ISourceControlProvider*> Providers = IModularFeatures::Get().GetModularFeatureImplementations<ISourceControlProvider>(SourceControlFeatureName);
|
|
check(Providers.IsValidIndex(ProviderIndex));
|
|
return Providers[ProviderIndex]->GetName();
|
|
}
|
|
|
|
TSharedPtr<class SSourceControlLogin> FSourceControlModule::GetLoginWidget() const
|
|
{
|
|
return SourceControlLoginPtr;
|
|
}
|
|
|
|
void FSourceControlModule::HandleModularFeatureRegistered(const FName& Type, IModularFeature* ModularFeature)
|
|
{
|
|
if(Type == SourceControlFeatureName)
|
|
{
|
|
InitializeSourceControlProviders();
|
|
}
|
|
}
|
|
|
|
void FSourceControlModule::HandleModularFeatureUnregistered(const FName& Type, IModularFeature* ModularFeature)
|
|
{
|
|
if(Type == SourceControlFeatureName && CurrentSourceControlProvider == static_cast<ISourceControlProvider*>(ModularFeature))
|
|
{
|
|
ClearCurrentSourceControlProvider();
|
|
}
|
|
}
|
|
|
|
bool FSourceControlModule::GetUseGlobalSettings() const
|
|
{
|
|
return SourceControlSettings.GetUseGlobalSettings();
|
|
}
|
|
|
|
void FSourceControlModule::SetUseGlobalSettings(bool bIsUseGlobalSettings)
|
|
{
|
|
SourceControlSettings.SetUseGlobalSettings(bIsUseGlobalSettings);
|
|
|
|
// force the user to re-log in
|
|
ShowLoginDialog(FSourceControlLoginClosed(), ELoginWindowMode::Modeless, EOnLoginWindowStartup::PreserveProvider);
|
|
}
|
|
|
|
FDelegateHandle FSourceControlModule::RegisterProviderChanged(const FSourceControlProviderChanged::FDelegate& SourceControlProviderChanged)
|
|
{
|
|
return OnSourceControlProviderChanged.Add(SourceControlProviderChanged);
|
|
}
|
|
|
|
void FSourceControlModule::UnregisterProviderChanged(FDelegateHandle Handle)
|
|
{
|
|
OnSourceControlProviderChanged.Remove(Handle);
|
|
}
|
|
|
|
void FSourceControlModule::RegisterPreSubmitDataValidation(const FSourceControlPreSubmitDataValidationDelegate& PreSubmitDataValidationDelegate)
|
|
{
|
|
OnSourceControlPreSubmitDataValidation = PreSubmitDataValidationDelegate;
|
|
}
|
|
|
|
void FSourceControlModule::UnregisterPreSubmitDataValidation()
|
|
{
|
|
OnSourceControlPreSubmitDataValidation = FSourceControlPreSubmitDataValidationDelegate();
|
|
}
|
|
|
|
FSourceControlPreSubmitDataValidationDelegate FSourceControlModule::GetRegisteredPreSubmitDataValidation()
|
|
{
|
|
return OnSourceControlPreSubmitDataValidation;
|
|
}
|
|
|
|
FDelegateHandle FSourceControlModule::RegisterPreSubmitFinalize(const FSourceControlPreSubmitFinalizeDelegate::FDelegate& Delegate)
|
|
{
|
|
return OnPresubmitFinalize.Add(Delegate);
|
|
}
|
|
|
|
void FSourceControlModule::UnregisterPreSubmitFinalize(FDelegateHandle Handle)
|
|
{
|
|
OnPresubmitFinalize.Remove(Handle);
|
|
}
|
|
|
|
const FSourceControlPreSubmitFinalizeDelegate& FSourceControlModule::GetOnPreSubmitFinalize() const
|
|
{
|
|
return OnPresubmitFinalize;
|
|
}
|
|
|
|
FDelegateHandle FSourceControlModule::RegisterFilesDeleted(const FSourceControlFilesDeletedDelegate::FDelegate& InDelegate)
|
|
{
|
|
return OnFilesDeleted.Add(InDelegate);
|
|
}
|
|
|
|
void FSourceControlModule::UnregisterFilesDeleted(FDelegateHandle InHandle)
|
|
{
|
|
OnFilesDeleted.Remove(InHandle);
|
|
}
|
|
|
|
const FSourceControlFilesDeletedDelegate& FSourceControlModule::GetOnFilesDeleted() const
|
|
{
|
|
return OnFilesDeleted;
|
|
}
|
|
|
|
void FSourceControlModule::RegisterSourceControlProjectDirDelegate(const FSourceControlProjectDirDelegate& InSourceControlProjectDirDelegate)
|
|
{
|
|
SourceControlProjectDirDelegate = InSourceControlProjectDirDelegate;
|
|
}
|
|
|
|
void FSourceControlModule::UnregisterSourceControlProjectDirDelegate()
|
|
{
|
|
SourceControlProjectDirDelegate = FSourceControlProjectDirDelegate();
|
|
}
|
|
|
|
FString FSourceControlModule::GetSourceControlProjectDir() const
|
|
{
|
|
if (SourceControlProjectDirDelegate.IsBound())
|
|
{
|
|
FString ProjectDir = SourceControlProjectDirDelegate.Execute();
|
|
if (!ProjectDir.IsEmpty())
|
|
{
|
|
return ProjectDir;
|
|
}
|
|
}
|
|
return FPaths::ProjectDir();
|
|
}
|
|
|
|
IMPLEMENT_MODULE( FSourceControlModule, SourceControl );
|
|
|
|
#undef LOCTEXT_NAMESPACE
|