Exemple #1
0
    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()
Exemple #2
0
 def accept(self):
     for root, path, status in thgrepo.recursiveMergeStatus(self.repo):
         if status == 'u':
             qtlib.InfoMsgBox(_('Merge caused file conflicts'),
                              _('File conflicts need to be resolved'))
             dlg = resolve.ResolveDialog(self._repoagent, self)
             dlg.finished.connect(dlg.deleteLater)
             dlg.exec_()
             break
     super(UpdateDialog, self).accept()
Exemple #3
0
def run(ui, *pats, **opts):
    from tortoisehg.util import paths
    repo = thgrepo.repository(ui, path=paths.find_root())
    if os.path.exists(repo.join('rebasestate')):
        qtlib.InfoMsgBox(_('Rebase already in progress'),
                          _('Resuming rebase already in progress'))
    elif not opts['source'] or not opts['dest']:
        qtlib.ErrorMsgBox(_('Abort'),
                          _('You must provide source and dest arguments'))
        import sys; sys.exit()
    return RebaseDialog(repo, None, **opts)
Exemple #4
0
def run(ui, *pats, **opts):
    from tortoisehg.util import paths
    rev = opts.get('rev') or None
    if not rev and len(pats):
        rev = pats[0]
    if not rev:
        import sys
        qtlib.InfoMsgBox(_('Unable to merge'),
                         _('Merge revision not specified or not found'))
        sys.exit()
    repo = thgrepo.repository(ui, path=paths.find_root())
    return MergeDialog(rev, repo, None)
Exemple #5
0
def rebase(ui, repoagent, *pats, **opts):
    """rebase dialog"""
    from tortoisehg.hgqt import rebase as rebasemod
    repo = repoagent.rawRepo()
    if os.path.exists(repo.join('rebasestate')):
        # TODO: move info dialog into RebaseDialog if possible
        qtlib.InfoMsgBox(
            hglib.tounicode(_('Rebase already in progress')),
            hglib.tounicode(_('Resuming rebase already in '
                              'progress')))
    elif not opts['source'] or not opts['dest']:
        raise util.Abort(_('You must provide source and dest arguments'))
    return rebasemod.RebaseDialog(repoagent, None, **opts)
Exemple #6
0
def run(ui, *revs, **opts):
    from tortoisehg.util import paths
    repo = thgrepo.repository(ui, path=paths.find_root())

    revs = list(revs)
    revs.extend(opts['rev'])

    if os.path.exists(repo.join('graftstate')):
        qtlib.InfoMsgBox(_('Graft already in progress'),
                          _('Resuming graft already in progress'))
    elif not revs:
        qtlib.ErrorMsgBox(_('Abort'),
                          _('You must provide revisions to graft'))
        import sys; sys.exit()
    return GraftDialog(repo, None, source=revs)
Exemple #7
0
 def getVdiffFiles(self, tree):
     paths = self.getSelectedPaths(tree)
     if not paths:
         return []
     files, sub = [], False
     for root, wfile in paths:
         if root == self.repo.root:
             files.append(wfile)
         else:
             sub = True
     if sub:
         qtlib.InfoMsgBox(_('Unable to show subrepository files'),
                 _('Visual diffs are not supported for files in '
                   'subrepositories. They will not be shown.'))
     return files
Exemple #8
0
 def removeFile(self, wfile):
     repo = self.repo
     ctx = self.ctx
     if isinstance(ctx, patchctx):
         repo.thgbackup(ctx._path)
         fp = util.atomictempfile(ctx._path, 'wb')
         try:
             if ctx._ph.comments:
                 fp.write('\n'.join(ctx._ph.comments))
                 fp.write('\n\n')
             for file in ctx._fileorder:
                 if file == wfile:
                     continue
                 for chunk in ctx._files[file]:
                     chunk.write(fp)
             fp.close()
         finally:
             del fp
         ctx.invalidate()
     else:
         fullpath = repo.wjoin(wfile)
         repo.thgbackup(fullpath)
         wasadded = wfile in repo[None].added()
         try:
             commands.revert(repo.ui,
                             repo,
                             fullpath,
                             rev='.',
                             no_backup=True)
             if wasadded and os.path.exists(fullpath):
                 os.unlink(fullpath)
         except EnvironmentError:
             qtlib.InfoMsgBox(
                 _("Unable to remove"),
                 _("Unable to remove file %s,\n"
                   "permission denied") % hglib.tounicode(wfile))
     self.fileModified.emit()
