2021-05-06 14:40:16 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "UncontrolledChangelistsModule.h"
2021-06-16 14:37:34 -04:00
# include "Algo/AnyOf.h"
2021-05-26 18:15:46 -04:00
# include "Algo/Copy.h"
2021-05-06 14:40:16 -04:00
# include "Algo/Find.h"
2021-06-21 11:05:22 -04:00
# include "Algo/ForEach.h"
2021-05-06 14:40:16 -04:00
# include "Algo/Transform.h"
2022-05-02 18:06:48 -04:00
# include "AssetRegistry/AssetRegistryModule.h"
2021-05-06 14:40:16 -04:00
# include "Dom/JsonObject.h"
2021-05-12 17:06:06 -04:00
# include "FileHelpers.h"
2022-02-02 05:30:58 -05:00
# include "HAL/FileManager.h"
2021-05-06 14:40:16 -04:00
# include "HAL/IConsoleManager.h"
# include "ISourceControlModule.h"
2021-05-12 17:06:06 -04:00
# include "ISourceControlProvider.h"
2021-05-06 14:40:16 -04:00
# include "Misc/FileHelper.h"
# include "Misc/Paths.h"
2021-05-12 17:06:06 -04:00
# include "PackagesDialog.h"
2021-05-06 14:40:16 -04:00
# include "Serialization/JsonSerializer.h"
# include "Serialization/JsonWriter.h"
2021-05-12 17:06:06 -04:00
# include "SourceControlOperations.h"
# include "Styling/SlateTypes.h"
2021-05-26 18:15:46 -04:00
# include "UObject/ObjectSaveContext.h"
2021-05-06 14:40:16 -04:00
# define LOCTEXT_NAMESPACE "UncontrolledChangelists"
static TAutoConsoleVariable < bool > CVarUncontrolledChangelistsEnable (
TEXT ( " UncontrolledChangelists.Enable " ) ,
false ,
TEXT ( " Enables Uncontrolled Changelists (experimental). " )
) ;
void FUncontrolledChangelistsModule : : StartupModule ( )
{
// Adds Default Uncontrolled Changelist if it is not already present.
FUncontrolledChangelist DefaultUncontrolledChangelist ( FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_GUID , FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_NAME . ToString ( ) ) ;
UncontrolledChangelistsStateCache . FindOrAdd ( MoveTemp ( DefaultUncontrolledChangelist ) , MakeShareable ( new FUncontrolledChangelistState ( DefaultUncontrolledChangelist ) ) ) ;
LoadState ( ) ;
FAssetRegistryModule & AssetRegistryModule = FModuleManager : : GetModuleChecked < FAssetRegistryModule > ( TEXT ( " AssetRegistry " ) ) ;
2021-06-21 11:05:22 -04:00
IAssetRegistry & AssetRegistry = AssetRegistryModule . Get ( ) ;
OnAssetAddedDelegateHandle = AssetRegistry . OnAssetAdded ( ) . AddLambda ( [ ] ( const struct FAssetData & AssetData ) { Get ( ) . OnAssetAdded ( AssetData ) ; } ) ;
2021-05-26 18:15:46 -04:00
OnObjectPreSavedDelegateHandle = FCoreUObjectDelegates : : OnObjectPreSave . AddLambda ( [ ] ( UObject * InAsset , const FObjectPreSaveContext & InPreSaveContext ) { Get ( ) . OnObjectPreSaved ( InAsset , InPreSaveContext ) ; } ) ;
2021-06-21 11:05:22 -04:00
TArray < FAssetData > AssetData ;
AssetRegistry . GetAllAssets ( AssetData ) ;
Algo : : ForEach ( AssetData , [ this ] ( const struct FAssetData & AssetData ) { OnAssetAdded ( AssetData ) ; } ) ;
2021-05-06 14:40:16 -04:00
}
void FUncontrolledChangelistsModule : : ShutdownModule ( )
{
FAssetRegistryModule * AssetRegistryModulePtr = static_cast < FAssetRegistryModule * > ( FModuleManager : : Get ( ) . GetModule ( TEXT ( " AssetRegistry " ) ) ) ;
// Check in case AssetRegistry has already been shutdown.
if ( AssetRegistryModulePtr ! = nullptr )
{
AssetRegistryModulePtr - > Get ( ) . OnAssetAdded ( ) . Remove ( OnAssetAddedDelegateHandle ) ;
}
2021-05-26 18:15:46 -04:00
FCoreUObjectDelegates : : OnObjectPreSave . Remove ( OnObjectPreSavedDelegateHandle ) ;
2021-05-06 14:40:16 -04:00
}
bool FUncontrolledChangelistsModule : : IsEnabled ( ) const
{
return CVarUncontrolledChangelistsEnable . GetValueOnGameThread ( ) ;
}
TArray < FUncontrolledChangelistStateRef > FUncontrolledChangelistsModule : : GetChangelistStates ( ) const
{
TArray < FUncontrolledChangelistStateRef > UncontrolledChangelistStates ;
if ( IsEnabled ( ) )
{
Algo : : Transform ( UncontrolledChangelistsStateCache , UncontrolledChangelistStates , [ ] ( const auto & Pair ) { return Pair . Value ; } ) ;
}
return UncontrolledChangelistStates ;
}
2021-12-10 12:39:11 -05:00
bool FUncontrolledChangelistsModule : : OnMakeWritable ( const FString & InFilename )
2021-05-06 14:40:16 -04:00
{
2021-05-26 18:15:46 -04:00
bool bHasStateChanged = false ;
2021-05-06 14:40:16 -04:00
if ( ! IsEnabled ( ) )
{
2021-12-10 12:39:11 -05:00
return false ;
2021-05-06 14:40:16 -04:00
}
FUncontrolledChangelist DefaultUncontrolledChangelist ( FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_GUID , FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_NAME . ToString ( ) ) ;
FUncontrolledChangelistsStateCache : : ValueType & UncontrolledChangelistState = UncontrolledChangelistsStateCache . FindOrAdd ( MoveTemp ( DefaultUncontrolledChangelist ) , MakeShareable ( new FUncontrolledChangelistState ( DefaultUncontrolledChangelist ) ) ) ;
2021-05-26 18:15:46 -04:00
bHasStateChanged = UncontrolledChangelistState - > AddFiles ( { InFilename } , FUncontrolledChangelistState : : ECheckFlags : : NotCheckedOut ) ;
2021-05-06 14:40:16 -04:00
2021-05-26 18:15:46 -04:00
if ( bHasStateChanged )
{
OnStateChanged ( ) ;
}
2021-12-10 12:39:11 -05:00
return bHasStateChanged ;
2021-05-06 14:40:16 -04:00
}
void FUncontrolledChangelistsModule : : UpdateStatus ( )
{
2021-05-26 18:15:46 -04:00
bool bHasStateChanged = false ;
2021-05-06 14:40:16 -04:00
if ( ! IsEnabled ( ) )
{
return ;
}
for ( FUncontrolledChangelistsStateCache : : ElementType & Pair : UncontrolledChangelistsStateCache )
{
FUncontrolledChangelistsStateCache : : ValueType & UncontrolledChangelistState = Pair . Value ;
2021-05-26 18:15:46 -04:00
bHasStateChanged | = UncontrolledChangelistState - > UpdateStatus ( ) ;
2021-05-06 14:40:16 -04:00
}
2021-05-26 18:15:46 -04:00
if ( bHasStateChanged )
{
OnStateChanged ( ) ;
}
}
FText FUncontrolledChangelistsModule : : GetReconcileStatus ( ) const
{
2021-06-21 11:05:22 -04:00
return FText : : Format ( LOCTEXT ( " ReconcileStatus " , " Assets to check for reconcile: {0} " ) , FText : : AsNumber ( AddedAssetsCache . Num ( ) ) ) ;
2021-05-26 18:15:46 -04:00
}
2021-06-21 11:05:22 -04:00
bool FUncontrolledChangelistsModule : : OnReconcileAssets ( )
2021-05-26 18:15:46 -04:00
{
2021-06-21 11:05:22 -04:00
if ( ( ! IsEnabled ( ) ) | | AddedAssetsCache . IsEmpty ( ) )
2021-05-26 18:15:46 -04:00
{
2021-06-21 11:05:22 -04:00
return false ;
2021-05-26 18:15:46 -04:00
}
CleanAssetsCaches ( ) ;
2021-06-21 11:05:22 -04:00
bool bHasStateChanged = AddFilesToDefaultUncontrolledChangelist ( AddedAssetsCache . Array ( ) , FUncontrolledChangelistState : : ECheckFlags : : All ) ;
2021-05-26 18:15:46 -04:00
2021-06-21 11:05:22 -04:00
AddedAssetsCache . Empty ( ) ;
2021-05-26 18:15:46 -04:00
2021-06-21 11:05:22 -04:00
return bHasStateChanged ;
2021-05-26 18:15:46 -04:00
}
2021-05-06 14:40:16 -04:00
void FUncontrolledChangelistsModule : : OnAssetAdded ( const struct FAssetData & AssetData )
{
2021-05-26 18:15:46 -04:00
if ( ! IsEnabled ( ) )
{
return ;
}
2021-06-21 11:05:22 -04:00
FPackagePath PackagePath ;
if ( ! FPackagePath : : TryFromPackageName ( AssetData . PackageName , PackagePath ) )
{
return ;
}
2022-01-24 06:32:49 -05:00
if ( ! FPackageName : : DoesPackageExist ( PackagePath , & PackagePath ) )
{
return ; // If the package does not exist on disk there is nothing more to do
}
2021-06-21 11:05:22 -04:00
const FString LocalFullPath ( PackagePath . GetLocalFullPath ( ) ) ;
if ( LocalFullPath . IsEmpty ( ) )
{
return ;
}
FString Fullpath = FPaths : : ConvertRelativePathToFull ( LocalFullPath ) ;
2021-05-06 14:40:16 -04:00
if ( Fullpath . IsEmpty ( ) )
{
return ;
}
2021-05-26 18:15:46 -04:00
2021-06-21 11:05:22 -04:00
if ( ! IFileManager : : Get ( ) . IsReadOnly ( * Fullpath ) )
{
AddedAssetsCache . Add ( MoveTemp ( Fullpath ) ) ;
}
2021-05-06 14:40:16 -04:00
}
2021-05-26 18:15:46 -04:00
void FUncontrolledChangelistsModule : : OnObjectPreSaved ( UObject * InAsset , const FObjectPreSaveContext & InPreSaveContext )
2021-05-06 14:40:16 -04:00
{
2021-05-26 18:15:46 -04:00
if ( ! IsEnabled ( ) )
{
return ;
}
FString Fullpath = FPaths : : ConvertRelativePathToFull ( InPreSaveContext . GetTargetFilename ( ) ) ;
2021-05-06 14:40:16 -04:00
if ( Fullpath . IsEmpty ( ) )
{
return ;
}
2021-05-26 18:15:46 -04:00
2021-06-21 11:05:22 -04:00
AddedAssetsCache . Add ( MoveTemp ( Fullpath ) ) ;
2021-05-06 14:40:16 -04:00
}
2021-05-12 17:06:06 -04:00
void FUncontrolledChangelistsModule : : MoveFilesToUncontrolledChangelist ( const TArray < FSourceControlStateRef > & InControlledFileStates , const TArray < FSourceControlStateRef > & InUncontrolledFileStates , const FUncontrolledChangelist & InUncontrolledChangelist )
2021-05-06 14:40:16 -04:00
{
2021-05-26 18:15:46 -04:00
bool bHasStateChanged = false ;
2021-05-06 14:40:16 -04:00
if ( ! IsEnabled ( ) )
{
return ;
}
2021-05-12 17:06:06 -04:00
FUncontrolledChangelistsStateCache : : ValueType * ChangelistState = UncontrolledChangelistsStateCache . Find ( InUncontrolledChangelist ) ;
2021-05-06 14:40:16 -04:00
if ( ChangelistState = = nullptr )
{
return ;
}
2021-05-12 17:06:06 -04:00
TArray < FString > Filenames ;
Algo : : Transform ( InControlledFileStates , Filenames , [ ] ( const FSourceControlStateRef & State ) { return State - > GetFilename ( ) ; } ) ;
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
auto RevertOperation = ISourceControlOperation : : Create < FRevert > ( ) ;
// Revert controlled files
RevertOperation - > SetSoftRevert ( true ) ;
SourceControlProvider . Execute ( RevertOperation , Filenames ) ;
// Removes selected Uncontrolled Files from their Uncontrolled Changelists
for ( const auto & Pair : UncontrolledChangelistsStateCache )
{
const FUncontrolledChangelistStateRef & UncontrolledChangelistState = Pair . Value ;
UncontrolledChangelistState - > RemoveFiles ( InUncontrolledFileStates ) ;
}
Algo : : Transform ( InUncontrolledFileStates , Filenames , [ ] ( const FSourceControlStateRef & State ) { return State - > GetFilename ( ) ; } ) ;
// Add all files to their UncontrolledChangelist
2021-05-26 18:15:46 -04:00
bHasStateChanged = ( * ChangelistState ) - > AddFiles ( Filenames , FUncontrolledChangelistState : : ECheckFlags : : None ) ;
2021-05-06 14:40:16 -04:00
2021-05-26 18:15:46 -04:00
if ( bHasStateChanged )
{
OnStateChanged ( ) ;
}
2021-05-06 14:40:16 -04:00
}
2021-05-12 17:06:06 -04:00
void FUncontrolledChangelistsModule : : MoveFilesToControlledChangelist ( const TArray < FSourceControlStateRef > & InUncontrolledFileStates , const FSourceControlChangelistPtr & InChangelist )
{
if ( ! IsEnabled ( ) )
{
return ;
}
TArray < FString > UncontrolledFilenames ;
2021-06-14 15:25:40 -04:00
Algo : : Transform ( InUncontrolledFileStates , UncontrolledFilenames , [ ] ( const FSourceControlStateRef & State ) { return State - > GetFilename ( ) ; } ) ;
MoveFilesToControlledChangelist ( UncontrolledFilenames , InChangelist ) ;
}
void FUncontrolledChangelistsModule : : MoveFilesToControlledChangelist ( const TArray < FString > & InUncontrolledFiles , const FSourceControlChangelistPtr & InChangelist )
{
if ( ! IsEnabled ( ) )
{
return ;
}
ISourceControlProvider & SourceControlProvider = ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2021-05-12 17:06:06 -04:00
TArray < FSourceControlStateRef > UpdatedFilestates ;
// Get updated filestates to check Checkout capabilities.
2021-06-14 15:25:40 -04:00
SourceControlProvider . GetState ( InUncontrolledFiles , UpdatedFilestates , EStateCacheUsage : : ForceUpdate ) ;
2021-05-12 17:06:06 -04:00
TArray < UPackage * > PackageConflicts ;
2021-06-14 15:25:40 -04:00
TArray < FString > FilesToAdd ;
TArray < FString > FilesToCheckout ;
2022-02-02 05:30:58 -05:00
TArray < FString > FilesToDelete ;
2021-05-12 17:06:06 -04:00
2021-06-14 15:25:40 -04:00
// Check if we can Checkout files or mark for add
2021-05-12 17:06:06 -04:00
for ( const FSourceControlStateRef & Filestate : UpdatedFilestates )
{
2021-06-14 15:25:40 -04:00
if ( ! Filestate - > IsSourceControlled ( ) )
{
FilesToAdd . Add ( Filestate - > GetFilename ( ) ) ;
}
2022-02-02 05:30:58 -05:00
else if ( ! IFileManager : : Get ( ) . FileExists ( * Filestate - > GetFilename ( ) ) )
{
FilesToDelete . Add ( Filestate - > GetFilename ( ) ) ;
}
else if ( Filestate - > CanCheckout ( ) )
2021-06-14 15:25:40 -04:00
{
FilesToCheckout . Add ( Filestate - > GetFilename ( ) ) ;
}
2021-05-12 17:06:06 -04:00
}
bool bCanProceed = true ;
// If we detected conflict, asking user if we should proceed.
if ( ! PackageConflicts . IsEmpty ( ) )
{
bCanProceed = ShowConflictDialog ( PackageConflicts ) ;
}
if ( bCanProceed )
{
2021-06-14 15:25:40 -04:00
if ( ! FilesToCheckout . IsEmpty ( ) )
{
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FCheckOut > ( ) , InChangelist , FilesToCheckout ) ;
}
if ( ! FilesToAdd . IsEmpty ( ) )
{
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FMarkForAdd > ( ) , InChangelist , FilesToAdd ) ;
}
2021-05-26 18:15:46 -04:00
2022-02-02 05:30:58 -05:00
if ( ! FilesToDelete . IsEmpty ( ) )
{
SourceControlProvider . Execute ( ISourceControlOperation : : Create < FDelete > ( ) , InChangelist , FilesToDelete ) ;
}
2021-05-26 18:15:46 -04:00
// UpdateStatus so UncontrolledChangelists can remove files from their cache if they were present before checkout.
UpdateStatus ( ) ;
2021-05-12 17:06:06 -04:00
}
}
bool FUncontrolledChangelistsModule : : ShowConflictDialog ( TArray < UPackage * > InPackageConflicts )
{
FPackagesDialogModule & CheckoutPackagesDialogModule = FModuleManager : : LoadModuleChecked < FPackagesDialogModule > ( TEXT ( " PackagesDialog " ) ) ;
CheckoutPackagesDialogModule . CreatePackagesDialog ( LOCTEXT ( " CheckoutPackagesDialogTitle " , " Check Out Assets " ) ,
LOCTEXT ( " CheckoutPackagesDialogMessage " , " Conflict detected in the following assets: " ) ,
true ) ;
CheckoutPackagesDialogModule . AddButton ( DRT_CheckOut , LOCTEXT ( " Dlg_CheckOutButton " , " Check Out " ) , LOCTEXT ( " Dlg_CheckOutTooltip " , " Attempt to Check Out Assets " ) ) ;
CheckoutPackagesDialogModule . AddButton ( DRT_Cancel , LOCTEXT ( " Dlg_Cancel " , " Cancel " ) , LOCTEXT ( " Dlg_CancelTooltip " , " Cancel Request " ) ) ;
CheckoutPackagesDialogModule . SetWarning ( LOCTEXT ( " CheckoutPackagesWarnMessage " , " Warning: These assets are locked or not at the head revision. You may lose your changes if you continue, as you will be unable to submit them to source control. " ) ) ;
for ( UPackage * Conflict : InPackageConflicts )
{
CheckoutPackagesDialogModule . AddPackageItem ( Conflict , ECheckBoxState : : Undetermined ) ;
}
EDialogReturnType UserResponse = CheckoutPackagesDialogModule . ShowPackagesDialog ( ) ;
return UserResponse = = DRT_CheckOut ;
}
2021-05-26 18:15:46 -04:00
void FUncontrolledChangelistsModule : : OnStateChanged ( )
{
OnUncontrolledChangelistModuleChanged . Broadcast ( ) ;
SaveState ( ) ;
}
void FUncontrolledChangelistsModule : : CleanAssetsCaches ( )
{
// Remove files we are already tracking in Uncontrolled Changelists
for ( FUncontrolledChangelistsStateCache : : ElementType & Pair : UncontrolledChangelistsStateCache )
{
FUncontrolledChangelistsStateCache : : ValueType & UncontrolledChangelistState = Pair . Value ;
2021-06-21 11:05:22 -04:00
UncontrolledChangelistState - > RemoveDuplicates ( AddedAssetsCache ) ;
2021-05-26 18:15:46 -04:00
}
}
2021-06-21 11:05:22 -04:00
bool FUncontrolledChangelistsModule : : AddFilesToDefaultUncontrolledChangelist ( const TArray < FString > & InFilenames , const FUncontrolledChangelistState : : ECheckFlags InCheckFlags )
2021-05-26 18:15:46 -04:00
{
bool bHasStateChanged = false ;
FUncontrolledChangelist DefaultUncontrolledChangelist ( FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_GUID , FUncontrolledChangelist : : DEFAULT_UNCONTROLLED_CHANGELIST_NAME . ToString ( ) ) ;
FUncontrolledChangelistsStateCache : : ValueType & UncontrolledChangelistState = UncontrolledChangelistsStateCache . FindOrAdd ( MoveTemp ( DefaultUncontrolledChangelist ) , MakeShareable ( new FUncontrolledChangelistState ( DefaultUncontrolledChangelist ) ) ) ;
// Try to add files, they will be added only if they pass the required checks
bHasStateChanged = UncontrolledChangelistState - > AddFiles ( InFilenames , InCheckFlags ) ;
if ( bHasStateChanged )
{
OnStateChanged ( ) ;
}
2021-06-21 11:05:22 -04:00
return bHasStateChanged ;
2021-05-26 18:15:46 -04:00
}
2021-05-06 14:40:16 -04:00
void FUncontrolledChangelistsModule : : SaveState ( ) const
{
TSharedPtr < FJsonObject > RootObject = MakeShareable ( new FJsonObject ) ;
TArray < TSharedPtr < FJsonValue > > UncontrolledChangelistsArray ;
RootObject - > SetNumberField ( VERSION_NAME , VERSION_NUMBER ) ;
for ( const auto & Pair : UncontrolledChangelistsStateCache )
{
const FUncontrolledChangelist & UncontrolledChangelist = Pair . Key ;
FUncontrolledChangelistStateRef UncontrolledChangelistState = Pair . Value ;
TSharedPtr < FJsonObject > UncontrolledChangelistObject = MakeShareable ( new FJsonObject ) ;
UncontrolledChangelist . Serialize ( UncontrolledChangelistObject . ToSharedRef ( ) ) ;
UncontrolledChangelistState - > Serialize ( UncontrolledChangelistObject . ToSharedRef ( ) ) ;
UncontrolledChangelistsArray . Add ( MakeShareable ( new FJsonValueObject ( UncontrolledChangelistObject ) ) ) ;
}
RootObject - > SetArrayField ( CHANGELISTS_NAME , UncontrolledChangelistsArray ) ;
using FStringWriter = TJsonWriter < TCHAR , TPrettyJsonPrintPolicy < TCHAR > > ;
using FStringWriterFactory = TJsonWriterFactory < TCHAR , TPrettyJsonPrintPolicy < TCHAR > > ;
FString RootObjectStr ;
TSharedRef < FStringWriter > Writer = FStringWriterFactory : : Create ( & RootObjectStr ) ;
FJsonSerializer : : Serialize ( RootObject . ToSharedRef ( ) , Writer ) ;
FFileHelper : : SaveStringToFile ( RootObjectStr , * GetPersistentFilePath ( ) ) ;
}
void FUncontrolledChangelistsModule : : LoadState ( )
{
FString ImportJsonString ;
TSharedPtr < FJsonObject > RootObject ;
uint32 VersionNumber = 0 ;
const TArray < TSharedPtr < FJsonValue > > * UncontrolledChangelistsArray = nullptr ;
if ( ! FFileHelper : : LoadFileToString ( ImportJsonString , * GetPersistentFilePath ( ) ) )
{
return ;
}
TSharedRef < TJsonReader < > > JsonReader = TJsonReaderFactory < > : : Create ( ImportJsonString ) ;
if ( ! FJsonSerializer : : Deserialize ( JsonReader , RootObject ) )
{
UE_LOG ( LogSourceControl , Error , TEXT ( " Cannot deserialize RootObject. " ) ) ;
return ;
}
if ( ! RootObject - > TryGetNumberField ( VERSION_NAME , VersionNumber ) )
{
UE_LOG ( LogSourceControl , Error , TEXT ( " Cannot get field %s. " ) , VERSION_NAME ) ;
return ;
}
if ( VersionNumber ! = VERSION_NUMBER )
{
UE_LOG ( LogSourceControl , Error , TEXT ( " Version number is invalid (file: %u, current: %u). " ) , VersionNumber , VERSION_NUMBER ) ;
return ;
}
if ( ! RootObject - > TryGetArrayField ( CHANGELISTS_NAME , UncontrolledChangelistsArray ) )
{
UE_LOG ( LogSourceControl , Error , TEXT ( " Cannot get field %s. " ) , CHANGELISTS_NAME ) ;
return ;
}
for ( const TSharedPtr < FJsonValue > & JsonValue : * UncontrolledChangelistsArray )
{
FUncontrolledChangelist TempKey ;
TSharedRef < FJsonObject > JsonObject = JsonValue - > AsObject ( ) . ToSharedRef ( ) ;
if ( ! TempKey . Deserialize ( JsonObject ) )
{
UE_LOG ( LogSourceControl , Error , TEXT ( " Cannot deserialize FUncontrolledChangelist. " ) ) ;
continue ;
}
FUncontrolledChangelistsStateCache : : ValueType & UncontrolledChangelistState = UncontrolledChangelistsStateCache . FindOrAdd ( MoveTemp ( TempKey ) , MakeShareable ( new FUncontrolledChangelistState ( TempKey ) ) ) ;
UncontrolledChangelistState - > Deserialize ( JsonObject ) ;
}
2021-10-21 09:53:24 -04:00
UE_LOG ( LogSourceControl , Display , TEXT ( " Uncontrolled Changelist persistency file loaded %s " ) , * GetPersistentFilePath ( ) ) ;
2021-05-06 14:40:16 -04:00
}
FString FUncontrolledChangelistsModule : : GetPersistentFilePath ( ) const
{
return FPaths : : ProjectSavedDir ( ) + TEXT ( " SourceControl/UncontrolledChangelists.json " ) ;
}
FString FUncontrolledChangelistsModule : : GetUObjectPackageFullpath ( const UObject * InObject ) const
{
FString Fullpath = TEXT ( " " ) ;
if ( InObject = = nullptr )
{
return Fullpath ;
}
const UPackage * Package = InObject - > GetPackage ( ) ;
if ( Package = = nullptr )
{
return Fullpath ;
}
const FString LocalFullPath ( Package - > GetLoadedPath ( ) . GetLocalFullPath ( ) ) ;
if ( LocalFullPath . IsEmpty ( ) )
{
return Fullpath ;
}
Fullpath = FPaths : : ConvertRelativePathToFull ( LocalFullPath ) ;
return Fullpath ;
}
2021-10-25 20:05:28 -04:00
IMPLEMENT_MODULE ( FUncontrolledChangelistsModule , UncontrolledChangelists ) ;
2021-05-06 14:40:16 -04:00
# undef LOCTEXT_NAMESPACE