Source control copies now integrate/copy instead of Delete + Add

TTP# 334923 - EDITOR: Perforce Integration (Move -> Delete + Add instead of Integrate)

New API: Added ISourceControlRevision::GetBranchSource.
Made sure the P4 and SVN providers perform integrates/copies so that history is maintained across file copies & moves.
Also fixed SCC icons not refreshing sometimes until source control operation has completed.
Added new branch icon.
Fixed date display in history.
This required some fairly nasty fixup to get it all working within the Editor copy code path, but the majority of the changes are in the source control providers.

reviewed by Andrew.Brown

[CL 2095604 by Thomas Sarkanen in Main branch]
This commit is contained in:
Thomas Sarkanen
2014-06-05 12:10:47 -04:00
committed by UnrealBot
parent 8cdab0f644
commit e27e005773
33 changed files with 583 additions and 47 deletions

View File

@@ -29,6 +29,7 @@ void FPerforceSourceControlModule::StartupModule()
PerforceSourceControlProvider.RegisterWorker( "Sync", FGetPerforceSourceControlWorker::CreateStatic( &CreateWorker<FPerforceSyncWorker> ) );
PerforceSourceControlProvider.RegisterWorker( "CheckIn", FGetPerforceSourceControlWorker::CreateStatic( &CreateWorker<FPerforceCheckInWorker> ) );
PerforceSourceControlProvider.RegisterWorker( "GetWorkspaces", FGetPerforceSourceControlWorker::CreateStatic( &CreateWorker<FPerforceGetWorkspacesWorker> ) );
PerforceSourceControlProvider.RegisterWorker( "Copy", FGetPerforceSourceControlWorker::CreateStatic( &CreateWorker<FPerforceCopyWorker> ) );
// load our settings
PerforceSourceControlSettings.LoadSettings();

View File

