HAxis sos

This commit is contained in:
guus
2018-08-11 16:46:35 +02:00
commit 510654f8a1
480 changed files with 54126 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "Mantis Plugin",
"Description": "A plugin to add an interface in Unreal for Mantis bug reports.",
"Category": "Bugs",
"CreatedBy": "Yoshi van Belkom",
"CreatedByURL": "http://www.yoshivanbelkom.com/",
"Modules": [
{
"Name": "Mantis",
"Type": "Developer",
"LoadingPhase": "PreDefault"
}
],
"EnabledByDefault": true,
"CanContainContent": true,
"IsBetaVersion": true,
"Installed": false
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,70 @@
#pragma once
#include "Engine/EngineTypes.h"
#include "MantisSettings.generated.h"
USTRUCT()
struct FBatchBinding
{
GENERATED_BODY()
/* Initialize the struct using a string from the config file. */
FBatchBinding( FString& InString )
{
FString CleanString = InString.Mid( 1, InString.Len() - 2 );
TArray<FString> VariableStrings;
CleanString.ParseIntoArray( VariableStrings, TEXT(",") );
TMap<FString, FString> Variables;
for ( int32 i = 0; i < VariableStrings.Num(); i++ )
{
TArray<FString> VariableString;
VariableStrings[i].ParseIntoArray( VariableString, TEXT( "=" ) );
if ( VariableString.Num() != 2 ) continue;
Variables.Add( VariableString[0], VariableString[1].TrimQuotes() );
}
FString* FieldIDValue = Variables.Find( "FieldID" );
if ( FieldIDValue != nullptr ) FieldID = *FieldIDValue;
FString* BatchPathValue = Variables.Find( "BatchPath" );
if ( BatchPathValue != nullptr ) BatchPath = *BatchPathValue;
}
/* Default constructor. */
FBatchBinding() {}
/*
* The ID of the field.
* e.g. category_id
*/
UPROPERTY( Config, EditAnywhere )
FString FieldID;
/*
* The path to the batch script. This is can be a relative path from the project folder (where the .uproject is located) or an absolute path.
* Relative e.g. /Scripts/GetCategory.bat
* Absolute e.g. C:/Perforce/Scripts/GetCategory.bat
*/
UPROPERTY( Config, EditAnywhere )
FString BatchPath;
};
UCLASS(config=Engine)
class UMantisSettings : public UObject
{
GENERATED_UCLASS_BODY()
public:
/*
* This is the root url of the Mantis.
* e.g. if the login url is: http://bugs.yourdomain.com/login_page.php
* this would be http://bugs.youdomain.com/
*/
UPROPERTY( Config, EditAnywhere, Category = General )
FString HostURL;
/*
* A list of batch scrips you want to use to load data for certain fields in the crash report.
*/
UPROPERTY( Config, EditAnywhere, Category = Advanced )
TArray<FBatchBinding> ScriptBindings;
};

View File

@@ -0,0 +1,29 @@
//////////////////////////////////////////
// Author: Yoshi van Belkom - 130118
//////////////////////////////////////////
// The Mantis Editor Module Settings.
//////////////////////////////////////////
namespace UnrealBuildTool.Rules
{
public class Mantis : ModuleRules
{
public Mantis(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(
new string[] {
"Core",
"CoreUObject",
"Engine",
"UnrealEd"
}
);
PrivateIncludePathModuleNames.AddRange(
new string[] {
"Settings"
}
);
}
}
}

View File

