495 lines
11 KiB
Python
Executable File
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 ) ] )
|
|
|
|
|
|
|