Skip to content

Commit d5fc41d

Browse files
committed
Properly evaluate gitignore and skip ignored files
(PR#186)[ProjectBorealis#186]
1 parent 8af6b84 commit d5fc41d

File tree

1 file changed

+62
-74
lines changed

1 file changed

+62
-74
lines changed

Source/GitSourceControl/Private/GitSourceControlOperations.cpp

Lines changed: 62 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "SourceControlHelpers.h"
1616
#include "Logging/MessageLog.h"
1717
#include "Misc/MessageDialog.h"
18+
#include "HAL/FileManager.h"
1819
#include "HAL/PlatformProcess.h"
1920
#include "GenericPlatform/GenericPlatformFile.h"
2021
#if ENGINE_MAJOR_VERSION >= 5
@@ -470,41 +471,41 @@ bool FGitDeleteWorker::UpdateStates() const
470471
}
471472

472473

473-
// Get lists of Missing files (ie "deleted"), Modified files, and "other than Added" Existing files
474-
void GetMissingVsExistingFiles(const TArray<FString>& InFiles, TArray<FString>& OutMissingFiles, TArray<FString>& OutAllExistingFiles, TArray<FString>& OutOtherThanAddedExistingFiles)
474+
void GroupFileCommandsForRevert(const TArray<FString>& InFiles, TArray<FString>& FilesToRemove, TArray<FString>& FilesToCheckout, TArray<FString>& FilesToReset, TArray<FString>& FilesToDelete)
475475
{
476476
FGitSourceControlModule& GitSourceControl = FGitSourceControlModule::Get();
477477
FGitSourceControlProvider& Provider = GitSourceControl.GetProvider();
478478

479-
const TArray<FString> Files = (InFiles.Num() > 0) ? (InFiles) : (Provider.GetFilesInCache());
480-
481479
TArray<TSharedRef<ISourceControlState, ESPMode::ThreadSafe>> LocalStates;
482-
Provider.GetState(Files, LocalStates, EStateCacheUsage::Use);
480+
Provider.GetState(InFiles, LocalStates, EStateCacheUsage::Use);
483481
for (const auto& State : LocalStates)
484482
{
485-
if (FPaths::FileExists(State->GetFilename()))
483+
if (State->IsAdded())
486484
{
487-
if (State->IsAdded())
488-
{
489-
OutAllExistingFiles.Add(State->GetFilename());
490-
}
491-
else if (State->IsModified())
485+
if (FPaths::FileExists(State->GetFilename()))
492486
{
493-
OutOtherThanAddedExistingFiles.Add(State->GetFilename());
494-
OutAllExistingFiles.Add(State->GetFilename());
487+
// Git rm won't delete the file because the engine still has it in use, and reset won't work on a file which doesn't exist on disk
488+
// so we have to delete it ourselves, and then remove it from the index.
489+
if (USourceControlPreferences::ShouldDeleteNewFilesOnRevert())
490+
{
491+
FilesToDelete.Add(State->GetFilename());
492+
FilesToRemove.Add(State->GetFilename());
493+
}
494+
else
495+
{
496+
FilesToReset.Add(State->GetFilename());
497+
}
495498
}
496-
else if (State->CanRevert()) // for locked but unmodified files
499+
else
497500
{
498-
OutOtherThanAddedExistingFiles.Add(State->GetFilename());
501+
// When you delete a file through content browser, UE will send a revert command to allow us to clean up the stage state.
502+
FilesToRemove.Add(State->GetFilename());
499503
}
500504
}
501-
else
505+
// Checkout to head will reset the file back to what it is in your current commit, and reset the index.
506+
else if (State->CanRevert())
502507
{
503-
// If already queued for deletion, don't try to delete again
504-
if (State->IsSourceControlled() && !State->IsDeleted())
505-
{
506-
OutMissingFiles.Add(State->GetFilename());
507-
}
508+
FilesToCheckout.Add(State->GetFilename());
508509
}
509510
}
510511
}
@@ -519,63 +520,62 @@ bool FGitRevertWorker::Execute(FGitSourceControlCommand& InCommand)
519520
InCommand.bCommandSuccessful = true;
520521

