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.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.importbinasciiimportosfrommercurialimportrevset,error,patchfromtortoisehg.utilimporthglibfromtortoisehg.hgqt.i18nimport_fromtortoisehg.hgqtimportqtlibfromtortoisehg.hgqt.qtlibimportQuestionMsgBox,InfoMsgBox,WarningMsgBoxfromtortoisehg.hgqt.qtlibimportDemandWidgetfromtortoisehg.hgqt.repomodelimportHgRepoListModelfromtortoisehg.hgqtimportcmdui,update,tag,backout,merge,visdifffromtortoisehg.hgqtimportarchive,thgimport,thgstrip,run,purge,bookmarkfromtortoisehg.hgqtimportbisect,rebase,resolve,thgrepo,compress,mqfromtortoisehg.hgqtimportqdelete,qreorder,qfold,qrename,shelvefromtortoisehg.hgqt.repofilterimportRepoFilterBarfromtortoisehg.hgqt.repoviewimportHgRepoViewfromtortoisehg.hgqt.revdetailsimportRevDetailsWidgetfromtortoisehg.hgqt.commitimportCommitWidgetfromtortoisehg.hgqt.manifestdialogimportManifestWidgetfromtortoisehg.hgqt.syncimportSyncWidgetfromtortoisehg.hgqt.grepimportSearchWidgetfromtortoisehg.hgqt.pbranchimportPatchBranchWidgetfromPyQt4.QtCoreimport*fromPyQt4.QtGuiimport*classRepoWidget(QWidget):showMessageSignal=pyqtSignal(QString)closeSelfSignal=pyqtSignal(QWidget)toolbarVisibilityChanged=pyqtSignal()output=pyqtSignal(QString,QString)progress=pyqtSignal(QString,object,QString,QString,object)makeLogVisible=pyqtSignal(bool)repoChanged=pyqtSignal(QString)revisionSelected=pyqtSignal(object)titleChanged=pyqtSignal(unicode)"""Emitted when changed the expected title for the RepoWidget tab"""showIcon=pyqtSignal(QIcon)shortNameChanged=pyqtSignal(QString,QString)baseNodeChanged=pyqtSignal(QString,object)repoLinkClicked=pyqtSignal(unicode)"""Emitted when clicked a link to open repository"""def__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.ubranch=u''self.bundle=Noneself.outgoingMode=Falseself.revset=[]self.busyIcons=[]self.namedTabs={}self.repolen=len(repo)self.shortname=Noneself.basenode=Noneself.destroyed.connect(self.repo.thginvalidate)# Determine the "initial revision" that must be shown when# opening the repo.# The "initial revision" can be selected via the settings, and it can# have 3 possible values:# - "current": Select the current (i.e. working dir parent) revision# - "tip": Select tip of the repository# - "workingdir": Select the working directory pseudo-revisioninitialRevision= \
self.repo.ui.config('tortoisehg','initialrevision','current').lower()initialRevisionDict={'current':'.','tip':'tip','workingdir':None}ifinitialRevisionininitialRevisionDict:default_rev=initialRevisionDict[initialRevision]else:# By default we'll select the current (i.e. working dir parent) revisiondefault_rev='.'ifrepo.parents()[0].rev()==-1:self._reload_rev='tip'else:self._reload_rev=default_revself.currentMessage=''self.dirty=Falseself.setupUi()self.createActions()self.loadSettings()self.setupModels()self.runner=cmdui.Runner(False,self)self.runner.output.connect(self.output)self.runner.progress.connect(self.progress)self.runner.makeLogVisible.connect(self.makeLogVisible)self.runner.commandFinished.connect(self.onCommandFinished)# Select the widget chosen by the userdefaultWidget= \
self.repo.ui.config('tortoisehg','defaultwidget','revdetails').lower()widgetDict={'revdetails':self.logTabIndex,'commit':self.commitTabIndex,'mq':self.mqTabIndex,'sync':self.syncTabIndex,'manifest':self.manifestTabIndex,'search':self.grepTabIndex}ifinitialRevision=='workingdir':# Do not allow selecting the revision details widget when the# selected revision is the working directory pseudo-revisionwidgetDict['revdetails']=self.commitTabIndexifdefaultWidgetinwidgetDict:widgetIndex=widgetDict[defaultWidget]# Note: if the mq extension is not enabled, self.mqTabIndex will# be negativeifwidgetIndex>0:self.taskTabsWidget.setCurrentIndex(widgetIndex)defsetupUi(self):SP=QSizePolicyself.repotabs_splitter=QSplitter(orientation=Qt.Vertical)self.setLayout(QVBoxLayout())self.layout().setContentsMargins(0,0,0,0)self.layout().setSpacing(0)self._infobarlayout=QVBoxLayout()# placeholder for InfoBarself.layout().addLayout(self._infobarlayout)self.filterbar=RepoFilterBar(self.repo,self)self.layout().addWidget(self.filterbar)self.filterbar.branchChanged.connect(self.setBranch)self.filterbar.progress.connect(self.progress)self.filterbar.showMessage.connect(self.showMessage)self.filterbar.setRevisionSet.connect(self.setRevisionSet)self.filterbar.clearRevisionSet.connect(self.clearRevisionSet)self.filterbar.filterToggled.connect(self.filterToggled)self.filterbar.hide()self.revsetfilter=self.filterbar.filtercb.isChecked()self.layout().addWidget(self.repotabs_splitter)cs=('workbench',_('Workbench Log Columns'))self.repoview=view=HgRepoView(self.repo,'repoWidget',cs,self)view.revisionClicked.connect(self.onRevisionClicked)view.revisionSelected.connect(self.onRevisionSelected)view.revisionAltClicked.connect(self.onRevisionSelected)view.revisionActivated.connect(self.onRevisionActivated)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,True)self.repotabs_splitter.setStretchFactor(0,1)self.taskTabsWidget=tt=QTabWidget()self.repotabs_splitter.addWidget(self.taskTabsWidget)self.repotabs_splitter.setStretchFactor(1,1)tt.setDocumentMode(True)self.updateTaskTabs()self.revDetailsWidget=w=RevDetailsWidget(self.repo,self)w.linkActivated.connect(self._openLink)w.revisionSelected.connect(self.repoview.goto)w.grepRequested.connect(self.grep)w.showMessage.connect(self.showMessage)w.updateToRevision.connect(lambdarev:self.updateToRevision())self.logTabIndex=idx=tt.addTab(w,qtlib.geticon('hg-log'),'')self.namedTabs['log']=idxtt.setTabToolTip(idx,_("Revision details","tab tooltip"))self.commitDemand=w=DemandWidget('createCommitWidget',self)self.commitTabIndex=idx=tt.addTab(w,qtlib.geticon('hg-commit'),'')self.namedTabs['commit']=idxtt.setTabToolTip(idx,_("Commit","tab tooltip"))if'mq'inself.repo.extensions():self.mqDemand=w=DemandWidget('createMQWidget',self)self.mqTabIndex=idx=tt.addTab(w,qtlib.geticon('thg-qrefresh'),'')tt.setTabToolTip(idx,_("MQ Patch","tab tooltip"))self.namedTabs['mq']=idxelse:self.mqTabIndex=-1self.syncDemand=w=DemandWidget('createSyncWidget',self)self.syncTabIndex=idx=tt.addTab(w,qtlib.geticon('thg-sync'),'')self.namedTabs['sync']=idxtt.setTabToolTip(idx,_("Synchronize","tab tooltip"))self.manifestDemand=w=DemandWidget('createManifestWidget',self)self.manifestTabIndex=idx=tt.addTab(w,qtlib.geticon('hg-annotate'),'')self.namedTabs['manifest']=idxtt.setTabToolTip(idx,_('Manifest',"tab tooltip"))self.grepDemand=w=DemandWidget('createGrepWidget',self)self.grepTabIndex=idx=tt.addTab(w,qtlib.geticon('hg-grep'),'')self.namedTabs['grep']=idxtt.setTabToolTip(idx,_("Search","tab tooltip"))if'pbranch'inself.repo.extensions():self.pbranchDemand=w=DemandWidget('createPatchBranchWidget',self)self.pbranchTabIndex=idx=tt.addTab(w,qtlib.geticon('branch'),'')tt.setTabToolTip(idx,_("Patch Branch","tab tooltip"))self.namedTabs['pbranch']=idxelse:self.pbranchTabIndex=-1defswitchToNamedTaskTab(self,tabname):iftabnameinself.namedTabs:idx=self.namedTabs[tabname]self.taskTabsWidget.setCurrentIndex(idx)deftitle(self):"""Returns the expected title for this widget [unicode]"""ifself.bundle:return_('%s <incoming>')%self.repo.shortnameelifself.ubranch:returnu'%s [%s]'%(self.repo.shortname,self.ubranch)else:returnself.repo.shortnamedeffilterBarVisible(self):returnself.filterbar.isVisible()@pyqtSlot(bool)deftoggleFilterBar(self,checked):"""Toggle display repowidget filter bar"""self.filterbar.setVisible(checked)@pyqtSlot(unicode)def_openLink(self,link):link=unicode(link)handlers={'cset':self.goto,'log':lambdaa:self.makeLogVisible.emit(True),'subrepo':self.repoLinkClicked.emit,'shelve':self.shelve}if':'inlink:scheme,param=link.split(':',1)hdr=handlers.get(scheme)ifhdr:returnhdr(param)QDesktopServices.openUrl(QUrl(link))defsetInfoBar(self,cls,*args,**kwargs):"""Show the given infobar at top of RepoWidget If the priority of the current infobar is higher than new one, the request is silently ignored. """cleared=self.clearInfoBar(priority=cls.infobartype)ifnotcleared:returnw=cls(*args,**kwargs)w.linkActivated.connect(self._openLink)self._infobarlayout.insertWidget(0,w)w.setFocus()# to handle key press by InfoBarreturnwdefclearInfoBar(self,priority=None):"""Close current infobar if available; return True if got empty"""it=self._infobarlayout.itemAt(0)ifnotit:returnTrueifpriorityisNoneorit.widget().infobartype<=priority:it.widget().close()returnTrueelse:returnFalse@pyqtSlot(unicode,unicode)def_showOutputOnInfoBar(self,msg,label):iflabel=='ui.error':self.setInfoBar(qtlib.CommandErrorInfoBar,unicode(msg).strip())@pyqtSlot(unicode)def_showMessageOnInfoBar(self,msg):ifmsg:self.setInfoBar(qtlib.StatusInfoBar,msg)else:self.clearInfoBar(priority=qtlib.StatusInfoBar.infobartype)defcreateCommitWidget(self):pats,opts={},{}cw=CommitWidget(self.repo,pats,opts,True,self,rev=self.rev)ifcw.hasmqbutton:cw.buttonHBox.addWidget(cw.mqSetupButton())else:b=QPushButton(_('Commit','action button'))b.setAutoDefault(True)f=b.font()f.setWeight(QFont.Bold)b.setFont(f)cw.buttonHBox.addWidget(b)cw.commitButtonEnable.connect(b.setEnabled)b.clicked.connect(cw.commit)cw.loadSettings(QSettings(),'workbench')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)QTimer.singleShot(0,cw.reload)returncwdefcreateManifestWidget(self):ifisinstance(self.rev,basestring):rev=Noneelse:rev=self.revw=ManifestWidget(self.repo,rev,self)w.loadSettings(QSettings(),'workbench')w.revChanged.connect(self.repoview.goto)w.linkActivated.connect(self._openLink)w.showMessage.connect(self.showMessage)w.grepRequested.connect(self.grep)returnwdefcreateSyncWidget(self):sw=SyncWidget(self.repo,self)sw.output.connect(self.output)sw.output.connect(self._showOutputOnInfoBar)sw.progress.connect(self.progress)sw.makeLogVisible.connect(self.makeLogVisible)sw.outgoingNodes.connect(self.setOutgoingNodes)sw.showMessage.connect(self.showMessage)sw.showMessage.connect(self._showMessageOnInfoBar)sw.incomingBundle.connect(self.setBundle)sw.pullCompleted.connect(self.onPullCompleted)sw.pushCompleted.connect(self.clearRevisionSet)sw.showBusyIcon.connect(self.onShowBusyIcon)sw.hideBusyIcon.connect(self.onHideBusyIcon)sw.refreshTargets(self.rev)returnsw@pyqtSlot(QString)defonShowBusyIcon(self,iconname):self.busyIcons.append(iconname)self.showIcon.emit(qtlib.geticon(self.busyIcons[-1]))@pyqtSlot(QString)defonHideBusyIcon(self,iconname):ificonnameinself.busyIcons:self.busyIcons.remove(iconname)ifself.busyIcons:self.showIcon.emit(qtlib.geticon(self.busyIcons[-1]))else:self.showIcon.emit(QIcon())@pyqtSlot(QString)defsetBundle(self,bfile):ifself.bundle:self.clearBundle()self.bundle=hglib.fromunicode(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.manifestDemand.forward('setRepo',self.repo)self.filterbar.revsetle.setText('incoming()')self.filterbar.setEnableFilter(False)self.titleChanged.emit(self.title())newlen=len(self.repo)self.revset=range(oldlen,newlen)self.repomodel.revset=self.revsetself.reload()self.repoview.resetBrowseHistory(self.revset)self._reload_rev=self.revset[0]w=self.setInfoBar(qtlib.ConfirmInfoBar,_('Found incoming changesets'))assertww.acceptButton.setText(_('Accept'))w.acceptButton.setToolTip(_('Pull incoming changesets into ''your repository'))w.rejectButton.setText(_('Reject'))w.rejectButton.setToolTip(_('Reject incoming changesets'))w.accepted.connect(self.acceptBundle)w.rejected.connect(self.rejectBundle)defclearBundle(self):self.filterbar.setEnableFilter(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)self.manifestDemand.forward('setRepo',self.repo)defonPullCompleted(self):ifself.bundle:# create a new bundlerepo instance; revision numbers may changebrepo=thgrepo.repository(self.repo.ui,self.repo.root,bundle=self.bundle)repo=thgrepo.repository(self.repo.ui,self.repo.root)iflen(repo)==len(brepo):# all bundle revisions pulledself.clearBundle()self.reload()else:# refresh revset with remaining revisionsself.revset=range(len(repo),len(brepo))self.repo=brepoself.repoview.setRepo(brepo)self.revDetailsWidget.setRepo(brepo)self.manifestDemand.forward('setRepo',brepo)self.reload()self.repomodel.revset=self.revsetself.repoview.resetBrowseHistory(self.revset)self._reload_rev=self.revset[0]defacceptBundle(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.pullBundle(self.bundle,None)defpullBundleToRev(self):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.syncDemand.pullBundle(self.bundle,self.rev)defrejectBundle(self):self.clearBundle()self.reload() @pyqtSlot()
def clearRevisionSet(self):
+ self.filterbar.revsetle.clear() self.toolbarVisibilityChanged.emit()
self.outgoingMode = False
if not self.revset:
returnself.revset=[]ifself.revsetfilter:self.reload()else:self.repomodel.revset=[]self.refresh()defsetRevisionSet(self,revisions):revs=revisions[:]revs.sort(reverse=True)self.revset=revsifself.revsetfilter:self.reload()else:self.repomodel.revset=self.revsetself.refresh()self.repoview.resetBrowseHistory(self.revset)self._reload_rev=self.revset[0]@pyqtSlot(bool)deffilterToggled(self,checked):self.revsetfilter=checkedifself.revset:self.repomodel.filterbyrevset=checkedself.reload()self.repoview.resetBrowseHistory(self.revset,self.rev)defsetOutgoingNodes(self,nodes):self.filterbar.revsetle.setText('outgoing()')self.setRevisionSet([self.repo[n].rev()forninnodes])w=self.setInfoBar(qtlib.ConfirmInfoBar,_('%d outgoing changesets')%len(nodes))assertww.acceptButton.setText(_('Push'))w.accepted.connect(lambda:self.push(False))# TODO: to the same URLw.rejected.connect(self.clearRevisionSet)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)gw.revisionSelected.connect(self.goto)returngwdefcreateMQWidget(self):mqw=mq.MQWidget(self.repo,self)mqw.output.connect(self.output)mqw.progress.connect(self.progress)mqw.makeLogVisible.connect(self.makeLogVisible)mqw.showMessage.connect(self.showMessage)returnmqwdefcreatePatchBranchWidget(self):pbw=PatchBranchWidget(self.repo,parent=self)pbw.output.connect(self.output)pbw.progress.connect(self.progress)pbw.makeLogVisible.connect(self.makeLogVisible)returnpbwdefreponame(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)self.generateSingleMenu()self.generatePairMenu()self.generateUnappliedPatchMenu()self.generateMultipleSelectionMenu()self.generateBundleMenu()self.generateOutgoingMenu()defdetectPatches(self,paths):filepaths=[]forpinpaths:ifnotos.path.isfile(p):continuetry:pf=open(p,'rb')earlybytes=pf.read(4096)if'\0'inearlybytes:continuepf.seek(0)filename,message,user,date,branch,node,p1,p2= \
patch.extract(self.repo.ui,pf)iffilename:filepaths.append(p)os.unlink(filename)exceptException:passreturnfilepathsdefdragEnterEvent(self,event):paths=[unicode(u.toLocalFile())foruinevent.mimeData().urls()]ifself.detectPatches(paths):event.setDropAction(Qt.CopyAction)event.accept()defdropEvent(self,event):paths=[unicode(u.toLocalFile())foruinevent.mimeData().urls()]patches=self.detectPatches(paths)ifnotpatches:returnevent.setDropAction(Qt.CopyAction)event.accept()self.thgimport(patches)## Begin Workbench event forwardsdefback(self):self.repoview.back()defforward(self):self.repoview.forward()defbisect(self):dlg=bisect.BisectDialog(self.repo,{},self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defresolve(self):dlg=resolve.ResolveDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defthgimport(self,paths=None):dlg=thgimport.ImportDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.patchImported.connect(self.gotoTip)ifpaths:dlg.setfilepaths(paths)dlg.exec_()defshelve(self,arg=None):dlg=shelve.ShelveDialog(self.repo,self)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defverify(self):cmdline=['--repository',self.repo.root,'verify','--verbose']dlg=cmdui.Dialog(cmdline,self)dlg.setWindowIcon(qtlib.geticon('hg-verify'))dlg.setWindowTitle(_('%s - verify repository')%self.repo.shortname)dlg.exec_()defrecover(self):cmdline=['--repository',self.repo.root,'recover','--verbose']dlg=cmdui.Dialog(cmdline,self)dlg.setWindowIcon(qtlib.geticon('hg-recover'))dlg.setWindowTitle(_('%s - recover repository')%self.repo.shortname)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(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_()## End workbench event forwards@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.revsetifr<len(self.repo)]branch=hglib.fromunicode(self.ubranch)self.repomodel=HgRepoListModel(self.repo,self.repoview.colselect[0],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)try:self._last_series=self.repo.mq.series[:]exceptAttributeError:self._last_series=[]defmodelFilled(self):'initial batch of revisions loaded'self.repoview.goto(self._reload_rev)# emits revisionSelectedself.repoview.resizeColumns()ifself.repo.shortname!=self.shortname:self.shortname=self.repo.shortnameself.shortNameChanged.emit(hglib.tounicode(self.repo.root),self.shortname)iflen(self.repo)andself.repo[0].node()!=self.basenode:self.basenode=self.repo[0].node()self.baseNodeChanged.emit(hglib.tounicode(self.repo.root),self.basenode)defmodelLoaded(self):'all revisions loaded (graph generator completed)'# Perhaps we can update a GUI element later, to indicate full loadpassdefonRevisionClicked(self,rev):'User clicked on a repoview row'tw=self.taskTabsWidgetcw=tw.currentWidget()ifnotcw.canswitch():returnctx=self.repo.changectx(rev)ifrevisNoneor('mq'inself.repo.extensions()and'qtip'inctx.tags()):# Clicking on working copy switches to commit tabtw.setCurrentIndex(self.commitTabIndex)else:# Clicking on a normal revision switches from commit tabtw.setCurrentIndex(self.logTabIndex)defonRevisionSelected(self,rev):'View selection changed, could be a reload'self.showMessage('')self.clearInfoBar(qtlib.InfoBar.INFO)ifself.repomodel.graphisNone:returntry:self.revDetailsWidget.onRevisionSelected(rev)self.revisionSelected.emit(rev)iftype(rev)!=str:# Regular patch or working directoryifself.manifestDemand.isHidden():self.manifestDemand.forward('selectRev',rev)else:self.manifestDemand.forward('setRev',rev)self.grepDemand.forward('setRevision',rev)self.syncDemand.forward('refreshTargets',rev)self.commitDemand.forward('setRev',rev)else:# unapplied patchifself.manifestDemand.isHidden():self.manifestDemand.forward('selectRev',None)else:self.manifestDemand.forward('setRev',None)except(IndexError,error.RevlogError,error.Abort),e:self.showMessage(hglib.tounicode(str(e)))defgotoParent(self):self.repoview.clearSelection()self.goto('.')defgotoTip(self):self.repoview.clearSelection()self.goto('tip')defgoto(self,rev):self._reload_rev=revself.repoview.goto(rev)defonRevisionActivated(self,rev):qgoto=Falseifisinstance(rev,basestring):qgoto=Trueelse:ctx=self.repo.changectx(rev)if'qparent'inctx.tags()orctx.thgmqappliedpatch():qgoto=Trueif'qtip'inctx.tags():qgoto=Falseifqgoto:self.qgotoRevision()else:self.visualDiffRevision()defreload(self):'Initiate a refresh of the repo model, rebuild graph'try:self.repo.thginvalidate()self.rebuildGraph()self.reloadTaskTab()exceptEnvironmentError,e:self.showMessage(hglib.tounicode(str(e)))defrebuildGraph(self):'Called by repositoryChanged signals, and during reload'self.showMessage('')iflen(self.repo)<self.repolen:# repo has been stripped, invalidate active revision setsifself.bundle:self.clearBundle()self.showMessage(_('Repository stripped, incoming preview ' 'cleared'))
elif self.revset:
self.revset = []
- self.filterbar.revsetle.setText('')
+ self.filterbar.revsetle.clear()
self.showMessage(_('Repository stripped, revision set cleared'))
if not self.bundle:
self.repolen = len(self.repo)
self._reload_rev=self.revifself.revisNone:passeliftype(self.rev)isstr:try:ifself.revnotinself.repo.mq.series:# patch is no longer in the series, find a neighboridx=self._last_series.index(self._reload_rev)-1self._reload_rev=self._last_series[idx]whileself._reload_revnotinself.repo.mq.seriesandidx:idx-=1self._reload_rev=self._last_series[idx]except(AttributeError,IndexError):self._reload_rev='tip'eliflen(self.repo)<=self.rev:self._reload_rev='tip'self.setupModels()self.filterbar.refresh()self.repoview.saveSettings()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()eliftti==self.mqTabIndex:ttw=self.mqDemand.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():try:self.rebuildGraph()except(error.RevlogError,error.RepoError),e:self.showMessage(hglib.tounicode(str(e)))self.repomodel=HgRepoListModel(None,self.repoview.colselect[0],None,None,False,self)self.repoview.setModel(self.repomodel)else:self.dirty=True# Update the repo registry entries related to the current repoself.repoChanged.emit(hglib.tounicode(self.repo.root))defconfigChanged(self):'Repository is reporting its config files have changed'self.repomodel.invalidate()self.revDetailsWidget.reload()self.titleChanged.emit(self.title())self.updateTaskTabs()ifself.repo.shortname!=self.shortname:self.shortname=self.repo.shortnameself.shortNameChanged.emit(hglib.tounicode(self.repo.root),self.shortname)defupdateTaskTabs(self):val=self.repo.ui.config('tortoisehg','tasktabs','off').lower()ifval=='east':self.taskTabsWidget.setTabPosition(QTabWidget.East)self.taskTabsWidget.tabBar().show()elifval=='west':self.taskTabsWidget.setTabPosition(QTabWidget.West)self.taskTabsWidget.tabBar().show()else:self.taskTabsWidget.tabBar().hide()@pyqtSlot(QString,bool)defsetBranch(self,branch,allparents=True):'Change the branch filter'self.ubranch=branchself.repomodel.setBranch(branch=branch,allparents=allparents)self.titleChanged.emit(self.title())ifself.revset:self.repoview.resetBrowseHistory(self.revset,self.rev)#### Workbench methods##defcanGoBack(self):returnself.repoview.canGoBack()defcanGoForward(self):returnself.repoview.canGoForward()defloadSettings(self):s=QSettings()repoid=str(self.repo[0])self.revDetailsWidget.loadSettings(s)self.filterbar.loadSettings(s)self.repotabs_splitter.restoreState(s.value('repowidget/splitter-'+repoid).toByteArray())QTimer.singleShot(0,lambda:self.toolbarVisibilityChanged.emit())defokToContinue(self):ifnotself.commitDemand.forward('canExit',default=True):self.taskTabsWidget.setCurrentIndex(self.commitTabIndex)self.showMessage(_('Commit tab cannot exit'))returnFalseifnotself.syncDemand.forward('canExit',default=True):self.taskTabsWidget.setCurrentIndex(self.syncTabIndex)self.showMessage(_('Sync tab cannot exit'))returnFalseif'mq'inself.repo.extensions():ifnotself.mqDemand.forward('canExit',default=True):self.taskTabsWidget.setCurrentIndex(self.mqTabIndex)self.showMessage(_('MQ tab cannot exit'))returnFalseifnotself.grepDemand.forward('canExit',default=True):self.taskTabsWidget.setCurrentIndex(self.grepTabIndex)self.showMessage(_('Search tab cannot exit'))returnFalseifself.runner.core.running():self.showMessage(_('Repository command still running'))returnFalsereturnTruedefcloseRepoWidget(self):'''returns False if close should be aborted'''ifnotself.okToContinue():returnFalses=QSettings()ifself.isVisible():try:repoid=str(self.repo[0])s.setValue('repowidget/splitter-'+repoid,self.repotabs_splitter.saveState())exceptEnvironmentError:passself.revDetailsWidget.saveSettings(s)self.commitDemand.forward('saveSettings',s,'workbench')self.manifestDemand.forward('saveSettings',s,'workbench')self.grepDemand.forward('saveSettings',s)self.filterbar.saveSettings(s)self.repoview.saveSettings(s)returnTruedefincoming(self):self.syncDemand.get().incoming()defpull(self):self.syncDemand.get().pull()defoutgoing(self):self.syncDemand.get().outgoing()self.outgoingMode=Truedefpush(self,confirm=True):"""Call sync push. If confirm is False, the user will not be prompted for confirmation. If confirm is True, the prompt might be used. """self.syncDemand.get().push(confirm)self.outgoingMode=False#### 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:returnifself.bundle:iflen(selection)==1:self.bundlemenu.exec_(point)returnifself.outgoingMode:iflen(selection)==1:self.outgoingcmenu.exec_(point)returnself.menuselection=selectionallunapp=Falseif'mq'inself.repo.extensions():forrevinselection:ifnotself.repo.changectx(rev).thgmqunappliedpatch():breakelse:allunapp=Trueifallunapp:self.unappliedPatchMenu(point,selection)eliflen(selection)==1:self.singleSelectionMenu(point,selection)eliflen(selection)==2:self.doubleSelectionMenu(point,selection)else:self.multipleSelectionMenu(point,selection)defsingleSelectionMenu(self,point,selection):ctx=self.repo.changectx(self.rev)applied=ctx.thgmqappliedpatch()working=self.revisNonetags=ctx.tags()foriteminself.singlecmenuitems:enabled=item.enableFunc(applied,working,tags)item.setEnabled(enabled)self.singlecmenu.exec_(point)defdoubleSelectionMenu(self,point,selection):forrinselection:# No pair menu if working directory or unapplied patchiftype(r)isnotint:returnself.paircmenu.exec_(point)defmultipleSelectionMenu(self,point,selection):forrinselection:# No multi menu if working directory or unapplied patchiftype(r)isnotint:returnself.multicmenu.exec_(point)defunappliedPatchMenu(self,point,selection):q=self.repo.mqispushable=Falseunapplied=0foriinxrange(q.seriesend(),len(q.series)):pushable,reason=q.pushable(i)ifpushable:ifunapplied==0:qnext=q.series[i]ifself.rev==q.series[i]:ispushable=Trueunapplied+=1self.unappacts[0].setEnabled(ispushableandlen(selection)==1)self.unappacts[1].setEnabled(ispushableandlen(selection)==1and \
self.rev!=qnext)self.unappacts[2].setEnabled('qtip'inself.repo.tags())self.unappacts[3].setEnabled(True)self.unappacts[4].setEnabled(unapplied>1)self.unappacts[5].setEnabled(len(selection)==1)self.unappcmenu.exec_(point)defgenerateSingleMenu(self,mode=None):items=[]# This menu will never be opened for an unapplied patch, they# have their own menu.## isrev = the changeset has an integer revision number# isctx = changectx or workingctx# fixed = the changeset is considered permanent# applied = an applied patch# qgoto = applied patch or qparentisrev=lambdaap,wd,tags:notwdisctx=lambdaap,wd,tags:Truefixed=lambdaap,wd,tags:not(aporwd)applied=lambdaap,wd,tags:apqgoto=lambdaap,wd,tags:('qparent'intags)or \
(ap)exs=self.repo.extensions()defentry(menu,ext=None,func=None,desc=None,icon=None,cb=None):ifextandextnotinexs:returnifdescisNone:menu.addSeparator()returnact=QAction(desc,self)act.triggered.connect(cb)ificon:act.setIcon(qtlib.getmenuicon(icon))act.enableFunc=funcmenu.addAction(act)items.append(act)menu=QMenu(self)ifmode=='outgoing':submenu=menu.addMenu(_('Push'))entry(submenu,None,isrev,_('Push all'),'hg-push',self.pushToRevision)entry(submenu,None,isrev,_('Push to here'),'',self.pushToRevision)entry(submenu,None,isrev,_('Push selected branch'),'',self.pushBranch)entry(menu)entry(menu,None,isrev,_('Update...'),'hg-update',self.updateToRevision)entry(menu)entry(menu,None,isctx,_('Visual diff...'),'visualdiff',self.visualDiffRevision)entry(menu,None,isrev,_('Diff to local...'),'ldiff',self.visualDiffToLocal)entry(menu,None,isctx,_('Browse at rev...'),'hg-annotate',self.manifestRevision)entry(menu)entry(menu,None,fixed,_('Merge with local...'),'hg-merge',self.mergeWithRevision)entry(menu)entry(menu,None,fixed,_('Tag...'),'hg-tag',self.tagToRevision)entry(menu,None,fixed,_('Bookmark...'),'hg-bookmarks',self.bookmarkRevision)entry(menu)entry(menu,None,fixed,_('Backout...'),'hg-revert',self.backoutToRevision)entry(menu)submenu=menu.addMenu(_('Export'))entry(submenu,None,isrev,_('Export patch...'),'hg-export',self.exportRevisions)entry(submenu,None,isrev,_('Email patch...'),'mail-forward',self.emailRevision)entry(submenu,None,isrev,_('Archive...'),'hg-archive',self.archiveRevision)entry(submenu,None,isrev,_('Bundle rev to tip...'),'menurelocate',self.bundleRevisions)entry(submenu,None,isctx,_('Copy patch'),'copy-patch',self.copyPatch)entry(menu)entry(menu,None,isrev,_('Copy hash'),'copy-hash',self.copyHash)entry(menu)entry(menu,'transplant',fixed,_('Transplant to local'),'hg-transplant',self.transplantRevisions)if'mq'inexsor'rebase'inexs:submenu=menu.addMenu(_('Modify history'))entry(submenu,'mq',qgoto,_('Unapply patch (QGoto parent)'),'hg-qgoto',self.qgotoRevision)entry(submenu,'mq',fixed,_('Import to MQ'),'qimport',self.qimportRevision)entry(submenu,'mq',applied,_('Finish patch'),'qfinish',self.qfinishRevision)entry(submenu,'mq',applied,_('Rename patch...'),None,self.qrename)entry(submenu,'mq')entry(submenu,'rebase',fixed,_('Rebase...'),'hg-rebase',self.rebaseRevision)entry(submenu,'rebase')entry(submenu,'mq',fixed,_('Strip...'),'menudelete',self.stripRevision)entry(menu,'reviewboard',fixed,_('Post to Review Board...'),'reviewboard',self.sendToReviewBoard)entry(menu,'rupdate',fixed,_('Remote Update...'),'hg-update',self.rupdate)ifmode=='outgoing':self.outgoingcmenu=menuself.outgoingcmenuitems=itemselse:self.singlecmenu=menuself.singlecmenuitems=itemsdefgeneratePairMenu(self):defdagrange():revA,revB=self.menuselectionifrevA>revB:B,A=self.menuselectionelse:A,B=self.menuselectionfunc=hglib.revsetmatch(self.repo.ui,'%s::%s'%(A,B))return[cforcinfunc(self.repo,range(len(self.repo)))]defexportPair():self.exportRevisions(self.menuselection)defexportDiff():root=self.repo.rootfilename='%s_%d_to_%d.diff'%(os.path.basename(root),self.menuselection[0],self.menuselection[1])file=QFileDialog.getSaveFileName(self,_('Write diff file'),hglib.tounicode(os.path.join(root,filename)))ifnotfile:returndiff=self.copyPatch(returnval=True)f=Nonetry:f=open(file,"wb")f.write(diff)exceptException,e:WarningMsgBox(_('Repository Error'),_('Unable to write diff file'))finally:iff:f.close()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)defbundleDagRange():l=dagrange()ifl:self.bundleRevisions(base=l[0],tip=l[-1])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_()menu=QMenu(self)forname,cb,iconin((_('Visual Diff...'),diffPair,'visualdiff'),(_('Export Diff...'),exportDiff,'hg-export'),(None,None,None),(_('Export Selected...'),exportPair,'hg-export'),(_('Email Selected...'),emailPair,'mail-forward'),(None,None,None),(_('Export DAG Range...'),exportDagRange,'hg-export'),(_('Email DAG Range...'),emailDagRange,'mail-forward'),(_('Bundle DAG Range...'),bundleDagRange,'menurelocate'),(None,None,None),(_('Bisect - Good, Bad...'),bisectNormal,'hg-bisect-good-bad'),(_('Bisect - Bad, Good...'),bisectReverse,'hg-bisect-bad-good'),(_('Compress History...'),compressDlg,'hg-compress')):ifnameisNone:menu.addSeparator()continuea=QAction(name,self)ificon:a.setIcon(qtlib.getmenuicon(icon))a.triggered.connect(cb)menu.addAction(a)if'transplant'inself.repo.extensions():a=QAction(_('Transplant Selected to local'),self)a.setIcon(qtlib.getmenuicon('hg-transplant'))a.triggered.connect(self.transplantRevisions)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.paircmenu=menudefgenerateUnappliedPatchMenu(self):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.fullseries: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_()menu=QMenu(self)acts=[]forname,cb,iconin((_('Apply patch (QGoto)'),self.qgotoRevision,'hg-qgoto'),(_('QPush --move'),self.qpushMoveRevision,'hg-qpush'),(_('Fold patches...'),qfoldact,'hg-qfold'),(_('Delete patches...'),qdeleteact,'hg-qdelete'),(_('Reorder patches...'),qreorderact,'hg-qreorder'),(_('Rename patch...'),self.qrename,None)):act=QAction(name,self)act.triggered.connect(cb)ificon:act.setIcon(qtlib.getmenuicon(icon))acts.append(act)menu.addAction(act)self.unappcmenu=menuself.unappacts=actsdefgenerateMultipleSelectionMenu(self):defexportSel():self.exportRevisions(self.menuselection)defemailSel():run.email(self.repo.ui,rev=self.menuselection,repo=self.repo)menu=QMenu(self)forname,cb,iconin((_('Export Selected...'),exportSel,'hg-export'),(_('Email Selected...'),emailSel,'mail-forward'),):a=QAction(name,self)ificon:a.setIcon(qtlib.getmenuicon(icon))a.triggered.connect(cb)menu.addAction(a)if'transplant'inself.repo.extensions():a=QAction(_('Transplant Selected to local'),self)a.setIcon(qtlib.getmenuicon('hg-transplant'))a.triggered.connect(self.transplantRevisions)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=menudefgenerateBundleMenu(self):menu=QMenu(self)forname,cb,iconin((_('Pull to here...'),self.pullBundleToRev,'hg-pull-to-here'),(_('Visual diff...'),self.visualDiffRevision,'visualdiff'),):a=QAction(name,self)a.triggered.connect(cb)ificon:a.setIcon(qtlib.getmenuicon(icon))menu.addAction(a)self.bundlemenu=menudefgenerateOutgoingMenu(self):self.generateSingleMenu(mode='outgoing')defexportRevisions(self,revisions):ifnotrevisions:revisions=[self.rev]udir=QFileDialog.getExistingDirectory(self,_('Export patch'),hglib.tounicode(self.repo.root))ifnotudir:returnstrdir=hglib.fromunicode(udir)epath=os.path.join(strdir,hglib.fromunicode(self.repo.shortname)+'_%r.patch')cmdline=['export','--repository',self.repo.root,'--verbose','--output',epath]existingRevisions=[]forrevinrevisions:ifos.path.exists(epath%rev):ifos.path.isfile(epath%rev):existingRevisions.append(rev)else:QMessageBox.warning(self,_('Cannot export revision'),(_('Cannot export revision %s into the file named:''\n\n%s\n')%(rev,epath%rev))+ \
_('There is already an existing folder ''with that same name.'))returncmdline.extend(['--rev',str(rev)])ifexistingRevisions:buttonNames=[_("Replace"),_("Append"),_("Abort")]warningMessage= \
_('There are existing patch files for %d revisions (%s) ''in the selected location (%s).\n\n') \
%(len(existingRevisions)," ,".join([str(rev)forrevinexistingRevisions]),udir)warningMessage+= \
_('What do you want to do?\n')+u'\n'+ \
u'- '+_('Replace the existing patch files.\n')+ \
u'- '+_('Append the changes to the existing patch files.\n')+ \
u'- '+_('Abort the export operation.\n')res=qtlib.CustomPrompt(_('Patch files already exist'),warningMessage,self,buttonNames,0,2).run()ifbuttonNames[res]==_("Replace"):# Remove the existing patch filesforrevinexistingRevisions:os.remove(epath%rev)elifbuttonNames[res]==_("Abort"):returnself.runCommand(cmdline)iflen(revisions)==1:# Show a message box with a link to the export folder and to the# exported filerev=revisions[0]patchfilename=os.path.normpath(epath%rev)patchdirname=os.path.normpath(strdir)patchshortname=os.path.basename(patchfilename)qtlib.InfoMsgBox(_('Patch exported'),_('Revision #%d (%s) was exported to:<p>''<a href="file:///%s">%s</a>%s''<a href="file:///%s">%s</a>') \
%(rev,str(self.repo[rev]),patchdirname,patchdirname,os.path.sep,patchfilename,patchshortname))else:# Show a message box with a link to the export folderqtlib.InfoMsgBox(_('Patches exported'),_('%d patches were exported to:<p>''<a href="file:///%s">%s</a>') \
%(len(revisions),strdir,strdir))defvisualDiffRevision(self):opts=dict(change=self.rev)dlg=visdiff.visualdiff(self.repo.ui,self.repo,[],opts)ifdlg:dlg.exec_()dlg.deleteLater()defvisualDiffToLocal(self):asserttype(self.rev)isintopts=dict(rev=['rev(%d)'%self.rev])dlg=visdiff.visualdiff(self.repo.ui,self.repo,[],opts)ifdlg:dlg.exec_()dlg.deleteLater()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_()defpushAll(self):self.syncDemand.forward('push',True)defpushToRevision(self):# Do not ask for confirmationself.syncDemand.forward('push',False,rev=self.rev)defpushBranch(self):# Do not ask for confirmationself.syncDemand.forward('push',False,branch=self.repo[self.rev].branch())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_()dlg.deleteLater()deftagToRevision(self):dlg=tag.TagDialog(self.repo,rev=str(self.rev),parent=self)dlg.showMessage.connect(self.showMessage)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defbookmarkRevision(self):dlg=bookmark.BookmarkDialog(self.repo,self.rev,self)dlg.showMessage.connect(self.showMessage)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.finished.connect(dlg.deleteLater)dlg.exec_()deftransplantRevisions(self):cmdline=['transplant','--repository',self.repo.root]forrevinself.repoview.selectedRevisions():cmdline.append(str(rev))self.runCommand(cmdline)defbackoutToRevision(self):dlg=backout.BackoutDialog(self.rev,self.repo,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.showBusyIcon.connect(self.onShowBusyIcon)dlg.hideBusyIcon.connect(self.onHideBusyIcon)dlg.finished.connect(dlg.deleteLater)dlg.exec_()defsendToReviewBoard(self):run.postreview(self.repo.ui,rev=self.repoview.selectedRevisions(),repo=self.repo)defrupdate(self):run.rupdate(self.repo.ui,rev=self.rev,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_()defbundleRevisions(self,base=None,tip=None):root=self.repo.rootifbaseisNoneorbaseisFalse:base=self.revdata=dict(name=os.path.basename(root),base=base)iftipisNone:filename='%(name)s_%(base)s_to_tip.hg'%dataelse:data.update(rev=tip)filename='%(name)s_%(base)s_to_%(rev)s.hg'%datafile=QFileDialog.getSaveFileName(self,_('Write bundle'),hglib.tounicode(os.path.join(root,filename)))ifnotfile:returncmdline=['bundle','--verbose','--repository',root]parents=[r.rev()==-1and'null'orstr(r.rev())forrinself.repo[base].parents()]forpinparents:cmdline.extend(['--base',p])iftip:cmdline.extend(['--rev',str(tip)])else:cmdline.extend(['--rev','heads(descendants(%s))'%base])cmdline.append(hglib.fromunicode(file))self.runCommand(cmdline)defcopyPatch(self,returnval=False):frommercurialimportcommands_ui=self.repo.ui_ui.pushbuffer()try:ifself.revandlen(self.menuselection)==1:classWritable(object):defwrite(self,*args,**opts):_ui.write(*args,**opts)defclose(self):passcommands.export(_ui,self.repo,self.rev,output=Writable())else:revs=self.revandself.menuselectionorNonecommands.diff(_ui,self.repo,rev=revs)exceptNameError:raiseexceptException,e:_ui.popbuffer()self.showMessage(hglib.tounicode(str(e)))if'THGDEBUG'inos.environ:importtracebacktraceback.print_exc()returnoutput=_ui.popbuffer()ifreturnval:returnoutputelse:QApplication.clipboard().setText(hglib.tounicode(output))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=''# Check whether there are existing patches in the MQ queue whose name# collides with the revisions that are going to be importedfunc=hglib.revsetmatch(self.repo.ui,'%s::%s'%(self.rev,endrev))revList=[cforcinfunc(self.repo,range(len(self.repo)))]ifendrevandnotrevList:# There is a qparent but the revision list is empty# This means that the qparent is not a descendant of the# selected revisionQMessageBox.warning(self,_('Cannot import selected revision'),_('The selected revision (rev #%d) cannot be imported ''because it is not a descendant of ''qparent'' (rev #%d)') \
%(self.rev,self.repo['qparent'].rev()))returnrevNameSet=set(['%d.diff'%revforrevinrevList])collidingPatchSet=revNameSet.intersection(set(self.repo.mq.series))ifcollidingPatchSet:# We will qimport each revision one by one, starting from the newest# To do so, we will find a valid and unique patch name for each# revision that we must qimport# and then we will import them one by one starting from the newest# one, using these unique namesdefgetUniquePatchName(baseName):patchName=baseName+'.diff'ifpatchNameincollidingPatchSet:maxRetries=99forninrange(1,maxRetries):patchName=baseName+'_%02d.diff'%nifnotpatchNameincollidingPatchSet:breakreturnpatchNamepatchNames={}revList.reverse()forrevinrevList:patchNames[rev]=getUniquePatchName(str(rev))cmdlines=[]forrevinrevList:cmdlines.append(['qimport','--rev','%s'%rev,'--repository',self.repo.root,'--name',patchNames[rev]])self.runCommand(*cmdlines)else:# There were no collisions with existing patch names, we can# simply qimport the whole revision set in a single gocmdline=['qimport','--rev','%s::%s'%(self.rev,endrev),'--repository',self.repo.root]self.runCommand(cmdline)defqfinishRevision(self):"""Finish applied patches up to and including selected revision"""cmdline=['qfinish','qbase::%s'%self.rev,'--repository',self.repo.root]self.runCommand(cmdline)defqgotoRevision(self):"""Make REV the top applied patch"""defqpopAll(repo):cmdline=['qpop','--all','--repository',repo.root]self.runCommand(cmdline)ctx=self.repo.changectx(self.rev)if'qparent'inctx.tags():returnqpopAll(self.repo)try:applied=ctx.thgmqappliedpatch()mqpatch=Trueexcept:applied=Truemqpatch=Falseifmqpatchandappliedand'qparent'inctx.p1().tags():returnqpopAll(self.repo)ifnotapplied:patchname=self.repo.changectx(self.rev).thgmqpatchname()else:thgp1=self.repo.changectx(self.repo.changectx(self.rev).p1().node())patchname=thgp1.thgmqpatchname()self.taskTabsWidget.setCurrentIndex(self.mqTabIndex)self.mqDemand.forward('qgotoRevision',patchname)defqrename(self):sel=self.menuselection[0]ifnotisinstance(sel,str):sel=self.repo.changectx(sel).thgmqpatchname()dlg=qrename.QRenameDialog(self.repo,sel,self)dlg.finished.connect(dlg.deleteLater)dlg.output.connect(self.output)dlg.makeLogVisible.connect(self.makeLogVisible)dlg.exec_()defqpushMoveRevision(self):"""Make REV the top applied patch"""ctx=self.repo.changectx(self.rev)patchname=ctx.thgmqpatchname()cmdline=['qpush','--move',str(patchname),'--repository',self.repo.root]self.runCommand(cmdline)defonCommandFinished(self,ret):self.repo.decrementBusyCount()defrunCommand(self,*cmdlines):ifself.runner.core.running():InfoMsgBox(_('Unable to start'),_('Previous command is still running'))returnself.repo.incrementBusyCount()self.runner.run(*cmdlines)
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.