bool FPerforceCheckInWorker::Execute(FPerforceSourceControlCommand& InCommand)
{
	FScopedPerforceConnection ScopedConnection(InCommand);
	if (!InCommand.IsCanceled() && ScopedConnection.IsValid())
	{	
		FPerforceConnection& Connection = ScopedConnection.GetConnection();

		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);
		if (ChangeList > 0)
		{
			// Batch reopen into multiple commands, to avoid command line limits
			const int32 BatchedCount = 100;
			InCommand.bCommandSuccessful = true;
			for (int32 StartingIndex = 0; StartingIndex < InCommand.Files.Num() && InCommand.bCommandSuccessful; StartingIndex += BatchedCount)
			{
				FP4RecordSet Records;
				TArray< FString > ReopenParams;
						
				//Add changelist information to params
				ReopenParams.Insert(TEXT("-c"), 0);
				ReopenParams.Insert(FString::Printf(TEXT("%d"), ChangeList), 1);
				int32 NextIndex = FMath::Min(StartingIndex + BatchedCount, InCommand.Files.Num());

				for (int32 FileIndex = StartingIndex; FileIndex < NextIndex; FileIndex++)
				{
					ReopenParams.Add(InCommand.Files[FileIndex]);
				}

				InCommand.bCommandSuccessful = Connection.RunCommand(TEXT("reopen"), ReopenParams, Records, InCommand.ErrorMessages, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);
			}

			if (InCommand.bCommandSuccessful)
			{
				// Only submit if reopen was successful
				TArray<FString> SubmitParams;
				FP4RecordSet Records;

				SubmitParams.Insert(TEXT("-c"), 0);
				SubmitParams.Insert(FString::Printf(TEXT("%d"), ChangeList), 1);

				InCommand.bCommandSuccessful = Connection.RunCommand(TEXT("submit"), SubmitParams, Records, InCommand.ErrorMessages, FOnIsCancelled::CreateRaw(&InCommand, &FPerforceSourceControlCommand::IsCanceled), InCommand.bConnectionDropped);

				if (InCommand.ErrorMessages.Num() > 0)
				{
					InCommand.bCommandSuccessful = false;
				}

				if (InCommand.bCommandSuccessful)
				{
					// Remove any deleted files from status cache
					FPerforceSourceControlModule& PerforceSourceControl = FModuleManager::GetModuleChecked<FPerforceSourceControlModule>("PerforceSourceControl");
					FPerforceSourceControlProvider& Provider = PerforceSourceControl.GetProvider();

					TArray<TSharedRef<ISourceControlState, ESPMode::ThreadSafe>> States;
					Provider.GetState(InCommand.Files, States, EStateCacheUsage::Use);
					for (const auto& State : States)
					{
						if (State->IsDeleted())
						{
							Provider.RemoveFileFromCache(State->GetFilename());
						}
					}

					StaticCastSharedRef<FCheckIn>(InCommand.Operation)->SetSuccessMessage(ParseSubmitResults(Records));

					for(auto Iter(InCommand.Files.CreateIterator()); Iter; Iter++)
					{
						OutResults.Add(*Iter, EPerforceState::ReadOnly);
					}
				}
			}
		}
		else
		{
			// Failed to create the changelist
			InCommand.bCommandSuccessful = false;
		}
	}

	return InCommand.bCommandSuccessful;
}
bool FSubversionCheckInWorker::Execute(FSubversionSourceControlCommand& InCommand)
{
	check(InCommand.Operation->GetName() == GetName());
	TSharedRef<FCheckIn, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FCheckIn>(InCommand.Operation);
	{
		// make a temp file to place our message in
		FScopedTempFile DescriptionFile(Operation->GetDescription());
		if(DescriptionFile.GetFilename().Len() > 0)
		{
			TArray<FString> Parameters;
			FString DescriptionFilename = DescriptionFile.GetFilename();
			// We need to manually quote the filename because we're not passing the file argument via RunCommand's InFiles parameter
			SubversionSourceControlUtils::QuoteFilename(DescriptionFilename);
			Parameters.Add(FString(TEXT("--file ")) + DescriptionFilename);
			Parameters.Add(TEXT("--encoding utf-8"));

			// we need commit directories that are marked for add here if we are committing any child files that are also marked for add
			TArray<FString> FilesToCommit = InCommand.Files;
			AddDirectoriesToCommit(InCommand, FilesToCommit);

			// we need another temp file to add our file list to (as this must be an atomic operation we cant risk overflowing command-line limits)
			FString Targets;
			for(auto It(FilesToCommit.CreateConstIterator()); It; It++)
			{
				Targets += *It + LINE_TERMINATOR;
			}

			FScopedTempFile TargetsFile(Targets);
			if(TargetsFile.GetFilename().Len() > 0)
			{
				// we first need to release locks if we have any copy (branch) operations in our changes
				ReleaseAnyLocksForCopies(InCommand.Files, InCommand.WorkingCopyRoot, InCommand.RepositoryRoot, InCommand.UserName);

				FString TargetsFilename = TargetsFile.GetFilename();
				// We need to manually quote the filename because we're not passing the file argument via RunCommand's InFiles parameter
				SubversionSourceControlUtils::QuoteFilename(TargetsFilename);
				Parameters.Add(FString(TEXT("--targets ")) + TargetsFilename);

				InCommand.bCommandSuccessful = SubversionSourceControlUtils::RunAtomicCommand(TEXT("commit"), TArray<FString>(), Parameters, InCommand.InfoMessages, InCommand.ErrorMessages, InCommand.UserName);
				if(InCommand.bCommandSuccessful)
				{
					// Remove any deleted files from status cache
					FSubversionSourceControlModule& SubversionSourceControl = FModuleManager::LoadModuleChecked<FSubversionSourceControlModule>("SubversionSourceControl");
					FSubversionSourceControlProvider& Provider = SubversionSourceControl.GetProvider();

					TArray<TSharedRef<ISourceControlState, ESPMode::ThreadSafe>> States;
					Provider.GetState(InCommand.Files, States, EStateCacheUsage::Use);
					for (const auto& State : States)
					{
						if (State->IsDeleted())
						{
							Provider.RemoveFileFromCache(State->GetFilename());
						}
					}

					StaticCastSharedRef<FCheckIn>(InCommand.Operation)->SetSuccessMessage(ParseCommitResults(InCommand.InfoMessages));
				}
			}
		}
	}

	// now update the status of our files
	{
		TArray<FXmlFile> ResultsXml;
		TArray<FString> StatusParameters;
		StatusParameters.Add(TEXT("--verbose"));
		StatusParameters.Add(TEXT("--show-updates"));

		InCommand.bCommandSuccessful &= SubversionSourceControlUtils::RunCommand(TEXT("status"), InCommand.Files, StatusParameters, ResultsXml, InCommand.ErrorMessages, InCommand.UserName);
		SubversionSourceControlUtils::ParseStatusResults(ResultsXml, InCommand.ErrorMessages, InCommand.UserName, InCommand.WorkingCopyRoot, OutStates);
	}

	return InCommand.bCommandSuccessful;
}