Пример #1
0
    def __init__(self, ui, repoagent, revs, parent=None):
        super(PostReviewDialog, self).__init__(parent)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        self.ui = ui
        self._repoagent = repoagent
        self.error_message = None
        self.cmd = None

        self.qui = Ui_PostReviewDialog()
        self.qui.setupUi(self)

        self.initChangesets(revs)
        self.readSettings()

        self.review_thread = LoadReviewDataThread(self)
        self.review_thread.finished.connect(self.errorPrompt)
        self.review_thread.start()
        QShortcut(QKeySequence('Ctrl+Return'), self, self.accept)
        QShortcut(QKeySequence('Ctrl+Enter'), self, self.accept)
Пример #2
0
    def __init__(self, ui, repo, revs, parent=None):
        super(PostReviewDialog, self).__init__(parent)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        self.ui = ui
        self.repo = repo
        self.error_message = None
        self.cmd = None

        self.qui = Ui_PostReviewDialog()
        self.qui.setupUi(self)

        self.initChangesets(revs)
        self.readSettings()

        self.review_thread = LoadReviewDataThread(self)
        self.review_thread.finished.connect(self.errorPrompt)
        self.review_thread.start()
        QShortcut(QKeySequence('Ctrl+Return'), self, self.accept)
        QShortcut(QKeySequence('Ctrl+Enter'), self, self.accept)