@@ -0,0 +1,332 @@
// Project Lab - NHTV IGAD
//////////////////////////////////////////
// Author: Yoshi van Belkom - 130118
//////////////////////////////////////////
#include "MantisPrivatePCH.h"
#include "ISettingsModule.h"
#include "MantisSettings.h"
#include "Runtime/Launch/Resources/Version.h"
#if PLATFORM_WINDOWS
#include <Winver.h>
#pragma comment( lib, "version.lib" )
#endif
//defines
#define LOCTEXT_NAMESPACE "Mantis"
#define STRINGIZE_(x) #x
#define STRINGIZE(x) STRINGIZE_(x)
#define PlatformFile FPlatformFileManager::Get().GetPlatformFile()
class FMantis : public IMantis
{
public:
/* IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
/* End IModuleInterface implementation */
FString GetEngineCrashClientPath();
FString GetMantisCrashClientPath();
void RegisterSettings();
void UnregisterSettings();
int32 IsMantisExe( FString FilePath );
void UpdateMantis();
bool MakeBackup( FString Original, FString Backup, bool bOverwrite = false );
};
DEFINE_LOG_CATEGORY(LogMantis);
//Get the path of the Engine Crash Report
FString FMantis::GetEngineCrashClientPath()
{
//Get Engine root path.
FString EnginePath = FPaths::RootDir();
FPaths::NormalizeDirectoryName(EnginePath);
TArray< FString > EnginePathDirs;
EnginePath.ParseIntoArray(EnginePathDirs, TEXT("/"), 1);
//Get the path to the CrashReportClient.exe
FString EngineCrashClientPath;
EnginePathDirs.Push(TEXT("Engine"));
EnginePathDirs.Push(TEXT("Binaries"));
EnginePathDirs.Push(TEXT("Win64"));
EnginePathDirs.Push(TEXT("CrashReportClient.exe"));
EngineCrashClientPath = FString::Join(EnginePathDirs, TEXT("/"));
//Check if file exists.
if (FPaths::FileExists(EngineCrashClientPath))
{
UE_LOG(LogMantis, Log, TEXT("Engine Crash Report file found!"));
}
else
{
UE_LOG(LogMantis, Warning, TEXT("Engine Crash Report file not found!"));
}
return EngineCrashClientPath;
}
FString FMantis::GetMantisCrashClientPath()
{
//Get the path of the Project File
FString ProjectPath = FPaths::GetPath( FPaths::GetProjectFilePath() );
FPaths::NormalizeDirectoryName( ProjectPath );
//Get the path to the Mantis Crash Report
TArray< FString > ProjectPathDirs;
ProjectPath.ParseIntoArray( ProjectPathDirs, TEXT( "/" ), 1 );
FString MantisCrashClientPath;
ProjectPathDirs.Push( TEXT( "Plugins" ) );
ProjectPathDirs.Push( TEXT( "Mantis" ) );
ProjectPathDirs.Push( TEXT( "Resources" ) );
ProjectPathDirs.Push( TEXT( "CrashReporter" ) );
ProjectPathDirs.Push( TEXT( STRINGIZE( ENGINE_MAJOR_VERSION ) "." STRINGIZE( ENGINE_MINOR_VERSION ) ) );
#if PLATFORM_64BITS
ProjectPathDirs.Push( TEXT( "Win64" ) );
#else
ProjectPathDirs.Push( TEXT( "Win32" ) );
#endif
ProjectPathDirs.Push( TEXT( "CrashReportClient.exe" ) );
MantisCrashClientPath = FString::Join( ProjectPathDirs, TEXT( "/" ) );
return MantisCrashClientPath;
}
void FMantis::RegisterSettings()
{
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
if (SettingsModule != nullptr)
{
SettingsModule->RegisterSettings("Project", "Plugins", "MantisPlugin",
LOCTEXT("MantisSettingsName", "Mantis Plugin"),
LOCTEXT("MantisSettingsDescription", "Set the setting for the Mantis Plugin."),
GetMutableDefault<UMantisSettings>()
);
}
else
{
UE_LOG(LogMantis, Log, TEXT("SettingsModule is null!"));
}
}
void FMantis::UnregisterSettings()
{
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
if (SettingsModule != nullptr)
{
SettingsModule->UnregisterSettings("Project", "Plugins", "MantisPlugin");
}
}
void FMantis::UpdateMantis()
{
//Get the path of the Engine Crash Report
FString EngineCrashClientPath = GetEngineCrashClientPath();
FString EngineCrashClientBackupPath = EngineCrashClientPath + ".ue";
FString EngineCrashClientTmpPath = EngineCrashClientPath + ".tmp";
//Get the path to the Mantis Crash Report
FString MantisCrashClientPath = GetMantisCrashClientPath();
UE_LOG( LogMantis, Log, TEXT( "MantisCrashClientPath: %s" ), *MantisCrashClientPath );
if ( FPaths::FileExists( MantisCrashClientPath ) )
{
UE_LOG( LogMantis, Log, TEXT( "Mantis Crash Report file found!" ) );
}
else
{
UE_LOG( LogMantis, Warning, TEXT( "Mantis Crash Report file not found!" ) );
return;
}
//Removing the read-only tag
PlatformFile.SetReadOnly( *EngineCrashClientPath, false );
if ( IsMantisExe( EngineCrashClientPath ) == 1 )
{
FDateTime EngineTimestamp = PlatformFile.GetTimeStamp( *EngineCrashClientPath );
FDateTime MantisTimestamp = PlatformFile.GetTimeStamp( *MantisCrashClientPath );
if ( EngineTimestamp >= MantisTimestamp )
{
UE_LOG( LogMantis, Log, TEXT( "Crash Report Client is up-to-date!" ) );
return;
}
else
{
UE_LOG( LogMantis, Log, TEXT( "Crash Report Client is out-of-date!" ) );
}
}
//Make temporary backup
if ( !MakeBackup( EngineCrashClientPath, EngineCrashClientTmpPath, true ) )
{
UE_LOG( LogMantis, Warning, TEXT( "Couldn't make temporary Crash Report Client backup!" ) );
return;
}
//Delete current file.
if ( !PlatformFile.DeleteFile( *EngineCrashClientPath ) )
{
UE_LOG( LogMantis, Log, TEXT( "Failed to delete the current Crash Report Client." ) );
return;
}
//Copy file if out of date.
if ( PlatformFile.CopyFile( *EngineCrashClientPath, *MantisCrashClientPath ) )
{
UE_LOG( LogMantis, Log, TEXT( "Crash Report Client is updated!" ) );
}
else
{
int32 errorNum = FPlatformMisc::GetLastError();
UE_LOG( LogMantis, Warning, TEXT( "Failed to update Crash Report Client! (Error: %i)" ), errorNum );
if ( PlatformFile.CopyFile( *EngineCrashClientPath, *EngineCrashClientPath ) )
{
UE_LOG( LogMantis, Log, TEXT( "Restored Crash Report Client." ) );
}
else
{
errorNum = FPlatformMisc::GetLastError();
UE_LOG( LogMantis, Warning, TEXT( "Failed to restore Crash Report Client! (Error: %i)" ), errorNum );
}
return;
}
//Delete temporary backup file.
if ( !PlatformFile.DeleteFile( *EngineCrashClientTmpPath ) )
{
UE_LOG( LogMantis, Log, TEXT( "Failed to delete the current Crash Report Client." ) );
return;
}
//Removing the read-only tag
PlatformFile.SetReadOnly( *EngineCrashClientPath, false );
}
bool FMantis::MakeBackup( FString Original, FString Backup, bool bOverwrite )
{
//Delete backup if it already exists.
if ( bOverwrite && FPaths::FileExists( Backup ) )
{
PlatformFile.DeleteFile( *Backup );
}
//Make backup.
if ( PlatformFile.CopyFile( *Backup, *Original ) )
{
UE_LOG( LogMantis, Log, TEXT( "Made a backup." ) );
}
else
{
int32 errorNum = FPlatformMisc::GetLastError();
UE_LOG( LogMantis, Warning, TEXT( "Original path: %s" ), *Original );
UE_LOG( LogMantis, Warning, TEXT( "Backup path: %s" ), *Backup );
UE_LOG( LogMantis, Warning, TEXT( "Failed to make a backup! (Error: %i)" ), errorNum );
return false;
}
return true;
}
void FMantis::StartupModule()
{
//Register the settings in the editor.
RegisterSettings();
#if PLATFORM_WINDOWS
//Get the path of the Engine Crash Report
FString EngineCrashClientPath = GetEngineCrashClientPath();
FString EngineCrashClientBackupPath = EngineCrashClientPath + ".ue";
int32 Result = IsMantisExe( EngineCrashClientPath );
if ( Result == 1 )
{
UpdateMantis();
}
else if ( Result == 0 )
{
MakeBackup( EngineCrashClientPath, EngineCrashClientBackupPath, true );
UpdateMantis();
}
#endif
}
void FMantis::ShutdownModule()
{
//Unregister the settings in the editor.
UnregisterSettings();
#if PLATFORM_WINDOWS
//Get the path of the Engine Crash Report
FString EngineCrashClientPath = GetEngineCrashClientPath();
FString EngineCrashClientBackupPath = EngineCrashClientPath + ".ue";
//Can't restore if there is no backup.
if ( !FPaths::FileExists( EngineCrashClientBackupPath ) )
{
UE_LOG( LogMantis, Warning, TEXT( "Backup file not found!" ) );
return;
}
//Check if backup is valid
if ( IsMantisExe( EngineCrashClientBackupPath ) == 1 )
{
UE_LOG( LogMantis, Warning, TEXT( "Backup file is not from Unreal!" ) );
return;
}
//Check if client is valid
int32 Result = IsMantisExe( EngineCrashClientPath );
if ( Result == 1 )
{
MakeBackup( EngineCrashClientBackupPath, EngineCrashClientPath, true );
}
#endif
// This function may be called during shutdown to clean up the module. For modules that support dynamic reloading,
// this function gets called before unloading the module.
}
int32 FMantis::IsMantisExe( FString FilePath )
{
#if PLATFORM_WINDOWS
// get the filename of the executable containing the version resource
LPWSTR FilePathW = (WCHAR*) *FilePath;
// allocate a block of memory for the version info
uint32 dummy;
uint32 dwSize = GetFileVersionInfoSize( FilePathW, (LPDWORD)&dummy );
if ( dwSize == 0 )
{
UE_LOG( LogMantis, Log, TEXT( "GetFileVersionInfoSize failed with error %d\n" ), FPlatformMisc::GetLastError() );
return -1;
}
TArray<BYTE> data;
data.SetNum( dwSize );
// load the version info
if ( !GetFileVersionInfo( FilePathW, NULL, dwSize, &data[0] ) )
{
UE_LOG( LogMantis, Log, TEXT( "GetFileVersionInfo failed with error %d\n" ), FPlatformMisc::GetLastError() );
return -1;
}
LPVOID pvFileDescription = NULL;
uint32 FileDescriptionLen = 0;
if ( !VerQueryValue( &data[0], _T( "\\StringFileInfo\\040904b0\\FileDescription" ), &pvFileDescription, &FileDescriptionLen ) )
{
UE_LOG( LogMantis, Log, TEXT( "Can't obtain ProductName and ProductVersion from resources\n" ) );
return -1;
}
FString MantisClientName = TEXT( "MantisCrashReportClient" );
TCHAR* ClientNameW = (TCHAR*)pvFileDescription;
FString ClientName = ClientNameW;
return ( ClientName == MantisClientName ) ? 1 : 0;
#else
return 0;
#endif
}
IMPLEMENT_MODULE( FMantis, Mantis )
#undef LOCTEXT_NAMESPACE

