diff --git a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp index 64c5c7b3..c6a470da 100644 --- a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp @@ -42,8 +42,16 @@ bool FGitConnectWorker::Execute(FGitSourceControlCommand& InCommand) { // Now update the status of assets in Content/ directory and also Config files TArray ProjectDirs; - ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir())); - ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir())); + FString ProjContentDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir()); + FString ProjectConfigDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir()); + if (ProjContentDir.Contains(InCommand.PathToRepositoryRoot)) + { + ProjectDirs.Add(ProjContentDir); + } + if (ProjectConfigDir.Contains(InCommand.PathToRepositoryRoot)) + { + ProjectDirs.Add(ProjectConfigDir); + } InCommand.bCommandSuccessful = GitSourceControlUtils::RunUpdateStatus(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.bUsingGitLfsLocking, ProjectDirs, InCommand.ErrorMessages, States); if(!InCommand.bCommandSuccessful || InCommand.ErrorMessages.Num() > 0) { @@ -60,6 +68,14 @@ bool FGitConnectWorker::Execute(FGitSourceControlCommand& InCommand) InCommand.bCommandSuccessful = GitSourceControlUtils::RunCommand(TEXT("lfs locks"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, TArray(), TArray(), InCommand.InfoMessages, InCommand.ErrorMessages); } } + + GitSourceControlUtils::GetCommitInfo(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.CommitId, InCommand.CommitSummary); + + if (InCommand.bUsingGitLfsLocking) + { + // Check server connection by checking lock status (when using Git LFS file Locking worflow) + InCommand.bCommandSuccessful = GitSourceControlUtils::RunCommand(TEXT("lfs locks"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, TArray(), TArray(), InCommand.InfoMessages, InCommand.ErrorMessages); + } } else { diff --git a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp index 687b698c..12997de6 100644 --- a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp @@ -49,6 +49,8 @@ void FGitSourceControlProvider::CheckGitAvailability() { FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); FString PathToGitBinary = GitSourceControl.AccessSettings().GetBinaryPath(); + FString PathToGitRepo = GitSourceControl.AccessSettings().GetRepoPath(); + if(PathToGitBinary.IsEmpty()) { // Try to find Git binary, and update settings accordingly @@ -74,11 +76,57 @@ void FGitSourceControlProvider::CheckGitAvailability() } } +bool FGitSourceControlProvider::CheckIfValidRepository(const FString& InPathToGitBinary, const FString& InPathToGitRepo) +{ + const FString PathToRepo = FPaths::ConvertRelativePathToFull(InPathToGitRepo); + bGitRepositoryFound = GitSourceControlUtils::FindRootDirectory(PathToRepo, PathToRepositoryRoot); + if (bGitRepositoryFound) + { + GitSourceControlMenu.Register(); + + // Get branch name + bGitRepositoryFound = GitSourceControlUtils::GetBranchName(InPathToGitBinary, PathToRepositoryRoot, BranchName); + if (bGitRepositoryFound) + { + GitSourceControlUtils::GetRemoteUrl(InPathToGitBinary, PathToRepositoryRoot, RemoteUrl); + } + else + { + UE_LOG(LogSourceControl, Error, TEXT("'%s' is not a valid Git repository"), *PathToRepositoryRoot); + } + } + else + { + UE_LOG(LogSourceControl, Warning, TEXT("'%s' is not part of a Git repository"), *FPaths::ProjectDir()); + } + + // Get user name & email (of the repository, else from the global Git config) + GitSourceControlUtils::GetUserConfig(InPathToGitBinary, PathToRepositoryRoot, UserName, UserEmail); + return bGitRepositoryFound; +} + void FGitSourceControlProvider::CheckRepositoryStatus(const FString& InPathToGitBinary) { - // Find the path to the root Git directory (if any, else uses the ProjectDir) - const FString PathToProjectDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()); - bGitRepositoryFound = GitSourceControlUtils::FindRootDirectory(PathToProjectDir, PathToRepositoryRoot); + // Get the root Git directory from loaded settings + FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); + FString PathToGitRepo = GitSourceControl.AccessSettings().GetRepoPath(); + + FString SearchedGitRepo; + + if (PathToGitRepo.IsEmpty()) + { + // Find the path to the root Git directory (if any, else uses the ProjectDir) + const FString PathToProjectDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()); + bGitRepositoryFound = GitSourceControlUtils::FindRootDirectory(PathToProjectDir, PathToRepositoryRoot); + SearchedGitRepo = PathToProjectDir; + } + else + { + // make sure the saved root Git directory is still valid and copy the path + bGitRepositoryFound = GitSourceControlUtils::FindRootDirectory(PathToGitRepo, PathToRepositoryRoot); + SearchedGitRepo = PathToGitRepo; + } + if(bGitRepositoryFound) { GitSourceControlMenu.Register(); @@ -96,7 +144,7 @@ void FGitSourceControlProvider::CheckRepositoryStatus(const FString& InPathToGit } else { - UE_LOG(LogSourceControl, Warning, TEXT("'%s' is not part of a Git repository"), *FPaths::ProjectDir()); + UE_LOG(LogSourceControl, Warning, TEXT("'%s' is not part of a Git repository"), *SearchedGitRepo); } // Get user name & email (of the repository, else from the global Git config) diff --git a/Source/GitSourceControl/Private/GitSourceControlProvider.h b/Source/GitSourceControl/Private/GitSourceControlProvider.h index 97dce5bf..99381704 100644 --- a/Source/GitSourceControl/Private/GitSourceControlProvider.h +++ b/Source/GitSourceControl/Private/GitSourceControlProvider.h @@ -93,6 +93,11 @@ class FGitSourceControlProvider : public ISourceControlProvider */ void CheckRepositoryStatus(const FString& InPathToGitBinary); + /** + * Check if a git repository can be found in the given path. + */ + bool CheckIfValidRepository(const FString& InPathToGitBinary, const FString& InPathToGitRepo); + /** Is git binary found and working. */ inline bool IsGitAvailable() const { diff --git a/Source/GitSourceControl/Private/GitSourceControlSettings.cpp b/Source/GitSourceControl/Private/GitSourceControlSettings.cpp index b03c6e51..423032e3 100644 --- a/Source/GitSourceControl/Private/GitSourceControlSettings.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlSettings.cpp @@ -26,6 +26,12 @@ const FString FGitSourceControlSettings::GetBinaryPath() const return BinaryPath; // Return a copy to be thread-safe } +const FString FGitSourceControlSettings::GetRepoPath() const +{ + FScopeLock ScopeLock(&CriticalSection); + return RepoPath; // Return a copy to be thread-safe +} + bool FGitSourceControlSettings::SetBinaryPath(const FString& InString) { FScopeLock ScopeLock(&CriticalSection); @@ -37,6 +43,17 @@ bool FGitSourceControlSettings::SetBinaryPath(const FString& InString) return bChanged; } +bool FGitSourceControlSettings::SetRepoPath(const FString& InString) +{ + FScopeLock ScopeLock(&CriticalSection); + const bool bChanged = (RepoPath != InString); + if (bChanged) + { + RepoPath = InString; + } + return bChanged; +} + /** Tell if using the Git LFS file Locking workflow */ bool FGitSourceControlSettings::IsUsingGitLfsLocking() const { @@ -76,6 +93,7 @@ void FGitSourceControlSettings::LoadSettings() FScopeLock ScopeLock(&CriticalSection); const FString& IniFile = SourceControlHelpers::GetSettingsIni(); GConfig->GetString(*GitSettingsConstants::SettingsSection, TEXT("BinaryPath"), BinaryPath, IniFile); + GConfig->GetString(*GitSettingsConstants::SettingsSection, TEXT("RepoRootPath"), RepoPath, IniFile); GConfig->GetBool(*GitSettingsConstants::SettingsSection, TEXT("UsingGitLfsLocking"), bUsingGitLfsLocking, IniFile); GConfig->GetString(*GitSettingsConstants::SettingsSection, TEXT("LfsUserName"), LfsUserName, IniFile); } @@ -85,6 +103,7 @@ void FGitSourceControlSettings::SaveSettings() const FScopeLock ScopeLock(&CriticalSection); const FString& IniFile = SourceControlHelpers::GetSettingsIni(); GConfig->SetString(*GitSettingsConstants::SettingsSection, TEXT("BinaryPath"), *BinaryPath, IniFile); + GConfig->SetString(*GitSettingsConstants::SettingsSection, TEXT("RepoRootPath"), *RepoPath, IniFile); GConfig->SetBool(*GitSettingsConstants::SettingsSection, TEXT("UsingGitLfsLocking"), bUsingGitLfsLocking, IniFile); GConfig->SetString(*GitSettingsConstants::SettingsSection, TEXT("LfsUserName"), *LfsUserName, IniFile); } diff --git a/Source/GitSourceControl/Private/GitSourceControlSettings.h b/Source/GitSourceControl/Private/GitSourceControlSettings.h index 3a9549f1..27025758 100644 --- a/Source/GitSourceControl/Private/GitSourceControlSettings.h +++ b/Source/GitSourceControl/Private/GitSourceControlSettings.h @@ -13,9 +13,15 @@ class FGitSourceControlSettings /** Get the Git Binary Path */ const FString GetBinaryPath() const; + /** Get the Git Root Path */ + const FString GetRepoPath() const; + /** Set the Git Binary Path */ bool SetBinaryPath(const FString& InString); + /** Set the Git Root Path */ + bool SetRepoPath(const FString& InString); + /** Tell if using the Git LFS file Locking workflow */ bool IsUsingGitLfsLocking() const; @@ -40,6 +46,9 @@ class FGitSourceControlSettings /** Git binary path */ FString BinaryPath; + + /** Git root path */ + FString RepoPath; /** Tells if using the Git LFS file Locking workflow */ bool bUsingGitLfsLocking; diff --git a/Source/GitSourceControl/Private/SGitSourceControlSettings.cpp b/Source/GitSourceControl/Private/SGitSourceControlSettings.cpp index ce1d9abd..91d0d674 100644 --- a/Source/GitSourceControl/Private/SGitSourceControlSettings.cpp +++ b/Source/GitSourceControl/Private/SGitSourceControlSettings.cpp @@ -17,6 +17,7 @@ #include "Widgets/Input/SCheckBox.h" #include "Widgets/Input/SEditableTextBox.h" #include "Widgets/Input/SFilePathPicker.h" +#include "Widgets/Input/SDirectoryPicker.h" #include "Widgets/Input/SMultiLineEditableTextBox.h" #include "Widgets/Layout/SBorder.h" #include "Widgets/Layout/SSeparator.h" @@ -102,11 +103,18 @@ void SGitSourceControlSettings::Construct(const FArguments& InArgs) ] +SHorizontalBox::Slot() .FillWidth(2.0f) + [ + SNew(SDirectoryPicker) + .Directory(SGitSourceControlSettings::GetPathToRepositoryRoot()) + .OnDirectoryChanged(this, &SGitSourceControlSettings::OnRepoPathPicked) + ] + /** [ SNew(STextBlock) .Text(this, &SGitSourceControlSettings::GetPathToRepositoryRoot) .Font(Font) ] + */ ] // User Name +SVerticalBox::Slot() @@ -404,6 +412,13 @@ FString SGitSourceControlSettings::GetBinaryPathString() const return GitSourceControl.AccessSettings().GetBinaryPath(); } +FString SGitSourceControlSettings::GetRepoPathString() const +{ + const FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); + return GitSourceControl.AccessSettings().GetRepoPath(); +} + + void SGitSourceControlSettings::OnBinaryPathPicked( const FString& PickedPath ) const { FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); @@ -420,10 +435,32 @@ void SGitSourceControlSettings::OnBinaryPathPicked( const FString& PickedPath ) } } -FText SGitSourceControlSettings::GetPathToRepositoryRoot() const +void SGitSourceControlSettings::OnRepoPathPicked(const FString& PickedPath) const +{ + FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); + FString PickedFullPath = FPaths::ConvertRelativePathToFull(PickedPath); + FString PathToGitBinary = GitSourceControl.AccessSettings().GetBinaryPath(); + bool RepoFound = GitSourceControl.GetProvider().CheckIfValidRepository(PathToGitBinary, PickedFullPath); + bool bChanged = false; + if (RepoFound) + { + bChanged = GitSourceControl.AccessSettings().SetRepoPath(PickedFullPath); + } + if (bChanged) + { + // Re-Check provided git binary path for each change + GitSourceControl.GetProvider().CheckGitAvailability(); + if (GitSourceControl.GetProvider().IsGitAvailable()) + { + GitSourceControl.SaveSettings(); + } + } +} + +FString SGitSourceControlSettings::GetPathToRepositoryRoot() { const FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); - return FText::FromString(GitSourceControl.GetProvider().GetPathToRepositoryRoot()); + return GitSourceControl.GetProvider().GetPathToRepositoryRoot(); } FText SGitSourceControlSettings::GetUserName() const diff --git a/Source/GitSourceControl/Private/SGitSourceControlSettings.h b/Source/GitSourceControl/Private/SGitSourceControlSettings.h index 38d4855f..9c31a435 100644 --- a/Source/GitSourceControl/Private/SGitSourceControlSettings.h +++ b/Source/GitSourceControl/Private/SGitSourceControlSettings.h @@ -35,9 +35,13 @@ class SGitSourceControlSettings : public SCompoundWidget /** Delegates to get Git binary path from/to settings */ FString GetBinaryPathString() const; void OnBinaryPathPicked(const FString & PickedPath) const; - - /** Delegate to get repository root, user name and email from provider */ - FText GetPathToRepositoryRoot() const; + + /** Delegates to get Git root path from/to settings */ + FString GetRepoPathString() const; + void OnRepoPathPicked(const FString & PickedPath) const; + + /** Delegate to get repository root, user name and email from provider */ + FString GetPathToRepositoryRoot(); FText GetUserName() const; FText GetUserEmail() const;