Exemple #9
0
    def initializePage(self):
        if self.layout():
            return
        self.setTitle(_('Prepare to backout'))
        self.setSubTitle(
            _('Verify backout revision and ensure your working '
              'directory is clean.'))
        self.setLayout(QVBoxLayout())

        self.groups = qtlib.WidgetGroups()

        repo = self.repo
        try:
            bctx = repo[self.wizard().backoutrev]
            pctx = repo['.']
        except error.RepoLookupError:
            qtlib.InfoMsgBox(_('Unable to backout'),
                             _('Backout revision not found'))
            QTimer.singleShot(0, self.wizard().close)
            return

        if pctx == bctx:
            lbl = _('Backing out a parent revision is a single step operation')
            self.layout().addWidget(QLabel(u'<b>%s</b>' % lbl))
            self.wizard().parentbackout = True

        op1, op2 = repo.dirstate.parents()
        if op1 is None:
            qtlib.InfoMsgBox(_('Unable to backout'),
                             _('Backout requires a parent revision'))
            QTimer.singleShot(0, self.wizard().close)
            return

        a = repo.changelog.ancestor(op1, bctx.node())
        if a != bctx.node():
            qtlib.InfoMsgBox(_('Unable to backout'),
                             _('Cannot backout change on a different branch'))
            QTimer.singleShot(0, self.wizard().close)

        ## backout revision
        style = csinfo.panelstyle(contents=csinfo.PANEL_DEFAULT)
        create = csinfo.factory(repo, None, style, withupdate=True)
        sep = qtlib.LabeledSeparator(_('Backout revision'))
        self.layout().addWidget(sep)
        backoutCsInfo = create(bctx.rev())
        self.layout().addWidget(backoutCsInfo)

        ## current revision
        contents = ('ishead', ) + csinfo.PANEL_DEFAULT
        style = csinfo.panelstyle(contents=contents)

        def markup_func(widget, item, value):
            if item == 'ishead' and value is False:
                text = _('Not a head, backout will create a new head!')
                return qtlib.markup(text, fg='red', weight='bold')
            raise csinfo.UnknownItem(item)

        custom = csinfo.custom(markup=markup_func)
        create = csinfo.factory(repo, custom, style, withupdate=True)

        sep = qtlib.LabeledSeparator(_('Current local revision'))
        self.layout().addWidget(sep)
        localCsInfo = create(pctx.rev())
        self.layout().addWidget(localCsInfo)
        self.localCsInfo = localCsInfo

        ## Merge revision backout handling
        if len(bctx.parents()) > 1:
            # Show two radio buttons letting the user which merge revision
            # parent to backout to
            p1rev = bctx.p1().rev()
            p2rev = bctx.p2().rev()

            def setBackoutMergeParentRev(rev):
                self.wizard().backoutmergeparentrev = rev

            setBackoutMergeParentRev(p1rev)

            sep = qtlib.LabeledSeparator(_('Merge parent to backout to'))
            self.layout().addWidget(sep)
            self.layout().addWidget(
                QLabel(
                    _('To backout a <b>merge</b> revision you must select which '
                      'parent to backout to '
                      '(i.e. whose changes will be <i>kept</i>)')))

            self.actionFirstParent = QRadioButton(
                _('First Parent: revision %s (%s)') \
                % (p1rev, str(bctx.p1())), self)
            self.actionFirstParent.setCheckable(True)
            self.actionFirstParent.setChecked(True)
            self.actionFirstParent.setShortcut('CTRL+1')
            self.actionFirstParent.setToolTip(
                _('Backout to the first parent of the merge revision'))
            self.actionFirstParent.clicked.connect(
                lambda: setBackoutMergeParentRev(p1rev))

            self.actionSecondParent = QRadioButton(
                _('Second Parent: revision %s (%s)') % (p2rev, str(bctx.p2())),
                self)
            self.actionSecondParent.setCheckable(True)
            self.actionSecondParent.setShortcut('CTRL+2')
            self.actionSecondParent.setToolTip(
                _('Backout to the second parent of the merge revision'))
            self.actionSecondParent.clicked.connect(
                lambda: setBackoutMergeParentRev(p2rev))

            self.layout().addWidget(self.actionFirstParent)
            self.layout().addWidget(self.actionSecondParent)

        ## working directory status
        sep = qtlib.LabeledSeparator(_('Working directory status'))
        self.layout().addWidget(sep)

        wdbox = QHBoxLayout()
        self.layout().addLayout(wdbox)
        self.wd_status = qtlib.StatusLabel()
        self.wd_status.set_status(_('Checking...'))
        wdbox.addWidget(self.wd_status)
        wd_prog = QProgressBar()
        wd_prog.setMaximum(0)
        wd_prog.setTextVisible(False)
        self.groups.add(wd_prog, 'prog')
        wdbox.addWidget(wd_prog, 1)

        text = _(
            'Before backout, you must <a href="commit"><b>commit</b></a>, '
            '<a href="shelve"><b>shelve</b></a> to patch, '
            'or <a href="discard"><b>discard</b></a> changes.')
        wd_text = QLabel(text)
        wd_text.setWordWrap(True)
        wd_text.linkActivated.connect(self.onLinkActivated)
        self.wd_text = wd_text
        self.groups.add(wd_text, 'dirty')
        self.layout().addWidget(wd_text)

        ## auto-resolve
        autoresolve_chk = QCheckBox(
            _('Automatically resolve merge conflicts '
              'where possible'))
        autoresolve_chk.setChecked(
            repo.ui.configbool('tortoisehg', 'autoresolve', False))
        self.registerField('autoresolve', autoresolve_chk)
        self.layout().addWidget(autoresolve_chk)
        self.autoresolve_chk = autoresolve_chk
        self.groups.set_visible(False, 'dirty')
