def __loadPage(self): """ Private method to load the requested page. """ if self.__loaded: return lock = QMutexLocker(self.__mutex) if self.__pageName == "adblock": contents = self.__adBlockPage() elif self.__pageName in ["home", "start", "startpage"]: contents = self.__startPage() elif self.__pageName == "speeddial": contents = self.__speedDialPage() else: contents = "" self.__buffer.setData(contents.encode("utf-8")) self.__buffer.open(QIODevice.ReadOnly) self.open(QIODevice.ReadOnly) lock.unlock() self.readyRead.emit() self.__loaded = True
def start(self, path): """ Public slot to populate the data. @param path directory name to show change lists for (string) """ self.changeListsDict = {} self.cancelled = False self.filesLabel.setText(self.tr("Files (relative to {0}):").format(path)) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() locker = QMutexLocker(self.vcs.vcsExecutionMutex) try: entries = self.client.get_changelist(path, depth=pysvn.depth.infinity) for entry in entries: file = entry[0] changelist = entry[1] if sys.version_info[0] == 2: file = file.decode("utf-8") changelist = changelist.decode("utf-8") if changelist not in self.changeListsDict: self.changeListsDict[changelist] = [] filename = file.replace(path + os.sep, "") if filename not in self.changeListsDict[changelist]: self.changeListsDict[changelist].append(filename) except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) self.__finish()
def __loadQtHelpPage(self, url): """ Private method to load the requested QtHelp page. @param url URL of the requested page @type QUrl """ if self.__engine.findFile(url).isValid(): data = self.__engine.fileData(url) else: data = QByteArray( self.tr("""<html>""" """<head><title>Error 404...</title></head>""" """<body><div align="center"><br><br>""" """<h1>The page could not be found</h1><br>""" """<h3>'{0}'</h3></div></body>""" """</html>""").format(url.toString()).encode("utf-8")) lock = QMutexLocker(self.__mutex) self.__buffer.setData(data) self.__buffer.open(QIODevice.ReadOnly) self.open(QIODevice.ReadOnly) lock.unlock() self.readyRead.emit()
def start(self, path): """ Public slot to populate the data. @param path directory name to show change lists for (string) """ self.changeListsDict = {} self.cancelled = False self.filesLabel.setText( self.tr("Files (relative to {0}):").format(path)) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() locker = QMutexLocker(self.vcs.vcsExecutionMutex) try: entries = self.client.get_changelist(path, depth=pysvn.depth.infinity) for entry in entries: file = entry[0] changelist = entry[1] if sys.version_info[0] == 2: file = file.decode('utf-8') changelist = changelist.decode('utf-8') if changelist not in self.changeListsDict: self.changeListsDict[changelist] = [] filename = file.replace(path + os.sep, "") if filename not in self.changeListsDict[changelist]: self.changeListsDict[changelist].append(filename) except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) self.__finish()
def start(self, fn): """ Public slot to start the svn blame command. @param fn filename to show the blame for (string) """ self.blameList.clear() self.errorGroup.hide() self.activateWindow() dname, fname = self.vcs.splitPath(fn) locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: annotations = self.client.annotate(fname) locker.unlock() for annotation in annotations: author = annotation["author"] line = annotation["line"] if sys.version_info[0] == 2: author = author.decode('utf-8') line = line.decode('utf-8') self.__generateItem( annotation["revision"].number, author, annotation["number"] + 1, line) except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0] + '\n') self.__finish() os.chdir(cwd)
def start(self, fn, recursive=False): """ Public slot to start the svn status command. @param fn filename(s) (string or list of strings) @param recursive flag indicating a recursive list is requested """ self.errorGroup.hide() self.propsList.clear() self.__args = fn self.__recursive = recursive self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.refreshButton.setEnabled(False) QApplication.processEvents() self.propsFound = False if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: for name in fnames: proplist = self.client.proplist(name, recurse=recursive) counter = 0 for path, prop in proplist: if sys.version_info[0] == 2: path = path.decode('utf-8') for propName, propVal in list(prop.items()): if sys.version_info[0] == 2: propName = propName.decode('utf-8') propVal = propVal.decode('utf-8') self.__generateItem(path, propName, propVal) self.propsFound = True counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() self.__finish() os.chdir(cwd)
def start(self, fn, recursive=False): """ Public slot to start the svn status command. @param fn filename(s) (string or list of strings) @param recursive flag indicating a recursive list is requested """ self.errorGroup.hide() QApplication.processEvents() self.propsFound = False if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: for name in fnames: proplist = self.client.proplist(name, recurse=recursive) counter = 0 for path, prop in proplist: if sys.version_info[0] == 2: path = path.decode('utf-8') for propName, propVal in list(prop.items()): if sys.version_info[0] == 2: propName = propName.decode('utf-8') propVal = propVal.decode('utf-8') self.__generateItem(path, propName, propVal) self.propsFound = True counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() self.__finish() os.chdir(cwd)
def process_packet(self, feedline): feedline = str(feedline) packet = {} if feedline.startswith("* "): self._finish_command_response(feedline[2:].rstrip(), True) return if feedline.startswith("- "): self._finish_command_response(feedline[2:].rstrip(), False) return if len(self.fields) == 0: return parts = feedline.rstrip().split(',') locker = QMutexLocker(self.lock) try: self.status = dict(zip(self.fields, parts)) except: return finally: locker.unlock() self.feed_update.emit()
def start(self, fn): """ Public slot to start the svn status command. @param fn filename(s)/directoryname(s) to show the status of (string or list of strings) """ self.errorGroup.hide() for act in self.menuactions: act.setEnabled(False) self.addButton.setEnabled(False) self.commitButton.setEnabled(False) self.diffButton.setEnabled(False) self.sbsDiffButton.setEnabled(False) self.revertButton.setEnabled(False) self.restoreButton.setEnabled(False) self.statusFilterCombo.clear() self.__statusFilters = [] QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.args = fn self.setWindowTitle(self.tr('Subversion Status')) self.activateWindow() self.raise_() if isinstance(fn, list): self.dname, fnames = self.vcs.splitPathList(fn) else: self.dname, fname = self.vcs.splitPath(fn) fnames = [fname] opts = self.vcs.options['global'] + self.vcs.options['status'] verbose = "--verbose" in opts recurse = "--non-recursive" not in opts update = "--show-updates" in opts hideChangelistColumn = True hidePropertyStatusColumn = True hideLockColumns = True hideUpToDateColumn = True hideHistoryColumn = True hideSwitchedColumn = True locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: for name in fnames: # step 1: determine changelists and their files changelistsDict = {} if hasattr(self.client, 'get_changelist'): if recurse: depth = pysvn.depth.infinity else: depth = pysvn.depth.immediate changelists = self.client.get_changelist(name, depth=depth) for fpath, changelist in changelists: if sys.version_info[0] == 2: fpath = fpath.decode('utf-8') changelist = changelist.decode('utf-8') fpath = Utilities.normcasepath(fpath) changelistsDict[fpath] = changelist hideChangelistColumn = hideChangelistColumn and \ len(changelistsDict) == 0 # step 2: determine status of files allFiles = self.client.status(name, recurse=recurse, get_all=verbose, ignore=True, update=update) counter = 0 for file in allFiles: uptodate = True if file.repos_text_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_text_status != \ pysvn.wc_status_kind.modified if file.repos_prop_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_prop_status != \ pysvn.wc_status_kind.modified lockState = " " if file.entry is not None and \ hasattr(file.entry, 'lock_token') and \ file.entry.lock_token is not None: lockState = "L" if hasattr(file, 'repos_lock') and update: if lockState == "L" and file.repos_lock is None: lockState = "B" elif lockState == " " and file.repos_lock is not None: lockState = "O" elif lockState == "L" and \ file.repos_lock is not None and \ file.entry.lock_token != \ file.repos_lock["token"]: lockState = "S" fpath = Utilities.normcasepath( os.path.join(self.dname, file.path)) if fpath in changelistsDict: changelist = changelistsDict[fpath] else: changelist = "" hidePropertyStatusColumn = hidePropertyStatusColumn and \ file.prop_status in [ pysvn.wc_status_kind.none, pysvn.wc_status_kind.normal ] hideLockColumns = hideLockColumns and \ not file.is_locked and lockState == " " hideUpToDateColumn = hideUpToDateColumn and uptodate hideHistoryColumn = hideHistoryColumn and \ not file.is_copied hideSwitchedColumn = hideSwitchedColumn and \ not file.is_switched self.__generateItem( changelist, file.text_status, file.prop_status, file.is_locked, file.is_copied, file.is_switched, lockState, uptodate, file.entry and file.entry.revision.number or "", file.entry and file.entry.commit_revision.number or "", file.entry and file.entry.commit_author or "", file.path ) counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0] + '\n') self.statusList.setColumnHidden(self.__propStatusColumn, hidePropertyStatusColumn) self.statusList.setColumnHidden(self.__lockedColumn, hideLockColumns) self.statusList.setColumnHidden(self.__lockinfoColumn, hideLockColumns) self.statusList.setColumnHidden(self.__upToDateColumn, hideUpToDateColumn) self.statusList.setColumnHidden(self.__historyColumn, hideHistoryColumn) self.statusList.setColumnHidden(self.__switchedColumn, hideSwitchedColumn) self.statusList.setColumnHidden(self.__changelistColumn, hideChangelistColumn) locker.unlock() self.__finish() os.chdir(cwd)
def __getLogEntries(self, startRev=None): """ Private method to retrieve log entries from the repository. @param startRev revision number to start from (integer, string) """ fetchLimit = 10 self._reset() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() limit = self.limitSpinBox.value() if startRev is None: start = pysvn.Revision(pysvn.opt_revision_kind.head) else: try: start = pysvn.Revision(pysvn.opt_revision_kind.number, int(startRev)) except TypeError: start = pysvn.Revision(pysvn.opt_revision_kind.head) locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: nextRev = 0 fetched = 0 logs = [] while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = start else: revstart = pysvn.Revision(pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log( self.fname, revision_start=revstart, discover_changed_paths=True, limit=flimit + 1, strict_node_history=self.stopCheckBox.isChecked()) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() for log in logs: author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode('utf-8') message = message.decode('utf-8') self.__generateLogItem(author, log["date"], message, log["revision"], log['changed_paths']) dt = dateFromTime_t(log["date"]) if not self.__maxDate.isValid() and \ not self.__minDate.isValid(): self.__maxDate = dt self.__minDate = dt else: if self.__maxDate < dt: self.__maxDate = dt if self.__minDate > dt: self.__minDate = dt if len(logs) < limit and not self.cancelled: self.nextButton.setEnabled(False) self.limitSpinBox.setEnabled(False) self.__filterLogsEnabled = False self.fromDate.setMinimumDate(self.__minDate) self.fromDate.setMaximumDate(self.__maxDate) self.fromDate.setDate(self.__minDate) self.toDate.setMinimumDate(self.__minDate) self.toDate.setMaximumDate(self.__maxDate) self.toDate.setDate(self.__maxDate) self.__filterLogsEnabled = True self.__resizeColumnsLog() self.__resortLog() self.__filterLogs() except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()
def start(self, path, tags=True): """ Public slot to start the svn status command. @param path name of directory to be listed (string) @param tags flag indicating a list of tags is requested (False = branches, True = tags) @return flag indicating success (boolean) """ self.errorGroup.hide() self.tagList.clear() if not tags: self.setWindowTitle(self.tr("Subversion Branches List")) self.activateWindow() QApplication.processEvents() dname, fname = self.vcs.splitPath(path) reposURL = self.vcs.svnGetReposName(dname) if reposURL is None: E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr( """The URL of the project repository could not be""" """ retrieved from the working copy. The list operation""" """ will be aborted""")) self.close() return False if self.vcs.otherData["standardLayout"]: # determine the base path of the project in the repository rx_base = QRegExp('(.+)/(trunk|tags|branches).*') if not rx_base.exactMatch(reposURL): E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr("""The URL of the project repository has an""" """ invalid format. The list operation will""" """ be aborted""")) return False reposRoot = rx_base.cap(1) if tags: path = "{0}/tags".format(reposRoot) else: path = "{0}/branches".format(reposRoot) else: reposPath, ok = QInputDialog.getText( self, self.tr("Subversion List"), self.tr("Enter the repository URL containing the" " tags or branches"), QLineEdit.Normal, self.vcs.svnNormalizeURL(reposURL)) if not ok: self.close() return False if not reposPath: E5MessageBox.critical( self, self.tr("Subversion List"), self.tr("""The repository URL is empty. Aborting...""")) self.close() return False path = reposPath locker = QMutexLocker(self.vcs.vcsExecutionMutex) self.tagsList = [] cwd = os.getcwd() os.chdir(dname) try: entries = self.client.list(path, recurse=False) # dirent, lock already unicode in Python 2 for dirent, _lock in entries: if dirent["path"] != path: name = dirent["path"].replace(path + '/', "") self.__generateItem(dirent["created_rev"].number, dirent["last_author"], formatTime(dirent["time"]), name) if self.vcs.otherData["standardLayout"]: self.tagsList.append(name) else: self.tagsList.append(path + '/' + name) if self._clientCancelCallback(): break res = True except pysvn.ClientError as e: self.__showError(e.args[0]) res = False except AttributeError: self.__showError( self.tr("The installed version of PySvn should be" " 1.4.0 or better.")) res = False locker.unlock() self.__finish() os.chdir(cwd) return res
def start(self, path, tags=True): """ Public slot to start the svn status command. @param path name of directory to be listed (string) @param tags flag indicating a list of tags is requested (False = branches, True = tags) @return flag indicating success (boolean) """ self.errorGroup.hide() self.tagList.clear() if not tags: self.setWindowTitle(self.tr("Subversion Branches List")) self.activateWindow() QApplication.processEvents() dname, fname = self.vcs.splitPath(path) reposURL = self.vcs.svnGetReposName(dname) if reposURL is None: E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr( """The URL of the project repository could not be""" """ retrieved from the working copy. The list operation""" """ will be aborted""")) self.close() return False if self.vcs.otherData["standardLayout"]: # determine the base path of the project in the repository rx_base = QRegExp('(.+)/(trunk|tags|branches).*') if not rx_base.exactMatch(reposURL): E5MessageBox.critical( self, self.tr("Subversion Error"), self.tr( """The URL of the project repository has an""" """ invalid format. The list operation will""" """ be aborted""")) return False reposRoot = rx_base.cap(1) if tags: path = "{0}/tags".format(reposRoot) else: path = "{0}/branches".format(reposRoot) else: reposPath, ok = QInputDialog.getText( self, self.tr("Subversion List"), self.tr("Enter the repository URL containing the" " tags or branches"), QLineEdit.Normal, self.vcs.svnNormalizeURL(reposURL)) if not ok: self.close() return False if not reposPath: E5MessageBox.critical( self, self.tr("Subversion List"), self.tr( """The repository URL is empty. Aborting...""")) self.close() return False path = reposPath locker = QMutexLocker(self.vcs.vcsExecutionMutex) self.tagsList = [] cwd = os.getcwd() os.chdir(dname) try: entries = self.client.list(path, recurse=False) # dirent, lock already unicode in Python 2 for dirent, lock in entries: if dirent["path"] != path: name = dirent["path"].replace(path + '/', "") self.__generateItem(dirent["created_rev"].number, dirent["last_author"], formatTime(dirent["time"]), name) if self.vcs.otherData["standardLayout"]: self.tagsList.append(name) else: self.tagsList.append(path + '/' + name) if self._clientCancelCallback(): break res = True except pysvn.ClientError as e: self.__showError(e.args[0]) res = False except AttributeError: self.__showError( self.tr("The installed version of PySvn should be" " 1.4.0 or better.")) res = False locker.unlock() self.__finish() os.chdir(cwd) return res
def start(self, fn, versions=None, urls=None, summary=False, pegRev=None, refreshable=False): """ Public slot to start the svn diff command. @param fn filename to be diffed (string) @param versions list of versions to be diffed (list of up to 2 integer or None) @keyparam urls list of repository URLs (list of 2 strings) @keyparam summary flag indicating a summarizing diff (only valid for URL diffs) (boolean) @keyparam pegRev revision number the filename is valid (integer) @keyparam refreshable flag indicating a refreshable diff (boolean) """ self.refreshButton.setVisible(refreshable) self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self._reset() self.errorGroup.hide() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn self.contents.clear() self.paras = 0 self.filesCombo.clear() self.__oldFile = "" self.__oldFileLine = -1 self.__fileSeparators = [] if Utilities.hasEnvironmentEntry('TEMP'): tmpdir = Utilities.getEnvironmentEntry('TEMP') elif Utilities.hasEnvironmentEntry('TMPDIR'): tmpdir = Utilities.getEnvironmentEntry('TMPDIR') elif Utilities.hasEnvironmentEntry('TMP'): tmpdir = Utilities.getEnvironmentEntry('TMP') elif os.path.exists('/var/tmp'): tmpdir = '/var/tmp' elif os.path.exists('/usr/tmp'): tmpdir = '/usr/tmp' elif os.path.exists('/tmp'): tmpdir = '/tmp' else: E5MessageBox.critical( self, self.tr("Subversion Diff"), self.tr("""There is no temporary directory available.""")) return tmpdir = os.path.join(tmpdir, 'svn_tmp') if not os.path.exists(tmpdir): os.mkdir(tmpdir) opts = self.vcs.options['global'] + self.vcs.options['diff'] recurse = "--non-recursive" not in opts if versions is not None: self.raise_() self.activateWindow() rev1 = self.__getVersionArg(versions[0]) if len(versions) == 1: rev2 = self.__getVersionArg("WORKING") else: rev2 = self.__getVersionArg(versions[1]) else: rev1 = self.__getVersionArg("BASE") rev2 = self.__getVersionArg("WORKING") if urls is not None: rev1 = self.__getVersionArg("HEAD") rev2 = self.__getVersionArg("HEAD") if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: dname = e5App().getObject('Project').getRelativePath(dname) if dname: dname += "/" for name in fnames: self.__showError( self.tr("Processing file '{0}'...\n").format(name)) if urls is not None: url1 = "{0}/{1}{2}".format(urls[0], dname, name) url2 = "{0}/{1}{2}".format(urls[1], dname, name) if summary: diff_summary = self.client.diff_summarize( url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) diff_list = [] for diff_sum in diff_summary: path = diff_sum['path'] if sys.version_info[0] == 2: path = path.decode('utf-8') diff_list.append("{0} {1}".format( self.__getDiffSummaryKind( diff_sum['summarize_kind']), path)) diffText = os.linesep.join(diff_list) else: diffText = self.client.diff( tmpdir, url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') else: if pegRev is not None: diffText = self.client.diff_peg( tmpdir, name, peg_revision=self.__getVersionArg(pegRev), revision_start=rev1, revision_end=rev2, recurse=recurse) else: diffText = self.client.diff( tmpdir, name, revision1=rev1, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') counter = 0 for line in diffText.splitlines(): if line.startswith("--- ") or \ line.startswith("+++ "): self.__processFileLine(line) self.__appendText("{0}{1}".format(line, os.linesep)) counter += 1 if counter == 30: # check for cancel every 30 lines counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd) self.__finish() if self.paras == 0: self.contents.setPlainText(self.tr('There is no difference.')) self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.paras > 0)
def start(self, fn): """ Public slot to start the svn status command. @param fn filename(s)/directoryname(s) to show the status of (string or list of strings) """ self.errorGroup.hide() for act in self.menuactions: act.setEnabled(False) self.addButton.setEnabled(False) self.commitButton.setEnabled(False) self.diffButton.setEnabled(False) self.sbsDiffButton.setEnabled(False) self.revertButton.setEnabled(False) self.restoreButton.setEnabled(False) self.statusFilterCombo.clear() self.__statusFilters = [] self.statusList.clear() self.shouldCancel = False self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self.refreshButton.setEnabled(False) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.args = fn self.setWindowTitle(self.tr('Subversion Status')) self.activateWindow() self.raise_() if isinstance(fn, list): self.dname, fnames = self.vcs.splitPathList(fn) else: self.dname, fname = self.vcs.splitPath(fn) fnames = [fname] opts = self.vcs.options['global'] + self.vcs.options['status'] verbose = "--verbose" in opts recurse = "--non-recursive" not in opts update = "--show-updates" in opts hideChangelistColumn = True hidePropertyStatusColumn = True hideLockColumns = True hideUpToDateColumn = True hideHistoryColumn = True hideSwitchedColumn = True locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: for name in fnames: # step 1: determine changelists and their files changelistsDict = {} if hasattr(self.client, 'get_changelist'): if recurse: depth = pysvn.depth.infinity else: depth = pysvn.depth.immediate changelists = self.client.get_changelist(name, depth=depth) for fpath, changelist in changelists: if sys.version_info[0] == 2: fpath = fpath.decode('utf-8') changelist = changelist.decode('utf-8') fpath = Utilities.normcasepath(fpath) changelistsDict[fpath] = changelist hideChangelistColumn = hideChangelistColumn and \ len(changelistsDict) == 0 # step 2: determine status of files allFiles = self.client.status(name, recurse=recurse, get_all=verbose, ignore=True, update=update) counter = 0 for file in allFiles: uptodate = True if file.repos_text_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_text_status != \ pysvn.wc_status_kind.modified if file.repos_prop_status != pysvn.wc_status_kind.none: uptodate = uptodate and \ file.repos_prop_status != \ pysvn.wc_status_kind.modified lockState = " " if file.entry is not None and \ hasattr(file.entry, 'lock_token') and \ file.entry.lock_token is not None: lockState = "L" if hasattr(file, 'repos_lock') and update: if lockState == "L" and file.repos_lock is None: lockState = "B" elif lockState == " " and file.repos_lock is not None: lockState = "O" elif lockState == "L" and \ file.repos_lock is not None and \ file.entry.lock_token != \ file.repos_lock["token"]: lockState = "S" fpath = Utilities.normcasepath( os.path.join(self.dname, file.path)) if fpath in changelistsDict: changelist = changelistsDict[fpath] else: changelist = "" hidePropertyStatusColumn = hidePropertyStatusColumn and \ file.prop_status in [ pysvn.wc_status_kind.none, pysvn.wc_status_kind.normal ] hideLockColumns = hideLockColumns and \ not file.is_locked and lockState == " " hideUpToDateColumn = hideUpToDateColumn and uptodate hideHistoryColumn = hideHistoryColumn and \ not file.is_copied hideSwitchedColumn = hideSwitchedColumn and \ not file.is_switched self.__generateItem( changelist, file.text_status, file.prop_status, file.is_locked, file.is_copied, file.is_switched, lockState, uptodate, file.entry and file.entry.revision.number or "", file.entry and file.entry.commit_revision.number or "", file.entry and file.entry.commit_author or "", file.path ) counter += 1 if counter == 30: # check for cancel every 30 items counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0] + '\n') self.statusList.setColumnHidden(self.__propStatusColumn, hidePropertyStatusColumn) self.statusList.setColumnHidden(self.__lockedColumn, hideLockColumns) self.statusList.setColumnHidden(self.__lockinfoColumn, hideLockColumns) self.statusList.setColumnHidden(self.__upToDateColumn, hideUpToDateColumn) self.statusList.setColumnHidden(self.__historyColumn, hideHistoryColumn) self.statusList.setColumnHidden(self.__switchedColumn, hideSwitchedColumn) self.statusList.setColumnHidden(self.__changelistColumn, hideChangelistColumn) locker.unlock() self.__finish() os.chdir(cwd)
def start(self, projectPath, fn): """ Public slot to start the svn info command. @param projectPath path name of the project (string) @param fn file or directory name relative to the project (string) """ locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(projectPath) try: entries = self.client.info2(fn, recurse=False) infoStr = "<table>" for path, info in entries: if sys.version_info[0] == 2: path = path.decode('utf-8') infoStr += self.tr( "<tr><td><b>Path (relative to project):</b></td>" "<td>{0}</td></tr>").format(path) if info['URL']: infoStr += self.tr( "<tr><td><b>Url:</b></td><td>{0}</td></tr>")\ .format(info['URL']) if info['rev']: infoStr += self.tr( "<tr><td><b>Revision:</b></td><td>{0}</td></tr>")\ .format(info['rev'].number) if info['repos_root_URL']: infoStr += self.tr( "<tr><td><b>Repository root URL:</b></td>" "<td>{0}</td></tr>").format(info['repos_root_URL']) if info['repos_UUID']: infoStr += self.tr("<tr><td><b>Repository UUID:</b></td>" "<td>{0}</td></tr>").format( info['repos_UUID']) if info['last_changed_author']: infoStr += self.tr( "<tr><td><b>Last changed author:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_author']) if info['last_changed_date']: infoStr += self.tr( "<tr><td><b>Last Changed Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(info['last_changed_date'])) if info['last_changed_rev'] and \ info['last_changed_rev'].kind == \ pysvn.opt_revision_kind.number: infoStr += self.tr( "<tr><td><b>Last changed revision:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_rev'].number) if info['kind']: if info['kind'] == pysvn.node_kind.file: nodeKind = self.tr("file") elif info['kind'] == pysvn.node_kind.dir: nodeKind = self.tr("directory") elif info['kind'] == pysvn.node_kind.none: nodeKind = self.tr("none") else: nodeKind = self.tr("unknown") infoStr += self.tr( "<tr><td><b>Node kind:</b></td><td>{0}</td></tr>")\ .format(nodeKind) if info['lock']: lockInfo = info['lock'] infoStr += self.tr( "<tr><td><b>Lock Owner:</b></td><td>{0}</td></tr>")\ .format(lockInfo['owner']) infoStr += self.tr( "<tr><td><b>Lock Creation Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['creation_date'])) if lockInfo['expiration_date'] is not None: infoStr += self.tr( "<tr><td><b>Lock Expiration Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['expiration_date'])) infoStr += self.tr( "<tr><td><b>Lock Token:</b></td><td>{0}</td></tr>")\ .format(lockInfo['token']) infoStr += self.tr( "<tr><td><b>Lock Comment:</b></td><td>{0}</td></tr>")\ .format(lockInfo['comment']) if info['wc_info']: wcInfo = info['wc_info'] if wcInfo['schedule']: if wcInfo['schedule'] == pysvn.wc_schedule.normal: schedule = self.tr("normal") elif wcInfo['schedule'] == pysvn.wc_schedule.add: schedule = self.tr("add") elif wcInfo['schedule'] == pysvn.wc_schedule.delete: schedule = self.tr("delete") elif wcInfo['schedule'] == pysvn.wc_schedule.replace: schedule = self.tr("replace") infoStr += self.tr( "<tr><td><b>Schedule:</b></td><td>{0}</td></tr>")\ .format(schedule) if wcInfo['copyfrom_url']: infoStr += self.tr( "<tr><td><b>Copied From URL:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_url']) infoStr += self.tr( "<tr><td><b>Copied From Rev:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_rev'].number) if wcInfo['text_time']: infoStr += self.tr( "<tr><td><b>Text Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['text_time'])) if wcInfo['prop_time']: infoStr += self.tr( "<tr><td><b>Properties Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['prop_time'])) if wcInfo['checksum']: infoStr += self.tr( "<tr><td><b>Checksum:</b></td><td>{0}</td></tr>")\ .format(wcInfo['checksum']) infoStr += "</table>" self.infoBrowser.setHtml(infoStr) except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd)
def __getLogEntries(self, startRev=None): """ Private method to retrieve log entries from the repository. @param startRev revision number to start from (integer, string) """ fetchLimit = 10 self._reset() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() limit = self.limitSpinBox.value() if startRev is None: start = pysvn.Revision(pysvn.opt_revision_kind.head) else: try: start = pysvn.Revision(pysvn.opt_revision_kind.number, int(startRev)) except TypeError: start = pysvn.Revision(pysvn.opt_revision_kind.head) locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(self.dname) try: nextRev = 0 fetched = 0 logs = [] while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = start else: revstart = pysvn.Revision( pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log( self.fname, revision_start=revstart, discover_changed_paths=True, limit=flimit + 1, strict_node_history=self.stopCheckBox.isChecked()) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() for log in logs: author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode('utf-8') message = message.decode('utf-8') self.__generateLogItem( author, log["date"], message, log["revision"], log['changed_paths']) dt = dateFromTime_t(log["date"]) if not self.__maxDate.isValid() and \ not self.__minDate.isValid(): self.__maxDate = dt self.__minDate = dt else: if self.__maxDate < dt: self.__maxDate = dt if self.__minDate > dt: self.__minDate = dt if len(logs) < limit and not self.cancelled: self.nextButton.setEnabled(False) self.limitSpinBox.setEnabled(False) self.__filterLogsEnabled = False self.fromDate.setMinimumDate(self.__minDate) self.fromDate.setMaximumDate(self.__maxDate) self.fromDate.setDate(self.__minDate) self.toDate.setMinimumDate(self.__minDate) self.toDate.setMaximumDate(self.__maxDate) self.toDate.setDate(self.__maxDate) self.__filterLogsEnabled = True self.__resizeColumnsLog() self.__resortLog() self.__filterLogs() except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()
def start(self, fn, noEntries=0): """ Public slot to start the svn log command. @param fn filename to show the log for (string) @param noEntries number of entries to show (integer) """ self.errorGroup.hide() fetchLimit = 10 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn dname, fname = self.vcs.splitPath(fn) opts = self.vcs.options['global'] + self.vcs.options['log'] verbose = "--verbose" in opts self.activateWindow() self.raise_() locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: nextRev = 0 fetched = 0 logs = [] limit = noEntries or 9999999 while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = pysvn.Revision(pysvn.opt_revision_kind.head) else: revstart = pysvn.Revision( pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log(fname, revision_start=revstart, discover_changed_paths=verbose, limit=flimit + 1, strict_node_history=False) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() self.contents.clear() self.__pegRev = None for log in logs: ver = "{0:d}".format(log["revision"].number) dstr = '<b>{0} {1}</b>'.format(self.revString, ver) if self.__pegRev is None: self.__pegRev = int(ver) try: lv = "{0:d}".format( logs[logs.index(log) + 1]["revision"].number) url = QUrl() url.setScheme("file") url.setPath(self.filename) query = lv + '_' + ver url.setQuery(query) dstr += ' [<a href="{0}" name="{1}">{2}</a>]'.format( url.toString(), query, self.tr('diff to {0}').format(lv) ) except IndexError: pass dstr += '<br />\n' self.contents.insertHtml(dstr) author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode('utf-8') message = message.decode('utf-8') dstr = self.tr('<i>author: {0}</i><br />\n')\ .format(author) self.contents.insertHtml(dstr) dstr = self.tr('<i>date: {0}</i><br />\n')\ .format(formatTime(log["date"])) self.contents.insertHtml(dstr) self.contents.insertHtml('<br />\n') for line in message.splitlines(): self.contents.insertHtml(Utilities.html_encode(line)) self.contents.insertHtml('<br />\n') if len(log['changed_paths']) > 0: self.contents.insertHtml('<br />\n') for changeInfo in log['changed_paths']: action = changeInfo["action"] path = changeInfo["path"] if sys.version_info[0] == 2: action = action.decode('utf-8') path = path.decode('utf-8') dstr = '{0} {1}'.format(self.flags[action], path) if changeInfo["copyfrom_path"] is not None: copyfrom_path = changeInfo["copyfrom_path"] if sys.version_info[0] == 2: copyfrom_path = copyfrom_path.decode('utf-8') dstr += self.tr( " (copied from {0}, revision {1})")\ .format(copyfrom_path, changeInfo["copyfrom_revision"].number) dstr += '<br />\n' self.contents.insertHtml(dstr) self.contents.insertHtml('<hr /><br />\n') except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()
def start(self, projectPath, fn): """ Public slot to start the svn info command. @param projectPath path name of the project (string) @param fn file or directory name relative to the project (string) """ locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(projectPath) try: entries = self.client.info2(fn, recurse=False) infoStr = "<table>" for path, info in entries: if sys.version_info[0] == 2: path = path.decode('utf-8') infoStr += self.tr( "<tr><td><b>Path (relative to project):</b></td>" "<td>{0}</td></tr>").format(path) if info['URL']: infoStr += self.tr( "<tr><td><b>Url:</b></td><td>{0}</td></tr>")\ .format(info['URL']) if info['rev']: infoStr += self.tr( "<tr><td><b>Revision:</b></td><td>{0}</td></tr>")\ .format(info['rev'].number) if info['repos_root_URL']: infoStr += self.tr( "<tr><td><b>Repository root URL:</b></td>" "<td>{0}</td></tr>").format(info['repos_root_URL']) if info['repos_UUID']: infoStr += self.tr( "<tr><td><b>Repository UUID:</b></td>" "<td>{0}</td></tr>").format(info['repos_UUID']) if info['last_changed_author']: infoStr += self.tr( "<tr><td><b>Last changed author:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_author']) if info['last_changed_date']: infoStr += self.tr( "<tr><td><b>Last Changed Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(info['last_changed_date'])) if info['last_changed_rev'] and \ info['last_changed_rev'].kind == \ pysvn.opt_revision_kind.number: infoStr += self.tr( "<tr><td><b>Last changed revision:</b></td>" "<td>{0}</td></tr>")\ .format(info['last_changed_rev'].number) if info['kind']: if info['kind'] == pysvn.node_kind.file: nodeKind = self.tr("file") elif info['kind'] == pysvn.node_kind.dir: nodeKind = self.tr("directory") elif info['kind'] == pysvn.node_kind.none: nodeKind = self.tr("none") else: nodeKind = self.tr("unknown") infoStr += self.tr( "<tr><td><b>Node kind:</b></td><td>{0}</td></tr>")\ .format(nodeKind) if info['lock']: lockInfo = info['lock'] infoStr += self.tr( "<tr><td><b>Lock Owner:</b></td><td>{0}</td></tr>")\ .format(lockInfo['owner']) infoStr += self.tr( "<tr><td><b>Lock Creation Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['creation_date'])) if lockInfo['expiration_date'] is not None: infoStr += self.tr( "<tr><td><b>Lock Expiration Date:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(lockInfo['expiration_date'])) infoStr += self.tr( "<tr><td><b>Lock Token:</b></td><td>{0}</td></tr>")\ .format(lockInfo['token']) infoStr += self.tr( "<tr><td><b>Lock Comment:</b></td><td>{0}</td></tr>")\ .format(lockInfo['comment']) if info['wc_info']: wcInfo = info['wc_info'] if wcInfo['schedule']: if wcInfo['schedule'] == pysvn.wc_schedule.normal: schedule = self.tr("normal") elif wcInfo['schedule'] == pysvn.wc_schedule.add: schedule = self.tr("add") elif wcInfo['schedule'] == pysvn.wc_schedule.delete: schedule = self.tr("delete") elif wcInfo['schedule'] == pysvn.wc_schedule.replace: schedule = self.tr("replace") infoStr += self.tr( "<tr><td><b>Schedule:</b></td><td>{0}</td></tr>")\ .format(schedule) if wcInfo['copyfrom_url']: infoStr += self.tr( "<tr><td><b>Copied From URL:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_url']) infoStr += self.tr( "<tr><td><b>Copied From Rev:</b></td>" "<td>{0}</td></tr>")\ .format(wcInfo['copyfrom_rev'].number) if wcInfo['text_time']: infoStr += self.tr( "<tr><td><b>Text Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['text_time'])) if wcInfo['prop_time']: infoStr += self.tr( "<tr><td><b>Properties Last Updated:</b></td>" "<td>{0}</td></tr>")\ .format(formatTime(wcInfo['prop_time'])) if wcInfo['checksum']: infoStr += self.tr( "<tr><td><b>Checksum:</b></td><td>{0}</td></tr>")\ .format(wcInfo['checksum']) infoStr += "</table>" self.infoBrowser.setHtml(infoStr) except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd)
def start(self, fn, versions=None, urls=None, summary=False, pegRev=None): """ Public slot to start the svn diff command. @param fn filename to be diffed (string) @param versions list of versions to be diffed (list of up to 2 integer or None) @keyparam urls list of repository URLs (list of 2 strings) @keyparam summary flag indicating a summarizing diff (only valid for URL diffs) (boolean) @keyparam pegRev revision number the filename is valid (integer) """ self.buttonBox.button(QDialogButtonBox.Save).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) self._reset() self.errorGroup.hide() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn self.contents.clear() self.paras = 0 self.filesCombo.clear() self.__oldFile = "" self.__oldFileLine = -1 self.__fileSeparators = [] if Utilities.hasEnvironmentEntry('TEMP'): tmpdir = Utilities.getEnvironmentEntry('TEMP') elif Utilities.hasEnvironmentEntry('TMPDIR'): tmpdir = Utilities.getEnvironmentEntry('TMPDIR') elif Utilities.hasEnvironmentEntry('TMP'): tmpdir = Utilities.getEnvironmentEntry('TMP') elif os.path.exists('/var/tmp'): tmpdir = '/var/tmp' elif os.path.exists('/usr/tmp'): tmpdir = '/usr/tmp' elif os.path.exists('/tmp'): tmpdir = '/tmp' else: E5MessageBox.critical( self, self.tr("Subversion Diff"), self.tr("""There is no temporary directory available.""")) return tmpdir = os.path.join(tmpdir, 'svn_tmp') if not os.path.exists(tmpdir): os.mkdir(tmpdir) opts = self.vcs.options['global'] + self.vcs.options['diff'] recurse = "--non-recursive" not in opts if versions is not None: self.raise_() self.activateWindow() rev1 = self.__getVersionArg(versions[0]) if len(versions) == 1: rev2 = self.__getVersionArg("WORKING") else: rev2 = self.__getVersionArg(versions[1]) else: rev1 = self.__getVersionArg("BASE") rev2 = self.__getVersionArg("WORKING") if urls is not None: rev1 = self.__getVersionArg("HEAD") rev2 = self.__getVersionArg("HEAD") if isinstance(fn, list): dname, fnames = self.vcs.splitPathList(fn) else: dname, fname = self.vcs.splitPath(fn) fnames = [fname] locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: dname = e5App().getObject('Project').getRelativePath(dname) if dname: dname += "/" for name in fnames: self.__showError( self.tr("Processing file '{0}'...\n").format(name)) if urls is not None: url1 = "{0}/{1}{2}".format(urls[0], dname, name) url2 = "{0}/{1}{2}".format(urls[1], dname, name) if summary: diff_summary = self.client.diff_summarize( url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) diff_list = [] for diff_sum in diff_summary: path = diff_sum['path'] if sys.version_info[0] == 2: path = path.decode('utf-8') diff_list.append("{0} {1}".format( self.__getDiffSummaryKind( diff_sum['summarize_kind']), path)) diffText = os.linesep.join(diff_list) else: diffText = self.client.diff( tmpdir, url1, revision1=rev1, url_or_path2=url2, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') else: if pegRev is not None: diffText = self.client.diff_peg( tmpdir, name, peg_revision=self.__getVersionArg(pegRev), revision_start=rev1, revision_end=rev2, recurse=recurse) else: diffText = self.client.diff( tmpdir, name, revision1=rev1, revision2=rev2, recurse=recurse) if sys.version_info[0] == 2: diffText = diffText.decode('utf-8') counter = 0 for line in diffText.splitlines(): if line.startswith("--- ") or \ line.startswith("+++ "): self.__processFileLine(line) self.__appendText("{0}{1}".format(line, os.linesep)) counter += 1 if counter == 30: # check for cancel every 30 lines counter = 0 if self._clientCancelCallback(): break if self._clientCancelCallback(): break except pysvn.ClientError as e: self.__showError(e.args[0]) locker.unlock() os.chdir(cwd) self.__finish() if self.paras == 0: self.contents.setCurrentCharFormat(self.cNormalFormat) self.contents.setPlainText( self.tr('There is no difference.')) self.buttonBox.button(QDialogButtonBox.Save).setEnabled(self.paras > 0)
def __listRepo(self, url, parent=None): """ Private method to perform the svn list command. @param url the repository URL to browser (string) @param parent reference to the item, the data should be appended to (QTreeWidget or QTreeWidgetItem) """ QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if parent is None: parent = self.repoTree locker = QMutexLocker(self.vcs.vcsExecutionMutex) try: try: entries = self.client.list(url, recurse=False) firstTime = parent == self.repoTree # dirent elements are all unicode in Python 2 for dirent, lock in entries: if (firstTime and dirent["path"] != url) or \ (parent != self.repoTree and dirent["path"] == url): continue if firstTime: if dirent["repos_path"] != "/": repoUrl = dirent["path"].replace( dirent["repos_path"], "") else: repoUrl = dirent["path"] if repoUrl != url: self.__ignoreExpand = True itm = self.__generateItem( parent, "/", "", "", 0, "", pysvn.node_kind.dir, repoUrl) itm.setExpanded(True) parent = itm urlPart = repoUrl for element in \ dirent["repos_path"].split("/")[:-1]: if element: urlPart = "{0}/{1}".format(urlPart, element) itm = self.__generateItem( parent, element, "", "", 0, "", pysvn.node_kind.dir, urlPart) itm.setExpanded(True) parent = itm self.__ignoreExpand = False itm = self.__generateItem( parent, dirent["repos_path"], dirent["created_rev"], dirent["last_author"], dirent["size"], dirent["time"], dirent["kind"], dirent["path"]) self.__resort() self.__resizeColumns() except pysvn.ClientError as e: self.__showError(e.args[0]) except AttributeError: self.__showError( self.tr("The installed version of PySvn should be " "1.4.0 or better.")) finally: locker.unlock() QApplication.restoreOverrideCursor()
def start(self, fn, noEntries=0): """ Public slot to start the svn log command. @param fn filename to show the log for (string) @param noEntries number of entries to show (integer) """ self.errorGroup.hide() fetchLimit = 10 QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() self.filename = fn dname, fname = self.vcs.splitPath(fn) opts = self.vcs.options["global"] + self.vcs.options["log"] verbose = "--verbose" in opts self.activateWindow() self.raise_() locker = QMutexLocker(self.vcs.vcsExecutionMutex) cwd = os.getcwd() os.chdir(dname) try: nextRev = 0 fetched = 0 logs = [] limit = noEntries or 9999999 while fetched < limit: flimit = min(fetchLimit, limit - fetched) if fetched == 0: revstart = pysvn.Revision(pysvn.opt_revision_kind.head) else: revstart = pysvn.Revision(pysvn.opt_revision_kind.number, nextRev) allLogs = self.client.log( fname, revision_start=revstart, discover_changed_paths=verbose, limit=flimit + 1, strict_node_history=False, ) if len(allLogs) <= flimit or self._clientCancelCallback(): logs.extend(allLogs) break else: logs.extend(allLogs[:-1]) nextRev = allLogs[-1]["revision"].number fetched += fetchLimit locker.unlock() self.contents.clear() self.__pegRev = None for log in logs: ver = "{0:d}".format(log["revision"].number) dstr = "<b>{0} {1}</b>".format(self.revString, ver) if self.__pegRev is None: self.__pegRev = int(ver) try: lv = "{0:d}".format(logs[logs.index(log) + 1]["revision"].number) url = QUrl() url.setScheme("file") url.setPath(self.filename) query = lv + "_" + ver url.setQuery(query) dstr += ' [<a href="{0}" name="{1}">{2}</a>]'.format( url.toString(), query, self.tr("diff to {0}").format(lv) ) except IndexError: pass dstr += "<br />\n" self.contents.insertHtml(dstr) author = log["author"] message = log["message"] if sys.version_info[0] == 2: author = author.decode("utf-8") message = message.decode("utf-8") dstr = self.tr("<i>author: {0}</i><br />\n").format(author) self.contents.insertHtml(dstr) dstr = self.tr("<i>date: {0}</i><br />\n").format(formatTime(log["date"])) self.contents.insertHtml(dstr) self.contents.insertHtml("<br />\n") for line in message.splitlines(): self.contents.insertHtml(Utilities.html_encode(line)) self.contents.insertHtml("<br />\n") if len(log["changed_paths"]) > 0: self.contents.insertHtml("<br />\n") for changeInfo in log["changed_paths"]: action = changeInfo["action"] path = changeInfo["path"] if sys.version_info[0] == 2: action = action.decode("utf-8") path = path.decode("utf-8") dstr = "{0} {1}".format(self.flags[action], path) if changeInfo["copyfrom_path"] is not None: copyfrom_path = changeInfo["copyfrom_path"] if sys.version_info[0] == 2: copyfrom_path = copyfrom_path.decode("utf-8") dstr += self.tr(" (copied from {0}, revision {1})").format( copyfrom_path, changeInfo["copyfrom_revision"].number ) dstr += "<br />\n" self.contents.insertHtml(dstr) self.contents.insertHtml("<hr /><br />\n") except pysvn.ClientError as e: locker.unlock() self.__showError(e.args[0]) os.chdir(cwd) self.__finish()