Mercurial and Git clients can push and pull from this alias URL to interact with this repository. You can change to which repository an alias points by going to the Aliases link on the project page.
# backout.py - Backout dialog for TortoiseHg## Copyright 2010 Yuki KODAMA <endflow.net@gmail.com>## This software may be used and distributed according to the terms of the# GNU General Public License version 2, incorporated herein by reference.frommercurialimporthg,mergeasmergemodfromtortoisehg.utilimporthglibfromtortoisehg.hgqt.i18nimport_fromtortoisehg.hgqtimportqtlib,csinfo,i18n,cmdui,status,resolvefromtortoisehg.hgqtimportcommit,qscilib,thgrepofromPyQt4.QtCoreimport*fromPyQt4.QtGuiimport*classBackoutDialog(QWizard):def__init__(self,rev,repo,parent):super(BackoutDialog,self).__init__(parent)f=self.windowFlags()self.setWindowFlags(f&~Qt.WindowContextHelpButtonHint)self.backoutrev=revself.parentbackout=Falseself.setWindowTitle(_('Backout - %s')%repo.displayname)self.setWindowIcon(qtlib.geticon('hg-revert'))self.setOption(QWizard.NoBackButtonOnStartPage,True)self.setOption(QWizard.NoBackButtonOnLastPage,True)self.setOption(QWizard.IndependentPages,True)self.addPage(SummaryPage(repo,self))self.addPage(BackoutPage(repo,self))self.addPage(CommitPage(repo,self))self.addPage(ResultPage(repo,self))self.currentIdChanged.connect(self.pageChanged)self.resize(QSize(700,489).expandedTo(self.minimumSizeHint()))repo.repositoryChanged.connect(self.repositoryChanged)repo.configChanged.connect(self.configChanged)defrepositoryChanged(self):self.currentPage().repositoryChanged()defconfigChanged(self):self.currentPage().configChanged()defpageChanged(self,id):ifid!=-1:self.currentPage().currentPage()defreject(self):ifself.currentPage().canExit():super(BackoutDialog,self).reject()classBasePage(QWizardPage):def__init__(self,repo,parent):super(BasePage,self).__init__(parent)self.repo=repodefvalidatePage(self):'user pressed NEXT button, can we proceed?'returnTruedefisComplete(self):'should NEXT button be sensitive?'returnTruedefrepositoryChanged(self):'repository has detected a change to changelog or parents'passdefconfigChanged(self):'repository has detected a change to config files'passdefcurrentPage(self):passdefcanExit(self):returnTrueclassSummaryPage(BasePage):def__init__(self,repo,parent):super(SummaryPage,self).__init__(repo,parent)self.clean=Falseself.th=NonedefinitializePage(self):ifself.layout():returnself.setTitle(_('Prepare to backout'))self.setSubTitle(_('Verify backout revision and ensure your working ''directory is clean.'))self.setLayout(QVBoxLayout())repo=self.repotry:bctx=repo[self.wizard().backoutrev]pctx=repo['.']excepterror.RepoLookupError:qtlib.InfoMsgBox(_('Unable to backout'),_('Backout revision not found'))QTimer.singleShot(0,self.wizard().close)ifpctx==bctx:lbl=_('Backing out a parent revision is a single step operation')self.layout().addWidget(QLabel(u'<b>%s</b>'%lbl))self.wizard().parentbackout=Trueop1,op2=repo.dirstate.parents()a=repo.changelog.ancestor(op1,bctx.node())ifa!=bctx.node():qtlib.InfoMsgBox(_('Unable to backout'),_('Cannot backout change on a different branch'))QTimer.singleShot(0,self.wizard().close)## backout revisionstyle=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 revisioncontents=('ishead',)+csinfo.PANEL_DEFAULTstyle=csinfo.panelstyle(contents=contents)defmarkup_func(widget,item,value):ifitem=='ishead'andvalueisFalse:text=_('Not a head, backout will create a new head!')returnqtlib.markup(text,fg='red',weight='bold')raisecsinfo.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## working directory statussep=qtlib.LabeledSeparator(_('Working directory status'))self.layout().addWidget(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)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_textself.groups.add(wd_text,'dirty')self.layout().addWidget(wd_text)## auto-resolveautoresolve_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_chkself.groups.set_visible(False,'dirty')defisComplete(self):'should Next button be sensitive?'returnself.cleandefrepositoryChanged(self):'repository has detected a change to changelog or parents'pctx=self.repo['.']self.localCsInfo.update(pctx)self.wizard().localrev=str(pctx.rev())defcanExit(self):'can backout tool be closed?'ifself.thisnotNoneandself.th.isRunning():self.th.cancel()self.th.wait()returnTruedefcurrentPage(self):self.refresh()defrefresh(self):ifself.thisNone:self.th=CheckThread(self.repo,self)self.th.finished.connect(self.threadFinished)ifself.th.isRunning():returnself.groups.set_visible(True,'prog')self.th.start()defthreadFinished(self):self.groups.set_visible(False,'prog')ifself.th.canceled:returndirty,parents=self.th.resultsself.clean=notdirtyifdirty:self.groups.set_visible(True,'dirty')self.wd_status.set_status(_('<b>Uncommitted local changes ''are detected</b>'),'thg-warning')else:self.groups.set_visible(False,'dirty')self.wd_status.set_status(_('Clean'),True)self.completeChanged.emit()@pyqtSlot(QString)defonLinkActivated(self,cmd):cmd=hglib.fromunicode(cmd)repo=self.repoifcmd=='commit':dlg=commit.CommitDialog(repo,[],{},self.wizard())dlg.finished.connect(dlg.deleteLater)dlg.exec_()self.refresh()elifcmd=='shelve':fromtortoisehg.hgqtimportshelvedlg=shelve.ShelveDialog(repo,self.wizard())dlg.finished.connect(dlg.deleteLater)dlg.exec_()self.refresh()elifcmd.startswith('discard'):ifcmd!='discard:noconfirm':labels=[(QMessageBox.Yes,_('&Discard')),(QMessageBox.No,_('Cancel'))]ifnotqtlib.QuestionMsgBox(_('Confirm Discard'),_('Discard outstanding changes to working directory?'),labels=labels,parent=self):returndeffinished(ret):repo.decrementBusyCount()self.refresh()cmdline=['update','--clean','--repository',repo.root,'--rev','.']self.runner=cmdui.Runner(True,self)self.runner.commandFinished.connect(finished)repo.incrementBusyCount()self.runner.run(cmdline)elifcmd=='view':dlg=status.StatusDialog(repo,[],{},self)dlg.exec_()self.refresh()else:raise'unknown command: %s'%cmdclassBackoutPage(BasePage):def__init__(self,repo,parent):super(BackoutPage,self).__init__(repo,parent)self.backoutcomplete=Falseself.setTitle(_('Backing out, then merging...'))self.setSubTitle(_('All conflicting files will be marked unresolved.'))self.setLayout(QVBoxLayout())self.cmd=cmdui.Widget(True,False,self)self.cmd.commandFinished.connect(self.onCommandFinished)self.cmd.setShowOutput(True)self.layout().addWidget(self.cmd)self.reslabel=QLabel()self.reslabel.linkActivated.connect(self.onLinkActivated)self.reslabel.setWordWrap(True)self.layout().addWidget(self.reslabel)self.autonext=QCheckBox(_('Automatically advance to next page ''when backout and merge are complete.'))checked=QSettings().value('backout/autoadvance',False).toBool()self.autonext.setChecked(checked)self.autonext.toggled.connect(self.tryAutoAdvance)self.layout().addWidget(self.autonext)defcurrentPage(self):ifself.wizard().parentbackout:self.wizard().next()returncmdline=['--repository',self.repo.root,'backout']tool=self.field('autoresolve').toBool()and'merge'or'fail'cmdline+=['--tool=internal:'+tool]cmdline+=['--rev',str(self.wizard().backoutrev)]self.repo.incrementBusyCount()self.cmd.core.clearOutput()self.cmd.run(cmdline)defisComplete(self):'should Next button be sensitive?'ifnotself.backoutcomplete:returnFalsecount=0forroot,path,statusinthgrepo.recursiveMergeStatus(self.repo):ifstatus=='u':count+=1ifcount:# if autoresolve is enabled, we know these were real conflictsself.reslabel.setText(_('%d files have <b>merge conflicts</b> ''that must be <a href="resolve">''<b>resolved</b></a>')%count)returnFalseelse:self.reslabel.setText(_('No merge conflicts, ready to commit'))returnTruedeftryAutoAdvance(self,checked):ifcheckedandself.isComplete():self.wizard().next()defcleanupPage(self):QSettings().setValue('backout/autoadvance',self.autonext.isChecked())defonCommandFinished(self,ret):self.repo.decrementBusyCount()ifretin(0,1):self.backoutcomplete=Trueifself.autonext.isChecked():self.tryAutoAdvance(True)self.completeChanged.emit()@pyqtSlot(QString)defonLinkActivated(self,cmd):ifcmd=='resolve':dlg=resolve.ResolveDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()ifself.autonext.isChecked():self.tryAutoAdvance(True)self.completeChanged.emit()classCommitPage(BasePage):def__init__(self,repo,parent):super(CommitPage,self).__init__(repo,parent) self.commitComplete = False
self.setTitle(_('Commit backout and merge results'))
+ self.setSubTitle(' ') self.setLayout(QVBoxLayout())
self.setCommitPage(True)
# csinfodeflabel_func(widget,item,ctx):ifitem=='rev':return_('Revision:')elifitem=='parents':return_('Parents')raisecsinfo.UnknownItem()defdata_func(widget,item,ctx):ifitem=='rev':return_('Working Directory'),str(ctx)elifitem=='parents':parents=[]cbranch=ctx.branch()forpctxinctx.parents():branch=Noneifhasattr(pctx,'branch')andpctx.branch()!=cbranch:branch=pctx.branch()parents.append((str(pctx.rev()),str(pctx),branch,pctx))returnparentsraisecsinfo.UnknownItem()defmarkup_func(widget,item,value):ifitem=='rev':text,rev=valueifself.wizard()andself.wizard().parentbackout:return'%s (%s)'%(text,rev)else:return'<a href="view">%s</a> (%s)'%(text,rev)elifitem=='parents':defbranch_markup(branch):opts=dict(fg='black',bg='#aaffaa')returnqtlib.markup(' %s '%branch,**opts)csets=[]forrnum,rid,branch,pctxinvalue:line='%s (%s)'%(rnum,rid)ifbranch:line='%s%s'%(line,branch_markup(branch))msg=widget.info.get_data('summary',widget,pctx,widget.custom)ifmsg:line='%s%s'%(line,msg)csets.append(line)returncsetsraisecsinfo.UnknownItem()custom=csinfo.custom(label=label_func,data=data_func,markup=markup_func)contents=('rev','user','dateage','branch','parents')style=csinfo.panelstyle(contents=contents,margin=6)# merged filesrev_sep=qtlib.LabeledSeparator(_('Working Directory (merged)'))self.layout().addWidget(rev_sep)bkCsInfo=csinfo.create(repo,None,style,custom=custom,withupdate=True)bkCsInfo.linkActivated.connect(self.onLinkActivated)self.layout().addWidget(bkCsInfo)# commit message areamsg_sep=qtlib.LabeledSeparator(_('Commit message'))self.layout().addWidget(msg_sep)msgEntry=commit.MessageEntry(self)msgEntry.installEventFilter(qscilib.KeyPressInterceptor(self))msgEntry.refresh(repo)msgEntry.loadSettings(QSettings(),'backout/message')msgEntry.textChanged.connect(self.completeChanged)self.layout().addWidget(msgEntry)self.msgEntry=msgEntryself.cmd=cmdui.Widget(True,False,self)self.cmd.commandFinished.connect(self.onCommandFinished)self.cmd.setShowOutput(False)self.layout().addWidget(self.cmd)deftryperform():ifself.isComplete():self.wizard().next()actionEnter=QAction('alt-enter',self)actionEnter.setShortcuts([Qt.CTRL+Qt.Key_Return,Qt.CTRL+Qt.Key_Enter])actionEnter.triggered.connect(tryperform)self.addAction(actionEnter)self.skiplast=QCheckBox(_('Skip final confirmation page, ''close after commit.'))checked=QSettings().value('backout/skiplast',False).toBool()self.skiplast.setChecked(checked)self.layout().addWidget(self.skiplast)defrefresh(self):passdefcleanupPage(self):s=QSettings()s.setValue('backout/skiplast',self.skiplast.isChecked())self.msgEntry.saveSettings(s,'backout/message')defcurrentPage(self):engmsg=self.repo.ui.configbool('tortoisehg','engmsg',False)msgset=i18n.keepgettext()._('Backed out changeset: ')msg=engmsgandmsgset['id']ormsgset['str']self.msgEntry.setText(msg+str(self.repo[self.wizard().backoutrev]))self.msgEntry.moveCursorToEnd()@pyqtSlot(QString)defonLinkActivated(self,cmd):ifcmd=='view':dlg=status.StatusDialog(self.repo,[],{},self)dlg.exec_()self.refresh()defisComplete(self):returnlen(self.msgEntry.text())>0defvalidatePage(self):ifself.commitComplete:# commit succeeded, repositoryChanged() called wizard().next()ifself.skiplast.isChecked():self.wizard().close()returnTrueifself.cmd.core.running():returnFalseuser=qtlib.getCurrentUsername(self,self.repo)ifnotuser:returnFalseifself.wizard().parentbackout:self.setTitle(_('Backing out and committing...'))self.setSubTitle(_('Please wait while making backout.'))message=hglib.fromunicode(self.msgEntry.text())cmdline=['backout','--verbose','--message',message,'--rev',str(self.wizard().backoutrev),'--user',user,'--repository',self.repo.root]else:self.setTitle(_('Committing...'))self.setSubTitle(_('Please wait while committing merged files.'))message=hglib.fromunicode(self.msgEntry.text())cmdline=['commit','--verbose','--message',message,'--repository',self.repo.root,'--user',user]commandlines=[cmdline]pushafter=self.repo.ui.config('tortoisehg','cipushafter')ifpushafter:cmd=['push','--repository',self.repo.root,pushafter]commandlines.append(cmd)self.repo.incrementBusyCount()self.cmd.setShowOutput(True)self.cmd.run(*commandlines)returnFalsedefonCommandFinished(self,ret):self.repo.decrementBusyCount()ifret==0:self.commitComplete=Trueself.wizard().next()classResultPage(BasePage):def__init__(self,repo,parent):super(ResultPage,self).__init__(repo,parent)self.setTitle(_('Finished'))self.setFinalPage(True)self.setLayout(QVBoxLayout())sep=qtlib.LabeledSeparator(_('Backout changeset'))self.layout().addWidget(sep)bkCsInfo=csinfo.create(self.repo,'tip',withupdate=True)self.layout().addWidget(bkCsInfo)self.bkCsInfo=bkCsInfoself.layout().addStretch(1)defcurrentPage(self):self.bkCsInfo.update(self.repo['tip'])self.wizard().setOption(QWizard.NoCancelButton,True)classCheckThread(QThread):def__init__(self,repo,parent):QThread.__init__(self,parent)self.repo=hg.repository(repo.ui,repo.root)self.results=(False,1)self.canceled=Falsedefrun(self):self.repo.dirstate.invalidate()unresolved=Falseforroot,path,statusinthgrepo.recursiveMergeStatus(self.repo):ifself.canceled:returnifstatus=='u':unresolved=Truebreakwctx=self.repo[None]dirty=bool(wctx.dirty())orunresolvedself.results=(dirty,len(wctx.parents()))defcancel(self):self.canceled=Truedefrun(ui,*pats,**opts):fromtortoisehg.utilimportpathsrepo=thgrepo.repository(ui,path=paths.find_root())ifopts.get('rev'):rev=opts.get('rev')eliflen(pats)==1:rev=pats[0]returnBackoutDialog(rev,repo,None)
Attach a Trello Card
Add a tag
Your session has expired
You are no longer logged in. Please log in and try your request again.
Filter RSS Feed
This RSS feed URL allows you to see the contents of your current filter using any feed reader.
This link includes a special authentication token. If you share the URL with anyone else, they can see this RSS feed's activity. You can disable these tokens when needed.
Your current filter is unsaved; changing it won't affect this RSS feed.