def revertFiles(self, selectedFileList): '''Revert selected files to last revisioned state''' revertFileNames = [] for f in selectedFileList: annotation = f[0] fileName = f[2:] if annotation in ['R', '!']: print "deleted %s recovered from revision control" % fileName revertFileNames.append(fileName) elif annotation == '>': print "rename %s recovered from revision control" % fileName renameFiles = fileName.split(' => ') revertFileNames.append(renameFiles[0]) elif annotation == 'A': print "added %s forgot from revision control" % fileName revertFileNames.append(fileName) elif annotation == 'M': print "modifications to %s reverted" % fileName revertFileNames.append(fileName) else: print "File %s not reverted" % fileName if len(revertFileNames): runProgram(['cg', 'restore', '-f'] + revertFileNames) print "%d file(s) reverted: %s" % (len(revertFileNames), ', '.join(revertFileNames)) else: print "No revertable files" return
def __getWorkingDirChanges(self, fileName, type): if self.diffCache.has_key(fileName): return self.diffCache[fileName] # For revisioned files, we use cg diff if type in ['A', 'M', 'R']: os.environ['PAGER'] = 'cat' text = runProgram(['cg', 'diff', fileName], expectedexits=[0, 1]) self.diffCache[fileName] = text return text elif type in ['!']: # Missing files can be retrieved with cat text = runProgram(['cg', 'admin-cat', fileName], expectedexits=[0, 1]) self.diffCache[fileName] = text return text elif type in ['?', 'I']: # For unrevisioned files, we return file contents if os.path.isdir(fileName): text = " <Unrevisioned Directory>" fnames = os.listdir(fileName) text += os.linesep + ' ' + '\n '.join(fnames) elif isBinary(fileName): text = " <Binary File>" else: f = open(fileName) text = f.read() f.close() self.diffCache[fileName] = text return text else: return "Unknown file type " + type
def commitFiles(self, selectedFileList, logMsgText): '''Commit selected files''' # Files in list are annotated (A, M, etc) so this function can # mark files for add or delete as necessary before instigating the commit. commitFileNames = [] renameFiles = [] for f in selectedFileList: annotation = f[0] fileName = f[2:] if annotation == '?' or annotation == 'I': print "Adding %s to revision control" % fileName runProgram(['bzr', 'add', fileName]) commitFileNames.append(fileName) elif annotation == '>': print "Commit rename: %s" % fileName renameFiles += fileName.split(' => ') else: commitFileNames.append(fileName) # Renamed files may be on the modified list as well, so we add # them at the end to prevent duplicates for f in renameFiles: if f not in commitFileNames: commitFileNames.append(f) (fd, filename) = mkstemp() file = os.fdopen(fd, "w+b") file.write(logMsgText) file.close() runProgram(['bzr', 'commit', '-F', filename] + commitFileNames) print "%d file(s) commited: %s" % (len(selectedFileList), ', '.join(commitFileNames))
def revertFiles(self, selectedFileList): '''Revert selected files to last revisioned state''' revertFileNames = [] for f in selectedFileList: status = f[0] fileName = f[2:] if status == 'R': print "deleted %s recovered from revision control" % fileName revertFileNames.append(self.clientToDepotMap[fileName]) elif status == '!': print "missing %s recovered from revision control" % fileName runProgram(['p4', 'sync', '-f', self.clientToDepotMap[fileName] ]) elif status == 'A': print "added %s forgot from revision control" % fileName revertFileNames.append(self.clientToDepotMap[fileName]) elif status == 'M': print "modifications to %s reverted" % fileName revertFileNames.append(self.clientToDepotMap[fileName]) else: print "File %s not reverted" % fileName if len(revertFileNames): runProgram(['p4', 'revert'] + revertFileNames) else: print "No revertable files"
def scanFiles(self, showIgnored): '''Request scan for all commitable files from VCS''' # Called at startup, when 'Refresh' button is pressed, or when # showIgnored toggled. fileList = [] self.wdCache = { } self.clientToDepotMap = { } # Find open files, this command returns depot paths statusOutput = runProgram(['p4', 'opened', '...']) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') for line in recs: if line.startswith('... '): break fileName = line.split('#')[0] # remove rev number and status results = getP4FileStatus(fileName) fileList.append(results[2] + ' ' + results[1]) self.clientToDepotMap[results[1]] = results[0] # Find missing files, this command returns client paths statusOutput = runProgram(['p4', 'diff', '-sd', '...']) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') for fileName in recs: # current directory may not be revisioned yet if fileName.startswith('... '): break results = getP4FileStatus(fileName) fileList.append('!' + ' ' + results[1]) self.clientToDepotMap[results[1]] = results[0] return fileList
def revertFiles(self, selectedFileList): '''Revert selected files to last revisioned state''' revertFileNames = [] for f in selectedFileList: type = f[0] fileName = f[2:] if type in ['R', '!', 'M']: prevState = self.stateNames[type] print "%s recovered to last revisioned state (was %s)" % ( fileName, prevState) revertFileNames.append(fileName) elif type == 'A': print "%s removed from revision control (was added)" % fileName revertFileNames.append(fileName) elif type == '>': runProgram([self.mtn_exe, 'revert', fileName]) targetName = self.renameTarget[fileName] os.unlink(targetName) print "Rename of %s reverted, %s removed" % (fileName, targetName) else: print "File %s not reverted" % fileName if revertFileNames: runProgram([self.mtn_exe, 'revert'] + revertFileNames)
def scanFiles(self, showIgnored, pb=None): '''Request scan for all commitable files from VCS, with optional progress bar ''' # Called at startup and when 'Refresh' button is pressed self.wdDiffCache = {} self.fileStatus = {} itemList = [] if pb: pb.setValue(1) if showIgnored: extra = ['--no-ignore'] else: extra = [] versionOutput = runProgram([self.svn_exe, '--version', '--quiet']) version = [ int(s) for s in versionOutput.split(os.linesep)[0].split('.') ] statusOutput = runProgram([self.svn_exe, '--ignore-externals'] + extra + ['status']) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') if pb: pb.setValue(2) for line in recs: # a 7th column was added in svn 1.6, see http://subversion.tigris.org/svn_1.6_releasenotes.html#svn-status if version[0] > 1 or version[0] == 1 and version[1] >= 6: if len(line) < 8: continue status = line[0] fname = line[8:] self.fileStatus[fname] = line[0:7] else: if len(line) < 7: continue status = line[0] fname = line[7:] self.fileStatus[fname] = line[0:6] if status == 'M': # modified itemList.append('M ' + fname) elif status == 'A': # added itemList.append('A ' + fname) elif status == '?': # unknown itemList.append('? ' + fname) elif status == '!': # missing itemList.append('! ' + fname) elif status == 'D': # deleted itemList.append('R ' + fname) elif status == 'C': # conflict (allow edit) itemList.append('C ' + fname) elif status in ('~', 'X', 'R'): # Skip these files, they are not commitable pass if pb: pb.setValue(3) return itemList
def getFileStatus(self, itemName): '''Request file deltas from VCS''' annotation = itemName[0] fileName = itemName[2:] bFileName = "%<b>" + fileName + "</b>" if annotation == 'A': note = bFileName + " has been added to VCS, but has never been commited" if self.diffCache.has_key(itemName): text = self.diffCache[itemName] else: text = runProgram(['bzr', 'diff', fileName], expectedexits=[0, 1])[:-len(os.linesep)] self.diffCache[itemName] = text return note + os.linesep + text elif annotation == 'R': note = bFileName + " has been marked for deletion, but has not yet been commited" if self.diffCache.has_key(itemName): text = self.diffCache[itemName] else: text = runProgram(['bzr', 'diff', fileName], expectedexits=[0, 1])[:-len(os.linesep)] self.diffCache[itemName] = text return note + os.linesep + text elif annotation == 'M': note = bFileName + " has been modified in your working directory" if self.diffCache.has_key(itemName): text = self.diffCache[itemName] else: text = runProgram(['bzr', 'diff', fileName], expectedexits=[0, 1])[:-len(os.linesep)] self.diffCache[itemName] = text return note + os.linesep + text elif annotation == '?': note = bFileName + " is not currently revisioned, will be added to VCS if commited" if self.diffCache.has_key(itemName): text = self.diffCache[itemName] else: text = runProgram(['diff', '-u', '/dev/null', fileName], expectedexits=[0, 1, 2]) if not text: text = "<empty file>" self.diffCache[itemName] = text return note + os.linesep + text elif annotation == 'I': note = bFileName + " is usually ignored, but will be added to VCS if commited" + os.linesep if self.diffCache.has_key(itemName): text = self.diffCache[itemName] else: text = runProgram(['diff', '-u', '/dev/null', fileName], expectedexits=[0, 1, 2]) if not text: text = "<empty file>" self.diffCache[itemName] = text return note + os.linesep + text elif annotation == '>': return "%<b>Rename event:</b> " + fileName else: return "Unknown file type " + annotation
def __getWorkingDirChanges(self, fileName, type): if self.wdDiffCache.has_key(fileName): return self.wdDiffCache[fileName] # For symlinks, we return the link data if type not in ['R', '!', '>']: lmode = os.lstat(fileName)[ST_MODE] if S_ISLNK(lmode): text = "Symlink: %s -> %s" % (fileName, os.readlink(fileName)) self.wdDiffCache[fileName] = text return text # For revisioned files, we use hg diff if type in ['A', 'M', 'R']: text = runProgram([self.mtn_exe, 'diff', fileName]) self.wdDiffCache[fileName] = text return text # For unrevisioned files, we return file contents if type in ['?', 'I']: if os.path.isdir(fileName): text = " <Unrevisioned Directory>" fnames = os.listdir(fileName) text += os.linesep + ' ' + '\n '.join(fnames) elif isBinary(fileName): text = " <Binary File>" else: f = open(fileName) text = f.read() f.close() self.wdDiffCache[fileName] = text return text if type == '>': target = self.renameTarget[fileName] text = 'Rename event: %s [%s] -> %s [%s]' % ( fileName, self.fileState[fileName], target, self.fileState[target]) self.wdDiffCache[fileName] = text return text # For missing files, we use mtn cat if type == '!': if self.fileState[fileName][1] == 'A': text = " <Missing file was never revisioned>" self.wdDiffCache[fileName] = text return text text = runProgram([self.mtn_exe, 'cat', fileName]) if not text: text = " <empty file>" elif '\0' in text: text = " <Binary File of %d KBytes>" % (len(text) / 1024) self.wdDiffCache[fileName] = text return text else: return "Unknown file type " + type
def runXargsStyle(origProg, args): steps = range(10, len(args), 10) prog = origProg[:] prev = 0 for i in steps: prog.extend(args[prev:i]) runProgram(prog) prog = origProg[:] prev = i prog.extend(args[prev:]) runProgram(prog)
def addIgnoreMask(self, newIgnoreMask): '''The user has provided a new ignoreMask to be added to revision control''' existingIgnores = runProgram( [self.svn_exe, 'propget', 'svn:ignore', '.']).split(os.linesep) existingIgnores.pop() existingIgnores.append(newIgnoreMask) (fd, filename) = mkstemp() file = os.fdopen(fd, "w+b") file.write(os.linesep.join(existingIgnores)) file.close() runProgram( [self.svn_exe, 'propset', '--file', filename, 'svn:ignore', '.'])
def commitFiles(self, selectedFileList, logMsgText): '''Commit selected files''' # Files in list are annotated (A, M, etc) so this function can # mark files for add or delete as necessary before instigating the commit. commitFileNames = [] dirList = [] addFileList = [] binaryAddFileList = [] removeFileList = [] for f in selectedFileList: type = f[0] fileName = f[2:] commitFileNames.append(fileName) if type in ['?', 'I']: if os.path.isdir(fileName): dirList.append(fileName) elif isBinary(fileName): binaryAddFileList.append(fileName) else: addFileList.append(fileName) elif type == '!': removeFileList.append(fileName) if dirList: # Sort added directories by name length, to avoid recursion problems dirList.sort(lambda x, y: cmp(len(x), len(y))) runProgram([self.svn_exe, 'add', '--non-recursive'] + dirList) print "Added %d directory(s) to revision control: %s" % ( len(dirList), ', '.join(dirList)) if binaryAddFileList: runProgram([self.svn_exe, 'add'] + addFileList) print "Added %d binary file(s) to revision control: %s" % ( len(addFileList), ', '.join(addFileList)) if addFileList: runProgram([self.svn_exe, 'add'] + addFileList) print "Added %d file(s) to revision control: %s" % ( len(addFileList), ', '.join(addFileList)) if removeFileList: runProgram([self.svn_exe, 'delete'] + removeFileList) print "Removed %d file(s) from revision control: %s" % ( len(removeFileList), ', '.join(removeFileList)) (fd, filename) = mkstemp() file = os.fdopen(fd, "w+b") file.write(logMsgText) file.close() runProgram([self.svn_exe, 'commit', '-F', filename] + commitFileNames) print "%d file(s) commited: %s" % (len(commitFileNames), ', '.join(commitFileNames))
def scanFiles(self, showIgnored, pb = None): '''Request scan for all commitable files from VCS, with optional progress bar ''' # Called at startup and when 'Refresh' button is pressed self.wdDiffCache = {} itemList = [] if pb: pb.setValue(1) # Provides ARM, same as diff, plus unknown ? and missing ! statusOutput = runProgram(['cvs', '-qn', 'update']) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') if pb: pb.setValue(2) nextFileMissing = False for line in recs: status = line[0] fname = line[2:] if line.endswith("' was lost"): nextFileMissing = True elif nextFileMissing: itemList.append('! ' + fname) nextFileMissing = False elif status not in ['U', 'D', 'P']: itemList.append(line) if pb: pb.setValue(3) return itemList
def __getWorkingDirChanges(self, fileName, type): if self.wdDiffCache.has_key(fileName): return self.wdDiffCache[fileName] # For revisioned files, we use cvs diff if type in ['A', 'M']: text = runProgram(['cvs', 'diff', '-du', fileName], expectedexits=[0,1]) self.wdDiffCache[fileName] = text return text if type in ['R', '!']: text = 'Deleted file, unable to retrieve contents' # TODO self.wdDiffCache[fileName] = text return text # For unrevisioned files, we return file contents if type in ['?', 'I']: if os.path.isdir(fileName): text = " <Unrevisioned Directory>" fnames = os.listdir(fileName) text += os.linesep + ' ' + '\n '.join(fnames) elif isBinary(fileName): text = " <Binary File>" else: f = open(fileName) text = f.read() f.close() self.wdDiffCache[fileName] = text return text else: return "Unknown file type " + type
def initRepo(self, argv): '''Initialize your revision control system, open repository''' self.mtn_exe = 'mtn' output = runProgram([self.mtn_exe, 'ls', 'unknown'], expectedexits=[0, 1]) if output.startswith('mtn: misuse: workspace required'): print "No Monotone repository found" return -1 # Verify we have a valid repository self.stateNames = { 'M': 'modified', 'R': 'removed', '!': 'missing', '?': 'unknown' } self.capList = [ 'ignore', # VCS supports ignore masks (addIgnoreMask) 'rename', # VCS supports revisioned renames (fileMoveDetected) 'progressbar' ] # back-end supports a progress bar return 0
def __selectChanges(self, workingFile): '''User would like to select changes made to this file for commit, unselected changes are left in working directory after commit or at exit. ''' self.vcs.dirtyCache(workingFile) workingCopy = '.qct/' + workingFile + '.orig' try: path = os.path.dirname(workingFile) os.makedirs('.qct/' + path) except OSError: pass try: os.remove(workingCopy) except OSError: pass try: os.rename(workingFile, workingCopy) except: return self.changeSelectedFiles.append(workingFile) try: self.vcs.generateParentFile(workingFile) if not self.twowayTool: dialog = ChangeDialog(workingCopy, workingFile) dialog.show() dialog.exec_() if not dialog.accepted: raise Exception # Copy permissions, times back to workingFile shutil.copystat(workingCopy, workingFile) return cmd = self.twowayTool if '%o' in cmd and '%m' in cmd: cmd = cmd.replace('%o', workingFile) cmd = cmd.replace('%m', workingCopy) cmd = cmd.replace('\\', '/') runProgram(shlex.split(cmd), expectedexits=[0,1,255]) else: runProgram([self.twowayTool, workingCopy, workingFile]) # Copy permissions, times back to workingFile shutil.copystat(workingCopy, workingFile) except: print "Change selection failed, returning working file" self.__resetChangeSelection(workingFile)
def initRepo(self, argv): '''Initialize your revision control system, open repository''' # Verify we have a valid repository output = runProgram(['p4', 'fstat', '.'], expectedexits=[0,1]) if output.startswith("Path "): print output return -1 else: return 0
def revertFiles(self, selectedFileList): '''Revert selected files to last revisioned state''' revertFileNames = [] for f in selectedFileList: type = f[0] fileName = f[2:] if type in ['R', '!', 'M']: prevState = self.stateNames[type] print "%s recovered to last revisioned state (was %s)" % (fileName, prevState) revertFileNames.append(fileName) elif type == 'A': print "%s removed from revision control (was added)" % fileName revertFileNames.append(fileName) else: print "File %s not reverted" % fileName if revertFileNames: runProgram(['cvs', 'update', '-C'] + revertFileNames) else: print "No revertable files"
def initRepo(self, argv): '''Initialize your revision control system, open repository''' # Verify we have a valid repository output = runProgram(['bzr', 'root'], expectedexits=[0, 3]) words = output.split(' ') if len(words) == 1: self.repoRoot = output[:-len(os.linesep)] return 0 else: print output return -1
def scanFiles(self, showIgnored, pb=None): '''Request scan for all commitable files from VCS''' # Called at startup, when 'Refresh' button is pressed, or when # showIgnored toggled. self.diffCache = {} statusOutput = runProgram(['bzr', 'status']) if pb: pb.setValue(1) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') itemList = [] fileList = [] type = '' for line in recs: if line == 'added:': type = 'A' elif line == 'modified:': type = 'M' elif line == 'unknown:': type = '?' elif line == 'removed:': type = 'R' elif line == 'renamed:': type = '>' elif line[-1] == '/': line = '' # nop, just skipping this directory else: # Prevent files from showing up w/ two status if line[2:] not in fileList: itemList.append(type + " " + line[2:]) fileList.append(line[2:]) if pb: pb.setValue(2) if showIgnored: statusOutput = runProgram(['bzr', 'ls', '--ignored']) recs = statusOutput.split(os.linesep) recs.pop() # remove last entry (which is '') for fileName in recs: itemList.append("I " + fileName) if pb: pb.setValue(3) return itemList
def commitFiles(self, selectedFileList, logMsgText): '''Commit selected files''' # Files in list are annotated (A, M, etc) so this function can # mark files for add or delete as necessary before instigating the commit. commitFileNames = [] addFileList = [] removeFileList = [] for f in selectedFileList: type = f[0] fileName = f[2:] commitFileNames.append(fileName) if type in ['?', 'I']: addFileList.append(fileName) elif type == '!': removeFileList.append(fileName) if addFileList: runProgram([self.mtn_exe, 'add'] + addFileList) print "Added %d file(s) to revision control: %s" % ( len(addFileList), ', '.join(addFileList)) if removeFileList: runProgram([self.mtn_exe, 'drop'] + removeFileList) print "Removed %d file(s) from revision control: %s" % ( len(removeFileList), ', '.join(removeFileList)) (fd, filename) = mkstemp() file = os.fdopen(fd, "w+b") file.write(logMsgText) file.close() runProgram([self.mtn_exe, 'commit', '--message-file', filename] + commitFileNames) print "%d file(s) commited: %s" % (len(commitFileNames), ', '.join(commitFileNames))
def commitFiles(self, selectedFileList, logMsgText): '''Commit selected files''' # Files in list are annotated (A, M, etc) so this function can # mark files for add or delete as necessary before instigating the commit. commitFileNames = [] renameFiles = [] for f in selectedFileList: annotation = f[0] fileName = f[2:] commitFileNames.append(fileName) if annotation in ('?', 'I'): runProgram(['cg', 'add', fileName]) elif type == '!': removeFileList.append(fileName) (fd, filename) = mkstemp() file = os.fdopen(fd, "w+b") file.write(logMsgText) file.close() runProgram(['cg', 'commit', '-M', filename] + commitFileNames) print "%d file(s) commited: %s" % (len(selectedFileList), ', '.join(commitFileNames)) return
def scanFiles(self, showIgnored): '''Request scan for all commitable files from VCS''' # Called at startup, when 'Refresh' button is pressed, or when # showIgnored toggled. list = runProgram(['git-diff-files', '--name-status', '-z']).split('\0') list.pop() fileList = [] nameList = [] while len(list): name = list.pop() nameList.append(name) type = list.pop() fileList.append(type + " " + name) runXargsStyle(['git-update-index', '--remove', '--'], nameList) # The returned file list will be annotated by type return fileList
def getFileStatus(self, itemName): '''Request file deltas from VCS''' annotation = itemName[0] fileName = itemName[2:] if annotation == 'A': return fileName + " has been added to VCS or is a rename target, but has never been commited" elif annotation == '?': return fileName + " is not currently tracked, will be added to VCS if commited" elif annotation == '!': return fileName + " was tracked but is now missing, will be removed from VCS if commited" elif annotation == 'I': return fileName + " is usually ignored, but will be added to VCS if commited" elif annotation == 'R': return fileName + " has been marked for deletion, or renamed, but has not yet been commited" elif annotation == 'M': return runProgram(['git-diff-cache', '-p', '-M', '--cached', 'HEAD', fileName]) else: return "Unknown file type " + annotation
def commitFiles(self, selectedFileList, logMsgText): '''Commit selected files''' # Files in list are annotated (A, M, etc) so this function can # mark files for add or delete as necessary before instigating the commit. depotFileNames = [] for f in selectedFileList: status = f[0] fileName = f[2:] if status == '?' or status == 'I': print "Adding %s to revision control" % fileName runProgram(['p4', 'add', fileName]) elif status == '!': print "Removing %s from revision control" % fileName runProgram(['p4', 'delete', self.clientToDepotMap[fileName] ]) if self.clientToDepotMap.has_key(fileName): depotFileNames.append(self.clientToDepotMap[fileName]) else: print "Unable to find depot name of " + fileName # Perforce doesn't allow you to specify a message on the command line. # What you have to do is pretend to do the commit and ask for the form it would # create. You then insert the log message and actual file list into that file and # then submit that with -i iform = runProgram(['p4', 'change', '-o']) recs = iform.split(os.linesep) oform = '' for line in recs: if line == '\t<enter description here>': logMsgLines = logMsgText.split(os.linesep) for l in logMsgLines: oform += '\t' + l + os.linesep elif line == 'Files:': oform += line + os.linesep for i in depotFileNames: oform += '\t' + i + os.linesep break else: oform += line + os.linesep # print "Output form that would be submitted to perforce: " + oform runProgram(['p4', 'submit', '-i'], oform) print "%d file(s) commited: %s" % (len(selectedFileList), ', '.join(depotFileNames))
def scanFiles(self, showIgnored, pb=None): '''Request scan for all commitable files from VCS''' # Called at startup and when 'Refresh' button is pressed self.diffCache = {} itemList = [] if pb: pb.setValue(1) if showIgnored: extra = ['-x'] else: extra = [] recs = runProgram(['cg', 'status'] + extra).split(os.linesep) recs.pop() # remove eoln if pb: pb.setValue(2) # Skip header lines by looking for blank line lookingForBlank = True for line in recs: if lookingForBlank: if not line: lookingForBlank = False continue status = line[0] fname = line[2:] if status == 'M': # modified itemList.append('M ' + fname) elif status == 'A': # added itemList.append('A ' + fname) elif status == '?': # unknown itemList.append('? ' + fname) elif status == '!': # missing itemList.append('! ' + fname) elif status == 'D': # deleted itemList.append('R ' + fname) elif status in ('m'): # Skip these files, they are not commitable pass else: print "Cogito returned unexpected status %s" % status if pb: pb.setValue(3) return itemList
def getFileStatus(self, itemName): '''Request file deltas from VCS''' status = itemName[0] fileName = itemName[2:] bFileName = "%<b>" + fileName + "</b> " if status == 'M': if self.wdCache.has_key(fileName): return self.wdCache[fileName] else: text = runProgram(['p4', 'diff', '-du', self.clientToDepotMap[fileName] ]) self.wdCache[fileName] = text[:-len(os.linesep)] return text elif status == 'A': return bFileName + "has been added to perforce, but not yet commited" elif status == 'R': return bFileName + "has been opened for delete, but has not yet been commited" elif status == '!': return bFileName + "was tracked but is now missing, will be removed from perforce if commited" elif status == '*': return bFileName + "has no recorded open reason with perforce (what's going on?)" else: return "Unknown file type " + status
def getP4FileStatus(fileName): '''Helper function which determines a file's open reason''' fstatOut = runProgram(['p4', 'fstat', fileName]) status = '*' # No open action # normalize case of pwd and client path, to have a good chance of this actually # working on windows cwd = os.path.normcase(os.getcwd()) afterCwd = len(cwd) + 1 recs = fstatOut.split(os.linesep) for line in recs: words = line.split(' ') if len(words) < 2: continue if words[1] == 'depotFile': depotName = words[2] elif words[1] == 'clientFile': clientName = os.path.normcase(words[2]) # Prune current working directory from client name (make relative) if clientName.startswith(cwd): clientName = clientName[afterCwd:] elif words[1] == 'action': if words[2] == 'add': status = 'A' elif words[2] == 'edit': status = 'M' elif words[2] == 'delete': status = 'R' return (depotName, clientName, status)
def fileMoveDetected(self, origFileName, newFileName): '''User has associated an unknown file with a missing file, describing a move/rename which occurred outside of revision control Requires 'rename' capability ''' runProgram([self.mtn_exe, 'rename', origFileName, newFileName])
def generateParentFile(self, workingFile): '''The GUI needs this file's parent revision in place so the user can select individual changes for commit (basically a revert) ''' runProgram([self.mtn_exe, 'revert', workingFile])