Files
UnrealEngineUWP/Engine/Source/Developer/SourceControl/Public/ISourceControlProvider.h
paul chipchase c08d860e2e Allow additional source control providers to be created so that specialized subsystems can maintain their own separate connection without interrupting the normal editor workflows.
#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]
2022-03-09 07:10:46 -05:00

351 lines
16 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "ISourceControlOperation.h"
#include "ISourceControlChangelist.h"
#include "ISourceControlState.h"
#include "ISourceControlChangelistState.h"
#include "Features/IModularFeature.h"
#ifndef SOURCE_CONTROL_WITH_SLATE
#error "SOURCE_CONTROL_WITH_SLATE must be defined. Did you forget a dependency on the 'SourceControl' module?"
#endif
class FSourceControlInitSettings;
class ISourceControlLabel;
/**
* Hint for how to execute the operation. Note that asynchronous operations require
* Tick() to be called to manage completed operations.
*/
namespace EConcurrency
{
enum Type
{
/** Force the operation to be issued on the same thread, blocking until complete. */
Synchronous,
/** Run the command on another thread, returning immediately. */
Asynchronous
};
}
/**
* Hint to provider when updating state
*/
namespace EStateCacheUsage
{
enum Type
{
/** Force a synchronous update of the state of the file. */
ForceUpdate,
/** Use the cached state if possible */
Use,
};
}
/**
* Results of a command execution
*/
namespace ECommandResult
{
enum Type
{
/** Command failed to execute correctly or was not supported by the provider. */
Failed,
/** Command executed successfully */
Succeeded,
/** Command was canceled before completion */
Cancelled,
};
}
/** Delegate used by providers for when operations finish */
DECLARE_DELEGATE_TwoParams(FSourceControlOperationComplete, const FSourceControlOperationRef&, ECommandResult::Type);
/** Delegate used by providers to create source control operations */
DECLARE_DELEGATE_RetVal(FSourceControlOperationRef, FGetSourceControlOperation);
/** Delegate called when the state of an item (or group of items) has changed. */
DECLARE_MULTICAST_DELEGATE(FSourceControlStateChanged);
/**
* Interface to talking with source control providers.
*/
class ISourceControlProvider : public IModularFeature
{
public:
/**
* Virtual destructor
*/
virtual ~ISourceControlProvider() {}
/**
* Initialize source control provider.
* @param bForceConnection If set, this flag forces the provider to attempt a connection to its server.
*/
virtual void Init(bool bForceConnection = true) = 0;
/**
* Shut down source control provider.
*/
virtual void Close() = 0;
/** Get the source control provider name */
virtual const FName& GetName() const = 0;
/** Get the source control status as plain, human-readable text */
virtual FText GetStatusText() const = 0;
/** 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 DefalutSourceProvider will return true. */
virtual bool IsEnabled() const = 0;
/**
* Quick check if source control is available for use (server-based providers can use this
* to return whether the server is available or not)
*
* @return true if source control is available, false if it is not
*/
virtual bool IsAvailable() const = 0;
/**
* Login to the source control server (if any).
* This is just a wrapper around Execute().
* @param InPassword The password (if required) to use when logging in.
* @param InConcurrency How to execute the operation, blocking or asynchronously on another thread.
* @param InOperationCompleteDelegate Delegate to call when the operation is completed. This is called back internal to this call when executed on the main thread, or from Tick() when queued for asynchronous execution. If the provider is not enabled or if the command is not suported the delegate is immediately called with ECommandResult::Failed.
* @return the result of the operation.
*/
SOURCECONTROL_API virtual ECommandResult::Type Login( const FString& InPassword = FString(), EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() );
/**
* Queries branch configuration from source control
* @param ConfigSrc The source path to the branch configuration file in source control
* @param ConfigDest The destination path to save the configuration to for parsing
*/
virtual bool QueryStateBranchConfig(const FString& ConfigSrc, const FString& ConfigDest) = 0;
/**
* Register branches to query for state in addition to the current branch
* @param BranchNames Names of the branches to query
* @param ContentRoot Path to the content root for branch mapping
*/
virtual void RegisterStateBranches(const TArray<FString>& BranchNames, const FString& ContentRoot) = 0;
/**
*Gets the state index of the specified branch, higher index branches are generally closer to releases
* @param BranchName Names of the branches to query
* @return the index of the specified branch
*/
virtual int32 GetStateBranchIndex(const FString& BranchName) const = 0;
/**
* Get the state of each of the passed-in files. State may be cached for faster queries. Note states can be NULL!
* @param InFiles The files to retrieve state for.
* @param OutState The states of the files. This will be empty if the operation fails. Note states can be NULL!
* @param InStateCacheUsage Whether to use the state cache or to force a (synchronous) state retrieval.
* @return the result of the operation.
*/
virtual ECommandResult::Type GetState( const TArray<FString>& InFiles, TArray<FSourceControlStateRef>& OutState, EStateCacheUsage::Type InStateCacheUsage ) = 0;
/**
* Helper overload for state retrieval, see GetState().
*/
SOURCECONTROL_API virtual ECommandResult::Type GetState( const TArray<UPackage*>& InPackages, TArray<FSourceControlStateRef>& OutState, EStateCacheUsage::Type InStateCacheUsage );
/**
* Helper overload for state retrieval, see GetState().
*/
SOURCECONTROL_API virtual FSourceControlStatePtr GetState( const FString& InFile, EStateCacheUsage::Type InStateCacheUsage );
/**
* Helper overload for state retrieval, see GetState().
*/
SOURCECONTROL_API virtual FSourceControlStatePtr GetState( const UPackage* InPackage, EStateCacheUsage::Type InStateCacheUsage );
/**
* Get the state of each of the passed-in changelists. State may be cached for faster queries. Note states can be NULL!
* @param InChangelists The changelists to retrieve state for.
* @param OutState The states of the changelists. This will be empty if the operation fails. Note states can be NULL!
* @param InStateCacheUsage Whether to use the state cache or to force a (synchronous) state retrieval.
* @return the result of the operation.
*/
virtual ECommandResult::Type GetState( const TArray<FSourceControlChangelistRef>& InChangelists, TArray<FSourceControlChangelistStateRef>& OutState, EStateCacheUsage::Type InStateCacheUsage ) = 0;
/**
* Helper overload for state retrieval, see GetState().
*/
SOURCECONTROL_API virtual FSourceControlChangelistStatePtr GetState( const FSourceControlChangelistRef& InChangelist, EStateCacheUsage::Type InStateCacheUsage );
/**
* Get all cached source control state objects for which the supplied predicate returns true
*/
virtual TArray<FSourceControlStateRef> GetCachedStateByPredicate(TFunctionRef<bool(const FSourceControlStateRef&)> Predicate) const = 0;
/**
* Register a delegate to be called when source control state(s) change
*/
virtual FDelegateHandle RegisterSourceControlStateChanged_Handle( const FSourceControlStateChanged::FDelegate& SourceControlStateChanged ) = 0;
/**
* Unregister a delegate to be called when source control state(s) change
*/
virtual void UnregisterSourceControlStateChanged_Handle( FDelegateHandle Handle ) = 0;
/**
* Attempt to execute an operation on the passed-in files (if any are required).
* @param InOperation The operation to perform.
* @param InChangelist The changelist to operate on, can be null.
* @param InFiles The files to operate on.
* @param InConcurrency How to execute the operation, blocking or asynchronously on another thread.
* @param InOperationCompleteDelegate Delegate to call when the operation is completed. This is called back internal to this call when executed on the main thread, or from Tick() when queued for asynchronous execution. If the provider is not enabled or if the command is not suported the delegate is immediately called with ECommandResult::Failed.
* @return the result of the operation.
*/
virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, FSourceControlChangelistPtr InChangelist, const TArray<FString>& InFiles, EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() ) = 0;
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute(const FSourceControlOperationRef& InOperation, const TArray<FString>& InFiles, EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete());
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, const EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() );
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, const UPackage* InPackage, const EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() );
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, const FString& InFile, const EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() );
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, const TArray<UPackage*>& InPackages, const EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() );
/**
* Helper overload for operation execution, see Execute().
*/
SOURCECONTROL_API virtual ECommandResult::Type Execute( const FSourceControlOperationRef& InOperation, FSourceControlChangelistPtr InChangelist, const EConcurrency::Type InConcurrency = EConcurrency::Synchronous, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete());
/**
* Check to see if we can cancel an operation.
* @param InOperation The operation to check.
* @return true if the operation was cancelled.
*/
virtual bool CanCancelOperation( const FSourceControlOperationRef& InOperation ) const = 0;
/**
* Attempt to cancel an operation in progress.
* @param InOperation The operation to attempt to cancel.
*/
virtual void CancelOperation( const FSourceControlOperationRef& InOperation ) = 0;
/**
* Get a label matching the passed-in name.
* @param InLabelName String specifying the label name
* @return the label, if any
*/
SOURCECONTROL_API virtual TSharedPtr<class ISourceControlLabel> GetLabel( const FString& InLabelName ) const;
/**
* Get an array of labels matching the passed-in spec.
* @param InMatchingSpec String specifying the label spec.
* @return an array of labels matching the spec.
*/
virtual TArray< TSharedRef<class ISourceControlLabel> > GetLabels( const FString& InMatchingSpec ) const = 0;
virtual TArray<FSourceControlChangelistRef> GetChangelists( EStateCacheUsage::Type InStateCacheUsage ) = 0;
/**
* Executes the FDownloadFile operation, but unlike the ::Execute method this can be called from a background thread, this
* works because FDownloadFile is thread safe and it does not change the state of source control.
* NOTE: This is only intended for use by the virtualization module and will be deprecated at some point in the future when
* thread safety is built into the system.
* NOTE: This is only implemented for the perforce source control provider with no plans to extend this to other providers.
*
* @param InOperation The download operation to be executed.
* @param InFile The depot path of a file to download.
* @return True if the operation was a success, otherwise false.
*/
SOURCECONTROL_API bool TryToDownloadFileFromBackgroundThread(const TSharedRef<class FDownloadFile>& InOperation, const FString& InFile);
/**
* Executes the FDownloadFile operation, but unlike the ::Execute method this can be called from a background thread, this
* works because FDownloadFile is thread safe and it does not change the state of source control.
* NOTE: This is only intended for use by the virtualization module and will be deprecated at some point in the future when
* thread safety is built into the system.
* NOTE: This is only implemented for the perforce source control provider with no plans to extend this to other providers.
*
* @param InOperation The download operation to be executed.
* @param InFile An array of depot paths for the files to download.
* @return True if the operation was a success, otherwise false.
*/
SOURCECONTROL_API virtual bool TryToDownloadFileFromBackgroundThread(const TSharedRef<class FDownloadFile>& InOperation, const TArray<FString>& InFiles);
/**
* Used to switch the provider from one workspace to another.
* NOTE: This concept is currently only implemented for the perforce source control provider.
*
* @param NewWorkspaceName The name of the workspace to switch to
* @param ResultInfo[out] Errors and info messages generated will be written here
* @param OutOldWorkspaceName[out] The name of the previous workspace will be written to this FString if the pointer is valid (optional)
*
* @return The result of the operation.
*/
SOURCECONTROL_API virtual ECommandResult::Type SwitchWorkspace(FStringView NewWorkspaceName, FSourceControlResultInfo& OutResultInfo, FString* OutOldWorkspaceName);
/**
* Whether the provider uses local read-only state to signal whether a file is editable.
*/
virtual bool UsesLocalReadOnlyState() const = 0;
/**
* Whether the provider uses changelists to identify commits/revisions
*/
virtual bool UsesChangelists() const = 0;
/**
* Whether the provider uses the checkout workflow
*/
virtual bool UsesCheckout() const = 0;
/**
* Called every update.
*/
virtual void Tick() = 0;
#if SOURCE_CONTROL_WITH_SLATE
/**
* Create a settings widget for display in the login window.
* @returns a widget used to edit the providers settings required prior to connection.
*/
virtual TSharedRef<class SWidget> MakeSettingsWidget() const = 0;
#endif // SOURCE_CONTROL_WITH_SLATE
protected:
/*
* The ::Create method is an easy way for us to create new providers, but we really don't
* want anything except FSourceControlModule calling it. For now we achieve this by having
* ::Create protected and making FSourceControlModule a friend.
* TODO Move the create to a factory system via IModularFeatures and remove the friend declaration.
*/
friend class FSourceControlModule;
/**
* Creates a new instance of the source control provider type. Derived providers
* should implement this if they can more than one provider of the same type existing.
* @see ISourceControlModule::CreateProvider
*/
virtual TUniquePtr<ISourceControlProvider> Create(const FStringView& OwnerName, const FSourceControlInitSettings& InitialSettings) const { return TUniquePtr<ISourceControlProvider>(); }
};