2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-08-01 15:48:59 -04:00
/*=============================================================================
BuildPatchToolMain . cpp : Implements the BuildPatchTool application ' s main loop .
The tool can be used in two modes of operation :
( 1 ) to generate patch data ( manifest , chunks , files ) for build images given the existing cloud data ; or
( 2 ) to " compactify " a cloud directory by removing all orphaned chunks , not referenced by any manifest file .
In order to trigger compactify functionality , the - compactify commandline argument should be specified .
GENERATE PATCH DATA MODE
The tool supports generating chunk based patches or simple file based patches . Chunk based patch data will be generated by default
but you can switch to file based patch data by adding the - nochunks commandline argument .
File based patch data is only recommended for small build images that probably wouldn ' t benefit from chunking . I . e . Updates are commonly only a few small changed files .
Required arguments :
2015-01-31 17:00:57 -05:00
- BuildRoot = " " Specifies in quotes the directory containing the build image to be read .
- CloudDir = " " Specifies in quotes the cloud directory where existing data will be recognised from , and new data added to .
- AppID = 123456 Specifies without quotes , the ID number for the app
- AppName = " " Specifies in quotes , the name of the app
- BuildVersion = " " Specifies in quotes , the version string for the build image
- AppLaunch = " " Specifies in quotes , the path to the app executable , must be relative to , and inside of BuildRoot .
- AppArgs = " " Specifies in quotes , the commandline to send to the app on launch .
2014-08-01 15:48:59 -04:00
Optional arguments :
2015-01-31 17:00:57 -05:00
- stdout Adds stdout logging to the app .
- nochunks Creates file based patch data instead of chunk based patch data . Should not be used with builds that have large files .
- FileIgnoreList = " " Specifies in quotes , the path to a text file containing BuildRoot relative files , separated by \ r \ n line endings , to not be included in the build .
- FileAttributeList = " " Specifies in quotes , the path to a text file containing quoted BuildRoot relative files followed by optional attribute keywords readonly compressed executable , separated by \ r \ n line endings . These attribute will be applied when build is installed client side .
- PrereqName = " " Specifies in quotes , the display name for the prerequisites installer
- PrereqPath = " " Specifies in quotes , the prerequisites installer to launch on successful product install
- PrereqArgs = " " Specifies in quotes , the commandline to send to prerequisites installer on launch
- DataAgeThreshold = 12.5 Specified the maximum age ( in days ) of existing patch data which can be reused in the generated manifest
2014-09-12 12:11:13 -04:00
2014-09-16 10:26:24 -04:00
NB : - DataAgeThreshold can also be present in the [ PatchGeneration ] section of BuildPatchTool . ini in the cloud directory
NB : If - DataAgeThreshold is not supplied , either on the command - line or in BuildPatchTool . ini , then all existing data is eligible for reuse in the generated manifest
2014-09-12 12:11:13 -04:00
Example command lines :
- BuildRoot = " D: \ Builds \ ExampleGame_[07-02_03.00] " - FileIgnoreList = " D: \ Builds \ ExampleGame_[07-02_03.00] \ Manifest_DebugFiles.txt " - CloudDir = " D: \ BuildPatchCloud " - AppID = 123456 - AppName = " Example " - BuildVersion = " ExampleGame_[07-02_03.00] " - AppLaunch = " . \ ExampleGame \ Binaries \ Win32 \ ExampleGame.exe " - AppArgs = " -pak -nosteam " - DataAgeThreshold = 12
- BuildRoot = " C: \ Program Files (x86) \ Community Portal " - CloudDir = " E: \ BuildPatchCloud " - AppID = 0 - AppName = " Community Portal " - BuildVersion = " ++depot+UE4-CL-1791234 " - AppLaunch = " . \ Engine \ Binaries \ Win32 \ CommunityPortal.exe " - AppArgs = " " - nochunks - DataAgeThreshold = 12
2014-08-01 15:48:59 -04:00
- custom = " field=value " Adds a custom string field to the build manifest
- customint = " field=number " Adds a custom int64 field to the build manifest
- customfloat = " field=number " Adds a custom double field to the build manifest
COMPACTIFY MODE
Required arguments :
- CloudDir = " " Specifies in quotes the cloud directory where manifest files and chunks to be compactified can be found .
- compactify Must be specified to launch the tool in compactify mode
Optional arguments :
- stdout Adds stdout logging to the app .
- preview Log all the actions it will take to update internal structures , but don ' t actually execute them .
2014-12-01 08:45:58 -05:00
- nopatchdelete When specified , will only set the modified date of referenced files to the current time , but will NOT delete any patch data .
2014-09-12 12:11:13 -04:00
- ManifestsList = " " Specifies in quotes , the list of manifest filenames to keep following the operation . If omitted , all manifests are kept .
- ManifestsFile = " " Specifies in quotes , the name of the file ( relative to CloudDir ) which contains a list of manifests to keep , one manifest filename per line
- DataAgeThreshold = 14.25 The maximum age in days of chunk files that will be retained . All older chunks will be deleted .
2014-08-01 15:48:59 -04:00
2014-09-12 12:11:13 -04:00
NB : If - ManifestsList is specified , then - ManifestsFile is ignored .
2014-09-16 10:26:24 -04:00
NB : - DataAgeThreshold can also be present in the [ Compactify ] section of BuildPatchTool . ini in the cloud directory
NB : If - DataAgeThreshold is not supplied , either on the command - line or in BuildPatchTool . ini , then all unreferenced existing data is eligible for deletion by the compactify process
2014-08-01 15:48:59 -04:00
Example command lines :
2014-09-12 12:11:13 -04:00
- CloudDir = " E: \ BuildPatchCloud " - compactify - DataAgeThreshold = 14
- CloudDir = " E: \ BuildPatchCloud " - compactify - DataAgeThreshold = 14 - ManifestsList = " Example_V1.manifest,Example_V2.manifest "
- CloudDir = " E: \ BuildPatchCloud " - compactify - DataAgeThreshold = 14 - ManifestsFile = " preserve_manifests.txt "
2015-03-13 08:26:18 -04:00
DATA ENUMERATE MODE
Required arguments :
- ManifestFile = " " Specifies in quotes the file path to the manifest to enumerate from
- OutputFile = " " Specifies in quotes the file path to a file where the list will be saved out , \ r \ n separated cloud relative paths .
2015-03-23 10:44:22 -04:00
- includesizes When specified , the size of each file ( in bytes ) will be output following the filename and a tab . I . e . / path / to / chunk \ t1233
2015-03-13 08:26:18 -04:00
- dataenumerate Must be specified to launch the tool in cloud seeder mode
2014-08-01 15:48:59 -04:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
# include "RequiredProgramMainCPPInclude.h"
# include "BuildPatchServices.h"
2014-10-08 06:33:06 -04:00
# include "CoreUObject.h"
2014-08-01 15:48:59 -04:00
// Ensure compiled with patch generation code
# if WITH_BUILDPATCHGENERATION
# else
# error BuildPatchTool must define WITH_BUILDPATCHGENERATION
# endif
IMPLEMENT_APPLICATION ( BuildPatchTool , " BuildPatchTool " ) ;
struct FCommandLineMatcher
{
2015-03-13 08:26:18 -04:00
const FString Command ;
2014-08-01 15:48:59 -04:00
2015-04-22 17:41:37 -04:00
FCommandLineMatcher ( FString InCommand )
: Command ( MoveTemp ( InCommand ) )
2015-03-13 08:26:18 -04:00
{ }
2014-08-01 15:48:59 -04:00
2014-09-30 11:35:57 -04:00
FORCEINLINE bool operator ( ) ( const FString & ToMatch ) const
2014-08-01 15:48:59 -04:00
{
2014-09-30 11:35:57 -04:00
if ( ToMatch . StartsWith ( Command , ESearchCase : : CaseSensitive ) )
2014-08-01 15:48:59 -04:00
{
return true ;
}
return false ;
}
} ;
class FBuildPatchOutputDevice : public FOutputDevice
{
public :
virtual void Serialize ( const TCHAR * V , ELogVerbosity : : Type Verbosity , const class FName & Category ) override
{
# if PLATFORM_USE_LS_SPEC_FOR_WIDECHAR
printf ( " \n %ls " , * FOutputDevice : : FormatLogLine ( Verbosity , Category , V , GPrintLogTimes ) ) ;
# else
wprintf ( TEXT ( " \n %s " ) , * FOutputDevice : : FormatLogLine ( Verbosity , Category , V , GPrintLogTimes ) ) ;
# endif
fflush ( stdout ) ;
}
} ;
2015-03-13 08:26:18 -04:00
namespace EBuildPatchToolMode
{
enum Type
{
PatchGeneration ,
Compactify ,
DataEnumeration ,
Unknown
} ;
}
2014-08-01 15:48:59 -04:00
int32 BuildPatchToolMain ( const TCHAR * CommandLine )
{
2015-04-29 11:57:46 -04:00
GEngineLoop . PreInit ( CommandLine ) ;
2014-08-01 15:48:59 -04:00
2015-04-29 11:57:46 -04:00
// Add log device
2014-08-01 15:48:59 -04:00
if ( FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " stdout " ) ) )
{
GLog - > AddOutputDevice ( new FBuildPatchOutputDevice ( ) ) ;
}
GLog - > Logf ( TEXT ( " BuildPatchToolMain ran with: %s " ) , CommandLine ) ;
bool bSuccess = false ;
FString RootDirectory ;
FString CloudDirectory ;
uint32 AppID = 0 ;
FString AppName ;
FString BuildVersion ;
FString LaunchExe ;
FString LaunchCommand ;
FString IgnoreListFile ;
2015-01-31 17:00:57 -05:00
FString AttributeListFile ;
2014-08-01 15:48:59 -04:00
FString PrereqName ;
FString PrereqPath ;
FString PrereqArgs ;
2014-09-12 12:11:13 -04:00
FString ManifestsList ;
FString ManifestsFile ;
float DataAgeThreshold = 0.0f ;
FString IniFile ;
2014-08-01 15:48:59 -04:00
TMap < FString , FVariant > CustomFields ;
2015-03-13 08:26:18 -04:00
FString ManifestFile ;
FString OutputFile ;
2014-08-01 15:48:59 -04:00
2015-03-13 08:26:18 -04:00
EBuildPatchToolMode : : Type ToolMode = EBuildPatchToolMode : : Unknown ;
2014-09-12 12:11:13 -04:00
bool bPreview = false ;
2014-12-01 08:45:58 -05:00
bool bNoPatchDelete = false ;
2014-09-16 10:26:24 -04:00
bool bPatchWithReuseAgeThreshold = true ;
2015-03-23 07:11:06 -04:00
bool bIncludeSizes = false ;
2014-08-01 15:48:59 -04:00
// Collect all the info from the CommandLine
TArray < FString > Tokens , Switches ;
FCommandLine : : Parse ( FCommandLine : : Get ( ) , Tokens , Switches ) ;
if ( Switches . Num ( ) > 0 )
{
int32 BuildRootIdx ;
int32 CloudDirIdx ;
int32 AppIDIdx ;
int32 AppNameIdx ;
int32 BuildVersionIdx ;
int32 AppLaunchIdx ;
int32 AppArgsIdx ;
int32 FileIgnoreListIdx ;
2015-01-31 17:00:57 -05:00
int32 FileAttributeListIdx ;
2014-08-01 15:48:59 -04:00
int32 PrereqNameIdx ;
int32 PrereqPathIdx ;
int32 PrereqArgsIdx ;
2014-09-12 12:11:13 -04:00
int32 ManifestsListIdx ;
int32 ManifestsFileIdx ;
int32 DataAgeThresholdIdx ;
2015-03-13 08:26:18 -04:00
int32 ManifestFileIdx ;
int32 OutputFileIdx ;
2014-08-01 15:48:59 -04:00
bSuccess = true ;
2015-03-13 08:26:18 -04:00
if ( Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " compactify " ) ) ) ! = INDEX_NONE )
{
ToolMode = EBuildPatchToolMode : : Compactify ;
}
else if ( Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " dataenumerate " ) ) ) ! = INDEX_NONE )
{
ToolMode = EBuildPatchToolMode : : DataEnumeration ;
}
else
{
ToolMode = EBuildPatchToolMode : : PatchGeneration ;
}
bPreview = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " preview " ) ) ) ! = INDEX_NONE ;
bNoPatchDelete = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " nopatchdelete " ) ) ) ! = INDEX_NONE ;
2015-03-23 07:11:06 -04:00
bIncludeSizes = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " includesizes " ) ) ) ! = INDEX_NONE ;
2015-03-13 08:26:18 -04:00
BuildRootIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " BuildRoot " ) ) ) ;
CloudDirIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " CloudDir " ) ) ) ;
AppIDIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " AppID " ) ) ) ;
AppNameIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " AppName " ) ) ) ;
BuildVersionIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " BuildVersion " ) ) ) ;
AppLaunchIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " AppLaunch " ) ) ) ;
AppArgsIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " AppArgs " ) ) ) ;
FileIgnoreListIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " FileIgnoreList " ) ) ) ;
FileAttributeListIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " FileAttributeList " ) ) ) ;
PrereqNameIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " PrereqName " ) ) ) ;
PrereqPathIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " PrereqPath " ) ) ) ;
PrereqArgsIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " PrereqArgs " ) ) ) ;
ManifestsListIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " ManifestsList " ) ) ) ;
ManifestsFileIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " ManifestsFile " ) ) ) ;
DataAgeThresholdIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " DataAgeThreshold " ) ) ) ;
ManifestFileIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " ManifestFile " ) ) ) ;
OutputFileIdx = Switches . IndexOfByPredicate ( FCommandLineMatcher ( TEXT ( " OutputFile " ) ) ) ;
2014-09-12 12:11:13 -04:00
2014-08-01 15:48:59 -04:00
// Check required param indexes
2015-03-13 08:26:18 -04:00
switch ( ToolMode )
2014-08-01 15:48:59 -04:00
{
2015-03-13 08:26:18 -04:00
case EBuildPatchToolMode : : PatchGeneration :
bSuccess = bSuccess & & CloudDirIdx ! = INDEX_NONE ;
2014-08-01 15:48:59 -04:00
bSuccess = bSuccess & & BuildRootIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & AppIDIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & AppNameIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & BuildVersionIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & AppLaunchIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & AppArgsIdx ! = INDEX_NONE ;
2015-03-13 08:26:18 -04:00
break ;
case EBuildPatchToolMode : : Compactify :
bSuccess = bSuccess & & CloudDirIdx ! = INDEX_NONE ;
break ;
case EBuildPatchToolMode : : DataEnumeration :
bSuccess = bSuccess & & ManifestFileIdx ! = INDEX_NONE ;
bSuccess = bSuccess & & OutputFileIdx ! = INDEX_NONE ;
break ;
2014-08-01 15:48:59 -04:00
}
// Get required param values
2015-03-13 08:26:18 -04:00
switch ( ToolMode )
2014-08-01 15:48:59 -04:00
{
2015-03-13 08:26:18 -04:00
case EBuildPatchToolMode : : PatchGeneration :
bSuccess = bSuccess & & FParse : : Value ( * Switches [ CloudDirIdx ] , TEXT ( " CloudDir= " ) , CloudDirectory ) ;
2014-08-01 15:48:59 -04:00
bSuccess = bSuccess & & FParse : : Value ( * Switches [ BuildRootIdx ] , TEXT ( " BuildRoot= " ) , RootDirectory ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ AppIDIdx ] , TEXT ( " AppID= " ) , AppID ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ AppNameIdx ] , TEXT ( " AppName= " ) , AppName ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ BuildVersionIdx ] , TEXT ( " BuildVersion= " ) , BuildVersion ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ AppLaunchIdx ] , TEXT ( " AppLaunch= " ) , LaunchExe ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ AppArgsIdx ] , TEXT ( " AppArgs= " ) , LaunchCommand ) ;
2015-03-13 08:26:18 -04:00
break ;
case EBuildPatchToolMode : : Compactify :
bSuccess = bSuccess & & FParse : : Value ( * Switches [ CloudDirIdx ] , TEXT ( " CloudDir= " ) , CloudDirectory ) ;
break ;
case EBuildPatchToolMode : : DataEnumeration :
bSuccess = bSuccess & & FParse : : Value ( * Switches [ ManifestFileIdx ] , TEXT ( " ManifestFile= " ) , ManifestFile ) ;
bSuccess = bSuccess & & FParse : : Value ( * Switches [ OutputFileIdx ] , TEXT ( " OutputFile= " ) , OutputFile ) ;
break ;
2014-08-01 15:48:59 -04:00
}
// Get optional param values
if ( FileIgnoreListIdx ! = INDEX_NONE )
{
FParse : : Value ( * Switches [ FileIgnoreListIdx ] , TEXT ( " FileIgnoreList= " ) , IgnoreListFile ) ;
}
2015-01-31 17:00:57 -05:00
if ( FileAttributeListIdx ! = INDEX_NONE )
{
FParse : : Value ( * Switches [ FileAttributeListIdx ] , TEXT ( " FileAttributeList= " ) , AttributeListFile ) ;
}
2014-08-01 15:48:59 -04:00
if ( PrereqNameIdx ! = INDEX_NONE )
{
2014-10-08 06:33:06 -04:00
FParse : : Value ( * Switches [ PrereqNameIdx ] , TEXT ( " PrereqName= " ) , PrereqName ) ;
2014-08-01 15:48:59 -04:00
}
if ( PrereqPathIdx ! = INDEX_NONE )
{
2014-10-08 06:33:06 -04:00
FParse : : Value ( * Switches [ PrereqPathIdx ] , TEXT ( " PrereqPath= " ) , PrereqPath ) ;
2014-08-01 15:48:59 -04:00
}
if ( PrereqArgsIdx ! = INDEX_NONE )
{
2014-10-08 06:33:06 -04:00
FParse : : Value ( * Switches [ PrereqArgsIdx ] , TEXT ( " PrereqArgs= " ) , PrereqArgs ) ;
2014-08-01 15:48:59 -04:00
}
2014-09-12 12:11:13 -04:00
if ( ManifestsListIdx ! = INDEX_NONE )
{
bool bShouldStopOnComma = false ;
FParse : : Value ( * Switches [ ManifestsListIdx ] , TEXT ( " ManifestsList= " ) , ManifestsList , bShouldStopOnComma ) ;
}
else if ( ManifestsFileIdx ! = INDEX_NONE )
{
FParse : : Value ( * Switches [ ManifestsFileIdx ] , TEXT ( " ManifestsFile= " ) , ManifestsFile ) ;
}
2014-08-01 15:48:59 -04:00
FString CustomValue ;
FString Left ;
FString Right ;
for ( const auto & Switch : Switches )
{
if ( FParse : : Value ( * Switch , TEXT ( " custom= " ) , CustomValue ) )
{
if ( CustomValue . Split ( TEXT ( " = " ) , & Left , & Right ) )
{
Left . Trim ( ) ;
Left . TrimTrailing ( ) ;
Right . Trim ( ) ;
Right . TrimTrailing ( ) ;
CustomFields . Add ( Left , FVariant ( Right ) ) ;
}
}
else if ( FParse : : Value ( * Switch , TEXT ( " customfloat= " ) , CustomValue ) )
{
if ( CustomValue . Split ( TEXT ( " = " ) , & Left , & Right ) )
{
Left . Trim ( ) ;
Left . TrimTrailing ( ) ;
Right . Trim ( ) ;
Right . TrimTrailing ( ) ;
if ( ! Right . IsNumeric ( ) )
{
2014-10-08 06:33:06 -04:00
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " An error occurred processing token -customfloat. Non Numeric character found right of = " ) ) ;
2014-08-01 15:48:59 -04:00
bSuccess = false ;
}
CustomFields . Add ( Left , FVariant ( TCString < TCHAR > : : Atod ( * Right ) ) ) ;
}
}
else if ( FParse : : Value ( * Switch , TEXT ( " customint= " ) , CustomValue ) )
{
if ( CustomValue . Split ( TEXT ( " = " ) , & Left , & Right ) )
{
Left . Trim ( ) ;
Left . TrimTrailing ( ) ;
Right . Trim ( ) ;
Right . TrimTrailing ( ) ;
if ( ! Right . IsNumeric ( ) )
{
2014-10-08 06:33:06 -04:00
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " An error occurred processing token -customint. Non Numeric character found right of = " ) ) ;
2014-08-01 15:48:59 -04:00
bSuccess = false ;
}
CustomFields . Add ( Left , FVariant ( TCString < TCHAR > : : Atoi64 ( * Right ) ) ) ;
}
}
}
FPaths : : NormalizeDirectoryName ( RootDirectory ) ;
FPaths : : NormalizeDirectoryName ( CloudDirectory ) ;
2014-09-12 12:11:13 -04:00
if ( bSuccess )
{
// Initialize the configuration system, we can only do this reliably if we have CloudDirectory (i.e. bSuccess is true)
IniFile = CloudDirectory / TEXT ( " BuildPatchTool.ini " ) ;
GConfig - > InitializeConfigSystem ( ) ;
2015-03-23 07:11:06 -04:00
if ( DataAgeThresholdIdx ! = INDEX_NONE )
{
FParse : : Value ( * Switches [ DataAgeThresholdIdx ] , TEXT ( " DataAgeThreshold= " ) , DataAgeThreshold ) ;
}
2015-03-13 08:26:18 -04:00
else
{
switch ( ToolMode )
2015-03-23 07:11:06 -04:00
{
2015-03-13 08:26:18 -04:00
case EBuildPatchToolMode : : Compactify :
2015-03-23 07:11:06 -04:00
// For compactification, if we don't pass in DataAgeThreshold, and it's not in BuildPatchTool.ini,
// then we set it to zero, to indicate that any unused chunks are valid for deletion
if ( ! GConfig - > GetFloat ( TEXT ( " Compactify " ) , TEXT ( " DataAgeThreshold " ) , DataAgeThreshold , IniFile ) )
{
GLog - > Log ( ELogVerbosity : : Warning , TEXT ( " DataAgeThreshold not supplied, so all unreferenced data is eliglble for deletion. Note that this process is NOT compatible with any concurrently running patch generaiton processes " ) ) ;
DataAgeThreshold = 0.0f ;
}
2015-03-13 08:26:18 -04:00
break ;
case EBuildPatchToolMode : : PatchGeneration :
2015-03-23 07:11:06 -04:00
// For patch generation, if we don't pass in DataAgeThreshold, and it's not specified in BuildPatchTool.ini,
// then we set bChunkWithReuseAgeThreshold to false, which indicates that *all* patch data is valid for reuse
if ( ! GConfig - > GetFloat ( TEXT ( " PatchGeneration " ) , TEXT ( " DataAgeThreshold " ) , DataAgeThreshold , IniFile ) )
{
GLog - > Log ( ELogVerbosity : : Warning , TEXT ( " DataAgeThreshold not supplied, so all existing data is eligible for reuse. Note that this process is NOT compatible with any concurrently running compactify processes " ) ) ;
DataAgeThreshold = 0.0f ;
bPatchWithReuseAgeThreshold = false ;
}
2015-03-13 08:26:18 -04:00
break ;
}
2014-09-12 12:11:13 -04:00
}
}
2014-08-01 15:48:59 -04:00
}
2015-01-31 17:00:57 -05:00
// Initialize the file manager
IFileManager : : Get ( ) . ProcessCommandLineOptions ( ) ;
2014-08-01 15:48:59 -04:00
// Check for argument error
if ( ! bSuccess )
{
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " An error occurred processing arguments " ) ) ;
return 1 ;
}
2015-03-13 08:26:18 -04:00
if ( ToolMode = = EBuildPatchToolMode : : Compactify & & bPreview & & bNoPatchDelete )
2014-10-20 10:03:26 -04:00
{
2014-12-01 08:45:58 -05:00
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " Only one of -preview and -nopatchdelete can be specified " ) ) ;
2014-10-20 10:03:26 -04:00
return 5 ;
}
2014-08-01 15:48:59 -04:00
2015-01-31 17:00:57 -05:00
if ( ! IgnoreListFile . IsEmpty ( ) & & ! FPaths : : FileExists ( IgnoreListFile ) )
{
GLog - > Logf ( ELogVerbosity : : Error , TEXT ( " Provided file ignore list was not found %s " ) , * IgnoreListFile ) ;
return 6 ;
}
if ( ! AttributeListFile . IsEmpty ( ) & & ! FPaths : : FileExists ( AttributeListFile ) )
{
GLog - > Logf ( ELogVerbosity : : Error , TEXT ( " Provided file attribute list was not found %s " ) , * AttributeListFile ) ;
return 7 ;
}
2014-08-01 15:48:59 -04:00
// Load the BuildPatchServices Module
TSharedPtr < IBuildPatchServicesModule > BuildPatchServicesModule = StaticCastSharedPtr < IBuildPatchServicesModule > ( FModuleManager : : Get ( ) . LoadModule ( TEXT ( " BuildPatchServices " ) ) ) ;
2014-10-08 06:33:06 -04:00
// Initialise the UObject system and process our uobject classes
FModuleManager : : Get ( ) . LoadModule ( TEXT ( " CoreUObject " ) ) ;
FCoreDelegates : : OnInit . Broadcast ( ) ;
ProcessNewlyLoadedUObjects ( ) ;
2014-08-01 15:48:59 -04:00
// Setup the module
BuildPatchServicesModule - > SetCloudDirectory ( CloudDirectory + TEXT ( " / " ) ) ;
2015-03-13 08:26:18 -04:00
// Run the mode!
switch ( ToolMode )
{
2015-03-23 07:11:06 -04:00
case EBuildPatchToolMode : : Compactify :
2014-08-01 15:48:59 -04:00
{
2014-09-12 12:11:13 -04:00
// Split out our manifests to keep arg (if any) into an array of manifest filenames
TArray < FString > ManifestsArr ;
if ( ManifestsList . Len ( ) > 0 )
{
2015-03-02 15:51:37 -05:00
ManifestsList . ParseIntoArray ( ManifestsArr , TEXT ( " , " ) , true ) ;
2014-09-12 12:11:13 -04:00
}
else if ( ManifestsFile . Len ( ) > 0 )
{
FString ManifestsFilePath = CloudDirectory / ManifestsFile ;
FString Temp ;
if ( FFileHelper : : LoadFileToString ( Temp , * ManifestsFilePath ) )
{
Temp . ReplaceInline ( TEXT ( " \r " ) , TEXT ( " \n " ) ) ;
2015-03-02 15:51:37 -05:00
Temp . ParseIntoArray ( ManifestsArr , TEXT ( " \n " ) , true ) ;
2014-09-12 12:11:13 -04:00
}
else
{
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " Could not open specified manifests to keep file " ) ) ;
BuildPatchServicesModule . Reset ( ) ;
2014-10-08 06:33:06 -04:00
FCoreDelegates : : OnExit . Broadcast ( ) ;
2014-09-12 12:11:13 -04:00
return 2 ;
}
}
2014-10-20 10:03:26 -04:00
// Determine our mode of operation
ECompactifyMode : : Type CompactifyMode = ECompactifyMode : : Full ;
if ( bPreview )
{
CompactifyMode = ECompactifyMode : : Preview ;
}
2014-12-01 08:45:58 -05:00
else if ( bNoPatchDelete )
2014-10-20 10:03:26 -04:00
{
2014-12-01 08:45:58 -05:00
CompactifyMode = ECompactifyMode : : NoPatchDelete ;
2014-10-20 10:03:26 -04:00
}
2014-08-01 15:48:59 -04:00
// Run the compactify routine
2014-10-20 10:03:26 -04:00
bSuccess = BuildPatchServicesModule - > CompactifyCloudDirectory ( ManifestsArr , DataAgeThreshold , CompactifyMode ) ;
2014-08-01 15:48:59 -04:00
}
2015-03-13 08:26:18 -04:00
break ;
2015-03-23 07:11:06 -04:00
case EBuildPatchToolMode : : PatchGeneration :
2014-08-01 15:48:59 -04:00
{
FBuildPatchSettings Settings ;
Settings . RootDirectory = RootDirectory + TEXT ( " / " ) ;
2014-10-08 06:33:06 -04:00
Settings . AppID = AppID ;
2014-08-01 15:48:59 -04:00
Settings . AppName = AppName ;
Settings . BuildVersion = BuildVersion ;
Settings . LaunchExe = LaunchExe ;
Settings . LaunchCommand = LaunchCommand ;
Settings . IgnoreListFile = IgnoreListFile ;
2015-01-31 17:00:57 -05:00
Settings . AttributeListFile = AttributeListFile ;
2014-08-01 15:48:59 -04:00
Settings . PrereqName = PrereqName ;
Settings . PrereqPath = PrereqPath ;
Settings . PrereqArgs = PrereqArgs ;
2014-09-12 12:11:13 -04:00
Settings . DataAgeThreshold = DataAgeThreshold ;
2014-09-16 10:26:24 -04:00
Settings . bShouldHonorReuseThreshold = bPatchWithReuseAgeThreshold ;
2014-08-01 15:48:59 -04:00
Settings . CustomFields = CustomFields ;
// Run the build generation
if ( FParse : : Param ( FCommandLine : : Get ( ) , TEXT ( " nochunks " ) ) )
{
bSuccess = BuildPatchServicesModule - > GenerateFilesManifestFromDirectory ( Settings ) ;
}
else
{
bSuccess = BuildPatchServicesModule - > GenerateChunksManifestFromDirectory ( Settings ) ;
}
}
2015-03-13 08:26:18 -04:00
break ;
2015-03-23 07:11:06 -04:00
case EBuildPatchToolMode : : DataEnumeration :
{
// Run the data enumeration routine
bSuccess = BuildPatchServicesModule - > EnumerateManifestData ( MoveTemp ( ManifestFile ) , MoveTemp ( OutputFile ) , bIncludeSizes ) ;
}
2015-03-13 08:26:18 -04:00
break ;
2015-03-23 07:11:06 -04:00
default :
2014-09-12 12:11:13 -04:00
{
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " Unknown tool mode " ) ) ;
BuildPatchServicesModule . Reset ( ) ;
2014-10-08 06:33:06 -04:00
FCoreDelegates : : OnExit . Broadcast ( ) ;
2015-03-23 07:11:06 -04:00
}
2014-09-12 12:11:13 -04:00
return 3 ;
}
2014-08-01 15:48:59 -04:00
// Release the module ptr
BuildPatchServicesModule . Reset ( ) ;
// Check for processing error
if ( ! bSuccess )
{
2014-09-12 12:11:13 -04:00
GLog - > Log ( ELogVerbosity : : Error , TEXT ( " A fatal error occurred executing BuildPatchTool.exe " ) ) ;
2014-10-08 06:33:06 -04:00
FCoreDelegates : : OnExit . Broadcast ( ) ;
2014-09-12 12:11:13 -04:00
return 4 ;
2014-08-01 15:48:59 -04:00
}
2014-10-08 06:33:06 -04:00
FCoreDelegates : : OnExit . Broadcast ( ) ;
2014-08-01 15:48:59 -04:00
GLog - > Log ( TEXT ( " BuildPatchToolMain completed successfuly " ) ) ;
return 0 ;
}
INT32_MAIN_INT32_ARGC_TCHAR_ARGV ( )
{
FString CommandLine ;
for ( int32 Option = 1 ; Option < ArgC ; Option + + )
{
CommandLine + = TEXT ( " " ) ;
FString Argument ( ArgV [ Option ] ) ;
if ( Argument . Contains ( TEXT ( " " ) ) )
{
if ( Argument . Contains ( TEXT ( " = " ) ) )
{
FString ArgName ;
FString ArgValue ;
Argument . Split ( TEXT ( " = " ) , & ArgName , & ArgValue ) ;
Argument = FString : : Printf ( TEXT ( " %s= \" %s \" " ) , * ArgName , * ArgValue ) ;
}
else
{
Argument = FString : : Printf ( TEXT ( " \" %s \" " ) , * Argument ) ;
}
}
CommandLine + = Argument ;
}
return BuildPatchToolMain ( * CommandLine ) ;
}