Пример #3
0
class PostReviewDialog(QDialog):
    """Dialog for sending patches to reviewboard"""
    def __init__(self, ui, repo, revs, parent=None):
        super(PostReviewDialog, self).__init__(parent)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        self.ui = ui
        self.repo = repo
        self.error_message = None
        self.cmd = None

        self.qui = Ui_PostReviewDialog()
        self.qui.setupUi(self)

        self.initChangesets(revs)
        self.readSettings()

        self.review_thread = LoadReviewDataThread(self)
        self.review_thread.finished.connect(self.errorPrompt)
        self.review_thread.start()
        QShortcut(QKeySequence('Ctrl+Return'), self, self.accept)
        QShortcut(QKeySequence('Ctrl+Enter'), self, self.accept)

    @pyqtSlot()
    def passwordPrompt(self):
        pwd, ok = QInputDialog.getText(self,
                                       _('Review Board'),
                                       _('Password:'******'Review Board'),
                              _('Error'), self.error_message)
            self.close()
        elif self.isValid():
            self.qui.post_review_button.setEnabled(True)

    def closeEvent(self, event):
        if self.cmd and self.cmd.core.running():
            self.cmd.commandFinished.disconnect(self.onCompletion)
            self.cmd.cancel()

        # Dispose of the review data thread
        self.review_thread.terminate()
        self.review_thread.wait()

        self.writeSettings()
        super(PostReviewDialog, self).closeEvent(event)

    def readSettings(self):
        s = QSettings()

        self.restoreGeometry(s.value('reviewboard/geom').toByteArray())

        self.qui.publish_immediately_check.setChecked(
                s.value('reviewboard/publish_immediately_check').toBool())
        self.qui.outgoing_changes_check.setChecked(
                s.value('reviewboard/outgoing_changes_check').toBool())
        self.qui.branch_check.setChecked(
                s.value('reviewboard/branch_check').toBool())
        self.qui.update_fields.setChecked(
                s.value('reviewboard/update_fields').toBool())
        self.qui.summary_edit.addItems(
                s.value('reviewboard/summary_edit_history').toStringList())

        try:
            self.repo_id = int(self.repo.ui.config('reviewboard', 'repoid'))
        except Exception:
            self.repo_id = None

        if not self.repo_id:
            self.repo_id = s.value('reviewboard/repo_id').toInt()[0]

        self.server = self.repo.ui.config('reviewboard', 'server')
        self.user = self.repo.ui.config('reviewboard', 'user')
        self.password = self.repo.ui.config('reviewboard', 'password')
        self.browser = self.repo.ui.config('reviewboard', 'browser')

    def writeSettings(self):
        s = QSettings()
        s.setValue('reviewboard/geom', self.saveGeometry())
        s.setValue('reviewboard/publish_immediately_check',
                   self.qui.publish_immediately_check.isChecked())
        s.setValue('reviewboard/branch_check',
                   self.qui.branch_check.isChecked())
        s.setValue('reviewboard/outgoing_changes_check',
                   self.qui.outgoing_changes_check.isChecked())
        s.setValue('reviewboard/update_fields',
                   self.qui.update_fields.isChecked())
        s.setValue('reviewboard/repo_id', self.getRepoId())

        def itercombo(w):
            if w.currentText():
                yield w.currentText()
            for i in xrange(w.count()):
                if w.itemText(i) != w.currentText():
                    yield w.itemText(i)

        s.setValue('reviewboard/summary_edit_history',
                   list(itercombo(self.qui.summary_edit))[:10])

    def initChangesets(self, revs, selected_revs=None):
        def purerevs(revs):
            return hglib.revrange(self.repo,
                                  iter(str(e) for e in revs))
        if selected_revs:
             selectedrevs = purerevs(selected_revs)
        else:
             selectedrevs = purerevs(revs)

        self._changesets = _ChangesetsModel(self.repo,
                                            # TODO: [':'] is inefficient
                                            revs=purerevs(revs or [':']),
                                            selectedrevs=selectedrevs,
                                            parent=self)

        self.qui.changesets_view.setModel(self._changesets)

    @property
    def selectedRevs(self):
        """Returns list of revisions to be sent"""
        return self._changesets.selectedrevs

    @property
    def allRevs(self):
        """Returns list of revisions to be sent"""
        return self._changesets.revs

    def getRepoId(self):
        comboText = self.qui.repo_id_combo.currentText().split(":")
        return str(comboText[0])

    def getReviewId(self):
        comboText = self.qui.review_id_combo.currentText().split(":")
        return str(comboText[0])

    def getSummary(self):
        comboText = self.qui.review_id_combo.currentText().split(":")
        return str(comboText[1])

    def postReviewOpts(self, **opts):
        """Generate opts for reviewboard by form values"""
        opts['outgoingchanges'] = self.qui.outgoing_changes_check.isChecked()
        opts['branch'] = self.qui.branch_check.isChecked()
        opts['publish'] = self.qui.publish_immediately_check.isChecked()

        if self.qui.tab_widget.currentIndex() == 1:
            opts["existing"] = self.getReviewId()
            opts['update'] = self.qui.update_fields.isChecked()
            opts['summary'] = self.getSummary()
        else:
            opts['repoid'] = self.getRepoId()
            opts['summary'] = hglib.fromunicode(self.qui.summary_edit.currentText())

        if (len(self.selectedRevs) > 1):
            #Set the parent to the revision below the last one on the list
            #so all checked revisions are included in the request
            opts['parent'] = str(self.selectedRevs[0] - 1)

        # Always use the upstream repo to determine the parent diff base
        # without the diff uploaded to review board dies
        opts['outgoing'] = True

        #Set the password just in  case the user has opted to not save it
        opts['password'] = str(self.password)

        #Finally we want to pass the repo path to the hg extension
        opts['repository'] = self.repo.root

        return opts

    def isValid(self):
        """Filled all required values?"""
        if not self.qui.repo_id_combo.currentText():
            return False

        if self.qui.tab_widget.currentIndex() == 1:
            if not self.qui.review_id_combo.currentText():
                return False

        if not self.allRevs:
            return False

        return True

    @pyqtSlot()
    def tabChanged(self):
        self.qui.post_review_button.setEnabled(self.isValid())

    @pyqtSlot()
    def branchCheckToggle(self):
        if self.qui.branch_check.isChecked():
            self.qui.outgoing_changes_check.setChecked(False)

        self.toggleOutgoingChangesets()

    @pyqtSlot()
    def outgoingChangesCheckToggle(self):
        if self.qui.outgoing_changes_check.isChecked():
            self.qui.branch_check.setChecked(False)

        self.toggleOutgoingChangesets()

    def toggleOutgoingChangesets(self):
        branch = self.qui.branch_check.isChecked()
        outgoing = self.qui.outgoing_changes_check.isChecked()
        if branch or outgoing:
            self.initChangesets(self.allRevs, [self.selectedRevs.pop()])
            self.qui.changesets_view.setEnabled(False)
        else:
            self.initChangesets(self.allRevs, self.allRevs)
            self.qui.changesets_view.setEnabled(True)

    def close(self):
        super(PostReviewDialog, self).close()

    def accept(self):
        if not self.isValid():
            return
        if not self.password and not self.passwordPrompt():
            return

        self.qui.progress_bar.show()
        self.qui.progress_label.setText("Posting Review...")
        self.qui.progress_label.show()

        def cmdargs(opts):
            args = []
            for k, v in opts.iteritems():
                if isinstance(v, bool):
                    if v:
                        args.append('--%s' % k.replace('_', '-'))
                else:
                    for e in isinstance(v, basestring) and [v] or v:
                        args += ['--%s' % k.replace('_', '-'), e]

            return args

        hglib.loadextension(self.ui, 'reviewboard')

        opts = self.postReviewOpts()

        revstr = str(self.selectedRevs.pop())

        self.qui.post_review_button.setEnabled(False)
        self.qui.close_button.setEnabled(False)

        self.cmd = cmdui.Runner(False, self)
        self.cmd.setTitle(_('Review Board'))
        self.cmd.commandFinished.connect(self.onCompletion)
        self.cmd.run(['postreview'] + cmdargs(opts) + [revstr])

    @pyqtSlot()
    def onCompletion(self):
        self.qui.progress_bar.hide()
        self.qui.progress_label.hide()

        output = self.cmd.core.rawoutput()

        saved = 'saved:' in output
        published = 'published:' in output
        if (saved or published):
            if saved:
                url = output.split('saved: ').pop().strip()
                msg = _('Review draft posted to %s\n' % url)
            else:
                url = output.split('published: ').pop().strip()
                msg = _('Review published to %s\n' % url)

            QDesktopServices.openUrl(QUrl(url))

            qtlib.InfoMsgBox(_('Review Board'), _('Success'),
                               msg, parent=self)
        else:
            error = output.split('abort: ').pop().strip()
            if error[:29] == "HTTP Error: basic auth failed":
                if self.passwordPrompt():
                    self.accept()
                else:
                    self.qui.post_review_button.setEnabled(True)
                    self.qui.close_button.setEnabled(True)
                    return
            else:
                qtlib.ErrorMsgBox(_('Review Board'),
                                  _('Error'), error)

        self.writeSettings()
        super(PostReviewDialog, self).accept()

    @pyqtSlot()
    def onSettingsButtonClicked(self):
        from tortoisehg.hgqt import settings
        if settings.SettingsDialog(parent=self, focus='reviewboard.server').exec_():
            # not use repo.configChanged because it can clobber user input
            # accidentally.
            self.repo.invalidateui()  # force reloading config immediately
            self.readSettings()
