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.
repowidget: do not connect commitComplete to self.reload anymore
Because the repowidget is connected to repositoryChanged signals, it gets notified of commits as soon as they happen. This extra signal was leading to a double refresh and the second refresh was set to reload the graph to -1 which caused the entire changelog graph to be loaded and for columns to shift around.
# repowidget.py - TortoiseHg repository widget## Copyright (C) 2007-2010 Logilab. All rights reserved.# Copyright (C) 2010 Adrian Buehlmann <adrian@cadifra.com>## This software may be used and distributed according to the terms# of the GNU General Public License, incorporated herein by reference.importbinasciiimportosfrommercurialimportutil,revsetfromtortoisehg.utilimportshlib,hglibfromtortoisehg.hgqt.i18nimport_fromtortoisehg.hgqt.qtlibimportgeticon,getfont,QuestionMsgBox,InfoMsgBoxfromtortoisehg.hgqt.qtlibimportCustomPrompt,SharedWidget,DemandWidgetfromtortoisehg.hgqt.repomodelimportHgRepoListModelfromtortoisehg.hgqtimportcmdui,update,tag,backout,merge,visdifffromtortoisehg.hgqtimportarchive,thgimport,thgstrip,run,purge,bookmarkfromtortoisehg.hgqtimportbisect,rebase,resolve,thgrepo,compressfromtortoisehg.hgqtimportqdelete,qreorder,qrename,qfoldfromtortoisehg.hgqt.repofilterimportRepoFilterBarfromtortoisehg.hgqt.repoviewimportHgRepoViewfromtortoisehg.hgqt.revdetailsimportRevDetailsWidgetfromtortoisehg.hgqt.commitimportCommitWidgetfromtortoisehg.hgqt.manifestdialogimportManifestTaskWidgetfromtortoisehg.hgqt.syncimportSyncWidgetfromtortoisehg.hgqt.grepimportSearchWidgetfromtortoisehg.hgqt.quickbarimportGotoQuickBarfromtortoisehg.hgqt.pbranchimportPatchBranchWidgetfromPyQt4.QtCoreimport*fromPyQt4.QtGuiimport*classRepoWidget(QWidget):showMessageSignal=pyqtSignal(QString)closeSelfSignal=pyqtSignal(QWidget)output=pyqtSignal(QString,QString)progress=pyqtSignal(QString,object,QString,QString,object)makeLogVisible=pyqtSignal(bool)revisionSelected=pyqtSignal(object)titleChanged=pyqtSignal(unicode)"""Emitted when changed the expected title for the RepoWidget tab"""repoLinkClicked=pyqtSignal(unicode)"""Emitted when clicked a link to open repository"""singlecmenu=Noneunappcmenu=Nonepaircmenu=Nonemulticmenu=Nonedef__init__(self,repo,parent=None):QWidget.__init__(self,parent,acceptDrops=True)self.repo=reporepo.repositoryChanged.connect(self.repositoryChanged)repo.repositoryDestroyed.connect(self.repositoryDestroyed)repo.configChanged.connect(self.configChanged)self.revsetfilter=Falseself.branch=''self.bundle=Noneself.revset=set()ifrepo.parents()[0].rev()==-1:self._reload_rev='tip'else:self._reload_rev='.'self.currentMessage=''self.runner=Noneself.dirty=Falseself.setupUi()self.createActions()self.restoreSettings()self.setupModels()defsetupUi(self):SP=QSizePolicyself.repotabs_splitter=QSplitter(orientation=Qt.Vertical)self.setLayout(QVBoxLayout())self.layout().setContentsMargins(0,0,0,0)self.layout().setSpacing(0)hbox=QHBoxLayout()hbox.setContentsMargins(0,0,0,0)hbox.setSpacing(0)self.layout().addLayout(hbox)self.gototb=tb=GotoQuickBar(self)tb.setObjectName('gototb')tb.gotoSignal.connect(self.goto)hbox.addWidget(tb)self.bundleAccept=b=QPushButton(_('Accept'))b.setShown(False)b.setToolTip(_('Pull incoming changesets into your repository'))b.clicked.connect(self.acceptBundle)hbox.addWidget(b)self.bundleReject=b=QPushButton(_('Reject'))b.setToolTip(_('Reject incoming changesets'))b.clicked.connect(self.rejectBundle)b.setShown(False)hbox.addWidget(b)self.filterbar=RepoFilterBar(self.repo,self)self.filterbar.branchChanged.connect(self.setBranch)self.filterbar.progress.connect(self.progress)self.filterbar.showMessage.connect(self.showMessage)self.filterbar.revisionSet.connect(self.setRevisionSet)self.filterbar.clearSet.connect(self.clearSet)self.filterbar.filterToggled.connect(self.filterToggled)hbox.addWidget(self.filterbar)self.filterbar.hide()self.revsetfilter=self.filterbar.filtercb.isChecked()self.layout().addWidget(self.repotabs_splitter)self.repoview=view=HgRepoView(self.repo,self)view.revisionSelected.connect(self.revision_selected)view.revisionClicked.connect(self.revision_clicked)view.revisionActivated.connect(self.revision_activated)view.showMessage.connect(self.showMessage)view.menuRequested.connect(self.viewMenuRequest)sp=SP(SP.Expanding,SP.Expanding)sp.setHorizontalStretch(0)sp.setVerticalStretch(1)sp.setHeightForWidth(self.repoview.sizePolicy().hasHeightForWidth())view.setSizePolicy(sp)view.setFrameShape(QFrame.StyledPanel)self.repotabs_splitter.addWidget(self.repoview)self.repotabs_splitter.setCollapsible(0,False)self.repotabs_splitter.setStretchFactor(0,1)tt=QTabWidget()tt.setDocumentMode(True)tt.setTabPosition(QTabWidget.East)ifnotself.repo.ui.configbool('tortoisehg','tasktabs'):tt.tabBar().hide()self.taskTabsWidget=ttself.repotabs_splitter.addWidget(self.taskTabsWidget)self.repotabs_splitter.setStretchFactor(1,1)self.revDetailsWidget=w=RevDetailsWidget(self.repo)w.linkActivated.connect(self._openLink)w.fileview.showDescSignal.connect(self.showMessage)self.logTabIndex=idx=tt.addTab(w,geticon('log'),'')tt.setTabToolTip(idx,_("Revision details"))self.commitDemand=w=DemandWidget(self.createCommitWidget)self.commitTabIndex=idx=tt.addTab(w,geticon('Checkmark'),'')tt.setTabToolTip(idx,_("Commit"))self.manifestDemand=w=DemandWidget(self.createManifestWidget)self.manifestTabIndex=idx=tt.addTab(w,geticon('annotate'),'')tt.setTabToolTip(idx,_('Manifest'))self.grepDemand=w=DemandWidget(self.createGrepWidget)self.grepTabIndex=idx=tt.addTab(w,geticon('repobrowse'),'')tt.setTabToolTip(idx,_("Search"))self.syncDemand=w=DemandWidget(self.createSyncWidget)self.syncTabIndex=idx=tt.addTab(w,geticon('view-refresh'),'')tt.setTabToolTip(idx,_("Synchronize"))self.pbranchDemand=w=DemandWidget(self.createPatchBranchWidget)self.updatePatchBranchTab()deftitle(self):"""Returns the expected title for this widget [unicode]"""ifself.bundle:return_('%s <incoming>')%self.repo.shortnameelifself.branch:return'%s [%s]'%(self.repo.shortname,self.branch)else:returnself.repo.shortname@pyqtSlot()deftoggleSearchBar(self):"""Toggle display of tasktab-specific search bar if available"""curtt=self.taskTabsWidget.currentWidget()show=getattr(curtt,'toggleSearchBar',None)ifshow:show()@pyqtSlot()deftoggleFilterBar(self):"""Toggle display repowidget filter bar"""vis=self.filterbar.isVisible()self.filterbar.setVisible(notvis)@pyqtSlot()deftoggleGotoBar(self):"""Toggle display repowidget goto bar"""vis=self.gototb.isVisible()self.gototb.setVisible(notvis)@pyqtSlot(unicode)def_openLink(self,link):link=unicode(link)handlers={'cset':self.goto,'subrepo':self.repoLinkClicked.emit}if':'inlink:scheme,param=link.split(':')hdr=handlers.get(scheme)ifhdr:returnhdr(param)QDesktopServices.openUrl(QUrl(link))defgetCommitWidget(self):returngetattr(self.repo,'_commitwidget',None)# TODO: uglydefcreateCommitWidget(self):cw=self.getCommitWidget()ifnotcw:pats={}opts={}b=QPushButton(_('Commit'))b.setAutoDefault(True)f=b.font()f.setWeight(QFont.Bold)b.setFont(f)cw=CommitWidget(pats,opts,self.repo.root,True,self)cw.buttonHBox.addWidget(b)cw.commitButtonName.connect(lambdan:b.setText(n))b.clicked.connect(cw.commit)cw.loadConfigs(QSettings())QTimer.singleShot(0,cw.reload) self.repo._commitwidget = cw
# connect directly in order to reload all related RepoWidgets
- cw.commitComplete.connect(self.reload)
+#cw.commitComplete.connect(self.reload)
cw = SharedWidget(cw)
cw.output.connect(self.output)
cw.progress.connect(self.progress)cw.makeLogVisible.connect(self.makeLogVisible)cw.linkActivated.connect(self._openLink)cw.showMessage.connect(self.showMessage)returncwdefcreateManifestWidget(self):deffilterrev(rev):ifisinstance(rev,basestring):# unapplied patchreturnNone# TODOelse:returnrevw=ManifestTaskWidget(self.repo.ui,self.repo,rev=filterrev(self.rev),parent=self)self.repoview.revisionClicked.connect(lambdarev:w.setRev(filterrev(rev)))w.revChanged.connect(self.repoview.goto)w.revisionHint.connect(self.showMessage)w.grepRequested.connect(self.grep)returnwdefcreateSyncWidget(self):sw=getattr(self.repo,'_syncwidget',None)# TODO: uglyifnotsw:sw=SyncWidget(self.repo,True,self)self.repo._syncwidget=swsw=SharedWidget(sw)sw.output.connect(self.output)sw.progress.connect(self.progress)sw.makeLogVisible.connect(self.makeLogVisible)sw.outgoingNodes.connect(self.setOutgoingNodes)sw.showMessage.connect(self.showMessage)sw.incomingBundle.connect(self.setBundle)sw.refreshTargets(self.rev)returnsw@pyqtSlot(QString)defsetBundle(self,bfile):self.bundle=unicode(bfile)oldlen=len(self.repo)self.repo=thgrepo.repository(self.repo.ui,self.repo.root,bundle=self.bundle)self.repoview.setRepo(self.repo)self.revDetailsWidget.setRepo(self.repo)self.bundleAccept.setHidden(False)self.bundleReject.setHidden(False)self.filterbar.revsetle.setText('incoming()')self.filterbar.setEnabled(False)self.filterbar.show()self.titleChanged.emit(self.title())newlen=len(self.repo)self.revset=[self.repo[n].node()forninrange(oldlen,newlen)]self.repomodel.revset=self.revsetself.reload()defclearBundle(self):self.bundleAccept.setHidden(True)self.bundleReject.setHidden(True)self.filterbar.setEnabled(True)self.filterbar.revsetle.setText('')self.revset=[]self.repomodel.revset=self.revsetself.bundle=Noneself.titleChanged.emit(self.title())self.repo=thgrepo.repository(self.repo.ui,self.repo.root)self.repoview.setRepo(self.repo)self.revDetailsWidget.setRepo(self.repo)defacceptBundle(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.pullBundle(self.bundle,None)self.clearBundle()defrejectBundle(self):self.clearBundle()self.reload()defclearSet(self):self.revset=[]ifself.revsetfilter:self.reload()else:self.repomodel.revset=[]self.refresh()defsetRevisionSet(self,nodes):self.revset=[self.repo[n].node()forninnodes]ifself.revsetfilter:self.reload()else:self.repomodel.revset=self.revsetself.refresh()@pyqtSlot(bool)deffilterToggled(self,checked):self.revsetfilter=checkedifself.revset:self.repomodel.filterbyrevset=checkedself.reload()defsetOutgoingNodes(self,nodes):self.filterbar.revsetle.setText('outgoing()')self.filterbar.show()self.setRevisionSet(nodes)defcreateGrepWidget(self):upats={}gw=SearchWidget(upats,self.repo,self)gw.setRevision(self.repoview.current_rev)gw.showMessage.connect(self.showMessage)gw.progress.connect(self.progress)returngwdefcreatePatchBranchWidget(self):pbw=PatchBranchWidget(self.repo,parent=self)pbw.output.connect(self.output)pbw.progress.connect(self.progress)pbw.makeLogVisible.connect(self.makeLogVisible)returnpbwdefupdatePatchBranchTab(self):"Only show pbranch tab when pbranch extension is installed"tt=self.taskTabsWidgetw=self.pbranchDemandself.pbranchTabIndex=idx=tt.indexOf(w)if'pbranch'inself.repo.extensions():ifidx==-1:self.pbranchTabIndex=idx=tt.addTab(w,geticon('branch'),'')tt.setTabToolTip(idx,_("Patch Branch"))defreponame(self):returnself.repo.shortname@propertydefrev(self):"""Returns the current active revision"""returnself.repoview.current_revdefshowMessage(self,msg):self.currentMessage=msgifself.isVisible():self.showMessageSignal.emit(msg)defshowEvent(self,event):QWidget.showEvent(self,event)self.showMessageSignal.emit(self.currentMessage)ifself.dirty:print'page was dirty, reloading...'self.reload()self.dirty=FalsedefcreateActions(self):QShortcut(QKeySequence('CTRL+P'),self,self.gotoParent)defdragEnterEvent(self,event):paths=[unicode(u.toLocalFile())foruinevent.mimeData().urls()]ifutil.any(os.path.isfile(p)forpinpaths):event.setDropAction(Qt.CopyAction)event.accept()defdropEvent(self,event):paths=[unicode(u.toLocalFile())foruinevent.mimeData().urls()]filepaths=[pforpinpathsifos.path.isfile(p)]iffilepaths:self.thgimport(filepaths)event.setDropAction(Qt.CopyAction)event.accept()defback(self):self.repoview.back()defforward(self):self.repoview.forward()defbisect(self,paths=None):dlg=bisect.BisectDialog(self.repo,{},self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defresolve(self,paths=None):dlg=resolve.ResolveDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defthgimport(self,paths=None):dlg=thgimport.ImportDialog(repo=self.repo,parent=self)dlg.finished.connect(dlg.deleteLater)ifpaths:dlg.setfilepaths(paths)dlg.exec_()defverify(self):cmdline=['--repository',self.repo.root,'verify','--verbose']dlg=cmdui.Dialog(cmdline,self)dlg.exec_()defrecover(self):cmdline=['--repository',self.repo.root,'recover','--verbose']dlg=cmdui.Dialog(cmdline,self)dlg.exec_()defrollback(self):defread_undo():ifos.path.exists(self.repo.sjoin('undo')):try:args=self.repo.opener('undo.desc','r').read().splitlines()ifargs[1]!='commit':returnNonereturnargs[1],int(args[0])except(IOError,IndexError,ValueError):passreturnNonedata=read_undo()ifdataisNone:InfoMsgBox(_('No transaction available'),_('There is no rollback transaction available'))returnelifdata[0]=='commit':ifnotQuestionMsgBox(_('Undo last commit?'),_('Undo most recent commit (%d), preserving file changes?')%data[1]):returnelse:ifnotQuestionMsgBox(_('Undo last transaction?'),_('Rollback to revision %d (undo %s)?')%(data[1]-1,data[0])):returntry:rev=self.repo['.'].rev()exceptException,e:InfoMsgBox(_('Repository Error'),_('Unable to determine working copy revision\n')+hglib.tounicode(e))returnifrev>=data[1]andnotQuestionMsgBox(_('Remove current working revision?'),_('Your current working revision (%d) will be removed ''by this rollback, leaving uncommitted changes.\n ''Continue?'%rev)):returncmdline=['rollback','--repository',self.repo.root,'--verbose']self.runCommand(_('Rollback - TortoiseHg'),cmdline)defpurge(self):dlg=purge.PurgeDialog(self.repo,self)dlg.setWindowFlags(Qt.Sheet)dlg.setWindowModality(Qt.WindowModal)dlg.showMessage.connect(self.showMessage)dlg.progress.connect(self.progress)dlg.finished.connect(dlg.deleteLater)dlg.exec_()@pyqtSlot(unicode,dict)defgrep(self,pattern='',opts={}):"""Open grep task tab"""opts=dict((str(k),str(v))fork,vinopts.iteritems())self.taskTabsWidget.setCurrentIndex(self.grepTabIndex)self.grepDemand.setSearch(pattern,**opts)defsetupModels(self):# Filter revision set in case revisions were removedself.revset=[rforrinself.revsetifrinself.repo]self.repomodel=HgRepoListModel(self.repo,self.branch,self.revset,self.revsetfilter,self)self.repomodel.filled.connect(self.modelFilled)self.repomodel.loaded.connect(self.modelLoaded)self.repomodel.showMessage.connect(self.showMessage)self.repoview.setModel(self.repomodel)self.gototb.setCompletionKeys(self.repo.tags().keys())defmodelFilled(self):'initial batch of revisions loaded'self.repoview.resizeColumns()self.repoview.goto(self._reload_rev)# emits revision_selectedself.revDetailsWidget.finishReload()defmodelLoaded(self):'all revisions loaded (graph generator completed)'# Perhaps we can update a GUI element later, to indicate full loadpassdefrevision_clicked(self,rev):'User clicked on a repoview row'tw=self.taskTabsWidgetiftype(rev)==str:# Clicking on a patch switches to revdetails tabtw.setCurrentIndex(self.logTabIndex)elifrevisNone:# Clicking on working copy switches to commit tabtw.setCurrentIndex(self.commitTabIndex)eliftw.currentWidget()==self.commitDemand:# Clicking on a normal revision switches from commit tabtw.setCurrentIndex(self.logTabIndex)defrevision_selected(self,rev):'View selection changed, could be a reload'ifself.repomodel.graphisNone:returniftype(rev)!=str:# unapplied patch# FIXME remove unapplied patch branch when# patches fully handled downstreamself.manifestDemand.forward('setRev',rev)self.grepDemand.forward('setRevision',rev)self.revDetailsWidget.revision_selected(rev)self.syncDemand.forward('refreshTargets',rev)self.revisionSelected.emit(rev)defgotoParent(self):self.repoview.clearSelection()self.goto('.')defgoto(self,rev):self._reload_rev=revself.repoview.goto(rev)defrevision_activated(self,rev=None):rev=revorself.revifisinstance(rev,basestring):# unapplied patchreturndlg=visdiff.visualdiff(self.repo.ui,self.repo,[],{'change':rev})ifdlg:dlg.exec_()defreload(self):'Initiate a refresh of the repo model, rebuild graph'self.repo.thginvalidate()self.rebuildGraph()self.filterbar.refresh()ifself.taskTabsWidget.currentIndex()==self.commitTabIndex:self.commitDemand.forward('reload')defrebuildGraph(self):self.showMessage('')ifself.revisNoneorlen(self.repo)>self.rev:self._reload_rev=self.revelse:self._reload_rev='tip'self.setupModels()self.revDetailsWidget.record()defreloadTaskTab(self):tti=self.taskTabsWidget.currentIndex()iftti==self.logTabIndex:ttw=self.revDetailsWidgeteliftti==self.commitTabIndex:ttw=self.commitDemand.get()eliftti==self.manifestTabIndex:ttw=self.manifestDemand.get()eliftti==self.syncTabIndex:ttw=self.syncDemand.get()eliftti==self.grepTabIndex:ttw=self.grepDemand.get()eliftti==self.pbranchTabIndex:ttw=self.pbranchDemand.get()ifttw:ttw.reload()defrefresh(self):'Refresh the repo model view, clear cached data'self.repo.thginvalidate()self.repomodel.invalidate()self.revDetailsWidget.reload()self.filterbar.refresh()defrepositoryDestroyed(self):'Repository has detected itself to be deleted'self.closeSelfSignal.emit(self)defrepositoryChanged(self):'Repository has detected a changelog / dirstate change'ifself.isVisible():self.rebuildGraph()else:self.dirty=TruedefconfigChanged(self):'Repository is reporting its config files have changed'self.repomodel.invalidate()self.revDetailsWidget.reload()self.updatePatchBranchTab()# TODO: emit only if actually changedself.titleChanged.emit(self.title())vis=self.repo.ui.configbool('tortoisehg','tasktabs')self.taskTabsWidget.tabBar().setShown(vis)@pyqtSlot(unicode,bool)defsetBranch(self,branch,allparents=True):'Change the branch filter'self.branch=branchself.repomodel.setBranch(branch=branch,allparents=allparents)self.titleChanged.emit(self.title())#### Workbench methods##defcanGoBack(self):returnself.repoview.canGoBack()defcanGoForward(self):returnself.repoview.canGoForward()defstoreSettings(self):self.revDetailsWidget.storeSettings()s=QSettings()repoid=str(self.repo[0])s.setValue('repowidget/splitter-'+repoid,self.repotabs_splitter.saveState())defrestoreSettings(self):self.revDetailsWidget.restoreSettings()s=QSettings()repoid=str(self.repo[0])self.repotabs_splitter.restoreState(s.value('repowidget/splitter-'+repoid).toByteArray())defokToContinue(self):returnself.commitDemand.forward('canExit',default=True)and \
self.syncDemand.forward('canExit',default=True)defcloseRepoWidget(self):'''returns False if close should be aborted'''ifnotself.okToContinue():returnFalseifself.isVisible():# assuming here that there is at most one RepoWidget visibleself.storeSettings()self.revDetailsWidget.storeSettings()s=QSettings()self.commitDemand.forward('storeConfigs',s)self.filterbar.storeConfigs(s)returnTruedefincoming(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.get().incoming()defpull(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.get().pull()defoutgoing(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.get().outgoing()defpush(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.get().push()defqpush(self):"""QPush a patch from MQ"""cmdline=['qpush','--repository',self.repo.root]self.runCommand(_('QPush - TortoiseHg'),cmdline)defqpop(self):"""QPop a patch from MQ"""cmdline=['qpop','--repository',self.repo.root]self.runCommand(_('QPop - TortoiseHg'),cmdline)#### Repoview context menu##defviewMenuRequest(self,point,selection):'User requested a context menu in repo view widget'# selection is a list of the currently selected revisions.# Integers for changelog revisions, None for the working copy,# or strings for unapplied patches.iflen(selection)==0:returnallunapp=Falseif'mq'inself.repo.extensions():forrevinselection:ifnotself.repo.changectx(rev).thgmqunappliedpatch():breakelse:allunapp=Trueifallunapp:self.unnapliedPatchMenu(point,selection)eliflen(selection)==1:self.singleSelectionMenu(point,selection)eliflen(selection)==2:self.doubleSelectionMenu(point,selection)else:self.multipleSelectionMenu(point,selection)defunnapliedPatchMenu(self,point,selection):defqdeleteact():"""Delete unapplied patch(es)"""dlg=qdelete.QDeleteDialog(self.repo,self.menuselection,self)dlg.finished.connect(dlg.deleteLater)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.exec_()defqreorderact():defcheckGuardsOrComments():cont=Trueforpinself.repo.mq.full_series:if'#'inp:cont=QuestionMsgBox('Confirm qreorder',_('<p>ATTENTION!<br>''Guard or comment found.<br>''Reordering patches will destroy them.<br>''<br>Continue?</p>'),parent=self,defaultbutton=QMessageBox.No)breakreturncontifcheckGuardsOrComments():dlg=qreorder.QReorderDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defqfoldact():dlg=qfold.QFoldDialog(self.repo,self.menuselection,self)dlg.finished.connect(dlg.deleteLater)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.exec_()# Special menu for unapplied patchesifnotself.unappcmenu:menu=QMenu(self)acts=[]forname,cbin((_('Goto patch'),self.qgotoRevision),(_('Rename patch'),self.qrenameRevision),(_('Fold patches'),qfoldact),(_('Delete patches'),qdeleteact),(_('Reorder patches'),qreorderact)):act=QAction(name,self)act.triggered.connect(cb)acts.append(act)menu.addAction(act)self.unappcmenu=menuself.unappacts=actsself.menuselection=selectionself.unappacts[0].setEnabled(len(selection)==1)self.unappacts[1].setEnabled(len(selection)==1)self.unappacts[2].setEnabled('qtip'inself.repo.tags())self.unappcmenu.exec_(point)defsingleSelectionMenu(self,point,selection):ifnotself.singlecmenu:items=[]# isrev = the changeset has an integer revision number# isctx = changectx or workingctx, not PatchContext# fixed = the changeset is considered permanent# patch = any patch applied or not# qpar = patch queue parentisrev=lambdaap,up,qp,wd:not(uporwd)isctx=lambdaap,up,qp,wd:notupfixed=lambdaap,up,qp,wd:not(aporuporwd)patch=lambdaap,up,qp,wd:aporupqpar=lambdaap,up,qp,wd:qpapplied=lambdaap,up,qp,wd:apunapp=lambdaap,up,qp,wd:upexs=self.repo.extensions()menu=QMenu(self)forext,func,desc,icon,cbin((None,isrev,_('Update...'),'update',self.updateToRevision),(None,fixed,_('Merge with...'),'merge',self.mergeWithRevision),(None,isctx,_('Browse at rev...'),None,self.manifestRevision),(None,fixed,_('Tag...'),'tag',self.tagToRevision),('bookmarks',fixed,_('Bookmark...'),'bookmark',self.bookmarkRevision),(None,fixed,_('Backout...'),None,self.backoutToRevision),(None,isrev,_('Export patch'),None,self.exportRevisions),(None,isrev,_('Email patch...'),None,self.emailRevision),(None,isrev,_('Archive...'),None,self.archiveRevision),(None,isrev,_('Copy hash'),None,self.copyHash),('transplant',fixed,_('Transplant to local'),None,self.transplantRevision),('rebase',None,None,None,None),('rebase',fixed,_('Rebase...'),None,self.rebaseRevision),('mq',None,None,None,None),('mq',fixed,_('Import to MQ'),None,self.qimportRevision),('mq',applied,_('Finish patch'),None,self.qfinishRevision),('mq',qpar,_('Pop all patches'),None,self.qpopAllRevision),('mq',patch,_('Goto patch'),None,self.qgotoRevision),('mq',patch,_('Rename patch'),None,self.qrenameRevision),('mq',fixed,_('Strip...'),None,self.stripRevision),('reviewboard',fixed,_('Post to Review Board...'),'reviewboard',self.sendToReviewBoard)):ifextandextnotinexs:continueifdescisNone:menu.addSeparator()else:act=QAction(desc,self)act.triggered.connect(cb)ificon:act.setIcon(geticon(icon))act.enableFunc=funcmenu.addAction(act)items.append(act)self.singlecmenu=menuself.singlecmenuitems=itemsctx=self.repo.changectx(self.rev)applied=ctx.thgmqappliedpatch()unapp=ctx.thgmqunappliedpatch()qparent='qparent'inctx.tags()working=self.revisNoneforiteminself.singlecmenuitems:enabled=item.enableFunc(applied,unapp,qparent,working)item.setEnabled(enabled)self.singlecmenu.exec_(point)defexportRevisions(self,revisions):ifnotrevisions:revisions=[self.rev]epath=os.path.join(self.repo.root,self.repo.shortname+'_%r.patch')cmdline=['export','--repository',self.repo.root,'--verbose','--output',epath]forrevinrevisions:cmdline.extend(['--rev',str(rev)])self.runCommand(_('Export - TortoiseHg'),cmdline)defdoubleSelectionMenu(self,point,selection):forrinselection:# No pair menu if working directory or unapplied patchiftype(r)isnotint:returndefdagrange():revA,revB=self.menuselectionifrevA>revB:B,A=self.menuselectionelse:A,B=self.menuselectionfunc=revset.match('%s::%s'%(A,B))return[cforcinfunc(self.repo,range(len(self.repo)))]defexportPair():self.exportRevisions(self.menuselection)defexportDagRange():l=dagrange()ifl:self.exportRevisions(l)defdiffPair():revA,revB=self.menuselectiondlg=visdiff.visualdiff(self.repo.ui,self.repo,[],{'rev':(str(revA),str(revB))})ifdlg:dlg.exec_()defemailPair():run.email(self.repo.ui,rev=self.menuselection,repo=self.repo)defemailDagRange():l=dagrange()ifl:run.email(self.repo.ui,rev=l,repo=self.repo)defbisectNormal():revA,revB=self.menuselectionopts={'good':str(revA),'bad':str(revB)}dlg=bisect.BisectDialog(self.repo,opts,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defbisectReverse():revA,revB=self.menuselectionopts={'good':str(revB),'bad':str(revA)}dlg=bisect.BisectDialog(self.repo,opts,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defcompressDlg():ctxa=self.repo[self.menuselection[0]]ctxb=self.repo[self.menuselection[1]]ifctxa.ancestor(ctxb)==ctxb:revs=self.menuselection[:]elifctxa.ancestor(ctxb)==ctxa:revs=self.menuselection[:]revs.reverse()else:InfoMsgBox(_('Unable to compress history'),_('Selected changeset pair not related'))returndlg=compress.CompressDialog(self.repo,revs,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()ifnotself.paircmenu:menu=QMenu(self)forname,cbin((_('Visual Diff...'),diffPair),(_('Export Pair'),exportPair),(_('Email Pair...'),emailPair),(_('Export DAG Range'),exportDagRange),(_('Email DAG Range...'),emailDagRange),(_('Bisect - Good, Bad...'),bisectNormal),(_('Bisect - Bad, Good...'),bisectReverse),(_('Compress History...'),compressDlg)):a=QAction(name,self)a.triggered.connect(cb)menu.addAction(a)if'reviewboard'inself.repo.extensions():a=QAction(_('Post Pair to Review Board...'),self)a.triggered.connect(self.sendToReviewBoard)menu.addAction(a)self.paircmenu=menuself.menuselection=selectionself.paircmenu.exec_(point)defmultipleSelectionMenu(self,point,selection):forrinselection:# No multi menu if working directory or unapplied patchiftype(r)isnotint:returndefexportSel():self.exportRevisions(self.menuselection)defemailSel():run.email(self.repo.ui,rev=self.menuselection,repo=self.repo)ifnotself.multicmenu:menu=QMenu(self)forname,cbin((_('Export Selected'),exportSel),(_('Email Selected...'),emailSel),):a=QAction(name,self)a.triggered.connect(cb)menu.addAction(a)if'reviewboard'inself.repo.extensions():a=QAction(_('Post Selected to Review Board...'),self)a.triggered.connect(self.sendToReviewBoard)menu.addAction(a)self.multicmenu=menuself.menuselection=selectionself.multicmenu.exec_(point)defupdateToRevision(self):dlg=update.UpdateDialog(self.repo,self.rev,self)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.progress.connect(self.progress)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defmanifestRevision(self):run.manifest(self.repo.ui,repo=self.repo,rev=self.rev)defmergeWithRevision(self):dlg=merge.MergeDialog(self.rev,self.repo,self)dlg.exec_()deftagToRevision(self):dlg=tag.TagDialog(self.repo,rev=str(self.rev),parent=self)dlg.localTagChanged.connect(self.refresh)dlg.showMessage.connect(self.showMessage)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defbookmarkRevision(self):dlg=bookmark.BookmarkDialog(self.repo,str(self.rev),self)dlg.showMessage.connect(self.showMessage)dlg.finished.connect(dlg.deleteLater)dlg.exec_()deftransplantRevision(self):cmdline=['transplant','--repository',self.repo.root,str(self.rev)]self.runCommand(_('Transplant - TortoiseHg'),cmdline)defbackoutToRevision(self):dlg=backout.BackoutDialog(self.repo,str(self.rev),self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defstripRevision(self):'Strip the selected revision and all descendants'dlg=thgstrip.StripDialog(self.repo,rev=str(self.rev),parent=self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defsendToReviewBoard(self):run.postreview(self.repo.ui,rev=self.repoview.selectedRevisions(),repo=self.repo)defemailRevision(self):run.email(self.repo.ui,rev=self.repoview.selectedRevisions(),repo=self.repo)defarchiveRevision(self):dlg=archive.ArchiveDialog(self.repo.ui,self.repo,self.rev,self)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.output.connect(self.output)dlg.progress.connect(self.progress)dlg.exec_()defcopyHash(self):clip=QApplication.clipboard()clip.setText(binascii.hexlify(self.repo[self.rev].node()))defrebaseRevision(self):"""Rebase selected revision on top of working directory parent"""opts={'source':self.rev,'dest':self.repo['.'].rev()}dlg=rebase.RebaseDialog(self.repo,self,**opts)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defqimportRevision(self):"""QImport revision and all descendents to MQ"""if'qparent'inself.repo.tags():endrev='qparent'else:endrev=''cmdline=['qimport','--rev','%s::%s'%(self.rev,endrev),'--repository',self.repo.root]self.runCommand(_('QImport - TortoiseHg'),cmdline)defqfinishRevision(self):"""Finish applied patches up to and including selected revision"""cmdline=['qfinish','qbase::%s'%self.rev,'--repository',self.repo.root]self.runCommand(_('QFinish - TortoiseHg'),cmdline)defqpopAllRevision(self):"""Unapply all patches"""cmdline=['qpop','--all','--repository',self.repo.root]self.runCommand(_('QPop All - TortoiseHg'),cmdline)defqgotoRevision(self):"""Make REV the top applied patch"""patchname=self.repo.changectx(self.rev).thgmqpatchname()cmdline=['qgoto',str(patchname),# FIXME force option'--repository',self.repo.root]self.runCommand(_('QGoto - TortoiseHg'),cmdline)defqrenameRevision(self):"""Rename the selected MQ patch"""patchname=self.repo.changectx(self.rev).thgmqpatchname()dlg=qrename.QRenameDialog(self.repo,patchname,self)dlg.finished.connect(dlg.deleteLater)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.exec_()defrunCommand(self,title,cmdline):ifself.runner:InfoMsgBox(_('Unable to start'),_('Previous command is still running'))returndeffinished(ret):self.repo.decrementBusyCount()self.runner=Noneself.runner=cmdui.Runner(title,False,self)self.runner.output.connect(self.output)self.runner.progress.connect(self.progress)self.runner.makeLogVisible.connect(self.makeLogVisible)self.runner.commandFinished.connect(finished)self.repo.incrementBusyCount()self.runner.run(cmdline)
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.