from P4 import P4, P4Exception import re class PerforceController(): p4Instance = None def __init__(self): try: self.p4Instance = P4() self.p4Instance.connect() except P4Exception: for e in self.p4Instance.errors: print e self.p4Instance = None ######################################################################## # Function to sync a specified file ######################################################################## def SyncFile(self, filename): if self.p4Instance is not None: try: self.p4Instance.run_sync(filename, tagged=False) return True except P4Exception: for e in self.p4Instance.errors: print e return False else: return False ######################################################################## # Function to retrieve the contents of a file from perforce ######################################################################## def GetFileContents(self, filename, revision=-1): if self.p4Instance is not None and revision != 0: try: if revision == -1: return self.p4Instance.run("print", "-q", filename, tagged=False) else: return self.p4Instance.run("print", "-q", "{0}#{1}".format(filename,str(revision)), tagged=False) except P4Exception: for e in self.p4Instance.errors: print e return [] else: return [] ######################################################################## # Function to return the fstat information of a file ######################################################################## def GetFStat(self, filename): if self.p4Instance is not None: try: return self.p4Instance.run_fstat(filename, tagged=False)[0] except P4Exception: for e in self.p4Instance.errors: print e return None else: return None ######################################################################## # Function to return the filelog information of a file ######################################################################## def GetFileLog(self, filename): if self.p4Instance is not None: try: return self.p4Instance.run_filelog(filename, tagged=False) except P4Exception: for e in self.p4Instance.errors: print e return None else: return None ######################################################################## # Function to check whether a file exists in the depot ######################################################################## def DoesFileExist(self, location): try: results = self.p4Instance.run("files", location) return True except P4Exception as e: nosuchfile = False for warning in e.warnings: if "no such file" in warning.lower(): nosuchfile = True break if(nosuchfile): return False else: raise e ######################################################################## # Function to check whether a folder exists in the depot ######################################################################## def DoesFolderExist(self, location): if(not location.endswith("...") and not location.endswith("/")): location = location + "/" if(location.endswith("/")): location = location + "..." try: results = self.p4Instance.run("files", location) return True except P4Exception as e: nosuchfile = False for warning in e.warnings: if "no such file" in warning.lower(): nosuchfile = True break if(nosuchfile): return False else: raise e ######################################################################## # Function to create an empty changelist and return its number ######################################################################## def CreateEmptyChangelist(self, description): changeList = self.p4Instance.fetch_change() changeList['Files'] = [] changeList['Description'] = description outputForm = self.p4Instance.save_change(changeList) return outputForm[0].split()[1] ######################################################################## # Function to create a changelist with files and return its number ######################################################################## def CreateChangelist(self, description, files): filesToAdd = [] for file in files: self.p4Instance.run_edit(file) fstat = self.GetFStat(file) filesToAdd.append(fstat['depotFile']) if len(filesToAdd) == 0: print("No files supplied to create changelist with") changeList = self.p4Instance.fetch_change() changeList['Files'] = filesToAdd changeList['Description'] = description outputForm = self.p4Instance.save_change(changeList) return outputForm[0].split()[1] ######################################################################## # Function to submit a changelist ######################################################################## def SubmitChangelist(self, changelist): changelistForm = self.p4Instance.fetch_change(changelist) self.p4Instance.run_submit(changelistForm) ######################################################################## # Function to return list of files in a location ######################################################################## def GetFilesInLocation(self, Location, allSubFolders=False, ignoreDeletes=False): if allSubFolders != False: if not Location.endswith("..."): if not Location.endswith("/"): Location = Location + "/" Location = Location + "..." else: if not Location.endswith("*"): if not Location.endswith("/"): Location = Location + "/" if Location.endswith("/"): Location = Location + "*" files = self.p4Instance.run("files", Location) ReturnFiles = [] for file in files: if(ignoreDeletes): if('delete' in file['action'].lower()): continue ReturnFiles.append(file['depotFile']) return ReturnFiles ######################################################################## # Function to return list of folders in a location ######################################################################## def GetFoldersInLocation(self, Location): if not Location.endswith("*"): Location = Location + "/" if Location.endswith("/"): Location = Location + "*" dirs = self.p4Instance.run("dirs", Location) ReturnDirs = [] for dir in dirs: ReturnDirs.append(dir['dir']) return ReturnDirs ######################################################################## # Function to convert a local location to a p4 location ######################################################################## def GetP4LocationOfFile(self, fileName): fstatOfFile = self.GetFStat(fileName) if fstatOfFile == None: return None return fstatOfFile['depotFile'] ######################################################################## # Run same logic as server to determine for a given changelist if any files are under its restriction limit ######################################################################## def GetUnderRestrictedFiles(self, changelist): description = self.p4Instance.run("describe", changelist)[0] files = description['depotFile'] fileTypes = description['type'] for curIdx in range(0, len(files)): fileType = fileTypes[curIdx] ALLOWEDSERVERLIMIT = 4 parts = fileType.split('+') if(len(parts) > 1): if('S' in parts[1]): captures = re.match(".*S([0-9]*)", parts[1], 0).group(1) if(captures is None or captures == "" or int(captures) < ALLOWEDSERVERLIMIT): print("File under server limit {0}".format(files[curIdx])) def GetChangelistsBetweenClAndHead(self, location, changelist): output = [] additionalFormat = "" if(changelist is not None): additionalFormat = "@{0},#head".format(changelist) changelists = self.p4Instance.run("changes", "{0}{1}".format(location, additionalFormat)) for cl in changelists: files = self.p4Instance.run("describe", cl['change'])[0]['depotFile'] output.append((cl['change'], files)) return output def GetFilesBetweenClAndHeadAndReportHeadCL(self, location, changelist): changelists = self.GetChangelistsBetweenClAndHead(location, changelist) headCL = changelists[0][0] output = [] for cl in changelists: if(str(cl[0]) != str(changelist)): for file in cl[1]: if(file not in output): output.append(file) return headCL,output