521522
// Filter files by status
522-
TArray<FString> MissingFiles;
523-
TArray<FString> AllExistingFiles;
524-
TArray<FString> OtherThanAddedExistingFiles;
525-
GetMissingVsExistingFiles(InCommand.Files, MissingFiles, AllExistingFiles, OtherThanAddedExistingFiles);
526-
527-
const bool bRevertAll = InCommand.Files.Num() < 1;
523+
const bool bRevertAll = InCommand.Files.Num() == 0;
528524
if (bRevertAll)
529525
{
530-
TArray<FString> Parms;
531-
Parms.Add(TEXT("--hard"));
532-
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("reset"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, Parms, FGitSourceControlModule::GetEmptyStringArray(), InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
526+
TArray<FString> Params;
527+
Params.Add(TEXT("--hard"));
528+
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("reset"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, Params, FGitSourceControlModule::GetEmptyStringArray(), InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
533529

534-
Parms.Reset(2);
535-
Parms.Add(TEXT("-f")); // force
536-
Parms.Add(TEXT("-d")); // remove directories
537-
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("clean"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, Parms, FGitSourceControlModule::GetEmptyStringArray(), InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
530+
Params.Reset(2);
531+
Params.Add(TEXT("-f")); // force
532+
Params.Add(TEXT("-d")); // remove directories
533+
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("clean"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, Params, FGitSourceControlModule::GetEmptyStringArray(), InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
538534
}
539535
else
540536
{
541-
if (MissingFiles.Num() > 0)
537+
TArray<FString> FilesToRemove;
538+
TArray<FString> FilesToCheckout;
539+
TArray<FString> FilesToReset;
540+
TArray<FString> FilesToDelete;
541+
GroupFileCommandsForRevert(InCommand.Files, FilesToRemove, FilesToCheckout, FilesToReset, FilesToDelete);
542+
543+
// Verify we haven't missed performing an operation on any file passed on for revert
544+
ensure(FilesToRemove.Num() + FilesToCheckout.Num() + FilesToReset.Num() == InCommand.Files.Num());
545+
546+
for (const FString& FileName : FilesToDelete)
542547
{
543-
// "Added" files that have been deleted needs to be removed from revision control
544-
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("rm"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), MissingFiles, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
548+
bool RequireExists = true;
549+
bool EvenReadOnly = true;
550+
IFileManager::Get().Delete(*FileName, RequireExists, EvenReadOnly);
545551
}
546-
if (AllExistingFiles.Num() > 0)
552+
if (FilesToReset.Num() > 0)
547553
{
548-
// reset and revert any changes already added to the index
549-
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("reset"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), AllExistingFiles, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
550-
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("checkout"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), AllExistingFiles, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
554+
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("reset"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), FilesToReset, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
551555
}
552-
if (OtherThanAddedExistingFiles.Num() > 0)
556+
if (FilesToRemove.Num() > 0)
553557
{
554-
// revert any changes in working copy (this would fails if the asset was in "Added" state, since after "reset" it is now "untracked")
555-
// may need to try a few times due to file locks from prior operations
556-
bool CheckoutSuccess = false;
557-
int32 Attempts = 10;
558-
while( Attempts-- > 0 )
559-
{
560-
CheckoutSuccess = GitSourceControlUtils::RunCommand(TEXT("checkout"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), OtherThanAddedExistingFiles, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
561-
if (CheckoutSuccess)
562-
{
563-
break;
564-
}
565-
566-
FPlatformProcess::Sleep(0.1f);
567-
}
568-
569-
InCommand.bCommandSuccessful &= CheckoutSuccess;
558+
// "Added" files that have been deleted needs to be removed from revision control
559+
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("rm"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, FGitSourceControlModule::GetEmptyStringArray(), FilesToRemove, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
560+
}
561+
if (FilesToCheckout.Num() > 0)
562+
{
563+
// HEAD param allows us to re-pull files which have been deleted.
564+
TArray<FString> Params;
565+
Params.Add(TEXT("HEAD"));
566+
// Checkout back to the last commit for any modified files.
567+
InCommand.bCommandSuccessful &= GitSourceControlUtils::RunCommand(TEXT("checkout"), InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, Params, FilesToCheckout, InCommand.ResultInfo.InfoMessages, InCommand.ResultInfo.ErrorMessages);
570568
}
571569
}
572570

571+
// This is all the files we "asked" to revert, in the case of InCommand.Files everything *should* be changed
572+
// in the case where we didn't pass in any files, we ran a revert on the repository root, so we should refresh everything
573+
const TArray<FString>& RequestedReverts = bRevertAll ? FGitSourceControlModule::Get().GetProvider().GetFilesInCache() : InCommand.Files;
573574
if (InCommand.bUsingGitLfsLocking)
574575
{
575576
// unlock files: execute the LFS command on relative filenames
576-
// (unlock only locked files, that is, not Added files)
577577
TArray<FString> LockedFiles;
578-
GitSourceControlUtils::GetLockedFiles(OtherThanAddedExistingFiles, LockedFiles);
578+
GitSourceControlUtils::GetLockedFiles(RequestedReverts, LockedFiles);
579579
if (LockedFiles.Num() > 0)
580580
{
581581
const TArray<FString>& RelativeFiles = GitSourceControlUtils::RelativeFilenames(LockedFiles, InCommand.PathToGitRoot);
@@ -591,19 +591,9 @@ bool FGitRevertWorker::Execute(FGitSourceControlCommand& InCommand)
591591
}
592592
}
593593

594-
// If no files were specified (full revert), refresh all relevant files instead of the specified files (which is an empty list in full revert)
595-
// This is required so that files that were "Marked for add" have their status updated after a full revert.
596-
TArray<FString> FilesToUpdate = InCommand.Files;
597-
if (InCommand.Files.Num() <= 0)
598-
{
599-
for (const auto& File : MissingFiles) FilesToUpdate.Add(File);
600-
for (const auto& File : AllExistingFiles) FilesToUpdate.Add(File);
601-
for (const auto& File : OtherThanAddedExistingFiles) FilesToUpdate.Add(File);
602-
}
603-
604594
// now update the status of our files
605595
TMap<FString, FGitSourceControlState> UpdatedStates;
606-
bool bSuccess = GitSourceControlUtils::RunUpdateStatus(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.bUsingGitLfsLocking, FilesToUpdate, InCommand.ResultInfo.ErrorMessages, UpdatedStates);
596+
bool bSuccess = GitSourceControlUtils::RunUpdateStatus(InCommand.PathToGitBinary, InCommand.PathToRepositoryRoot, InCommand.bUsingGitLfsLocking, RequestedReverts, InCommand.ResultInfo.ErrorMessages, UpdatedStates);
607597
if (bSuccess)
608598
{
609599
GitSourceControlUtils::CollectNewStates(UpdatedStates, States);
@@ -856,7 +846,6 @@ bool FGitResolveWorker::UpdateStates() const
856846
return GitSourceControlUtils::UpdateCachedStates(States);
857847
}
858848

859-
#if ENGINE_MAJOR_VERSION == 5
860849
FName FGitMoveToChangelistWorker::GetName() const
861850
{
862851
return "MoveToChangelist";
@@ -906,6 +895,5 @@ bool FGitUpdateStagingWorker::UpdateStates() const
906895
{
907896
return true;
908897
}
909-
#endif
910898

911-
#undef LOCTEXT_NAMESPACE
899+
#undef LOCTEXT_NAMESPACE

0 commit comments

Comments
 (0)