View File

@@ -0,0 +1,12 @@
// Project Lab - NHTV IGAD
//////////////////////////////////////////
// Author: Yoshi van Belkom - 130118
//////////////////////////////////////////
// The Mantis Module Pre Compiled Header.
//////////////////////////////////////////
#pragma once
#include "IMantis.h"
DECLARE_LOG_CATEGORY_EXTERN(LogMantis, Log, All);

View File

@@ -0,0 +1,7 @@
#pragma once
#include "MantisPrivatePCH.h"
#include "MantisSettings.h"
UMantisSettings::UMantisSettings(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer), HostURL(TEXT(""))
{}

View File

@@ -0,0 +1,27 @@
// Project Lab - NHTV IGAD
//////////////////////////////////////////
// Author: Yoshi van Belkom - 130118
//////////////////////////////////////////
// The Mantis Editor Module Interface.
//////////////////////////////////////////
#pragma once
#include "ModuleManager.h"
class IMantis : public IModuleInterface
{
public:
//Function to Get the Singleton of this Module if it's loaded.
static inline IMantis& Get()
{
return FModuleManager::LoadModuleChecked< IMantis >( "Mantis" );
}
//Function to check if the Module is loaded.
static inline bool IsAvailable()
{
return FModuleManager::Get().IsModuleLoaded( "Mantis" );
}
};