Пример #4
0
class PostReviewDialog(QDialog):
    """Dialog for sending patches to reviewboard"""
    def __init__(self, ui, repo, revs, parent=None):
        super(PostReviewDialog, self).__init__(parent)
        self.setWindowFlags(self.windowFlags()
                            & ~Qt.WindowContextHelpButtonHint)
        self.ui = ui
        self.repo = repo
        self.error_message = None
        self.cmd = None

        self.qui = Ui_PostReviewDialog()
        self.qui.setupUi(self)

        self.initChangesets(revs)
        self.readSettings()

        self.review_thread = LoadReviewDataThread(self)
        self.review_thread.finished.connect(self.errorPrompt)
        self.review_thread.start()
        QShortcut(QKeySequence('Ctrl+Return'), self, self.accept)
        QShortcut(QKeySequence('Ctrl+Enter'), self, self.accept)

    @pyqtSlot()
    def passwordPrompt(self):
        pwd, ok = qtlib.getTextInput(self,
                                     _('Review Board'),
                                     _('Password:'******'Review Board'), _('Error'),
                              self.error_message)
            self.close()
        elif self.isValid():
            self.qui.post_review_button.setEnabled(True)

    def closeEvent(self, event):
        if self.cmd and self.cmd.core.running():
            self.cmd.commandFinished.disconnect(self.onCompletion)
            self.cmd.cancel()

        # Dispose of the review data thread
        self.review_thread.terminate()
        self.review_thread.wait()

        self.writeSettings()
        super(PostReviewDialog, self).closeEvent(event)

    def readSettings(self):
        s = QSettings()

        self.restoreGeometry(s.value('reviewboard/geom').toByteArray())

        self.qui.publish_immediately_check.setChecked(
            s.value('reviewboard/publish_immediately_check').toBool())
        self.qui.outgoing_changes_check.setChecked(
            s.value('reviewboard/outgoing_changes_check').toBool())
        self.qui.branch_check.setChecked(
            s.value('reviewboard/branch_check').toBool())
        self.qui.update_fields.setChecked(
            s.value('reviewboard/update_fields').toBool())
        self.qui.summary_edit.addItems(
            s.value('reviewboard/summary_edit_history').toStringList())

        try:
            self.repo_id = int(self.repo.ui.config('reviewboard', 'repoid'))
        except Exception:
            self.repo_id = None

        if not self.repo_id:
            self.repo_id = s.value('reviewboard/repo_id').toInt()[0]

        self.server = self.repo.ui.config('reviewboard', 'server')
        self.user = self.repo.ui.config('reviewboard', 'user')
        self.password = self.repo.ui.config('reviewboard', 'password')
        self.browser = self.repo.ui.config('reviewboard', 'browser')

    def writeSettings(self):
        s = QSettings()
        s.setValue('reviewboard/geom', self.saveGeometry())
        s.setValue('reviewboard/publish_immediately_check',
                   self.qui.publish_immediately_check.isChecked())
        s.setValue('reviewboard/branch_check',
                   self.qui.branch_check.isChecked())
        s.setValue('reviewboard/outgoing_changes_check',
                   self.qui.outgoing_changes_check.isChecked())
        s.setValue('reviewboard/update_fields',
                   self.qui.update_fields.isChecked())
        s.setValue('reviewboard/repo_id', self.getRepoId())

        def itercombo(w):
            if w.currentText():
                yield w.currentText()
            for i in xrange(w.count()):
                if w.itemText(i) != w.currentText():
                    yield w.itemText(i)

        s.setValue('reviewboard/summary_edit_history',
                   list(itercombo(self.qui.summary_edit))[:10])

    def initChangesets(self, revs, selected_revs=None):
        def purerevs(revs):
            return scmutil.revrange(self.repo, iter(str(e) for e in revs))

        if selected_revs:
            selectedrevs = purerevs(selected_revs)
        else:
            selectedrevs = purerevs(revs)

        self._changesets = _ChangesetsModel(
            self.repo,
            # TODO: [':'] is inefficient
            revs=purerevs(revs or [':']),
            selectedrevs=selectedrevs,
            parent=self)

        self.qui.changesets_view.setModel(self._changesets)

    @property
    def selectedRevs(self):
        """Returns list of revisions to be sent"""
        return self._changesets.selectedrevs

    @property
    def allRevs(self):
        """Returns list of revisions to be sent"""
        return self._changesets.revs

    def getRepoId(self):
        comboText = self.qui.repo_id_combo.currentText().split(":")
        return str(comboText[0])

    def getReviewId(self):
        comboText = self.qui.review_id_combo.currentText().split(":")
        return str(comboText[0])

    def getSummary(self):
        comboText = self.qui.review_id_combo.currentText().split(":")
        return str(comboText[1])

    def postReviewOpts(self, **opts):
        """Generate opts for reviewboard by form values"""
        opts['outgoingchanges'] = self.qui.outgoing_changes_check.isChecked()
        opts['branch'] = self.qui.branch_check.isChecked()
        opts['publish'] = self.qui.publish_immediately_check.isChecked()

        if self.qui.tab_widget.currentIndex() == 1:
            opts["existing"] = self.getReviewId()
            opts['update'] = self.qui.update_fields.isChecked()
            opts['summary'] = self.getSummary()
        else:
            opts['repoid'] = self.getRepoId()
            opts['summary'] = hglib.fromunicode(
                self.qui.summary_edit.currentText())

        if (len(self.selectedRevs) > 1):
            #Set the parent to the revision below the last one on the list
            #so all checked revisions are included in the request
            opts['parent'] = str(self.selectedRevs[0] - 1)

        # Always use the upstream repo to determine the parent diff base
        # without the diff uploaded to review board dies
        opts['outgoing'] = True

        #Set the password just in  case the user has opted to not save it
        opts['password'] = str(self.password)

        #Finally we want to pass the repo path to the hg extension
        opts['repository'] = self.repo.root

        return opts

    def isValid(self):
        """Filled all required values?"""
        if not self.qui.repo_id_combo.currentText():
            return False

        if self.qui.tab_widget.currentIndex() == 1:
            if not self.qui.review_id_combo.currentText():
                return False

        if not self.allRevs:
            return False

        return True

    @pyqtSlot()
    def tabChanged(self):
        self.qui.post_review_button.setEnabled(self.isValid())

    @pyqtSlot()
    def branchCheckToggle(self):
        if self.qui.branch_check.isChecked():
            self.qui.outgoing_changes_check.setChecked(False)

        self.toggleOutgoingChangesets()

    @pyqtSlot()
    def outgoingChangesCheckToggle(self):
        if self.qui.outgoing_changes_check.isChecked():
            self.qui.branch_check.setChecked(False)

        self.toggleOutgoingChangesets()

    def toggleOutgoingChangesets(self):
        branch = self.qui.branch_check.isChecked()
        outgoing = self.qui.outgoing_changes_check.isChecked()
        if branch or outgoing:
            self.initChangesets(self.allRevs, [self.selectedRevs.pop()])
            self.qui.changesets_view.setEnabled(False)
        else:
            self.initChangesets(self.allRevs, self.allRevs)
            self.qui.changesets_view.setEnabled(True)

    def close(self):
        super(PostReviewDialog, self).close()

    def accept(self):
        if not self.isValid():
            return
        if not self.password and not self.passwordPrompt():
            return

        self.qui.progress_bar.show()
        self.qui.progress_label.setText("Posting Review...")
        self.qui.progress_label.show()

        def cmdargs(opts):
            args = []
            for k, v in opts.iteritems():
                if isinstance(v, bool):
                    if v:
                        args.append('--%s' % k.replace('_', '-'))
                else:
                    for e in isinstance(v, basestring) and [v] or v:
                        args += ['--%s' % k.replace('_', '-'), e]

            return args

        hglib.loadextension(self.ui, 'reviewboard')

        opts = self.postReviewOpts()

        revstr = str(self.selectedRevs.pop())

        self.qui.post_review_button.setEnabled(False)
        self.qui.close_button.setEnabled(False)

        self.cmd = cmdui.Runner(False, self)
        self.cmd.setTitle(_('Review Board'))
        self.cmd.commandFinished.connect(self.onCompletion)
        self.cmd.run(['postreview'] + cmdargs(opts) + [revstr])

    @pyqtSlot()
    def onCompletion(self):
        self.qui.progress_bar.hide()
        self.qui.progress_label.hide()

        output = self.cmd.core.rawoutput()

        saved = 'saved:' in output
        published = 'published:' in output
        if (saved or published):
            if saved:
                url = output.split('saved: ').pop().strip()
                msg = _('Review draft posted to %s\n') % url
            else:
                url = output.split('published: ').pop().strip()
                msg = _('Review published to %s\n') % url

            QDesktopServices.openUrl(QUrl(url))

            qtlib.InfoMsgBox(_('Review Board'), _('Success'), msg, parent=self)
        else:
            error = output.split('abort: ').pop().strip()
            if error[:29] == "HTTP Error: basic auth failed":
                if self.passwordPrompt():
                    self.accept()
                else:
                    self.qui.post_review_button.setEnabled(True)
                    self.qui.close_button.setEnabled(True)
                    return
            else:
                qtlib.ErrorMsgBox(_('Review Board'), _('Error'), error)

        self.writeSettings()
        super(PostReviewDialog, self).accept()

    @pyqtSlot()
    def onSettingsButtonClicked(self):
        from tortoisehg.hgqt import settings
        if settings.SettingsDialog(parent=self,
                                   focus='reviewboard.server').exec_():
            # not use repo.configChanged because it can clobber user input
            # accidentally.
            self.repo.invalidateui()  # force reloading config immediately
            self.readSettings()