From 32c7036938777fa83f648e50824d44c019467ebf Mon Sep 17 00:00:00 2001 From: Yan Kaganovsky Date: Tue, 19 May 2020 13:41:03 +0300 Subject: [PATCH 1/4] allow user to change the root directory for the Git repository --- .../Private/GitSourceControlOperations.cpp | 9 ++++ .../Private/GitSourceControlProvider.cpp | 29 +++++++++++++ .../Private/GitSourceControlProvider.h | 5 +++ .../Private/GitSourceControlSettings.cpp | 19 +++++++++ .../Private/GitSourceControlSettings.h | 9 ++++ .../Private/SGitSourceControlSettings.cpp | 41 ++++++++++++++++++- .../Private/SGitSourceControlSettings.h | 10 +++-- 7 files changed, 117 insertions(+), 5 deletions(-) diff --git a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp index 64c5c7b3..15e58b71 100644 --- a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp @@ -45,6 +45,7 @@ bool FGitConnectWorker::Execute(FGitSourceControlCommand& InCommand) ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir())); ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir())); InCommand.bCommandSuccessful = GitSourceControlUtils::RunUpdateStatus(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.bUsingGitLfsLocking, ProjectDirs, InCommand.ErrorMessages, States); + /** if(!InCommand.bCommandSuccessful || InCommand.ErrorMessages.Num() > 0) { Operation->SetErrorText(LOCTEXT("NotAGitRepository", "Failed to enable Git source control. You need to initialize the project as a Git repository first.")); @@ -60,6 +61,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..78046747 100644 --- a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp @@ -74,6 +74,35 @@ 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) 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; From 57a435dee97e7975cd6d7a561b0093cf2057274b Mon Sep 17 00:00:00 2001 From: Yan Kaganovsky Date: Tue, 19 May 2020 13:46:08 +0300 Subject: [PATCH 2/4] Added TODO related to checking git status on content folder, which was temporarily removed --- Source/GitSourceControl/Private/GitSourceControlOperations.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp index 15e58b71..68685946 100644 --- a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp @@ -45,6 +45,7 @@ bool FGitConnectWorker::Execute(FGitSourceControlCommand& InCommand) ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir())); ProjectDirs.Add(FPaths::ConvertRelativePathToFull(FPaths::ProjectConfigDir())); InCommand.bCommandSuccessful = GitSourceControlUtils::RunUpdateStatus(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.bUsingGitLfsLocking, ProjectDirs, InCommand.ErrorMessages, States); + // TODO: determine if the commented part below is neccessary and if so adjust it to changes in git root / else delete /** if(!InCommand.bCommandSuccessful || InCommand.ErrorMessages.Num() > 0) { From 6bc54a71b7ab8de2eb042598f7b7d152f357ec92 Mon Sep 17 00:00:00 2001 From: Yan Kaganovsky Date: Mon, 25 May 2020 12:25:35 +0300 Subject: [PATCH 3/4] make sure root path to git repo is loaded correctly from saved settings (instead of defaulting to project dir everytime the editor restarts) --- .../Private/GitSourceControlProvider.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp index 78046747..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 @@ -105,9 +107,26 @@ bool FGitSourceControlProvider::CheckIfValidRepository(const FString& InPathToGi 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(); @@ -125,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) From 35d596c9f207ff45e6f2bd7bec594113cf2aba54 Mon Sep 17 00:00:00 2001 From: Yan Kaganovsky Date: Mon, 25 May 2020 13:11:27 +0300 Subject: [PATCH 4/4] restored original status check of content and config folders of the Unreal project but ONLY if they are included in the chosen repository tree (now that we have freedom to choose the root repo dir, these folders might be excluded from the repo) --- .../Private/GitSourceControlOperations.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp index 68685946..c6a470da 100644 --- a/Source/GitSourceControl/Private/GitSourceControlOperations.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlOperations.cpp @@ -42,11 +42,17 @@ 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); - // TODO: determine if the commented part below is neccessary and if so adjust it to changes in git root / else delete - /** if(!InCommand.bCommandSuccessful || InCommand.ErrorMessages.Num() > 0) { Operation->SetErrorText(LOCTEXT("NotAGitRepository", "Failed to enable Git source control. You need to initialize the project as a Git repository first.")); @@ -62,7 +68,7 @@ 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)