@@ -125,6 +125,10 @@ static void ParseRecordSetForState(const FP4RecordSet& InRecords, TMap<FString,
OutResults.Add(FullPath, EPerforceState::ReadOnly);
}
}
else if(Action == TEXT("branch"))
{
OutResults.Add(FullPath, EPerforceState::Branched);
}
}
}
}
@@ -210,7 +214,7 @@ bool FPerforceConnectWorker::Execute(FPerforceSourceControlCommand& InCommand)
InCommand.bCommandSuccessful = CheckWorkspaceRecordSet(Records, InCommand.ErrorMessages, Notification);
if(!InCommand.bCommandSuccessful)
{
check(InCommand.Operation->GetName() == "Connect");
check(InCommand.Operation->GetName() == GetName());
TSharedRef<FConnect, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FConnect>(InCommand.Operation);
Operation->SetErrorText(Notification);
}
@@ -226,7 +230,7 @@ bool FPerforceConnectWorker::Execute(FPerforceSourceControlCommand& InCommand)
bool FPerforceConnectWorker::UpdateStates() const
{
return false;
return true;
}
FName FPerforceCheckOutWorker::GetName() const
@@ -283,7 +287,7 @@ bool FPerforceCheckInWorker::Execute(FPerforceSourceControlCommand& InCommand)
{
FPerforceConnection& Connection = ScopedConnection.GetConnection();
check(InCommand.Operation->GetName() == "CheckIn");
check(InCommand.Operation->GetName() == GetName());
TSharedRef<FCheckIn, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FCheckIn>(InCommand.Operation);
int32 ChangeList = Connection.CreatePendingChangelist(Operation->GetDescription(), FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.ErrorMessages);
@@ -328,7 +332,6 @@ bool FPerforceCheckInWorker::Execute(FPerforceSourceControlCommand& InCommand)
if (InCommand.bCommandSuccessful)
{
check(InCommand.Operation->GetName() == "CheckIn");
StaticCastSharedRef<FCheckIn>(InCommand.Operation)->SetSuccessMessage(ParseSubmitResults(Records));
for(auto Iter(InCommand.Files.CreateIterator()); Iter; Iter++)
@@ -560,7 +563,14 @@ static void ParseUpdateStatusResults(const FP4RecordSet& InRecords, const TArray
}
else if (OpenType.Len() > 0)
{
State.State = EPerforceState::CheckedOut;
if(Action.Len() > 0 && Action == TEXT("branch"))
{
State.State = EPerforceState::Branched;
}
else
{
State.State = EPerforceState::CheckedOut;
}
}
else if (OtherOpen.Len() > 0)
{
@@ -771,6 +781,22 @@ static void ParseHistoryResults(const FP4RecordSet& InRecords, const TArray<FPer
check(ClientRecord.Contains(*VarName));
FString ClientSpec = ClientRecord(*VarName);
// check for branch
TSharedPtr<FPerforceSourceControlRevision, ESPMode::ThreadSafe> BranchSource;
VarName = FString::Printf(TEXT("how%d,0"), RevisionNumbers);
if(ClientRecord.Contains(*VarName))
{
BranchSource = MakeShareable( new FPerforceSourceControlRevision() );
VarName = FString::Printf(TEXT("file%d,0"), RevisionNumbers);
FString BranchSourceFileName = ClientRecord(*VarName);
BranchSource->FileName = FindWorkspaceFile(InStates, BranchSourceFileName);
VarName = FString::Printf(TEXT("erev%d,0"), RevisionNumbers);
FString BranchSourceRevision = ClientRecord(*VarName);
BranchSource->RevisionNumber = FCString::Atoi(*BranchSourceRevision);
}
TSharedRef<FPerforceSourceControlRevision, ESPMode::ThreadSafe> Revision = MakeShareable( new FPerforceSourceControlRevision() );
Revision->FileName = LocalFileName;
Revision->RevisionNumber = FCString::Atoi(*RevisionNumber);
@@ -779,6 +805,7 @@ static void ParseHistoryResults(const FP4RecordSet& InRecords, const TArray<FPer
Revision->UserName = UserName;
Revision->ClientSpec = ClientSpec;
Revision->Action = Action;
Revision->BranchSource = BranchSource;
Revision->Date = FDateTime(1970, 1, 1, 0, 0, 0, 0) + FTimespan(0, 0, FCString::Atoi(*Date));
Revision->FileSize = FCString::Atoi(*FileSize);
@@ -837,7 +864,7 @@ bool FPerforceUpdateStatusWorker::Execute(FPerforceSourceControlCommand& InComma
}
// update using any special hints passed in via the operation
check(InCommand.Operation->GetName() == "UpdateStatus");
check(InCommand.Operation->GetName() == GetName());
TSharedRef<FUpdateStatus, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FUpdateStatus>(InCommand.Operation);
if(Operation->ShouldUpdateHistory())
@@ -914,7 +941,8 @@ bool FPerforceUpdateStatusWorker::UpdateStates() const
for(FHistoryMap::TConstIterator It(OutHistory); It; ++It)
{
TSharedRef<FPerforceSourceControlState, ESPMode::ThreadSafe> State = PerforceSourceControl.GetProvider().GetStateInternal(It.Key());
State->History = It.Value();
const TArray< TSharedRef<FPerforceSourceControlRevision, ESPMode::ThreadSafe> >& History = It.Value();
State->History = History;
State->TimeStamp = FDateTime::Now();
bUpdated = true;
}
@@ -946,7 +974,7 @@ bool FPerforceGetWorkspacesWorker::Execute(FPerforceSourceControlCommand& InComm
TArray<FString> ClientSpecList;
InCommand.bCommandSuccessful = Connection.GetWorkspaceList(InCommand.ConnectionInfo, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), ClientSpecList, InCommand.ErrorMessages);
check(InCommand.Operation->GetName() == "GetWorkspaces");
check(InCommand.Operation->GetName() == GetName());
TSharedRef<FGetWorkspaces, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FGetWorkspaces>(InCommand.Operation);
Operation->Results = ClientSpecList;
}
@@ -958,4 +986,47 @@ bool FPerforceGetWorkspacesWorker::UpdateStates() const
return false;
}
FName FPerforceCopyWorker::GetName() const
{
return "Copy";
}
bool FPerforceCopyWorker::Execute(class FPerforceSourceControlCommand& InCommand)
{
FScopedPerforceConnection ScopedConnection(InCommand);
if(ScopedConnection.IsValid())
{
FPerforceConnection& Connection = ScopedConnection.GetConnection();
check(InCommand.Operation->GetName() == GetName());
TSharedRef<FCopy, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FCopy>(InCommand.Operation);
FString DestinationPath = FPaths::ConvertRelativePathToFull(Operation->GetDestination());
TArray<FString> Parameters;
Parameters.Append(InCommand.Files);
Parameters.Add(DestinationPath);
FP4RecordSet Records;
InCommand.bCommandSuccessful = Connection.RunCommand(TEXT("integrate"), Parameters, Records, InCommand.ErrorMessages, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);
// we now need to do a p4 edit as the editor will be assuming the file is writable, and p4 integrate does not do this
if(InCommand.bCommandSuccessful)
{
TArray<FString> EditParameters;
EditParameters.Add(DestinationPath);
InCommand.bCommandSuccessful = Connection.RunCommand(TEXT("edit"), EditParameters, Records, InCommand.ErrorMessages, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);
ParseRecordSetForState(Records, OutResults);
}
}
return InCommand.bCommandSuccessful;
}
bool FPerforceCopyWorker::UpdateStates() const
{
return UpdateCachedStates(OutResults);
}
#undef LOCTEXT_NAMESPACE

View File

@@ -125,4 +125,17 @@ public:
virtual FName GetName() const OVERRIDE;
virtual bool Execute(class FPerforceSourceControlCommand& InCommand) OVERRIDE;
virtual bool UpdateStates() const OVERRIDE;
};
class FPerforceCopyWorker : public IPerforceSourceControlWorker
{
public:
// IPerforceSourceControlWorker interface
virtual FName GetName() const OVERRIDE;
virtual bool Execute(class FPerforceSourceControlCommand& InCommand) OVERRIDE;
virtual bool UpdateStates() const OVERRIDE;
public:
/** Map of filenames to perforce state */
TMap<FString, EPerforceState::Type> OutResults;
};

View File

@@ -236,6 +236,11 @@ const FString& FPerforceSourceControlRevision::GetAction() const
return Action;
}
TSharedPtr<ISourceControlRevision, ESPMode::ThreadSafe> FPerforceSourceControlRevision::GetBranchSource() const
{
return BranchSource;
}
const FDateTime& FPerforceSourceControlRevision::GetDate() const
{
return Date;

View File

@@ -11,6 +11,7 @@ public:
: RevisionNumber(0)
, ChangelistNumber(0)
, FileSize(0)
, Date(0)
{
}
@@ -24,6 +25,7 @@ public:
virtual const FString& GetUserName() const OVERRIDE;
virtual const FString& GetClientSpec() const OVERRIDE;
virtual const FString& GetAction() const OVERRIDE;
virtual TSharedPtr<ISourceControlRevision, ESPMode::ThreadSafe> GetBranchSource() const OVERRIDE;
virtual const FDateTime& GetDate() const OVERRIDE;
virtual int32 GetCheckInIdentifier() const OVERRIDE;
virtual int32 GetFileSize() const OVERRIDE;
@@ -41,12 +43,15 @@ public:
/** THe user that made the change for this revision */
FString UserName;
/** THe workspace the change was made form */
/** The workspace the change was made from */
FString ClientSpec;
/** The action (edit, add etc.) that was performed for at this revision */
FString Action;
/** Source of branch, if any */
TSharedPtr<FPerforceSourceControlRevision, ESPMode::ThreadSafe> BranchSource;
/** The date of this revision */
FDateTime Date;

View File

@@ -52,6 +52,8 @@ FName FPerforceSourceControlState::GetIconName() const
return FName("Perforce.OpenForAdd");
case EPerforceState::MarkedForDelete:
return NAME_None;
case EPerforceState::Branched:
return FName("Perforce.Branched");
}
}
@@ -78,6 +80,8 @@ FName FPerforceSourceControlState::GetSmallIconName() const
return FName("Perforce.OpenForAdd_Small");
case EPerforceState::MarkedForDelete:
return NAME_None;
case EPerforceState::Branched:
return FName("Perforce.Branched_Small");
}
}
@@ -104,6 +108,8 @@ FText FPerforceSourceControlState::GetDisplayName() const
return LOCTEXT("OpenedForAdd", "Opened for add");
case EPerforceState::MarkedForDelete:
return LOCTEXT("MarkedForDelete", "Marked for delete");
case EPerforceState::Branched:
return LOCTEXT("Branched", "Branched");
}
}
@@ -130,6 +136,8 @@ FText FPerforceSourceControlState::GetDisplayTooltip() const
return LOCTEXT("OpenedForAdd_Tooltip", "The file(s) are opened for add");
case EPerforceState::MarkedForDelete:
return LOCTEXT("MarkedForDelete_Tooltip", "The file(s) are marked for delete");
case EPerforceState::Branched:
return LOCTEXT("Branched_Tooltip", "The file(s) are opened for branching");
}
}
@@ -145,7 +153,7 @@ const FDateTime& FPerforceSourceControlState::GetTimeStamp() const
bool FPerforceSourceControlState::CanCheckIn() const
{
return (State == EPerforceState::CheckedOut) || (State == EPerforceState::OpenForAdd);
return (State == EPerforceState::CheckedOut) || (State == EPerforceState::OpenForAdd) || (State == EPerforceState::Branched);
}
bool FPerforceSourceControlState::CanCheckout() const
@@ -207,7 +215,7 @@ bool FPerforceSourceControlState::IsIgnored() const
bool FPerforceSourceControlState::CanEdit() const
{
return State == EPerforceState::CheckedOut || State == EPerforceState::OpenForAdd;
return State == EPerforceState::CheckedOut || State == EPerforceState::OpenForAdd || State == EPerforceState::Branched;
}
bool FPerforceSourceControlState::IsUnknown() const

View File

@@ -38,6 +38,9 @@ namespace EPerforceState
/** Not under client root */
NotUnderClientRoot = 9,
/** Opened for branch */
Branched = 10,
};
}