Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
4.3 KiB

  1. import subprocess, marshal, os, stat, sys
  2. g_bPerforceVerbose = False
  3. # Make all lowercase and forward slashes.
  4. def FixFilename( f ):
  5. return f.replace( '\\', '/' ).lower()
  6. def SetPerforceVerbose( bVerbose ):
  7. global g_bPerforceVerbose
  8. g_bPerforceVerbose = bVerbose
  9. def CheckPerforceReturn( cmd ):
  10. po = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
  11. sStdout = po.stdout.read()
  12. sStderr = po.stderr.read()
  13. ret = po.wait()
  14. if ret != 0:
  15. print >>sys.stderr, "A command returned %d: %s\nstdout = %s\nstderr = %s" % (ret, cmd, sStdout, sStderr)
  16. sys.exit( ret )
  17. def ReadPerforceOutput( cmd, bCheckReturn=True ):
  18. if g_bPerforceVerbose:
  19. print "Running: " + cmd
  20. po = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE )
  21. results = []
  22. try:
  23. while True:
  24. try:
  25. entry = marshal.load(po.stdout)
  26. except ValueError:
  27. print '----------------------------------------------'
  28. print 'Marshal.load(po.stdout) got ValueError'
  29. print 'Next data:'
  30. print po.stdout.readline()
  31. print po.stdout.readline()
  32. print po.stdout.readline()
  33. print '----------------------------------------------'
  34. raise
  35. results.append(entry)
  36. except EOFError:
  37. pass
  38. ret = ( po.wait(), results )
  39. # Check the return value?
  40. if bCheckReturn and ret[0] != 0:
  41. print >>sys.stderr, "A command returned %d: %s" % (ret[0], cmd)
  42. sys.exit( 1 )
  43. return ( ret )
  44. # Get the list of files. These are returned in a dictionary where the keys are the
  45. # FixFilename'd filenames (lowercase and forward-slashes-only) and the values are
  46. # the non-lowercased version (which you need to send to Linux).
  47. def GetP4OpenedFiles( perforceRoot, cmd ):
  48. if perforceRoot != None:
  49. perforceRoot = FixFilename( perforceRoot )
  50. (x,files) = ReadPerforceOutput( cmd, bCheckReturn=True )
  51. srcfiles = {}
  52. depotFiles = [ (x['depotFile'], x['action']) for x in files]
  53. for (perforceFilename,action) in depotFiles:
  54. # For now, just ignore delete commands. This means they won't get mirrored over
  55. # to the remote end.
  56. if action == 'delete':
  57. continue
  58. fixed = FixFilename( perforceFilename )
  59. if len(fixed) == 0:
  60. break
  61. if perforceRoot == None or fixed.startswith( perforceRoot ):
  62. srcfiles[fixed] = perforceFilename
  63. return srcfiles
  64. # Returns 'add', 'edit', 'remove', or 'none' (which either means nothing's happening to it or that depot file doesn't exist).
  65. def GetClientFileAction( sDepotFilename ):
  66. kv = ReadPerforceOutput( 'p4 -G fstat \"%s\"' % sDepotFilename )[1][0]
  67. if kv.has_key( 'action' ):
  68. return kv[ 'action' ]
  69. else:
  70. return 'none'
  71. # Returns ( client filename, perforce filename, action [edit/add/remove] )
  72. def GetClientFileInfo( perforceFilename ):
  73. kv = ReadPerforceOutput( 'p4 -G fstat \"%s\"' % perforceFilename )[1][0]
  74. try:
  75. ret = [ kv['clientFile'], kv['depotFile'] ]
  76. except KeyError:
  77. print >>sys.stderr, "\nGetClientFileInfo( %s ) failed.\nPerhaps your clientspec doesn't include this file?" % perforceFilename
  78. sys.exit( 1 )
  79. if kv.has_key( 'action' ):
  80. ret.append( kv['action'] )
  81. else:
  82. ret.append( 'none' )
  83. return ret
  84. # Returns a dictionary with info from p4 client.
  85. # Particularly interesting are 'Root' (client's root folder), 'Client' (client name)
  86. def GetClientInfo():
  87. return ReadPerforceOutput( 'p4 -G client -o' )[1][0]
  88. # Scan the directory tree and get filenames relative to the specified dir.
  89. def GetFilenamesRelativeTo_R( dirname ):
  90. ret = []
  91. for f in os.listdir( os.path.join(dirname) ):
  92. if f[0] == '.':
  93. continue
  94. fullname = os.path.join( dirname, f )
  95. s = os.stat( fullname )
  96. if stat.S_ISDIR( s[stat.ST_MODE] ):
  97. names = GetFilenamesRelativeTo_R( fullname )
  98. ret.extend( names )
  99. else:
  100. ret.append( fullname )
  101. return ret
  102. def GetFilenamesRelativeTo( dirname ):
  103. ret = GetFilenamesRelativeTo_R( dirname )
  104. return [ x[len(dirname)+1:] for x in ret ]
  105. def GetPendingChanges( p4client, fileFilter = "" ):
  106. cmd = 'p4 -G changes -s pending -c ' + p4client
  107. if ( len(fileFilter) > 0 ):
  108. cmd += ' ' + fileFilter
  109. return ReadPerforceOutput( cmd )[1]
  110. def P4Where( file ):
  111. cmd = 'p4 -G where %s' % file
  112. return ReadPerforceOutput( cmd )[1][0][ "depotFile" ]
  113. def GetSyncedRevision( p4ClientRoot ):
  114. cmd = 'p4 -G changes -s submitted -m 1 %s/...' % p4ClientRoot
  115. return ReadPerforceOutput( cmd )[1][0]['change']