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.

259 lines
6.2 KiB

  1. import os, sys
  2. class PySSException:
  3. pass
  4. g_bVerbose = 0
  5. class PySourceSafe:
  6. """
  7. PySourceSafe represents a connection to a SS database.
  8. Pass the directory to the database in the constructor, or \\hl2vss\hl2vss is assumed.
  9. """
  10. def __init__( self, dbPath=r"\\hl2vss\hl2vss" ):
  11. # Store this off so we can put it in the environment when we run ss.
  12. self.m_DBPath = dbPath
  13. self.bUseExceptions = 0
  14. self.m_VSSCommand = None
  15. # Since we can't use spawnvpe to have it find ss.exe for us, we have to look in the path for it manually.
  16. paths = os.environ['path'].split( ';' )
  17. for path in paths:
  18. if path[-1:] == '/' or path[-1:] == '\\':
  19. testFilename = path + 'ss.exe'
  20. else:
  21. testFilename = path + '\\' + 'ss.exe'
  22. testFilename = testFilename.replace( '\"', '' )
  23. if os.access( testFilename, os.F_OK ):
  24. self.m_VSSCommand = testFilename
  25. break
  26. # If we can't find the vss command, they we're screwed so throw an exception.
  27. if not self.m_VSSCommand:
  28. raise PySSException
  29. for_cmd = 'for %I in ("' + self.m_VSSCommand + '") do echo %~sI'
  30. p = os.popen(for_cmd)
  31. self.m_VSSCommand = p.readlines()[-1] # last line from for command
  32. p.close()
  33. self.m_VSSCommand = self.m_VSSCommand.replace( '\n', '' )
  34. self.lastExitStatus = 0
  35. self.m_LastCommandOutput = ''
  36. # Throw an exception on error? Default is no.
  37. def EnableExceptions( self, bEnable ):
  38. self.bUseExceptions = 1
  39. # Get the output from the last command.
  40. # This returns a list of the lines of text with the output.
  41. def GetLastCommandOutput():
  42. return self.m_LastCommandOutput
  43. # Return a list of the filenames in a directory.
  44. def ListFiles( self, rootDir ):
  45. outlines = self.__RunCommand( ['dir',rootDir] )
  46. if not outlines:
  47. return None
  48. returnList = []
  49. for i in range( 1, len( outlines ) ):
  50. if len( outlines[i] ) == 0:
  51. break
  52. elif outlines[i][0:1] != '$':
  53. returnList.append( outlines[i] )
  54. return returnList
  55. def ListDirectories( self, rootDir ):
  56. outlines = self.__RunCommand( ['dir',rootDir] )
  57. if not outlines:
  58. return None
  59. returnList = []
  60. for i in range( 1, len( outlines ) ):
  61. if len( outlines[i] ) == 0:
  62. break
  63. elif outlines[i][0:1] == '$':
  64. returnList.append( outlines[i] )
  65. return returnList
  66. # Example: p.AddFile( "$/hl2/release/dev/hl2/scripts", "c:\\test.txt", "some comment here" )
  67. def AddFile( self, vssDir, localFilename, comment=None ):
  68. if not self.__RunCommand( ['cp', vssDir] ):
  69. return None
  70. args = ['add', localFilename, '-I-']
  71. if comment:
  72. args.append( '-C%s' % comment )
  73. return self.__RunCommand( args )
  74. # Create a new directory (or 'subproject').
  75. # Example: p.CreateDirectory( '$/tfc/models/test' )
  76. # Note: this WILL create the subdirectories leading up to the final one if they don't exist.
  77. def CreateDirectory( self, vssDir, comment=None ):
  78. if not comment:
  79. comment = ''
  80. lastRet = []
  81. # Create all directories leading up to this one/
  82. dirs = vssDir.split( '/' )
  83. curDir = ''
  84. for dir in dirs:
  85. if len( curDir ) == 0:
  86. curDir = dir
  87. else:
  88. curDir = curDir + '/' + dir
  89. # Does it exist already?
  90. self.__RunCommand( ['properties', curDir], 0 )
  91. if self.lastExitStatus != 0 and self.lastExitStatus != None:
  92. lastRet = self.__RunCommand( ['create', curDir, '-C%s' % comment, '-I-'] )
  93. if lastRet == None:
  94. break
  95. return lastRet
  96. # Remove a file. Returns:
  97. # 0 if the file doesn't exist
  98. # 1 if it existed and was removed
  99. # None if the file existed but there was an error.
  100. def DeleteFile( self, vssFilename ):
  101. self.__RunCommand( ['properties', vssFilename], 0 )
  102. if self.lastExitStatus:
  103. return 0
  104. else:
  105. # Now try to remove it.
  106. self.__RunCommand( ['delete', vssFilename, '-I-'] )
  107. if self.lastExitStatus:
  108. return None
  109. else:
  110. return 1
  111. # Get the checkout status of a file (and find out if the file even exists).
  112. def GetFileStatus( self, ssFilename ):
  113. pass
  114. # Get the local working directory for the specified SS directory.
  115. def GetWorkingDirectory( self, ssDir ):
  116. pass
  117. # Get the local filename for the specified file.
  118. def GetLocalFilename( self, ssFilename ):
  119. pass
  120. # For all the CheckOut and Get commands, if localFilename is not None, then it'll
  121. # treat that as the local file. Otherwise, it'll use the default working directory for that directory in SS.
  122. # Returns 1 if successful, 0 if there was an error.
  123. # Check out a file.
  124. # Use GetLastOutput() to get the output string.
  125. def CheckOutFile( self, ssFilename, localFilename=None ):
  126. pass
  127. # Check out the whole directory.
  128. def CheckOutDir( self, ssDirName, localDirName=None, bRecursive=0 ):
  129. pass
  130. # Get a file.
  131. def GetFile( self, ssFilename, localFilename=None ):
  132. pass
  133. # Get a whole directory.
  134. def GetFile( self, ssFilename, localFilename=None ):
  135. pass
  136. # Check in a file. Optionally specify a comment.
  137. # Returns 1 if successful, 0 otherwise.
  138. def CheckInFile( self, ssFilename, localFilename=None, comment=None ):
  139. pass
  140. # The big master function to run a vss command and get the results back in a list.
  141. def __RunCommand( self, args, bHandleErrors=1 ):
  142. # First, set the environment up.
  143. tempEnviron = os.environ
  144. os.environ['ssdir'] = self.m_DBPath
  145. # Now build the command.
  146. cmd = self.m_VSSCommand
  147. for i in args:
  148. cmd = cmd + ' \"%s\"' % i
  149. if g_bVerbose:
  150. print "VSS: " + cmd
  151. # Run the command and capture its output.
  152. f = os.popen( cmd, 'r' )
  153. lines = f.readlines()
  154. self.lastExitStatus = f.close()
  155. self.m_LastCommandOutput = lines
  156. lines = [i.strip() for i in lines]
  157. # Restore the environment.
  158. os.environ = tempEnviron
  159. if self.lastExitStatus != 0 and self.lastExitStatus != None:
  160. if bHandleErrors:
  161. print 'VSS Error (status: %d): ' % self.lastExitStatus
  162. print 'cmd: %s' % cmd
  163. print 'output: '
  164. for i in lines:
  165. print '\t%s' % i
  166. if self.bUseExceptions:
  167. raise PySSException
  168. else:
  169. return None
  170. return lines
  171. p = PySourceSafe()
  172. # TEST CODE
  173. """
  174. print "Files"
  175. files = p.ListFiles( '$/hl2/release/dev' )
  176. for i in files:
  177. print i
  178. print "\n\nDirectories"
  179. files = p.ListDirectories( '$/hl2/release/dev' )
  180. for i in files:
  181. print i
  182. vssRoot = '$/tfc/models'
  183. p.AddFile( "$/tfc", "c:\\test.txt", "test comment blah blah" )
  184. p.CreateDirectory( '$/tfc/aa/bb/cc/dd', 'here is hte comment' )
  185. """