Exemple #10
0
    def mergeChunks(self, wfile, chunks):
        def isAorR(header):
            for line in header:
                if line.startswith('--- /dev/null'):
                    return True
                if line.startswith('+++ /dev/null'):
                    return True
            return False

        repo = self.repo
        ctx = self.ctx
        if isinstance(ctx, patchctx):
            if wfile in ctx._files:
                patchchunks = ctx._files[wfile]
                if isAorR(chunks[0].header) or isAorR(patchchunks[0].header):
                    qtlib.InfoMsgBox(
                        _('Unable to merge chunks'),
                        _('Add or remove patches must be merged '
                          'in the working directory'))
                    return False
                # merge new chunks into existing chunks, sorting on start line
                newchunks = [chunks[0]]
                pidx = nidx = 1
                while pidx < len(patchchunks) or nidx < len(chunks):
                    if pidx == len(patchchunks):
                        newchunks.append(chunks[nidx])
                        nidx += 1
                    elif nidx == len(chunks):
                        newchunks.append(patchchunks[pidx])
                        pidx += 1
                    elif chunks[nidx].fromline < patchchunks[pidx].fromline:
                        newchunks.append(chunks[nidx])
                        nidx += 1
                    else:
                        newchunks.append(patchchunks[pidx])
                        pidx += 1
                ctx._files[wfile] = newchunks
            else:
                # add file to patch
                ctx._files[wfile] = chunks
                ctx._fileorder.append(wfile)
            repo.thgbackup(ctx._path)
            fp = util.atomictempfile(ctx._path, 'wb')
            try:
                if ctx._ph.comments:
                    fp.write('\n'.join(ctx._ph.comments))
                    fp.write('\n\n')
                for file in ctx._fileorder:
                    for chunk in ctx._files[file]:
                        chunk.write(fp)
                fp.close()
                ctx.invalidate()
                self.fileModified.emit()
                return True
            finally:
                del fp
        else:
            # Apply chunks to wfile
            repo.thgbackup(repo.wjoin(wfile))
            fp = cStringIO.StringIO()
            for c in chunks:
                c.write(fp)
            fp.seek(0)
            wlock = repo.wlock()
            try:
                return self.runPatcher(fp, wfile, True)
            finally:
                wlock.release()
