This repository has been archived on 2021-12-21. You can view files and clone it, but cannot push or open issues or pull requests.
Bookworm/Plugins/UE4GitPlugin-2.17-beta/Source/GitSourceControl/Private/GitSourceControlState.cpp

387 lines
11 KiB
C++

// Copyright (c) 2014-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
//
// Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
// or copy at http://opensource.org/licenses/MIT)
#include "GitSourceControlState.h"
#define LOCTEXT_NAMESPACE "GitSourceControl.State"
int32 FGitSourceControlState::GetHistorySize() const
{
return History.Num();
}
TSharedPtr<class ISourceControlRevision, ESPMode::ThreadSafe> FGitSourceControlState::GetHistoryItem( int32 HistoryIndex ) const
{
check(History.IsValidIndex(HistoryIndex));
return History[HistoryIndex];
}
TSharedPtr<class ISourceControlRevision, ESPMode::ThreadSafe> FGitSourceControlState::FindHistoryRevision( int32 RevisionNumber ) const
{
for(const auto& Revision : History)
{
if(Revision->GetRevisionNumber() == RevisionNumber)
{
return Revision;
}
}
return nullptr;
}
TSharedPtr<class ISourceControlRevision, ESPMode::ThreadSafe> FGitSourceControlState::FindHistoryRevision(const FString& InRevision) const
{
for(const auto& Revision : History)
{
if(Revision->GetRevision() == InRevision)
{
return Revision;
}
}
return nullptr;
}
TSharedPtr<class ISourceControlRevision, ESPMode::ThreadSafe> FGitSourceControlState::GetBaseRevForMerge() const
{
for(const auto& Revision : History)
{
// look for the the SHA1 id of the file, not the commit id (revision)
if(Revision->FileHash == PendingMergeBaseFileHash)
{
return Revision;
}
}
return nullptr;
}
// @todo add Slate icons for git specific states (NotAtHead vs Conflicted...)
FName FGitSourceControlState::GetIconName() const
{
if(LockState == ELockState::Locked)
{
return FName("Subversion.CheckedOut");
}
else if(LockState == ELockState::LockedOther)
{
return FName("Subversion.CheckedOutByOtherUser");
}
else if (!IsCurrent())
{
return FName("Subversion.NotAtHeadRevision");
}
switch(WorkingCopyState)
{
case EWorkingCopyState::Modified:
if(bUsingGitLfsLocking)
{
return FName("Subversion.NotInDepot");
}
else
{
return FName("Subversion.CheckedOut");
}
case EWorkingCopyState::Added:
return FName("Subversion.OpenForAdd");
case EWorkingCopyState::Renamed:
case EWorkingCopyState::Copied:
return FName("Subversion.Branched");
case EWorkingCopyState::Deleted: // Deleted & Missing files does not show in Content Browser
case EWorkingCopyState::Missing:
return FName("Subversion.MarkedForDelete");
case EWorkingCopyState::Conflicted:
return FName("Subversion.ModifiedOtherBranch");
case EWorkingCopyState::NotControlled:
return FName("Subversion.NotInDepot");
case EWorkingCopyState::Unknown:
case EWorkingCopyState::Unchanged: // Unchanged is the same as "Pristine" (not checked out) for Perforce, ie no icon
case EWorkingCopyState::Ignored:
default:
return NAME_None;
}
return NAME_None;
}
FName FGitSourceControlState::GetSmallIconName() const
{
if(LockState == ELockState::Locked)
{
return FName("Subversion.CheckedOut_Small");
}
else if(LockState == ELockState::LockedOther)
{
return FName("Subversion.CheckedOutByOtherUser_Small");
}
else if (!IsCurrent())
{
return FName("Subversion.NotAtHeadRevision_Small");
}
switch(WorkingCopyState)
{
case EWorkingCopyState::Modified:
if(bUsingGitLfsLocking)
{
return FName("Subversion.NotInDepot_Small");
}
else
{
return FName("Subversion.CheckedOut_Small");
}
case EWorkingCopyState::Added:
return FName("Subversion.OpenForAdd_Small");
case EWorkingCopyState::Renamed:
case EWorkingCopyState::Copied:
return FName("Subversion.Branched_Small");
case EWorkingCopyState::Deleted: // Deleted & Missing files can appear in the Submit to Source Control window
case EWorkingCopyState::Missing:
return FName("Subversion.MarkedForDelete_Small");
case EWorkingCopyState::Conflicted:
return FName("Subversion.ModifiedOtherBranch_Small");
case EWorkingCopyState::NotControlled:
return FName("Subversion.NotInDepot_Small");
case EWorkingCopyState::Unknown:
case EWorkingCopyState::Unchanged: // Unchanged is the same as "Pristine" (not checked out) for Perforce, ie no icon
case EWorkingCopyState::Ignored:
default:
return NAME_None;
}
return NAME_None;
}
FText FGitSourceControlState::GetDisplayName() const
{
if(LockState == ELockState::Locked)
{
return LOCTEXT("Locked", "Locked For Editing");
}
else if(LockState == ELockState::LockedOther)
{
return FText::Format( LOCTEXT("LockedOther", "Locked by "), FText::FromString(LockUser) );
}
else if (!IsCurrent())
{
return LOCTEXT("NotCurrent", "Not current");
}
switch(WorkingCopyState)
{
case EWorkingCopyState::Unknown:
return LOCTEXT("Unknown", "Unknown");
case EWorkingCopyState::Unchanged:
return LOCTEXT("Unchanged", "Unchanged");
case EWorkingCopyState::Added:
return LOCTEXT("Added", "Added");
case EWorkingCopyState::Deleted:
return LOCTEXT("Deleted", "Deleted");
case EWorkingCopyState::Modified:
return LOCTEXT("Modified", "Modified");
case EWorkingCopyState::Renamed:
return LOCTEXT("Renamed", "Renamed");
case EWorkingCopyState::Copied:
return LOCTEXT("Copied", "Copied");
case EWorkingCopyState::Conflicted:
return LOCTEXT("ContentsConflict", "Contents Conflict");
case EWorkingCopyState::Ignored:
return LOCTEXT("Ignored", "Ignored");
case EWorkingCopyState::NotControlled:
return LOCTEXT("NotControlled", "Not Under Source Control");
case EWorkingCopyState::Missing:
return LOCTEXT("Missing", "Missing");
}
return FText();
}
FText FGitSourceControlState::GetDisplayTooltip() const
{
if(LockState == ELockState::Locked)
{
return LOCTEXT("Locked_Tooltip", "Locked for editing by current user");
}
else if(LockState == ELockState::LockedOther)
{
return FText::Format( LOCTEXT("LockedOther_Tooltip", "Locked for editing by: {0}"), FText::FromString(LockUser) );
}
else if (!IsCurrent())
{
return LOCTEXT("NotCurrent_Tooltip", "The file(s) are not at the head revision");
}
switch(WorkingCopyState)
{
case EWorkingCopyState::Unknown:
return LOCTEXT("Unknown_Tooltip", "Unknown source control state");
case EWorkingCopyState::Unchanged:
return LOCTEXT("Pristine_Tooltip", "There are no modifications");
case EWorkingCopyState::Added:
return LOCTEXT("Added_Tooltip", "Item is scheduled for addition");
case EWorkingCopyState::Deleted:
return LOCTEXT("Deleted_Tooltip", "Item is scheduled for deletion");
case EWorkingCopyState::Modified:
return LOCTEXT("Modified_Tooltip", "Item has been modified");
case EWorkingCopyState::Renamed:
return LOCTEXT("Renamed_Tooltip", "Item has been renamed");
case EWorkingCopyState::Copied:
return LOCTEXT("Copied_Tooltip", "Item has been copied");
case EWorkingCopyState::Conflicted:
return LOCTEXT("ContentsConflict_Tooltip", "The contents of the item conflict with updates received from the repository.");
case EWorkingCopyState::Ignored:
return LOCTEXT("Ignored_Tooltip", "Item is being ignored.");
case EWorkingCopyState::NotControlled:
return LOCTEXT("NotControlled_Tooltip", "Item is not under version control.");
case EWorkingCopyState::Missing:
return LOCTEXT("Missing_Tooltip", "Item is missing (e.g., you moved or deleted it without using Git). This also indicates that a directory is incomplete (a checkout or update was interrupted).");
}
return FText();
}
const FString& FGitSourceControlState::GetFilename() const
{
return LocalFilename;
}
const FDateTime& FGitSourceControlState::GetTimeStamp() const
{
return TimeStamp;
}
// Deleted and Missing assets cannot appear in the Content Browser, but the do in the Submit files to Source Control window!
bool FGitSourceControlState::CanCheckIn() const
{
if(bUsingGitLfsLocking)
{
return ( ( (LockState == ELockState::Locked) && !IsConflicted() ) || (WorkingCopyState == EWorkingCopyState::Added) ) && IsCurrent();
}
else
{
return (WorkingCopyState == EWorkingCopyState::Added
|| WorkingCopyState == EWorkingCopyState::Deleted
|| WorkingCopyState == EWorkingCopyState::Missing
|| WorkingCopyState == EWorkingCopyState::Modified
|| WorkingCopyState == EWorkingCopyState::Renamed) && IsCurrent();
}
}
bool FGitSourceControlState::CanCheckout() const
{
if(bUsingGitLfsLocking)
{
// We don't want to allow checkout if the file is out-of-date, as modifying an out-of-date binary file will most likely result in a merge conflict
return (WorkingCopyState == EWorkingCopyState::Unchanged || WorkingCopyState == EWorkingCopyState::Modified) && LockState == ELockState::NotLocked && IsCurrent();
}
else
{
return false; // With Git all tracked files in the working copy are always already checked-out (as opposed to Perforce)
}
}
bool FGitSourceControlState::IsCheckedOut() const
{
if (bUsingGitLfsLocking)
{
return LockState == ELockState::Locked;
}
else
{
return IsSourceControlled(); // With Git all tracked files in the working copy are always checked-out (as opposed to Perforce)
}
}
bool FGitSourceControlState::IsCheckedOutOther(FString* Who) const
{
if (Who != NULL)
{
*Who = LockUser;
}
return LockState == ELockState::LockedOther;
}
bool FGitSourceControlState::IsCurrent() const
{
return !bNewerVersionOnServer;
}
bool FGitSourceControlState::IsSourceControlled() const
{
return WorkingCopyState != EWorkingCopyState::NotControlled && WorkingCopyState != EWorkingCopyState::Ignored && WorkingCopyState != EWorkingCopyState::Unknown;
}
bool FGitSourceControlState::IsAdded() const
{
return WorkingCopyState == EWorkingCopyState::Added;
}
bool FGitSourceControlState::IsDeleted() const
{
return WorkingCopyState == EWorkingCopyState::Deleted || WorkingCopyState == EWorkingCopyState::Missing;
}
bool FGitSourceControlState::IsIgnored() const
{
return WorkingCopyState == EWorkingCopyState::Ignored;
}
bool FGitSourceControlState::CanEdit() const
{
return IsCurrent(); // With Git all files in the working copy are always editable (as opposed to Perforce)
}
bool FGitSourceControlState::CanDelete() const
{
return !IsCheckedOutOther() && IsSourceControlled() && IsCurrent();
}
bool FGitSourceControlState::IsUnknown() const
{
return WorkingCopyState == EWorkingCopyState::Unknown;
}
bool FGitSourceControlState::IsModified() const
{
// Warning: for Perforce, a checked-out file is locked for modification (whereas with Git all tracked files are checked-out),
// so for a clean "check-in" (commit) checked-out files unmodified should be removed from the changeset (the index)
// http://stackoverflow.com/questions/12357971/what-does-revert-unchanged-files-mean-in-perforce
//
// Thus, before check-in UE4 Editor call RevertUnchangedFiles() in PromptForCheckin() and CheckinFiles().
//
// So here we must take care to enumerate all states that need to be commited,
// all other will be discarded :
// - Unknown
// - Unchanged
// - NotControlled
// - Ignored
return WorkingCopyState == EWorkingCopyState::Added
|| WorkingCopyState == EWorkingCopyState::Deleted
|| WorkingCopyState == EWorkingCopyState::Modified
|| WorkingCopyState == EWorkingCopyState::Renamed
|| WorkingCopyState == EWorkingCopyState::Copied
|| WorkingCopyState == EWorkingCopyState::Missing
|| WorkingCopyState == EWorkingCopyState::Conflicted;
}
bool FGitSourceControlState::CanAdd() const
{
return WorkingCopyState == EWorkingCopyState::NotControlled;
}
bool FGitSourceControlState::IsConflicted() const
{
return WorkingCopyState == EWorkingCopyState::Conflicted;
}
bool FGitSourceControlState::CanRevert() const
{
return CanCheckIn();
}
#undef LOCTEXT_NAMESPACE