void FCollectionManager::LoadCollections() { const double LoadStartTime = FPlatformTime::Seconds(); int32 NumCollectionsLoaded = 0; for (int32 CacheIdx = 0; CacheIdx < ECollectionShareType::CST_All; ++CacheIdx) { const FString& CollectionFolder = CollectionFolders[CacheIdx]; const FString WildCard = FString::Printf(TEXT("%s/*.%s"), *CollectionFolder, *CollectionExtension); TArray<FString> Filenames; IFileManager::Get().FindFiles(Filenames, *WildCard, true, false); for (int32 FileIdx = 0; FileIdx < Filenames.Num(); ++FileIdx) { const FString Filename = CollectionFolder / Filenames[FileIdx]; FCollection Collection; const bool bUseSCC = ShouldUseSCC(ECollectionShareType::Type(CacheIdx)); if ( Collection.LoadFromFile(Filename, bUseSCC) ) { AddCollection(Collection, ECollectionShareType::Type(CacheIdx)); } else { UE_LOG(LogCollectionManager, Warning, TEXT("Failed to load collection file %s"), *Filename); } } NumCollectionsLoaded += CachedCollections[CacheIdx].Num(); } UE_LOG( LogCollectionManager, Log, TEXT( "Loaded %d collections in %0.6f seconds" ), NumCollectionsLoaded, FPlatformTime::Seconds() - LoadStartTime ); }
bool FCollection::DeleteFromSourceControl(FText& OutError) { ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); if ( !ISourceControlModule::Get().IsEnabled() ) { OutError = LOCTEXT("Error_SCCDisabled", "Source control is not enabled. Enable source control in the preferences menu."); return false; } if ( !SourceControlProvider.IsAvailable() ) { OutError = LOCTEXT("Error_SCCNotAvailable", "Source control is currently not available. Check your connection and try again."); return false; } bool bDeletedSuccessfully = false; const int32 DeleteProgressDenominator = 2; int32 DeleteProgressNumerator = 0; const FText CollectionNameText = FText::FromName( CollectionName ); FFormatNamedArguments Args; Args.Add( TEXT("CollectionName"), CollectionNameText ); const FText StatusUpdate = FText::Format( LOCTEXT("DeletingCollection", "Deleting Collection {CollectionName}"), Args ); GWarn->BeginSlowTask( StatusUpdate, true ); GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator); FString AbsoluteFilename = FPaths::ConvertRelativePathToFull(SourceFilename); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator); // If checked out locally for some reason, revert if (SourceControlState.IsValid() && (SourceControlState->IsAdded() || SourceControlState->IsCheckedOut() || SourceControlState->IsDeleted())) { if ( !RevertCollection(OutError) ) { // Failed to revert, just bail out GWarn->EndSlowTask(); return false; } // Make sure we get a fresh state from the server SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); } // If not at the head revision, sync up if (SourceControlState.IsValid() && !SourceControlState->IsCurrent()) { if ( !SourceControlProvider.Execute(ISourceControlOperation::Create<FSync>(), AbsoluteFilename) ) { // Could not sync up with the head revision GWarn->EndSlowTask(); OutError = LOCTEXT("Error_SCCSync", "Failed to sync collection to the head revision."); return false; } // Check to see if the file exists at the head revision if ( IFileManager::Get().FileSize(*SourceFilename) < 0 ) { // File was already deleted, consider this a success GWarn->EndSlowTask(); return true; } FCollection NewCollection; if ( !NewCollection.LoadFromFile(SourceFilename, false) ) { // Failed to load the head revision file so it isn't safe to delete it GWarn->EndSlowTask(); OutError = LOCTEXT("Error_SCCBadHead", "Failed to load the collection at the head revision."); return false; } // Loaded the head revision, now merge up so the files are in a consistent state MergeWithCollection(NewCollection); // Make sure we get a fresh state from the server SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); } GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator); if(SourceControlState.IsValid()) { if(SourceControlState->IsAdded() || SourceControlState->IsCheckedOut()) { OutError = LOCTEXT("Error_SCCDeleteWhileCheckedOut", "Failed to delete collection in source control because it is checked out or open for add."); } else if(SourceControlState->CanCheckout()) { if ( SourceControlProvider.Execute(ISourceControlOperation::Create<FDelete>(), AbsoluteFilename) ) { // Now check in the delete const FText ChangelistDesc = FText::Format( LOCTEXT("CollectionDeletedDesc", "Deleted collection: {CollectionName}"), CollectionNameText ); TSharedRef<FCheckIn, ESPMode::ThreadSafe> CheckInOperation = ISourceControlOperation::Create<FCheckIn>(); CheckInOperation->SetDescription(ChangelistDesc.ToString()); if ( SourceControlProvider.Execute( CheckInOperation, AbsoluteFilename ) ) { // Deleted successfully! bDeletedSuccessfully = true; } else { FText Unused; if ( !RevertCollection(Unused) ) { UE_LOG(LogCollectionManager, Warning, TEXT("Failed to revert collection '%s' after failing to check in the file that was marked for delete."), *CollectionName.ToString()); } OutError = LOCTEXT("Error_SCCCheckIn", "Failed to check in collection."); } } else { OutError = LOCTEXT("Error_SCCDeleteFailed", "Failed to delete collection in source control."); } } else if(!SourceControlState->IsSourceControlled()) { // Not yet in the depot or deleted. We can just delete it from disk. bDeletedSuccessfully = IFileManager::Get().Delete(*AbsoluteFilename); if ( !bDeletedSuccessfully ) { OutError = LOCTEXT("Error_DiskDeleteFailed", "Failed to delete the collection file from disk."); } } else if (!SourceControlState->IsCurrent()) { OutError = LOCTEXT("Error_SCCNotCurrent", "Collection is not at head revision after sync."); } else if(SourceControlState->IsCheckedOutOther()) { OutError = LOCTEXT("Error_SCCCheckedOutOther", "Collection is checked out by another user."); } else { OutError = LOCTEXT("Error_SCCUnknown", "Could not determine source control state."); } } else { OutError = LOCTEXT("Error_SCCInvalid", "Source control state is invalid."); } GWarn->UpdateProgress(DeleteProgressNumerator++, DeleteProgressDenominator); GWarn->EndSlowTask(); return bDeletedSuccessfully; }
bool FCollection::CheckoutCollection(FText& OutError) { if ( !ensure(SourceFilename.Len()) ) { OutError = LOCTEXT("Error_Internal", "There was an internal error."); return false; } ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider(); if ( !ISourceControlModule::Get().IsEnabled() ) { OutError = LOCTEXT("Error_SCCDisabled", "Source control is not enabled. Enable source control in the preferences menu."); return false; } if ( !SourceControlProvider.IsAvailable() ) { OutError = LOCTEXT("Error_SCCNotAvailable", "Source control is currently not available. Check your connection and try again."); return false; } FString AbsoluteFilename = FPaths::ConvertRelativePathToFull(SourceFilename); FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); bool bSuccessfullyCheckedOut = false; TArray<FString> FilesToBeCheckedOut; FilesToBeCheckedOut.Add(AbsoluteFilename); if (SourceControlState.IsValid() && SourceControlState->IsDeleted()) { // Revert our delete if ( !RevertCollection(OutError) ) { return false; } // Make sure we get a fresh state from the server SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); } // If not at the head revision, sync up if (SourceControlState.IsValid() && !SourceControlState->IsCurrent()) { if ( !SourceControlProvider.Execute(ISourceControlOperation::Create<FSync>(), FilesToBeCheckedOut) ) { // Could not sync up with the head revision OutError = LOCTEXT("Error_SCCSync", "Failed to sync collection to the head revision."); return false; } // Check to see if the file exists at the head revision if ( IFileManager::Get().FileSize(*SourceFilename) < 0 ) { // File was deleted at head... // Just add our changes to an empty list so we can mark it for add FCollection NewCollection; MergeWithCollection(NewCollection); } else { // File found! Load it and merge with our local changes FCollection NewCollection; if ( !NewCollection.LoadFromFile(SourceFilename, false) ) { // Failed to load the head revision file so it isn't safe to delete it OutError = LOCTEXT("Error_SCCBadHead", "Failed to load the collection at the head revision."); return false; } // Loaded the head revision, now merge up so the files are in a consistent state MergeWithCollection(NewCollection); } // Make sure we get a fresh state from the server SourceControlState = SourceControlProvider.GetState(AbsoluteFilename, EStateCacheUsage::ForceUpdate); } if(SourceControlState.IsValid()) { if(SourceControlState->IsAdded() || SourceControlState->IsCheckedOut()) { // Already checked out or opened for add bSuccessfullyCheckedOut = true; } else if(SourceControlState->CanCheckout()) { // In depot and needs to be checked out bSuccessfullyCheckedOut = (SourceControlProvider.Execute(ISourceControlOperation::Create<FCheckOut>(), FilesToBeCheckedOut) == ECommandResult::Succeeded); if (!bSuccessfullyCheckedOut) { OutError = LOCTEXT("Error_SCCCheckout", "Failed to check out collection."); } } else if(!SourceControlState->IsSourceControlled()) { // Not yet in the depot. Add it. bSuccessfullyCheckedOut = (SourceControlProvider.Execute(ISourceControlOperation::Create<FMarkForAdd>(), FilesToBeCheckedOut) == ECommandResult::Succeeded); if (!bSuccessfullyCheckedOut) { OutError = LOCTEXT("Error_SCCAdd", "Failed to add new collection to source control."); } } else if(!SourceControlState->IsCurrent()) { OutError = LOCTEXT("Error_SCCNotCurrent", "Collection is not at head revision after sync."); } else if(SourceControlState->IsCheckedOutOther()) { OutError = LOCTEXT("Error_SCCCheckedOutOther", "Collection is checked out by another user."); } else { OutError = LOCTEXT("Error_SCCUnknown", "Could not determine source control state."); } } else { OutError = LOCTEXT("Error_SCCInvalid", "Source control state is invalid."); } return bSuccessfullyCheckedOut; }