We are running UE 5.1 Source Build, and the perforce integration does not respect our ignore file. It shows all files in the Engine/Plugins Content folders and Engine/Content folder as “Not in Depot” and tries to submit them (which will not work because they are ignored). Reverting them deletes them (obviously), but when we add them back in, the same problem persists.
This is incredibly annoying. Because we do not have access to Epic Games Perforce Streams, we got it from Git and then Diffed everything that gets loaded through GitDependencies.exe into a Zip that we download onto our machines. All the content folders are contained in the archive, and we don’t see any value in adding 3000+ Engine Content files to our source control just because the engine ignores the ignore file.
Is there any workaround or fix to this? Or is this working as intended?
Spent 4 hours working through the Perforce Plugins Source Code. I really have no clue what is wrong with it. At first, I thought it depends on the fact that those files were once tracked (uploaded due to ignore file misconfiguration). I manually purged/obliterated all those files and their metadata from the Perforce server. But they still showed up inside Unreal Engine and still cluttered the Submit Window.
Because Perforce Visual Client works as expected and even trying to reconciling the exact files does nothing (well it ignores them as instructed) I was close to giving up.
If anyone ever faces this issue… here is a fix that works for us, but might come with unexpected results if you aren’t careful with your ignore file (if you ignore stuff that is tracked – pls don’t). Source Build only → Modify the PerforceSourceControlOperations.cpp file in Engine/Plugins/Developer/PerforceSourceControl/Source/Private. In the ParseOpenedResults Function (The one that returns TMap), add FileState.State != EPerforceState::Ignore to the condition so that all files that are reported as ignore are actually not sent upward to the engine. Make sure your Engine is closed and build the Plugin project or Engine again.
We ran into similar issue with “Submit Content” dialog showing ignored assets, this is a potential fix you can try if you are building from source.
This part is in Engine\Plugins\Developer\PerforceSourceControl\Source\PerforceSourceControl\Private\PerforceSourceControlOperations.cpp,
in function FPerforceUpdateStatusWorker::Execute(), around line 1950.
Top portion is to help find place in code, added code starts at comment // BEGIN_ADDED_CODE
FP4RecordSet Records;
InCommand.bCommandSuccessful &= Connection.RunCommand(TEXT("fstat"), Parameters, Records, InCommand.ResultInfo, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);
ParseUpdateStatusResults(Records, InCommand.ResultInfo.ErrorMessages, OutStates, ContentRoot, BranchModifications);
RemoveRedundantErrors(InCommand, TEXT(" - no such file(s)."), false);
RemoveRedundantErrors(InCommand, TEXT("' is not under client's root '"));
RemoveRedundantErrors(InCommand, TEXT(" - protected namespace - access denied"), false);
// BEGIN_ADDED_CODE
//
// Currently Perforce integration has an enum value "EPerforceState::Ignored", but nothing is setting it.
// We will try checking which ones are ignored for files that's not in depot yet.
TArray<FString> LocalOnlyFilesToCheck;
TMap<FString, FPerforceSourceControlState*> LocalFileToControlStates;
for (FPerforceSourceControlState& State : OutStates)
{
// ignore recursive directories that ends with "..."
if (State.GetState() == EPerforceState::NotInDepot
&& !State.LocalFilename.EndsWith(TEXT("...")))
{
LocalOnlyFilesToCheck.Add(State.LocalFilename);
LocalFileToControlStates.Add(State.LocalFilename, &State);
}
}
if (LocalOnlyFilesToCheck.Num() > 0)
{
// p4's C++ integration doesn't have "p4 ignores -i files..." command,
// we will use "p4 add -n files...", where -n option is used as a way to preview whether file can be added or not.
TArray<FString> IgnoreParams;
IgnoreParams.Add(TEXT("-n"));
IgnoreParams.Append(LocalOnlyFilesToCheck);
FP4RecordSet IgnoreRecords;
FSourceControlResultInfo IgnoreResultInfo;
Connection.RunCommand(TEXT("add"), IgnoreParams, IgnoreRecords, IgnoreResultInfo, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);
// Note using same way Unreal's code is checking for status by command result messages,
// won't work if message is localized but that will be true for the whole integration.
// Not sure if this works if number of files is very large, it not can try batches.
const FString IgnoredFileMessage = TEXT(" - ignored file");
for (const FText& MessageText : IgnoreResultInfo.InfoMessages)
{
const FString& MessageString = MessageText.ToString();
if (MessageString.Contains(IgnoredFileMessage))
{
int32 IgnoreStartIndex = MessageString.Find(IgnoredFileMessage);
FString FileName = MessageString.Mid(0, IgnoreStartIndex);
// output uses \\ instead of /, replace those to match original inputs
FileName = FileName.Replace(TEXT("\\"), TEXT("/"));
if (LocalFileToControlStates.Contains(FileName))
{
LocalFileToControlStates[FileName]->SetState(EPerforceState::Ignore);
}
}
}
}
// END_ADDED_CODE