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
259 lines
6.2 KiB
|
|
|
|
import os, sys |
|
|
|
|
|
class PySSException: |
|
pass |
|
|
|
|
|
g_bVerbose = 0 |
|
|
|
|
|
class PySourceSafe: |
|
""" |
|
PySourceSafe represents a connection to a SS database. |
|
Pass the directory to the database in the constructor, or \\hl2vss\hl2vss is assumed. |
|
""" |
|
|
|
def __init__( self, dbPath=r"\\hl2vss\hl2vss" ): |
|
# Store this off so we can put it in the environment when we run ss. |
|
self.m_DBPath = dbPath |
|
self.bUseExceptions = 0 |
|
|
|
self.m_VSSCommand = None |
|
|
|
# Since we can't use spawnvpe to have it find ss.exe for us, we have to look in the path for it manually. |
|
paths = os.environ['path'].split( ';' ) |
|
for path in paths: |
|
if path[-1:] == '/' or path[-1:] == '\\': |
|
testFilename = path + 'ss.exe' |
|
else: |
|
testFilename = path + '\\' + 'ss.exe' |
|
|
|
testFilename = testFilename.replace( '\"', '' ) |
|
if os.access( testFilename, os.F_OK ): |
|
self.m_VSSCommand = testFilename |
|
break |
|
|
|
# If we can't find the vss command, they we're screwed so throw an exception. |
|
if not self.m_VSSCommand: |
|
raise PySSException |
|
|
|
for_cmd = 'for %I in ("' + self.m_VSSCommand + '") do echo %~sI' |
|
p = os.popen(for_cmd) |
|
self.m_VSSCommand = p.readlines()[-1] # last line from for command |
|
p.close() |
|
|
|
self.m_VSSCommand = self.m_VSSCommand.replace( '\n', '' ) |
|
self.lastExitStatus = 0 |
|
self.m_LastCommandOutput = '' |
|
|
|
|
|
# Throw an exception on error? Default is no. |
|
def EnableExceptions( self, bEnable ): |
|
self.bUseExceptions = 1 |
|
|
|
|
|
# Get the output from the last command. |
|
# This returns a list of the lines of text with the output. |
|
def GetLastCommandOutput(): |
|
return self.m_LastCommandOutput |
|
|
|
|
|
# Return a list of the filenames in a directory. |
|
def ListFiles( self, rootDir ): |
|
outlines = self.__RunCommand( ['dir',rootDir] ) |
|
if not outlines: |
|
return None |
|
|
|
returnList = [] |
|
for i in range( 1, len( outlines ) ): |
|
if len( outlines[i] ) == 0: |
|
break |
|
elif outlines[i][0:1] != '$': |
|
returnList.append( outlines[i] ) |
|
|
|
return returnList |
|
|
|
|
|
def ListDirectories( self, rootDir ): |
|
outlines = self.__RunCommand( ['dir',rootDir] ) |
|
if not outlines: |
|
return None |
|
|
|
returnList = [] |
|
for i in range( 1, len( outlines ) ): |
|
if len( outlines[i] ) == 0: |
|
break |
|
elif outlines[i][0:1] == '$': |
|
returnList.append( outlines[i] ) |
|
|
|
return returnList |
|
|
|
|
|
# Example: p.AddFile( "$/hl2/release/dev/hl2/scripts", "c:\\test.txt", "some comment here" ) |
|
def AddFile( self, vssDir, localFilename, comment=None ): |
|
if not self.__RunCommand( ['cp', vssDir] ): |
|
return None |
|
|
|
args = ['add', localFilename, '-I-'] |
|
if comment: |
|
args.append( '-C%s' % comment ) |
|
|
|
return self.__RunCommand( args ) |
|
|
|
|
|
# Create a new directory (or 'subproject'). |
|
# Example: p.CreateDirectory( '$/tfc/models/test' ) |
|
# Note: this WILL create the subdirectories leading up to the final one if they don't exist. |
|
def CreateDirectory( self, vssDir, comment=None ): |
|
if not comment: |
|
comment = '' |
|
|
|
lastRet = [] |
|
|
|
# Create all directories leading up to this one/ |
|
dirs = vssDir.split( '/' ) |
|
curDir = '' |
|
for dir in dirs: |
|
if len( curDir ) == 0: |
|
curDir = dir |
|
else: |
|
curDir = curDir + '/' + dir |
|
|
|
# Does it exist already? |
|
self.__RunCommand( ['properties', curDir], 0 ) |
|
if self.lastExitStatus != 0 and self.lastExitStatus != None: |
|
lastRet = self.__RunCommand( ['create', curDir, '-C%s' % comment, '-I-'] ) |
|
if lastRet == None: |
|
break |
|
|
|
return lastRet |
|
|
|
|
|
# Remove a file. Returns: |
|
# 0 if the file doesn't exist |
|
# 1 if it existed and was removed |
|
# None if the file existed but there was an error. |
|
def DeleteFile( self, vssFilename ): |
|
self.__RunCommand( ['properties', vssFilename], 0 ) |
|
if self.lastExitStatus: |
|
return 0 |
|
else: |
|
# Now try to remove it. |
|
self.__RunCommand( ['delete', vssFilename, '-I-'] ) |
|
if self.lastExitStatus: |
|
return None |
|
else: |
|
return 1 |
|
|
|
|
|
# Get the checkout status of a file (and find out if the file even exists). |
|
def GetFileStatus( self, ssFilename ): |
|
pass |
|
|
|
|
|
# Get the local working directory for the specified SS directory. |
|
def GetWorkingDirectory( self, ssDir ): |
|
pass |
|
|
|
|
|
# Get the local filename for the specified file. |
|
def GetLocalFilename( self, ssFilename ): |
|
pass |
|
|
|
|
|
# For all the CheckOut and Get commands, if localFilename is not None, then it'll |
|
# treat that as the local file. Otherwise, it'll use the default working directory for that directory in SS. |
|
# Returns 1 if successful, 0 if there was an error. |
|
|
|
# Check out a file. |
|
# Use GetLastOutput() to get the output string. |
|
def CheckOutFile( self, ssFilename, localFilename=None ): |
|
pass |
|
|
|
|
|
# Check out the whole directory. |
|
def CheckOutDir( self, ssDirName, localDirName=None, bRecursive=0 ): |
|
pass |
|
|
|
|
|
# Get a file. |
|
def GetFile( self, ssFilename, localFilename=None ): |
|
pass |
|
|
|
|
|
# Get a whole directory. |
|
def GetFile( self, ssFilename, localFilename=None ): |
|
pass |
|
|
|
# Check in a file. Optionally specify a comment. |
|
# Returns 1 if successful, 0 otherwise. |
|
def CheckInFile( self, ssFilename, localFilename=None, comment=None ): |
|
pass |
|
|
|
|
|
# The big master function to run a vss command and get the results back in a list. |
|
def __RunCommand( self, args, bHandleErrors=1 ): |
|
# First, set the environment up. |
|
tempEnviron = os.environ |
|
os.environ['ssdir'] = self.m_DBPath |
|
|
|
# Now build the command. |
|
cmd = self.m_VSSCommand |
|
for i in args: |
|
cmd = cmd + ' \"%s\"' % i |
|
|
|
if g_bVerbose: |
|
print "VSS: " + cmd |
|
|
|
# Run the command and capture its output. |
|
f = os.popen( cmd, 'r' ) |
|
lines = f.readlines() |
|
self.lastExitStatus = f.close() |
|
|
|
self.m_LastCommandOutput = lines |
|
lines = [i.strip() for i in lines] |
|
|
|
# Restore the environment. |
|
os.environ = tempEnviron |
|
|
|
if self.lastExitStatus != 0 and self.lastExitStatus != None: |
|
if bHandleErrors: |
|
print 'VSS Error (status: %d): ' % self.lastExitStatus |
|
print 'cmd: %s' % cmd |
|
print 'output: ' |
|
for i in lines: |
|
print '\t%s' % i |
|
|
|
if self.bUseExceptions: |
|
raise PySSException |
|
else: |
|
return None |
|
|
|
return lines |
|
|
|
|
|
|
|
p = PySourceSafe() |
|
|
|
|
|
# TEST CODE |
|
""" |
|
print "Files" |
|
files = p.ListFiles( '$/hl2/release/dev' ) |
|
for i in files: |
|
print i |
|
|
|
print "\n\nDirectories" |
|
files = p.ListDirectories( '$/hl2/release/dev' ) |
|
for i in files: |
|
print i |
|
|
|
|
|
vssRoot = '$/tfc/models' |
|
p.AddFile( "$/tfc", "c:\\test.txt", "test comment blah blah" ) |
|
|
|
p.CreateDirectory( '$/tfc/aa/bb/cc/dd', 'here is hte comment' ) |
|
"""
|
|
|