Exemple #11
0
            qtlib.ErrorMsgBox(_('Error executing init'),
                    _('Error when creating repository'),
                    traceback.format_exc())
            return False

        # Create the .hg* file, mainly to workaround
        # Explorer's problem in creating files with a name
        # beginning with a dot.
        if (self.add_files_chk.isChecked() and
                os.path.exists(os.path.sep.join([dest, '.hg']))):
            hgignore = os.path.join(dest, '.hgignore')
            if not os.path.exists(hgignore):
                try:
                    open(hgignore, 'wb')
                except:
                    pass

        if self.run_wb_chk.isChecked():
            # TODO: implement by using signal-slot if possible
            from tortoisehg.hgqt import run
            run.qtrun.showRepoInWorkbench(udest)
        else:
            if not self.parent():
                qtlib.InfoMsgBox(_('Init'),
                _('<p>Repository successfully created at</p><p>%s</p>') % udest)

        self.accept()

    def reject(self):
        super(InitDialog, self).reject()
Exemple #12
0
    def initializePage(self):
        if self.layout():
            return
        self.setTitle(_('Prepare to merge'))
        self.setSubTitle(
            _('Verify merge targets and ensure your working '
              'directory is clean.'))
        self.setLayout(QVBoxLayout())

        repo = self.repo
        contents = ('ishead', ) + csinfo.PANEL_DEFAULT
        style = csinfo.panelstyle(contents=contents)

        def markup_func(widget, item, value):
            if item == 'ishead' and value is False:
                text = _('Not a head revision!')
                return qtlib.markup(text, fg='red', weight='bold')
            raise csinfo.UnknownItem(item)

        custom = csinfo.custom(markup=markup_func)
        create = csinfo.factory(repo, custom, style, withupdate=True)

        ## merge target
        other_sep = qtlib.LabeledSeparator(_('Merge from (other revision)'))
        self.layout().addWidget(other_sep)
        try:
            otherCsInfo = create(self.wizard().otherrev)
            self.layout().addWidget(otherCsInfo)
            self.otherCsInfo = otherCsInfo
        except error.RepoLookupError:
            qtlib.InfoMsgBox(_('Unable to merge'),
                             _('Merge revision not specified or not found'))
            QTimer.singleShot(0, self.wizard().close)

        ## current revision
        local_sep = qtlib.LabeledSeparator(_('Merge to (working directory)'))
        self.layout().addWidget(local_sep)
        localCsInfo = create(self.wizard().localrev)
        self.layout().addWidget(localCsInfo)
        self.localCsInfo = localCsInfo

        ## working directory status
        wd_sep = qtlib.LabeledSeparator(_('Working directory status'))
        self.layout().addWidget(wd_sep)

        self.groups = qtlib.WidgetGroups()

        wdbox = QHBoxLayout()
        self.layout().addLayout(wdbox)
        self.wd_status = qtlib.StatusLabel()
        self.wd_status.set_status(_('Checking...'))
        wdbox.addWidget(self.wd_status)
        wd_prog = QProgressBar()
        wd_prog.setMaximum(0)
        wd_prog.setTextVisible(False)
        self.groups.add(wd_prog, 'prog')
        wdbox.addWidget(wd_prog, 1)

        wd_merged = QLabel(
            _('The working directory is already <b>merged</b>. '
              '<a href="skip"><b>Continue</b></a> or '
              '<a href="discard"><b>discard</b></a> existing '
              'merge.'))
        wd_merged.linkActivated.connect(self.onLinkActivated)
        wd_merged.setWordWrap(True)
        self.groups.add(wd_merged, 'merged')
        self.layout().addWidget(wd_merged)

        text = _(
            'Before merging, you must <a href="commit"><b>commit</b></a>, '
            '<a href="shelve"><b>shelve</b></a> to patch, '
            'or <a href="discard"><b>discard</b></a> changes.')
        wd_text = QLabel(text)
        wd_text.setWordWrap(True)
        wd_text.linkActivated.connect(self.onLinkActivated)
        self.wd_text = wd_text
        self.groups.add(wd_text, 'dirty')
        self.layout().addWidget(wd_text)

        wdbox = QHBoxLayout()
        self.layout().addLayout(wdbox)
        wd_alt = QLabel(_('Or use:'))
        self.groups.add(wd_alt, 'dirty')
        wdbox.addWidget(wd_alt)
        force_chk = QCheckBox(
            _('Force a merge with outstanding changes '
              '(-f/--force)'))
        force_chk.toggled.connect(lambda c: self.completeChanged.emit())
        self.registerField('force', force_chk)
        self.groups.add(force_chk, 'dirty')
        wdbox.addWidget(force_chk)

        ### options
        expander = qtlib.ExpanderLabel(_('Options'), False)
        expander.expanded.connect(self.toggleShowOptions)
        self.layout().addWidget(expander)
        self.expander = expander

        ### discard option
        discard_chk = QCheckBox(
            _('Discard all changes from merge target '
              '(other) revision'))
        self.registerField('discard', discard_chk)
        self.layout().addWidget(discard_chk)
        self.discard_chk = discard_chk

        ## auto-resolve
        autoresolve_chk = QCheckBox(
            _('Automatically resolve merge conflicts '
              'where possible'))
        autoresolve_chk.setChecked(
            repo.ui.configbool('tortoisehg', 'autoresolve', False))
        self.registerField('autoresolve', autoresolve_chk)
        self.layout().addWidget(autoresolve_chk)
        self.autoresolve_chk = autoresolve_chk

        self.groups.set_visible(False, 'dirty')
        self.groups.set_visible(False, 'merged')
        self.toggleShowOptions(self.expander.is_expanded())
