source-engine/devtools/p4helpers.py

162 lines
4.3 KiB
Python
Raw Permalink Normal View History

2020-04-22 16:56:21 +00:00
import subprocess, marshal, os, stat, sys
g_bPerforceVerbose = False
# Make all lowercase and forward slashes.
def FixFilename( f ):
return f.replace( '\\', '/' ).lower()
def SetPerforceVerbose( bVerbose ):
global g_bPerforceVerbose
g_bPerforceVerbose = bVerbose
def CheckPerforceReturn( cmd ):
po = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
sStdout = po.stdout.read()
sStderr = po.stderr.read()
ret = po.wait()
if ret != 0:
print >>sys.stderr, "A command returned %d: %s\nstdout = %s\nstderr = %s" % (ret, cmd, sStdout, sStderr)
sys.exit( ret )
def ReadPerforceOutput( cmd, bCheckReturn=True ):
if g_bPerforceVerbose:
print "Running: " + cmd
po = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
results = []
try:
while True:
try:
entry = marshal.load(po.stdout)
except ValueError:
print '----------------------------------------------'
print 'Marshal.load(po.stdout) got ValueError'
print 'Next data:'
print po.stdout.readline()
print po.stdout.readline()
print po.stdout.readline()
print '----------------------------------------------'
raise
results.append(entry)
except EOFError:
pass
ret = ( po.wait(), results )
# Check the return value?
if bCheckReturn and ret[0] != 0:
print >>sys.stderr, "A command returned %d: %s" % (ret[0], cmd)
sys.exit( 1 )
return ( ret )
# Get the list of files. These are returned in a dictionary where the keys are the
# FixFilename'd filenames (lowercase and forward-slashes-only) and the values are
# the non-lowercased version (which you need to send to Linux).
def GetP4OpenedFiles( perforceRoot, cmd ):
if perforceRoot != None:
perforceRoot = FixFilename( perforceRoot )
(x,files) = ReadPerforceOutput( cmd, bCheckReturn=True )
srcfiles = {}
depotFiles = [ (x['depotFile'], x['action']) for x in files]
for (perforceFilename,action) in depotFiles:
# For now, just ignore delete commands. This means they won't get mirrored over
# to the remote end.
if action == 'delete':
continue
fixed = FixFilename( perforceFilename )
if len(fixed) == 0:
break
if perforceRoot == None or fixed.startswith( perforceRoot ):
srcfiles[fixed] = perforceFilename
return srcfiles
# Returns 'add', 'edit', 'remove', or 'none' (which either means nothing's happening to it or that depot file doesn't exist).
def GetClientFileAction( sDepotFilename ):
kv = ReadPerforceOutput( 'p4 -G fstat \"%s\"' % sDepotFilename )[1][0]
if kv.has_key( 'action' ):
return kv[ 'action' ]
else:
return 'none'
# Returns ( client filename, perforce filename, action [edit/add/remove] )
def GetClientFileInfo( perforceFilename ):
kv = ReadPerforceOutput( 'p4 -G fstat \"%s\"' % perforceFilename )[1][0]
try:
ret = [ kv['clientFile'], kv['depotFile'] ]
except KeyError:
print >>sys.stderr, "\nGetClientFileInfo( %s ) failed.\nPerhaps your clientspec doesn't include this file?" % perforceFilename
sys.exit( 1 )
if kv.has_key( 'action' ):
ret.append( kv['action'] )
else:
ret.append( 'none' )
return ret
# Returns a dictionary with info from p4 client.
# Particularly interesting are 'Root' (client's root folder), 'Client' (client name)
def GetClientInfo():
return ReadPerforceOutput( 'p4 -G client -o' )[1][0]
# Scan the directory tree and get filenames relative to the specified dir.
def GetFilenamesRelativeTo_R( dirname ):
ret = []
for f in os.listdir( os.path.join(dirname) ):
if f[0] == '.':
continue
fullname = os.path.join( dirname, f )
s = os.stat( fullname )
if stat.S_ISDIR( s[stat.ST_MODE] ):
names = GetFilenamesRelativeTo_R( fullname )
ret.extend( names )
else:
ret.append( fullname )
return ret
def GetFilenamesRelativeTo( dirname ):
ret = GetFilenamesRelativeTo_R( dirname )
return [ x[len(dirname)+1:] for x in ret ]
def GetPendingChanges( p4client, fileFilter = "" ):
cmd = 'p4 -G changes -s pending -c ' + p4client
if ( len(fileFilter) > 0 ):
cmd += ' ' + fileFilter
return ReadPerforceOutput( cmd )[1]
def P4Where( file ):
cmd = 'p4 -G where %s' % file
return ReadPerforceOutput( cmd )[1][0][ "depotFile" ]
def GetSyncedRevision( p4ClientRoot ):
cmd = 'p4 -G changes -s submitted -m 1 %s/...' % p4ClientRoot
return ReadPerforceOutput( cmd )[1][0]['change']