diff --git a/Source/GitSourceControl/Private/GitSourceControlCommand.cpp b/Source/GitSourceControl/Private/GitSourceControlCommand.cpp index 1bf25ec8..170d64a6 100644 --- a/Source/GitSourceControl/Private/GitSourceControlCommand.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlCommand.cpp @@ -7,6 +7,7 @@ #include "Modules/ModuleManager.h" #include "GitSourceControlModule.h" +#include "GitSourceControlUtils.h" FGitSourceControlCommand::FGitSourceControlCommand(const TSharedRef& InOperation, const TSharedRef& InWorker, const FSourceControlOperationComplete& InOperationCompleteDelegate) : Operation(InOperation) @@ -25,7 +26,10 @@ FGitSourceControlCommand::FGitSourceControlCommand(const TSharedRef& AbsoluteFilePaths) +{ + PathToRepositoryRoot = GitSourceControlUtils::ChangeRepositoryRootIfSubmodule(AbsoluteFilePaths, PathToRepositoryRoot); +} bool FGitSourceControlCommand::DoWork() { bCommandSuccessful = Worker->Execute(*this); diff --git a/Source/GitSourceControl/Private/GitSourceControlCommand.h b/Source/GitSourceControl/Private/GitSourceControlCommand.h index 42c1a899..10f3ec2f 100644 --- a/Source/GitSourceControl/Private/GitSourceControlCommand.h +++ b/Source/GitSourceControl/Private/GitSourceControlCommand.h @@ -18,6 +18,11 @@ class FGitSourceControlCommand : public IQueuedWork FGitSourceControlCommand(const TSharedRef& InOperation, const TSharedRef& InWorker, const FSourceControlOperationComplete& InOperationCompleteDelegate = FSourceControlOperationComplete() ); + /** + * Modify the repo root if all selected files are in a plugin subfolder, and the plugin subfolder is a git repo + * This supports the case where each plugin is a sub module + */ + void UpdateRepositoryRootIfSubmodule(const TArray& AbsoluteFilePaths); /** * This is where the real thread work is done. All work that is done for * this queued object should be done from within the call to this function. diff --git a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp index aa6c2564..042d930c 100644 --- a/Source/GitSourceControl/Private/GitSourceControlProvider.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlProvider.cpp @@ -254,6 +254,8 @@ ECommandResult::Type FGitSourceControlProvider::Execute( const TSharedRefFiles = AbsoluteFiles; + Command->UpdateRepositoryRootIfSubmodule(AbsoluteFiles); + Command->OperationCompleteDelegate = InOperationCompleteDelegate; // fire off operation diff --git a/Source/GitSourceControl/Private/GitSourceControlRevision.cpp b/Source/GitSourceControl/Private/GitSourceControlRevision.cpp index 0858f7f2..9c0e19cb 100644 --- a/Source/GitSourceControl/Private/GitSourceControlRevision.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlRevision.cpp @@ -17,8 +17,13 @@ bool FGitSourceControlRevision::Get( FString& InOutFilename ) const { FGitSourceControlModule& GitSourceControl = FModuleManager::GetModuleChecked("GitSourceControl"); const FString PathToGitBinary = GitSourceControl.AccessSettings().GetBinaryPath(); - const FString PathToRepositoryRoot = GitSourceControl.GetProvider().GetPathToRepositoryRoot(); + FString PathToRepositoryRoot = GitSourceControl.GetProvider().GetPathToRepositoryRoot(); + // the repo root can be customised if in a plugin that has it's own repo + if (PathToRepoRoot.Len()) + { + PathToRepositoryRoot = PathToRepoRoot; + } // if a filename for the temp file wasn't supplied generate a unique-ish one if(InOutFilename.Len() == 0) { @@ -28,7 +33,6 @@ bool FGitSourceControlRevision::Get( FString& InOutFilename ) const const FString TempFileName = FString::Printf(TEXT("%stemp-%s-%s"), *FPaths::DiffDir(), *CommitId, *FPaths::GetCleanFilename(Filename)); InOutFilename = FPaths::ConvertRelativePathToFull(TempFileName); } - // Diff against the revision const FString Parameter = FString::Printf(TEXT("%s:%s"), *CommitId, *Filename); diff --git a/Source/GitSourceControl/Private/GitSourceControlRevision.h b/Source/GitSourceControl/Private/GitSourceControlRevision.h index d2cf7ab2..1f35a700 100644 --- a/Source/GitSourceControl/Private/GitSourceControlRevision.h +++ b/Source/GitSourceControl/Private/GitSourceControlRevision.h @@ -70,6 +70,8 @@ class FGitSourceControlRevision : public ISourceControlRevision, public TSharedF /** The size of the file at this revision */ int32 FileSize; + + FString PathToRepoRoot; }; /** History composed of the last 100 revisions of the file */ diff --git a/Source/GitSourceControl/Private/GitSourceControlUtils.cpp b/Source/GitSourceControl/Private/GitSourceControlUtils.cpp index 42014585..5726d4a0 100644 --- a/Source/GitSourceControl/Private/GitSourceControlUtils.cpp +++ b/Source/GitSourceControl/Private/GitSourceControlUtils.cpp @@ -55,7 +55,45 @@ const FString& FGitScopedTempFile::GetFilename() const namespace GitSourceControlUtils { +FString ChangeRepositoryRootIfSubmodule(const TArray& AbsoluteFilePaths, const FString& PathToRepositoryRoot) +{ + FString Ret = PathToRepositoryRoot; + FString PluginsRoot = FPaths::ConvertRelativePathToFull(FPaths::ProjectPluginsDir()); + // note this is not going to support operations where selected files are both in the root repo and the submodule/plugin's repo + int NumPluginFiles = 0; + + for (auto& FilePath : AbsoluteFilePaths) + { + if (FilePath.Contains(PluginsRoot)) + { + NumPluginFiles++; + } + } + // if all plugins? + // modify Source control base path + if ((NumPluginFiles == AbsoluteFilePaths.Num()) && (AbsoluteFilePaths.Num() > 0)) + { + FString FullPath = AbsoluteFilePaths[0]; + + FString PluginPart = FullPath.Replace(*PluginsRoot, *FString("")); + PluginPart = PluginPart.Left(PluginPart.Find("/")); + + FString CandidateRepoRoot = PluginsRoot + PluginPart; + + FString IsItUsingGitPath = CandidateRepoRoot + "/.git"; + if (FPaths::FileExists(IsItUsingGitPath) || FPaths::DirectoryExists(IsItUsingGitPath)) + { + Ret = CandidateRepoRoot; + } + } + return Ret; +} +FString ChangeRepositoryRootIfSubmodule(const FString& AbsoluteFilePath, const FString& PathToRepositoryRoot) +{ + TArray AbsoluteFilePaths = { AbsoluteFilePath }; + return ChangeRepositoryRootIfSubmodule(AbsoluteFilePaths, PathToRepositoryRoot); +} // Launch the Git command line process and extract its results & errors static bool RunCommandInternalRaw(const FString& InCommand, const FString& InPathToGitBinary, const FString& InRepositoryRoot, const TArray& InParameters, const TArray& InFiles, FString& OutResults, FString& OutErrors, const int32 ExpectedReturnCode = 0) { @@ -1451,6 +1489,7 @@ bool RunGetHistory(const FString& InPathToGitBinary, const FString& InRepository Revision->FileHash = LsTree.FileHash; Revision->FileSize = LsTree.FileSize; } + Revision->PathToRepoRoot = InRepositoryRoot; } return bResults; diff --git a/Source/GitSourceControl/Private/GitSourceControlUtils.h b/Source/GitSourceControl/Private/GitSourceControlUtils.h index 971b433b..0cf9c708 100644 --- a/Source/GitSourceControl/Private/GitSourceControlUtils.h +++ b/Source/GitSourceControl/Private/GitSourceControlUtils.h @@ -35,6 +35,23 @@ struct FGitVersion; namespace GitSourceControlUtils { +/** +* Returns an updated repo root if all selected files are in a plugin subfolder, and the plugin subfolder is a git repo +* This supports the case where each plugin is a sub module +* +* @param AbsoluteFilePaths The list of files in the SC operation +* @param PathToRepositoryRoot The original path to the repository root (used by default) +*/ +FString ChangeRepositoryRootIfSubmodule(const TArray& AbsoluteFilePaths, const FString& PathToRepositoryRoot); + +/** +* Returns an updated repo root if all selected file is in a plugin subfolder, and the plugin subfolder is a git repo +* This supports the case where each plugin is a sub module +* +* @param AbsoluteFilePath The file in the SC operation +* @param PathToRepositoryRoot The original path to the repository root (used by default) +*/ +FString ChangeRepositoryRootIfSubmodule(const FString& AbsoluteFilePath, const FString& PathToRepositoryRoot); /** * Find the path to the Git binary, looking into a few places (standalone Git install, and other common tools embedding Git)