Exemple #13
0
    def addSubrepo(self):
        'menu action handler for adding a new subrepository'
        root = hglib.tounicode(self.selitem.internalPointer().rootpath())
        caption = _('Select an existing repository to add as a subrepo')
        FD = QFileDialog
        path = unicode(
            FD.getExistingDirectory(caption=caption,
                                    directory=root,
                                    options=FD.ShowDirsOnly | FD.ReadOnly))
        if path:
            path = os.path.normpath(path)
            sroot = paths.find_root(path)

            root = os.path.normcase(os.path.normpath(root))

            if not sroot:
                qtlib.WarningMsgBox(_('Cannot add subrepository'),
                                    _('%s is not a valid repository') % path,
                                    parent=self)
                return
            elif not os.path.isdir(sroot):
                qtlib.WarningMsgBox(_('Cannot add subrepository'),
                                    _('"%s" is not a folder') % sroot,
                                    parent=self)
                return
            elif os.path.normcase(sroot) == root:
                qtlib.WarningMsgBox(
                    _('Cannot add subrepository'),
                    _('A repository cannot be added as a subrepo of itself'),
                    parent=self)
                return
            elif root != paths.find_root(
                    os.path.dirname(os.path.normcase(path))):
                qtlib.WarningMsgBox(
                    _('Cannot add subrepository'),
                    _('The selected folder:<br><br>%s<br><br>'
                      'is not inside the target repository.<br><br>'
                      'This may be allowed but is greatly discouraged.<br>'
                      'If you want to add a non trivial subrepository mapping '
                      'you must manually edit the <i>.hgsub</i> file') % root,
                    parent=self)
                return
            else:
                # The selected path is the root of a repository that is inside
                # the selected repository

                # Use forward slashes for relative subrepo root paths
                srelroot = sroot[len(root) + 1:]
                srelroot = util.pconvert(srelroot)

                # Is is already on the selected repository substate list?
                try:
                    repo = hg.repository(ui.ui(), hglib.fromunicode(root))
                except:
                    qtlib.WarningMsgBox(
                        _('Cannot open repository'),
                        _('The selected repository:<br><br>%s<br><br>'
                          'cannot be open!') % root,
                        parent=self)
                    return

                if hglib.fromunicode(srelroot) in repo['.'].substate:
                    qtlib.WarningMsgBox(
                        _('Subrepository already exists'),
                        _('The selected repository:<br><br>%s<br><br>'
                          'is already a subrepository of:<br><br>%s<br><br>'
                          'as: "%s"') % (sroot, root, srelroot),
                        parent=self)
                    return
                else:
                    # Already a subrepo!

                    # Read the current .hgsub file contents
                    lines = []
                    hasHgsub = os.path.exists(repo.wjoin('.hgsub'))
                    if hasHgsub:
                        try:
                            fsub = repo.wopener('.hgsub', 'r')
                            lines = fsub.readlines()
                            fsub.close()
                        except:
                            qtlib.WarningMsgBox(
                                _('Failed to add subrepository'),
                                _('Cannot open the .hgsub file in:<br><br>%s') \
                                % root, parent=self)
                            return

                    # Make sure that the selected subrepo (or one of its
                    # subrepos!) is not already on the .hgsub file
                    linesep = ''
                    for line in lines:
                        line = hglib.tounicode(line)
                        spath = line.split("=")[0].strip()
                        if not spath:
                            continue
                        if not linesep:
                            linesep = hglib.getLineSeparator(line)
                        spath = util.pconvert(spath)
                        if line.startswith(srelroot):
                            qtlib.WarningMsgBox(
                                _('Failed to add repository'),
                                _('The .hgsub file already contains the '
                                  'line:<br><br>%s') % line,
                                parent=self)
                            return
                    if not linesep:
                        linesep = os.linesep

                    # Append the new subrepo to the end of the .hgsub file
                    lines.append(
                        hglib.fromunicode('%s = %s' % (srelroot, srelroot)))
                    lines = [line.strip(linesep) for line in lines]

                    # and update the .hgsub file
                    try:
                        fsub = repo.wopener('.hgsub', 'w')
                        fsub.write(linesep.join(lines) + linesep)
                        fsub.close()
                        if not hasHgsub:
                            commands.add(ui.ui(), repo, repo.wjoin('.hgsub'))
                        qtlib.InfoMsgBox(
                            _('Subrepo added to .hgsub file'),
                            _('The selected subrepo:<br><br><i>%s</i><br><br>'
                            'has been added to the .hgsub file of the repository:<br><br><i>%s</i><br><br>'
                            'Remember that in order to finish adding the '
                            'subrepo <i>you must still <u>commit</u></i> the '
                            'changes to the .hgsub file in order to confirm '
                            'the addition of the subrepo.') \
                            % (srelroot, root), parent=self)
                    except:
                        qtlib.WarningMsgBox(
                            _('Failed to add repository'),
                            _('Cannot update the .hgsub file in:<br><br>%s') \
                            % root, parent=self)
                return