Files
2025-09-29 00:52:08 +02:00

495 lines
11 KiB
Python
Executable File

'''
Perforce
Author: Jason Hayes <jason.hayes@rockstarsandiego.com>
Description:
Helper functions for interfacing with Perforce through our .NET RSG.SourceControl.Perforce library.
'''
import os
import types
import clr
import RS.Config
clr.AddReference( "RSG.SourceControl.Perforce" )
from RSG.SourceControl.Perforce import P4
from RSG.SourceControl.Perforce import FileState
from RSG.SourceControl.Perforce import FileAction
from RSG.SourceControl.Perforce import Changelist
## Constants ##
# Setup the Perforce connection to use the current project root.
p4 = P4()
p4.CWD = RS.Config.Project.Path.Root
## Functions ##
def _AssertFileState( fileStateObj ):
'''
Asserts if the supplied object isn't of type RSG.SourceControl.Perforce.FileState
Arguments:
fileStateObj: The RSG.SourceControl.Perforce.FileState object to check.
'''
assert isinstance( fileStateObj, FileState ), 'Incorrect type: Must supply a RSG.SourceControl.Perforce.FileState object!'
def DoesFileExist( filename ):
'''
Checks to see if the supplied filename exists in Perforce.
Arguments:
filename: The filename to check.
Returns:
True or False
'''
return p4.Exists( filename )
def IsLatest( fileStateObj ):
'''
Checks to see if the supplied RSG.SourceControl.Perforce.FileState object is the latest revision.
Arguments:
fileStateObj: The RSG.SourceControl.Perforce.FileState object to check.
Returns:
True or False
'''
_AssertFileState( fileStateObj )
return fileStateObj.HaveRevision == fileStateObj.HeadRevision
def IsOpenForEdit( fileStateObj ):
'''
Checks whether or not the supplied file is opened for edit by the current user.
Arguments:
fileStateObj: The RSG.SourceControl.Perforce.FileState object to check.
Returns:
True or False
'''
_AssertFileState( fileStateObj )
return fileStateObj.OpenAction == FileAction.Edit
def CanOpenForEdit( fileStateObj ):
'''
Tests whether or not a file can be opened for edit by the current user.
Arguments:
fileStateObj: The RSG.SourceControl.Perforce.FileState object to check.
Returns:
True or False
'''
_AssertFileState( fileStateObj )
return fileStateObj.Locked
def GetFileState( filenames ):
'''
Runs fstat on the supplied filenames.
Arguments:
filenames: The filenames to test.
Returns:
A list of RSG.SourceControl.Perforce.FileState objects.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
fileStates = list( FileState.Create( p4, filenames ) )
if len( fileStates ) == 1:
return fileStates[ 0 ]
return fileStates
def Add( filenames, changelistNum = None):
'''
Adds the supplied filenames to Perforce.
Arguments:
filenames: The filenames to add.
Keyword Arguments:
changelistNum: Add files to the specified changelist.
Returns:
A single or list of RSG.SourceControl.Perforce.FileState objects that were added.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
args = []
if changelistNum:
args = [ '-c', str( changelistNum ) ]
for filename in filenames:
args.append( filename )
recordSet = p4.Run( 'add', args )
fileStates = list( FileState.Create( p4, recordSet ) )
if len( fileStates ) == 1:
return fileStates[ 0 ]
return fileStates
def Find( searchString, searchDirectory='/'):
'''
Runs 'files' p4 command on a depot path and search string
Arguments:
searchString = partial or full string to search for, no need to include wildcards, it gets built into the arguments
searchDirectory = starting path for the search in the depot
Returns:
A single list of paths found.
'''
global p4
p4.Connect()
args = ["-e", searchDirectory + "/..." + searchString]
recordSet = p4.Run( 'files', args )
fileStates = list( FileState.Create( p4, recordSet ) )
foundFiles = []
for state in fileStates:
foundFiles.append(state.get_DepotFilename())
return foundFiles
def Edit( filenames, changelistNum = None ):
'''
Opens for edit the supplied filenames.
Arguments:
filenames: The filenames to open for edit.
Keyword Arguments:
changelistNum: Open for edit the files under this changelist.
Returns:
A single or list of RSG.SourceControl.Perforce.FileState objects that were opened for edit.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
args = []
if changelistNum:
args.append( '-c' )
args.append( str( changelistNum ) )
for filename in filenames:
args.append( filename )
recordSet = p4.Run( 'edit', args )
fileStates = list( FileState.Create( p4, recordSet ) )
if len( fileStates ) == 1:
return fileStates[ 0 ]
return fileStates
def Sync( filenames, force = False, revision = None ):
'''
Syncs the supplied filename(s).
Arguments:
filenames: The filename(s) to sync.
Keyword Arguments:
force: Whether or not to force the sync.
revision: Sync to the specified revision.
Returns:
A single or list of RSG.SourceControl.Perforce.FileState objects that were synced.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
args = []
if force:
args.append( '-f' )
for filename in filenames:
if revision:
filename += '#{0}'.format( revision )
args.append( filename )
recordSet = p4.Run( 'sync', args )
fileStates = list( FileState.Create( p4, recordSet ) )
if len( fileStates ) == 1:
return fileStates[ 0 ]
return fileStates
def GetChangelist( changelistNum ):
'''
Query a changelist.
Arguments:
changelistNum: The changelist number to query.
Returns:
RSG.SourceControl.Perforce.Changelist object. None if not found.
'''
global p4
p4.Connect()
changelist = Changelist.Create( p4, [ changelistNum ] )
if changelist.Length == 1:
return changelist[ 0 ]
return None
def CreateChangelist( description ):
'''
Creates a new changelist.
Arguments:
description: The changelist desription.
Returns:
RSG.SourceControl.Perforce.Changelist object.
'''
global p4
p4.Connect()
changelist = p4.CreatePendingChangelist( description )
return GetChangelist( changelist.Number )
def GetFilesInChangelist( changelistNum ):
'''
Query all files in a changelist.
Arguments:
changelistNum: The changelist number to query.
Returns:
List of files found in the changelist.
'''
changelist = GetChangelist( changelistNum )
if changelist:
return list( changelist.Files )
return None
def DeleteChangelist( changelistNum, deleteShelvedFiles = True ):
'''
Delete a changelist.
Arguments:
changelistNum: The changelist number to delete.
Keyword Arguments:
deleteShelvedFiles: Delete shelved files in the changelist.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
if deleteShelvedFiles:
DeleteShelvedFiles( changelistNum )
return p4.Run( 'change', [ '-d', str( changelistNum ) ] )
def RevertChangelist( changelistNum, deleteShelvedFiles = False ):
'''
Revert all files in a changelist.
Arguments:
changelistNum: The changelist number to delete.
Keyword Arguments:
deleteShelvedFiles: Delete any shelved files in the changelist.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
if deleteShelvedFiles:
DeleteShelvedFiles( changelistNum )
return p4.Run( 'revert', [ '-c', str( changelistNum ), '//...' ] )
def DeleteShelvedFiles( changelistNum ):
'''
Delete all shelved files in a changelist.
Arguments:
changelistNum: The changelist number to delete.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
return p4.Run( 'shelve', [ '-c', str( changelistNum ), '-d' ] )
def ShelveChangelist( changelistNum ):
'''
Shelve all files in a changelist.
Arguments:
changelistNum: The changelist number.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
return p4.Run( 'shelve', [ '-c', str( changelistNum ), '-f' ] )
def Shelve( filenames, changelistNum = None ):
'''
Shelve a list of files.
Arguments:
filenames: The filenames to shelve.
Keyword Arguments:
changelistNum: The changelist number.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
args = []
if changelistNum:
args.append( '-c' )
args.append( str( changelistNum ) )
args.append( '-f' )
for filename in filenames:
args.append( filename )
return p4.Run( 'shelve', args )
def Revert( filenames ):
'''
Revert a list of files.
Arguments:
filenames: The filenames to revert.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
if type( filenames ) != types.TupleType and type( filenames ) != types.ListType:
filenames = [ filenames ]
args = []
for filename in filenames:
args.append( filename )
return p4.Run( 'revert', args )
def Submit( changelistNum ):
'''
Submit a changelist.
Arguments:
changelistNum: The changelist number to submit.
Returns:
P4API.P4RecordSet object.
'''
global p4
p4.Connect()
return p4.Run( 'submit', [ '-c', str( changelistNum ) ] )