Skip to content

Commit 95eb46e

Browse files
committed
fix #80
1 parent 8550cd7 commit 95eb46e

File tree

4 files changed

+94
-43
lines changed

4 files changed

+94
-43
lines changed

Source/GitSourceControl/Private/GitSourceControlModule.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ class FGitSourceControlModule : public IModuleInterface
118118
return FModuleManager::Get().LoadModuleChecked< FGitSourceControlModule >("GitSourceControl");
119119
}
120120

121+
static inline FGitSourceControlModule* GetThreadSafe()
122+
{
123+
IModuleInterface* ModulePtr = FModuleManager::Get().GetModule("GitSourceControl");
124+
if (!ModulePtr)
125+
{
126+
// Main thread should never have this unloaded.
127+
check(!IsInGameThread());
128+
return nullptr;
129+
}
130+
return static_cast<FGitSourceControlModule*>(ModulePtr);
131+
}
132+
121133
/** Set list of error messages that occurred after last git command */
122134
static void SetLastErrors(const TArray<FText>& InErrors);
123135

Source/GitSourceControl/Private/GitSourceControlRevision.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ bool FGitSourceControlRevision::Get( FString& InOutFilename, EConcurrency::Type
2525
bool FGitSourceControlRevision::Get( FString& InOutFilename ) const
2626
{
2727
#endif
28-
const FGitSourceControlModule& GitSourceControl = FGitSourceControlModule::Get();
29-
const FGitSourceControlProvider& Provider = GitSourceControl.GetProvider();
28+
const FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
29+
if (!GitSourceControl)
30+
{
31+
return false;
32+
}
33+
const FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
3034
const FString PathToGitBinary = Provider.GetGitBinaryPath();
3135
FString PathToRepositoryRoot = Provider.GetPathToRepositoryRoot();
3236
// the repo root can be customised if in a plugin that has it's own repo

Source/GitSourceControl/Private/GitSourceControlRunner.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@ uint32 FGitSourceControlRunner::Run()
4646
// Flag that we're running the task already
4747
bRefreshSpawned = true;
4848
const auto ExecuteResult = Async(EAsyncExecution::TaskGraphMainThread, [=] {
49+
FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
4950
// Module not loaded, bail. Usually happens when editor is shutting down, and this prevents a crash from bad timing.
50-
if (!FModuleManager::Get().GetModule("GitSourceControl"))
51+
if (!GitSourceControl)
5152
{
5253
return ECommandResult::Failed;
5354
}
54-
FGitSourceControlModule& GitSourceControl = FGitSourceControlModule::Get();
55-
FGitSourceControlProvider& Provider = GitSourceControl.GetProvider();
55+
FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
5656
TSharedRef<FGitFetch, ESPMode::ThreadSafe> RefreshOperation = ISourceControlOperation::Create<FGitFetch>();
5757
RefreshOperation->bUpdateStatus = true;
5858
#if ENGINE_MAJOR_VERSION >= 5

Source/GitSourceControl/Private/GitSourceControlUtils.cpp

Lines changed: 73 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,12 @@ void GetUserConfig(const FString& InPathToGitBinary, const FString& InRepository
556556

557557
bool GetBranchName(const FString& InPathToGitBinary, const FString& InRepositoryRoot, FString& OutBranchName)
558558
{
559-
const FGitSourceControlProvider& Provider = FGitSourceControlModule::Get().GetProvider();
559+
const FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
560+
if (!GitSourceControl)
561+
{
562+
return false;
563+
}
564+
const FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
560565
if (!Provider.GetBranchName().IsEmpty())
561566
{
562567
OutBranchName = Provider.GetBranchName();
@@ -597,7 +602,12 @@ bool GetBranchName(const FString& InPathToGitBinary, const FString& InRepository
597602

598603
bool GetRemoteBranchName(const FString& InPathToGitBinary, const FString& InRepositoryRoot, FString& OutBranchName)
599604
{
600-
const FGitSourceControlProvider& Provider = FGitSourceControlModule::Get().GetProvider();
605+
const FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
606+
if (!GitSourceControl)
607+
{
608+
return false;
609+
}
610+
const FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
601611
if (!Provider.GetRemoteBranchName().IsEmpty())
602612
{
603613
OutBranchName = Provider.GetRemoteBranchName();
@@ -813,6 +823,7 @@ class FGitLfsLocksParser
813823
// Filename ID (or we expect it to be the username, but it's empty, or is the ID, we have to assume it's the current user)
814824
if (Informations.Num() == 2 || Informations[1].IsEmpty() || Informations[1].StartsWith(TEXT("ID:")))
815825
{
826+
// TODO: thread safety
816827
LockUser = FGitSourceControlModule::Get().GetProvider().GetLockUser();
817828
}
818829
// Filename Username ID
@@ -1123,8 +1134,13 @@ R Content/Textures/T_Perlin_Noise_M.uasset -> Content/Textures/T_Perlin_Noise_M
11231134
static void ParseFileStatusResult(const FString& InPathToGitBinary, const FString& InRepositoryRoot, const bool InUsingLfsLocking, const TSet<FString>& InFiles,
11241135
const TMap<FString, FString>& InResults, TMap<FString, FGitSourceControlState>& OutStates)
11251136
{
1126-
FGitSourceControlModule& GitSourceControl = FGitSourceControlModule::Get();
1127-
const FString& LfsUserName = GitSourceControl.GetProvider().GetLockUser();
1137+
FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
1138+
if (!GitSourceControl)
1139+
{
1140+
return;
1141+
}
1142+
FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
1143+
const FString& LfsUserName = Provider.GetLockUser();
11281144

11291145
TMap<FString, FString> LockedFiles;
11301146
TMap<FString, FString> Results = InResults;
@@ -1280,7 +1296,13 @@ void CheckRemote(const FString& InPathToGitBinary, const FString& InRepositoryRo
12801296
// We can obtain a list of files that were modified between our remote branches and HEAD. Assumes that fetch has been run to get accurate info.
12811297

12821298
// Gather valid remote branches
1283-
const TArray<FString> StatusBranches = FGitSourceControlModule::Get().GetProvider().GetStatusBranchNames();
1299+
FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
1300+
if (!GitSourceControl)
1301+
{
1302+
return;
1303+
}
1304+
FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
1305+
const TArray<FString> StatusBranches = Provider.GetStatusBranchNames();
12841306

12851307
TSet<FString> BranchesToDiff{ StatusBranches };
12861308

@@ -1339,7 +1361,7 @@ void CheckRemote(const FString& InPathToGitBinary, const FString& InRepositoryRo
13391361
// Check if there's newer binaries pending on this branch
13401362
if (bCurrentBranch && (NewerFileName == TEXT(".checksum") || NewerFileName.StartsWith("Binaries")))
13411363
{
1342-
FGitSourceControlModule::Get().GetProvider().bPendingRestart = true;
1364+
Provider.bPendingRestart = true;
13431365
}
13441366
continue;
13451367
}
@@ -1384,7 +1406,7 @@ bool GetAllLocks(const FString& InRepositoryRoot, const FString& GitBinaryFallba
13841406
const FTimespan CacheTimeElapsed = CurrentTime - FGitLockedFilesCache::LastUpdated;
13851407
bCacheExpired = CacheTimeElapsed > CacheLimit;
13861408
}
1387-
bool bResult;
1409+
bool bResult = false;
13881410
if (bCacheExpired)
13891411
{
13901412
// Our cache expired, or they asked us to expire cache. Query locks directly from the remote server.
@@ -1411,42 +1433,51 @@ bool GetAllLocks(const FString& InRepositoryRoot, const FString& GitBinaryFallba
14111433
TArray<FString> Params;
14121434
Params.Add(TEXT("--cached"));
14131435

1414-
const FString& LockUser = FGitSourceControlModule::Get().GetProvider().GetLockUser();
1415-
1416-
Results.Reset();
1417-
bResult = RunLFSCommand(TEXT("locks"), InRepositoryRoot, GitBinaryFallback, Params, FGitSourceControlModule::GetEmptyStringArray(), Results, OutErrorMessages);
1418-
for (const FString& Result : Results)
1436+
FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
1437+
if (!GitSourceControl)
14191438
{
1420-
FGitLfsLocksParser LockFile(InRepositoryRoot, Result);
1421-
#if UE_BUILD_DEBUG && GIT_DEBUG_STATUS
1422-
UE_LOG(LogSourceControl, Log, TEXT("LockedFile(%s, %s)"), *LockFile.LocalFilename, *LockFile.LockUser);
1423-
#endif
1424-
// Only update remote locks
1425-
if (LockFile.LockUser != LockUser)
1439+
bResult = false;
1440+
}
1441+
else
1442+
{
1443+
FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
1444+
const FString& LockUser = Provider.GetLockUser();
1445+
1446+
Results.Reset();
1447+
bResult = RunLFSCommand(TEXT("locks"), InRepositoryRoot, GitBinaryFallback, Params, FGitSourceControlModule::GetEmptyStringArray(), Results, OutErrorMessages);
1448+
for (const FString& Result : Results)
14261449
{
1427-
OutLocks.Add(MoveTemp(LockFile.LocalFilename), MoveTemp(LockFile.LockUser));
1450+
FGitLfsLocksParser LockFile(InRepositoryRoot, Result);
1451+
#if UE_BUILD_DEBUG && GIT_DEBUG_STATUS
1452+
UE_LOG(LogSourceControl, Log, TEXT("LockedFile(%s, %s)"), *LockFile.LocalFilename, *LockFile.LockUser);
1453+
#endif
1454+
// Only update remote locks
1455+
if (LockFile.LockUser != LockUser)
1456+
{
1457+
OutLocks.Add(MoveTemp(LockFile.LocalFilename), MoveTemp(LockFile.LockUser));
1458+
}
14281459
}
1429-
}
1430-
// Get the latest local state of our own locks
1431-
Params.Reset(1);
1432-
Params.Add(TEXT("--local"));
1460+
// Get the latest local state of our own locks
1461+
Params.Reset(1);
1462+
Params.Add(TEXT("--local"));
14331463

1434-
Results.Reset();
1435-
bResult &= RunLFSCommand(TEXT("locks"), InRepositoryRoot, GitBinaryFallback, Params, FGitSourceControlModule::GetEmptyStringArray(), Results, OutErrorMessages);
1436-
for (const FString& Result : Results)
1437-
{
1438-
FGitLfsLocksParser LockFile(InRepositoryRoot, Result);
1439-
#if UE_BUILD_DEBUG && GIT_DEBUG_STATUS
1440-
UE_LOG(LogSourceControl, Log, TEXT("LockedFile(%s, %s)"), *LockFile.LocalFilename, *LockFile.LockUser);
1441-
#endif
1442-
// Only update local locks
1443-
if (LockFile.LockUser == LockUser)
1464+
Results.Reset();
1465+
bResult &= RunLFSCommand(TEXT("locks"), InRepositoryRoot, GitBinaryFallback, Params, FGitSourceControlModule::GetEmptyStringArray(), Results, OutErrorMessages);
1466+
for (const FString& Result : Results)
14441467
{
1445-
OutLocks.Add(MoveTemp(LockFile.LocalFilename), MoveTemp(LockFile.LockUser));
1468+
FGitLfsLocksParser LockFile(InRepositoryRoot, Result);
1469+
#if UE_BUILD_DEBUG && GIT_DEBUG_STATUS
1470+
UE_LOG(LogSourceControl, Log, TEXT("LockedFile(%s, %s)"), *LockFile.LocalFilename, *LockFile.LockUser);
1471+
#endif
1472+
// Only update local locks
1473+
if (LockFile.LockUser == LockUser)
1474+
{
1475+
OutLocks.Add(MoveTemp(LockFile.LocalFilename), MoveTemp(LockFile.LockUser));
1476+
}
14461477
}
14471478
}
14481479
}
1449-
else
1480+
if (!bResult)
14501481
{
14511482
// We can use our internally tracked local lock cache (an effective combination of --cached and --local)
14521483
OutLocks = FGitLockedFilesCache::LockedFiles;
@@ -1917,9 +1948,13 @@ bool UpdateCachedStates(const TMap<const FString, FGitState>& InResults)
19171948
{
19181949
return false;
19191950
}
1920-
1921-
FGitSourceControlModule& GitSourceControl = FGitSourceControlModule::Get();
1922-
FGitSourceControlProvider& Provider = GitSourceControl.GetProvider();
1951+
1952+
FGitSourceControlModule* GitSourceControl = FGitSourceControlModule::GetThreadSafe();
1953+
if (!GitSourceControl)
1954+
{
1955+
return false;
1956+
}
1957+
FGitSourceControlProvider& Provider = GitSourceControl->GetProvider();
19231958
const bool bUsingGitLfsLocking = Provider.UsesCheckout();
19241959

19251960
// TODO without LFS : Workaround a bug with the Source Control Module not updating file state after a simple "Save" with no "Checkout" (when not using File Lock)

0 commit comments

Comments
 (0)