// 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) #pragma once #include "GitSourceControlChangelist.h" #include "GitSourceControlRevision.h" #include "Runtime/Launch/Resources/Version.h" /** A consolidation of state priorities. */ namespace EGitState { enum Type { Unset, NotAtHead, #if 0 AddedAtHead, DeletedAtHead, #endif LockedOther, NotLatest, /** Unmerged state (modified, but conflicts) */ Unmerged, Added, Deleted, Modified, /** Not modified, but locked explicitly. */ CheckedOut, Untracked, Lockable, Unmodified, Ignored, /** Whatever else. */ None, }; } /** Corresponds to diff file states. */ namespace EFileState { enum Type { Unset, Unknown, Added, Copied, Deleted, Modified, Renamed, Missing, Unmerged, }; } /** Where in the world is this file? */ namespace ETreeState { enum Type { Unset, /** This file is synced to commit */ Unmodified, /** This file is modified, but not in staging tree */ Working, /** This file is in staging tree (git add) */ Staged, /** This file is not tracked in the repo yet */ Untracked, /** This file is ignored by the repo */ Ignored, /** This file is outside the repo folder */ NotInRepo, }; } /** LFS locks status of this file */ namespace ELockState { enum Type { Unset, Unknown, Unlockable, NotLocked, Locked, LockedOther, }; } /** What is this file doing at HEAD? */ namespace ERemoteState { enum Type { Unset, /** Up to date */ UpToDate, /** Local version is behind remote */ NotAtHead, #if 0 // TODO: handle these /** Remote file does not exist on local */ AddedAtHead, /** Local was deleted on remote */ DeletedAtHead, #endif /** Not at the latest revision amongst the tracked branches */ NotLatest, }; } /** Combined state, for updating cache in a map. */ struct FGitState { EFileState::Type FileState = EFileState::Unknown; ETreeState::Type TreeState = ETreeState::NotInRepo; ELockState::Type LockState = ELockState::Unknown; /** Name of user who has locked the file */ FString LockUser; ERemoteState::Type RemoteState = ERemoteState::UpToDate; /** The branch with the latest commit for this file */ FString HeadBranch; }; class FGitSourceControlState : public ISourceControlState { public: FGitSourceControlState(const FString &InLocalFilename) : LocalFilename(InLocalFilename) , TimeStamp(0) , HeadAction(TEXT("Changed")) , HeadCommit(TEXT("Unknown")) { } /** ISourceControlState interface */ virtual int32 GetHistorySize() const override; virtual TSharedPtr GetHistoryItem(int32 HistoryIndex) const override; virtual TSharedPtr FindHistoryRevision(int32 RevisionNumber) const override; virtual TSharedPtr FindHistoryRevision(const FString& InRevision) const override; #if ENGINE_MAJOR_VERSION < 5 || ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION < 3 virtual TSharedPtr GetBaseRevForMerge() const override; #else virtual FResolveInfo GetResolveInfo() const override; #endif #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2 virtual TSharedPtr GetCurrentRevision() const override; #endif #if ENGINE_MAJOR_VERSION >= 5 virtual FSlateIcon GetIcon() const override; #else virtual FName GetIconName() const override; virtual FName GetSmallIconName() const override; #endif virtual FText GetDisplayName() const override; virtual FText GetDisplayTooltip() const override; virtual const FString& GetFilename() const override; virtual const FDateTime& GetTimeStamp() const override; virtual bool CanCheckIn() const override; virtual bool CanCheckout() const override; virtual bool IsCheckedOut() const override; virtual bool IsCheckedOutOther(FString* Who = NULL) const override; virtual bool IsCheckedOutInOtherBranch(const FString& CurrentBranch = FString()) const override; virtual bool IsModifiedInOtherBranch(const FString& CurrentBranch = FString()) const override; virtual bool IsCheckedOutOrModifiedInOtherBranch(const FString& CurrentBranch = FString()) const override { return IsModifiedInOtherBranch(CurrentBranch); } virtual TArray GetCheckedOutBranches() const override { return TArray(); } virtual FString GetOtherUserBranchCheckedOuts() const override { return FString(); } virtual bool GetOtherBranchHeadModification(FString& HeadBranchOut, FString& ActionOut, int32& HeadChangeListOut) const override; virtual bool IsCurrent() const override; virtual bool IsSourceControlled() const override; virtual bool IsAdded() const override; virtual bool IsDeleted() const override; virtual bool IsIgnored() const override; virtual bool CanEdit() const override; virtual bool IsUnknown() const override; virtual bool IsModified() const override; virtual bool CanAdd() const override; virtual bool CanDelete() const override; virtual bool IsConflicted() const override; virtual bool CanRevert() const override; private: EGitState::Type GetGitState() const; public: /** History of the item, if any */ TGitSourceControlHistory History; /** Filename on disk */ FString LocalFilename; #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 3 /** Pending rev info with which a file must be resolved, invalid if no resolve pending */ FResolveInfo PendingResolveInfo; UE_DEPRECATED(5.3, "Use PendingResolveInfo.BaseRevision instead") #endif /** File Id with which our local revision diverged from the remote revision */ FString PendingMergeBaseFileHash; /** Status of the file */ FGitState State; FGitSourceControlChangelist Changelist; /** The timestamp of the last update */ FDateTime TimeStamp; /** The action within the head branch TODO */ FString HeadAction; /** The last file modification time in the head branch TODO */ int64 HeadModTime; /** The change list the last modification TODO */ FString HeadCommit; };