2020-09-01 08:38:42 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================================================
CommandletPackageHelper . cpp : Utility class that provides tools to handle packages & source control operations .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "Commandlets/CommandletPackageHelper.h"
# include "Logging/LogMacros.h"
# include "UObject/Package.h"
# include "HAL/FileManager.h"
# include "HAL/PlatformFileManager.h"
2020-09-11 08:14:37 -04:00
# include "PackageTools.h"
2020-09-01 08:38:42 -04:00
# include "ISourceControlOperation.h"
# include "ISourceControlModule.h"
# include "ISourceControlState.h"
# include "ISourceControlProvider.h"
# include "SourceControlOperations.h"
DEFINE_LOG_CATEGORY_STATIC ( LogCommandletPackageHelper , Log , All ) ;
FCommandletPackageHelper : : FCommandletPackageHelper ( )
{
}
2020-09-11 08:14:37 -04:00
FCommandletPackageHelper : : ~ FCommandletPackageHelper ( )
2020-09-01 08:38:42 -04:00
{
2020-09-11 08:14:37 -04:00
UPackage : : WaitForAsyncFileWrites ( ) ;
}
bool FCommandletPackageHelper : : UseSourceControl ( ) const
{
return ISourceControlModule : : Get ( ) . GetProvider ( ) . IsEnabled ( ) ;
}
ISourceControlProvider & FCommandletPackageHelper : : GetSourceControlProvider ( ) const
{
return ISourceControlModule : : Get ( ) . GetProvider ( ) ;
2020-09-01 08:38:42 -04:00
}
bool FCommandletPackageHelper : : Delete ( const FString & PackageName ) const
{
FString Filename = SourceControlHelpers : : PackageFilename ( PackageName ) ;
UE_LOG ( LogCommandletPackageHelper , Verbose , TEXT ( " Deleting %s " ) , * Filename ) ;
if ( ! UseSourceControl ( ) )
{
if ( ! IPlatformFile : : GetPlatformPhysical ( ) . SetReadOnly ( * Filename , false ) | |
! IPlatformFile : : GetPlatformPhysical ( ) . DeleteFile ( * Filename ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error deleting %s " ) , * Filename ) ;
return false ;
}
}
else
{
FSourceControlStatePtr SourceControlState = GetSourceControlProvider ( ) . GetState ( Filename , EStateCacheUsage : : ForceUpdate ) ;
if ( SourceControlState . IsValid ( ) & & SourceControlState - > IsSourceControlled ( ) )
{
FString OtherCheckedOutUser ;
if ( SourceControlState - > IsCheckedOutOther ( & OtherCheckedOutUser ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Overwriting package %s already checked out by %s, will not submit " ) , * Filename , * OtherCheckedOutUser ) ;
return false ;
}
else if ( ! SourceControlState - > IsCurrent ( ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Overwriting package %s (not at head revision), will not submit " ) , * Filename ) ;
return false ;
}
else if ( SourceControlState - > IsAdded ( ) )
{
if ( GetSourceControlProvider ( ) . Execute ( ISourceControlOperation : : Create < FRevert > ( ) , Filename ) ! = ECommandResult : : Succeeded )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error reverting package %s from source control " ) , * Filename ) ;
return false ;
}
}
else
{
UE_LOG ( LogCommandletPackageHelper , Log , TEXT ( " Deleting package %s from source control " ) , * Filename ) ;
if ( SourceControlState - > IsCheckedOut ( ) )
{
if ( GetSourceControlProvider ( ) . Execute ( ISourceControlOperation : : Create < FRevert > ( ) , Filename ) ! = ECommandResult : : Succeeded )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error reverting package %s from source control " ) , * Filename ) ;
return false ;
}
}
if ( GetSourceControlProvider ( ) . Execute ( ISourceControlOperation : : Create < FDelete > ( ) , Filename ) ! = ECommandResult : : Succeeded )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error deleting package %s from source control " ) , * Filename ) ;
return false ;
}
}
}
else
{
if ( ! IFileManager : : Get ( ) . Delete ( * Filename , false , true ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error deleting package %s locally " ) , * Filename ) ;
return false ;
}
}
}
return true ;
}
bool FCommandletPackageHelper : : Delete ( UPackage * Package ) const
{
2020-09-11 08:14:37 -04:00
TArray < UPackage * > Packages = { Package } ;
return Delete ( Packages ) ;
}
bool FCommandletPackageHelper : : Delete ( const TArray < FAssetData > & Assets ) const
{
bool bAllPackagesDeleted = true ;
for ( const FAssetData & AssetToDelete : Assets )
{
bAllPackagesDeleted & = Delete ( AssetToDelete . PackageName . ToString ( ) ) ;
}
return bAllPackagesDeleted ;
}
bool FCommandletPackageHelper : : Delete ( const TArray < UPackage * > & Packages ) const
{
2020-09-11 12:13:50 -04:00
if ( Packages . IsEmpty ( ) )
{
return true ;
}
2020-09-11 08:14:37 -04:00
// Store all packages names as we won't be able to retrieve them from the UPackages once they are unloaded
TArray < FString > PackagesNames ;
PackagesNames . Reserve ( Packages . Num ( ) ) ;
for ( UPackage * Package : Packages )
{
PackagesNames . Add ( Package - > GetName ( ) ) ;
// Must clear dirty flag befor unloading
Package - > SetDirtyFlag ( false ) ;
}
// Unload packages so we can delete them
FText ErrorMessage ;
if ( ! UPackageTools : : UnloadPackages ( Packages , ErrorMessage ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error unloading package: %s " ) , * ErrorMessage . ToString ( ) ) ;
return false ;
}
bool bAllPackagesDeleted = true ;
for ( const FString & PackageName : PackagesNames )
{
bAllPackagesDeleted & = Delete ( PackageName ) ;
}
return bAllPackagesDeleted ;
2020-09-01 08:38:42 -04:00
}
bool FCommandletPackageHelper : : AddToSourceControl ( UPackage * Package ) const
{
if ( UseSourceControl ( ) )
{
FString PackageFilename = SourceControlHelpers : : PackageFilename ( Package ) ;
FSourceControlStatePtr SourceControlState = GetSourceControlProvider ( ) . GetState ( PackageFilename , EStateCacheUsage : : ForceUpdate ) ;
if ( SourceControlState . IsValid ( ) & & ! SourceControlState - > IsSourceControlled ( ) )
{
UE_LOG ( LogCommandletPackageHelper , Log , TEXT ( " Adding package %s to source control " ) , * PackageFilename ) ;
if ( GetSourceControlProvider ( ) . Execute ( ISourceControlOperation : : Create < FMarkForAdd > ( ) , Package ) ! = ECommandResult : : Succeeded )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error adding %s to source control. " ) , * PackageFilename ) ;
return false ;
}
}
}
return true ;
}
bool FCommandletPackageHelper : : Save ( UPackage * Package ) const
{
FString PackageFileName = SourceControlHelpers : : PackageFilename ( Package ) ;
if ( ! UPackage : : SavePackage ( Package , nullptr , RF_Standalone , * PackageFileName , GError , nullptr , false , true , SAVE_Async ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error saving %s " ) , * PackageFileName ) ;
return false ;
}
return true ;
}
bool FCommandletPackageHelper : : Checkout ( UPackage * Package ) const
{
if ( UseSourceControl ( ) )
{
FString PackageFilename = SourceControlHelpers : : PackageFilename ( Package ) ;
FSourceControlStatePtr SourceControlState = GetSourceControlProvider ( ) . GetState ( PackageFilename , EStateCacheUsage : : ForceUpdate ) ;
if ( SourceControlState . IsValid ( ) )
{
FString OtherCheckedOutUser ;
if ( SourceControlState - > IsCheckedOutOther ( & OtherCheckedOutUser ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Overwriting package %s already checked out by %s, will not submit " ) , * PackageFilename , * OtherCheckedOutUser ) ;
return false ;
}
else if ( ! SourceControlState - > IsCurrent ( ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Overwriting package %s (not at head revision), will not submit " ) , * PackageFilename ) ;
return false ;
}
else if ( SourceControlState - > IsCheckedOut ( ) | | SourceControlState - > IsAdded ( ) )
{
UE_LOG ( LogCommandletPackageHelper , Log , TEXT ( " Skipping package %s (already checked out) " ) , * PackageFilename ) ;
return true ;
}
else if ( SourceControlState - > IsSourceControlled ( ) )
{
UE_LOG ( LogCommandletPackageHelper , Log , TEXT ( " Checking out package %s from source control " ) , * PackageFilename ) ;
return GetSourceControlProvider ( ) . Execute ( ISourceControlOperation : : Create < FCheckOut > ( ) , Package ) = = ECommandResult : : Succeeded ;
}
}
}
else
{
FString PackageFilename = SourceControlHelpers : : PackageFilename ( Package ) ;
if ( IPlatformFile : : GetPlatformPhysical ( ) . FileExists ( * PackageFilename ) )
{
if ( ! IPlatformFile : : GetPlatformPhysical ( ) . SetReadOnly ( * PackageFilename , false ) )
{
UE_LOG ( LogCommandletPackageHelper , Error , TEXT ( " Error setting %s writable " ) , * PackageFilename ) ;
return false ;
}
}
}
return true ;
}