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.
# history.py - Changelog dialog for TortoiseHg## Copyright 2007 Brad Schick, brad at gmail . com# Copyright 2008 Steve Borho <steve@borho.org>## This software may be used and distributed according to the terms of the# GNU General Public License version 2, incorporated herein by reference.importosimportsysimportgtkimportgobjectimportQueueimportshutilimporttempfileimportatexitfrommercurialimportui,hg,cmdutil,commands,extensions,util,match,urlfromtortoisehg.util.i18nimport_fromtortoisehg.utilimporthglib,thread2fromtortoisehg.hgtk.logview.treeviewimportTreeViewasLogTreeViewfromtortoisehg.hgtkimportgdialog,gtklib,hgcmd,gorev,thgstripfromtortoisehg.hgtkimportbackout,status,hgemail,tagadd,update,mergefromtortoisehg.hgtkimportarchive,changeset,thgconfig,thgmq,histdetailsdefcreate_menu(label,callback):menuitem=gtk.MenuItem(label,True)menuitem.connect('activate',callback)menuitem.set_border_width(1)returnmenuitemclassGLog(gdialog.GDialog):'GTK+ based dialog for displaying repository logs'definit(self):self.filter='all'self.no_merges=Falseself.lastrevid=Noneself.currevid=Noneself.origtip=len(self.repo)self.ready=Falseself.filterbox=Noneself.details_model=Noneself.syncbox=Noneself.filteropts=Noneself.bundledir=Noneself.bfile=Noneself.npreviews=0self.outgoing=[]self.useproxy=Noneself.revrange=Noneself.forcepush=Falseos.chdir(self.repo.root)# Load extension support for commands which need itextensions.loadall(self.ui)self.exs=[nameforname,moduleinextensions.extensions()]defget_help_url(self):return'changelog.html'defget_title(self):str=_('%s - changelog')%self.get_reponame()ifself.bfile:str+=_(' (Bundle Preview)')returnstrdefget_icon(self):return'menulog.ico'defget_default_setting(self):return'tortoisehg.authorcolor'defparse_opts(self):# Disable quiet to get full log infoself.ui.quiet=Falsedefget_tbbuttons(self):tbar=[self.make_toolbutton(gtk.STOCK_REFRESH,_('Re_fresh'),self.refresh_clicked,name='refresh',tip=_('Reload revision history')),gtk.SeparatorToolItem(),self.make_toolbutton(gtk.STOCK_NETWORK,_('Synchronize'),self.synch_clicked,name='synchronize',tip=_('Launch synchronize tool')),gtk.SeparatorToolItem(),]if'mq'inself.exs:self.mqtb=self.make_toolbutton(gtk.STOCK_DIRECTORY,_('Patch Queue'),self.mq_clicked,name='mq',tip=_('Show/Hide Patch Queue'),toggle=True,icon='menupatch.ico')tbar+=[self.mqtb,gtk.SeparatorToolItem()]returntbardefget_menu_list(self):deftoggle_proxy(menuitem):self.useproxy=menuitem.get_active()deftoggle_force(menuitem):self.forcepush=menuitem.get_active()defrefresh(menuitem,resetmarks):ifresetmarks:self.outgoing=[]self.origtip=len(self.repo)self.reload_log()defnavigate(menuitem,revname):ifrevname:self.goto_rev(revname)elifself.gorev_dialog:self.gorev_dialog.show()self.gorev_dialog.present()else:self.show_goto_dialog()defdisable_maxdiff(menuitem):ifmenuitem.get_active():hglib._maxdiff=sys.maxintelse:hglib._maxdiff=Noneself.reload_log()lb=self.get_live_branches()bmenus=[]iflen(lb)>1or(lbandlb[0]!='default'):bmenus.append(dict(text='----'))fornameinlb[:10]:bmenus.append(dict(text=hglib.toutf(name),func=navigate,args=[name]))fnc=self.toggle_view_columnifself.repo.ui.configbool('tortoisehg','disable-syncbar'):sync_bar_item=[]else:sync_bar_item=[dict(text=_('Sync Bar'),ascheck=True,func=self.toggle_show_syncbar,check=self.show_syncbar)]if'mq'inself.exs:mq_item=[dict(text=_('Patch Queue'),name='mq',ascheck=True,func=self.mq_clicked,check=self.setting_mqvis)]else:mq_item=[]return[(_('_View'),[dict(text=_('Load more Revisions'),name='load-more',func=self.more_clicked,icon=gtk.STOCK_GO_DOWN),dict(text=_('Load all Revisions'),name='load-all',func=self.load_all_clicked,icon=gtk.STOCK_GOTO_BOTTOM),dict(text='----'),dict(text=_('Toolbar'),ascheck=True,check=self.show_toolbar,func=self.toggle_show_toolbar),]+sync_bar_item+[dict(text=_('Filter Bar'),ascheck=True, func=self.toggle_show_filterbar, check=self.show_filterbar),
] + mq_item + [
dict(text='----'),
+ dict(text=_('Other Parent'), name='other-parent', + ascheck=True, check=False, sensitive=False,+ func=self.parent_toggled),+ dict(text='----'), dict(text=_('Choose Details...'), func=self.details_clicked),
dict(text='----'),
dict(text=_('Refresh'), func=refresh, args=[False],
icon=gtk.STOCK_REFRESH),dict(text=_('Reset Marks'),func=refresh,args=[True],icon=gtk.STOCK_REMOVE),dict(text='----'),dict(name='compact-graph',text=('Compact Graph'),ascheck=True,func=self.toggle_compactgraph,check=self.compactgraph),dict(name='color-by-branch',text=_('Color by Branch'),ascheck=True,func=self.toggle_branchcolor,check=self.branch_color),dict(text=_('Ignore Max Diff Size'),ascheck=True,func=disable_maxdiff),]),(_('_Navigate'),[dict(text=_('Tip'),func=navigate,args=['tip']),dict(text=_('Working Parent'),func=navigate,args=['.']),dict(text='----'),dict(text=_('Revision...'),func=navigate,args=[None]),]+bmenus),(_('_Synchronize'),[dict(text=_('Incoming'),name='incoming',func=self.incoming_clicked),dict(text=_('Pull'),name='pull',func=self.pull_clicked),dict(text=_('Outgoing'),name='outgoing',func=self.outgoing_clicked),dict(text=_('Push'),name='push',func=self.push_clicked),dict(text=_('Email...'),name='email',func=self.email_clicked),dict(text='----'),dict(text=_('Add Bundle...'),name='add-bundle',sensitive=notbool(self.bfile),func=self.add_bundle_clicked),dict(text=_('Accept Bundle'),name='accept',sensitive=bool(self.bfile),func=self.apply_clicked,icon=gtk.STOCK_APPLY),dict(text=_('Reject Bundle'),name='reject',sensitive=bool(self.bfile),func=self.reject_clicked,icon=gtk.STOCK_DIALOG_ERROR),dict(text='----'),dict(name='use-proxy-server',text=_('Use proxy server'),ascheck=True,func=toggle_proxy),dict(text=_('Force push'),ascheck=True,func=toggle_force), ])
]
+ def parent_toggled(self, item):+ pass+ def synch_clicked(self, toolbutton, data):
def sync_closed(dialog):
self.cmd_set_sensitive('synchronize', True)
defsynch_callback(parents):self.repo.invalidate()newparents=[x.node()forxinself.repo.parents()]ifparents!=newparents:self.refresh_model()fromtortoisehg.hgtkimportsynchparents=[x.node()forxinself.repo.parents()]dlg=synch.SynchDialog([],False)dlg.set_notify_func(synch_callback,parents)dlg.connect('destroy',sync_closed)dlg.show_all()self.cmd_set_sensitive('synchronize',False)deftoggle_view_column(self,button,property):active=button.get_active()self.graphview.set_property(property,active)deftoggle_branchcolor(self,button):active=button.get_active()ifself.branch_color!=active:self.graphview.set_property('branch-color',active)self.branch_color=activeself.reload_log()deftoggle_compactgraph(self,button):active=button.get_active()ifself.compactgraph!=active:self.compactgraph=activeself.reload_log()deftoggle_show_filterbar(self,button):self.show_filterbar=button.get_active()ifself.filterboxisnotNone:self.filterbox.set_property('visible',self.show_filterbar)deftoggle_show_syncbar(self,button):self.show_syncbar=button.get_active()ifself.syncboxisnotNone:self.syncbox.set_property('visible',self.show_syncbar)deftoggle_show_toolbar(self,button):self.show_toolbar=button.get_active()self.toolbar.set_property('visible',self.show_toolbar)defmore_clicked(self,button,data=None):self.graphview.next_revision_batch(self.limit)defload_all_clicked(self,button,data=None):self.graphview.load_all_revisions()self.cmd_set_sensitive('load-more',False)self.cmd_set_sensitive('load-all',False)defselection_changed(self,graphview):'Graphview reports a new row selected'treeview=graphview.treeview(model,paths)=treeview.get_selection().get_selected_rows()ifnotpaths:self.currevid=NonereturnFalseself.currevid=graphview.get_revid_at_path(paths[0])self.ancestrybutton.set_sensitive(True)ifself.currevid!=self.lastrevid:self.lastrevid=self.currevidself.changeview.opts['rev']=[str(self.currevid)]self.changeview.load_details(self.currevid)returnFalsedefrevisions_loaded(self,graphview):'Graphview reports log generator has exited'ifnotgraphview.graphdata:self.changeview._buffer.set_text('')self.changeview._filelist.clear()self.cmd_set_sensitive('load-more',False)self.cmd_set_sensitive('load-all',False)defdetails_clicked(self,toolbutton,data=None):self.show_details_dialog()defshow_details_dialog(self):columns={}columns['graph']=(self.graphcol,_('Graph'),'graphcol','graph')defcolumn(col,text):prop=col+'-column-visible'vis=self.graphview.get_property(prop)columns[col]=(vis,text,prop,col)column('rev',_('Revision Number'))column('id',_('Changeset ID'))column('branch',_('Branch Name'))column('msg',_('Summary'))column('user',_('User'))column('date',_('Local Date'))column('utc',_('UTC Date'))column('age',_('Age'))column('tag',_('Tags'))model=gtk.ListStore(gobject.TYPE_BOOLEAN,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING)forcinself.graphview.get_columns():vis,text,prop,col=columns[c]model.append([vis,text,prop,col])self.details_model=modeldlg=histdetails.LogDetailsDialog(model,self.apply_details)dlg.show()defapply_details(self):ifself.details_model:columns=[]forshow,uitext,property,colnameinself.details_model:columns.append(colname)self.graphview.set_columns(columns)self.column_order=' '.join(columns)reload=Falseforshow,uitext,property,colnameinself.details_model:ifproperty=='graphcol':ifself.graphcol!=show:self.graphcol=showreload=Trueself.cmd_set_sensitive('compact-graph',self.graphcol)self.cmd_set_sensitive('color-by-branch',self.graphcol)else:self.graphview.set_property(property,show)self.showcol[property]=showifreload:self.reload_log()deffilter_entry_activated(self,entry,combo):'User pressed enter in the filter entry'opts={}mode=combo.get_active()text=entry.get_text()ifnottext:returnifmode==0:# Rev Rangetry:opts['revs']=cmdutil.revrange(self.repo,[text])exceptException,e:gdialog.Prompt(_('Invalid revision range'),str(e),self).run()returnelifmode==1:# File Patternsopts['pats']=[w.strip()forwintext.split(',')]elifmode==2:# Keywordsopts['keyword']=[w.strip()forwintext.split(',')]elifmode==3:# Datetry:# return of matchdate not used, just sanity checkingutil.matchdate(text)opts['date']=textexcept(ValueError,util.Abort),e:gdialog.Prompt(_('Invalid date specification'),str(e),self).run()returnelifmode==4:# Useropts['user']=[w.strip()forwintext.split(',')]else:returnself.custombutton.set_active(True)self.filter='custom'self.reload_log(**opts)deffilter_selected(self,widget,type):iftype=='no_merges':self.no_merges=widget.get_active()self.reload_log()returnifnotwidget.get_active():returniftype=='branch':self.select_branch(self.branchcombo)returnself.filter=typeself.filteropts=Noneself.reload_log()defupdate_hide_merges_button(self):compatible=self.filterin['all','branch','custom']ifcompatible:self.hidemerges.set_sensitive(True)else:self.hidemerges.set_active(False)self.hidemerges.set_sensitive(False)self.no_merges=Falsedefpatch_selected(self,mqwidget,revid,patchname):ifrevid<0:patchfile=os.path.join(self.repo.root,'.hg','patches',patchname)self.currevid=self.lastrevid=Noneself.changeview.load_patch_details(patchfile)else:self.currevid=revidifself.currevid!=self.lastrevid:self.lastrevid=self.currevidself.changeview.opts['rev']=[str(self.currevid)]self.changeview.load_details(self.currevid)defrepo_invalidated(self,mqwidget):self.reload_log()defprepare_display(self):'Called at end of display() method'self.ready=Trueroot=self.repo.rootos.chdir(root)# for paths relative to repo rootself.origtip=len(self.repo)self.graphview.set_property('branch-color',self.branch_color)# ignore file patterns that imply repo rootiflen(self.pats)==1andself.pats[0]in(root,root+os.sep,''):self.pats=[]opts=self.optsifopts['filehist']:self.custombutton.set_active(True)self.filter='custom'self.filtercombo.set_active(1)self.filterentry.set_text(opts['filehist'])opts['pats']=[opts['filehist']]elifself.pats:self.custombutton.set_active(True)self.filter='custom'self.filtercombo.set_active(1)self.filterentry.set_text(', '.join(self.pats))opts['pats']=self.patsself.reload_log(**opts)# unfortunately, idle_add is needed heregtklib.idle_add_single_call(self.toolbar.set_property,'visible',self.show_toolbar)self.filterbox.set_property('visible',self.show_filterbar)self.filterbox.set_no_show_all(True)self.syncbox.set_property('visible',self.show_syncbar)self.syncbox.set_no_show_all(True)forcolin('rev','date','id','branch','utc','age','tag'):ifcolinself.showcol:self.graphview.set_property(col+'-column-visible',self.showcol[col])try:self.graphview.set_columns(self.column_order.split())exceptKeyError:# ignore unknown column names, these could originate from garbeled# persisted datapassself.cmd_set_sensitive('compact-graph',self.graphcol)self.cmd_set_sensitive('color-by-branch',self.graphcol)item=self.get_menuitem('use-proxy-server')ifui.ui().config('http_proxy','host'):item.set_sensitive(True)item.set_active(True)else:item.set_sensitive(False)# enable MQ panelself.enable_mqpanel()defget_proxy_args(self):item=self.get_menuitem('use-proxy-server')ifitem.get_property('sensitive')andnotitem.get_active():return['--config','http_proxy.host=']else:return[]defget_graphlimit(self,suggestion):limit_opt=self.repo.ui.config('tortoisehg','graphlimit','500')l=0forlimitin(suggestion,limit_opt):try:l=int(limit)ifl>0:returnlexcept(TypeError,ValueError):passreturnlor500defsave_settings(self):settings=gdialog.GDialog.save_settings(self)settings['glog-vpane']=self.vpaned.get_position()settings['glog-hpane']=self.hpaned.get_position()ifhasattr(self,'mqpaned')andself.mqwidget.has_patch():curpos=self.mqpaned.get_position()settings['glog-mqpane']=curposorself.setting_mqhpossettings['glog-mqvis']=bool(curpos)else:settings['glog-mqpane']=self.setting_mqhpossettings['glog-mqvis']=self.setting_mqvissettings['branch-color']=self.graphview.get_property('branch-color')settings['show-toolbar']=self.show_toolbarsettings['show-filterbar']=self.show_filterbarsettings['show-syncbar']=self.show_syncbarsettings['graphcol']=self.graphcolsettings['compactgraph']=self.compactgraphforcolin('rev','date','id','branch','utc','age','tag'):vis=self.graphview.get_property(col+'-column-visible')settings['glog-vis-'+col]=vissettings['filter-mode']=self.filtercombo.get_active()settings['column-order']=' '.join(self.graphview.get_columns())returnsettingsdefload_settings(self,settings):'Called at beginning of display() method'gdialog.GDialog.load_settings(self,settings)self.setting_vpos=settings.get('glog-vpane',-1)self.setting_hpos=settings.get('glog-hpane',-1)self.setting_mqhpos=settings.get('glog-mqpane',140)or140self.setting_mqvis=settings.get('glog-mqvis',False)self.branch_color=settings.get('branch-color',False)self.show_toolbar=settings.get('show-toolbar',True)self.show_filterbar=settings.get('show-filterbar',True)self.show_syncbar=settings.get('show-syncbar',True)ifself.repo.ui.configbool('tortoisehg','disable-syncbar'):self.show_syncbar=Falseself.graphcol=settings.get('graphcol',True)self.compactgraph=settings.get('compactgraph',False)self.showcol={}forcolin('rev','date','id','branch','utc','age','tag'):key='glog-vis-'+colifkeyinsettings:self.showcol[col]=settings[key]self.filter_mode=settings.get('filter-mode',1)default_co='graph rev id branch msg user date utc age tag'self.column_order=settings.get('column-order',default_co)defrefresh_model(self):'Refresh data in the history model, without reloading graph'ifself.graphview.model:self.graphview.model.refresh()# refresh MQ widget if existsifhasattr(self,'mqwidget'):self.mqwidget.refresh()# force a redraw of the visible rowsself.graphview.hide()self.graphview.show()defreload_log(self,**kwopts):'Send refresh event to treeview object'self.update_hide_merges_button()opts={'date':None,'no_merges':False,'only_merges':False,'keyword':[],'branch':None,'pats':[],'filehist':None,'revrange':[],'revlist':[],'noheads':False,'branch-view':False,'rev':[],'user':[]}ifself.filteroptsandnotkwopts:opts=self.filteroptsopts.update(kwopts)# handle strips, rebases, etcself.origtip=min(len(self.repo),self.origtip)ifnotself.bfile:self.npreviews=0opts['branch-view']=self.compactgraphopts['outgoing']=self.outgoingopts['orig-tip']=self.origtipopts['npreviews']=self.npreviewsopts['no_merges']=self.no_mergesself.cmd_set_sensitive('load-more',True)self.cmd_set_sensitive('load-all',True)self.ancestrybutton.set_sensitive(False)pats=opts.get('pats',[])self.changeview.pats=patsself.lastrevid=Nonedefftitle(filtername):t=self.get_title()iffilternameisnotNone:t=t+' - '+filternameself.set_title(t)ifself.filter!='custom':self.filterentry.set_text('')graphcol=self.graphcolifself.no_merges:graphcol=Falsefilterprefix=_('Filter')filtertext=filterprefix+': 'ifself.filter=='branch':branch=opts.get('branch',None)self.graphview.refresh(graphcol,None,opts)ftitle(_('%s branch')%branch)filtertext+=_("Branch '%s'")%branchelifself.filter=='custom':npats=hglib.normpats(pats)iflen(npats)==1:kind,name=match._patsplit(npats[0],None)ifkind=='path'andnotos.path.isdir(name):ftitle(_('file history: ')+hglib.toutf(name))opts['filehist']=nameself.graphview.refresh(graphcol,[name],opts)ifnotopts.get('filehist'):ftitle(_('custom filter'))self.graphview.refresh(False,npats,opts)filtertext+=self.filtercombo.get_active_text()elifself.filter=='all':ftitle(None)self.graphview.refresh(graphcol,None,opts)filtertext=''elifself.filter=='only_merges':ftitle(_('merges'))opts['only_merges']=Trueself.graphview.refresh(False,[],opts)filtertext+=_('only Merges')elifself.filter=='ancestry':ftitle(_('revision ancestry'))range=[self.currevid,0]opts['noheads']=Trueopts['revrange']=rangeself.graphview.refresh(graphcol,None,opts)filtertext+=_("Ancestry of %s")%self.currevidelifself.filter=='tagged':ftitle(_('tagged revisions'))tagged=[]fort,rinself.repo.tagslist():hr=self.repo[r].rev()ifhrnotintagged:tagged.insert(0,hr)opts['revlist']=taggedself.graphview.refresh(False,[],opts)filtertext+=_("Tagged Revisions")elifself.filter=='parents':ftitle(_('working parents'))repo_parents=[x.rev()forxinself.repo.parents()]opts['revlist']=[str(x)forxinrepo_parents]self.graphview.refresh(False,[],opts)filtertext+=_("Parents")elifself.filter=='heads':ftitle(_('heads'))heads=[self.repo[x].rev()forxinself.repo.heads()]opts['revlist']=[str(x)forxinheads]self.graphview.refresh(False,[],opts)filtertext+=_("Heads")nomergestext=_('no Merges')ifself.no_merges:iffiltertext:filtertext+=', %s'%nomergestextelse:filtertext='%s: %s'%(filterprefix,nomergestext)self.stbar.set_right2_text(filtertext)# refresh MQ widget if existsifhasattr(self,'mqwidget'):self.mqwidget.refresh()# Remember options to next time reload_log is calledself.filteropts=optsdeftree_context_menu(self):m=gtklib.MenuItems()m.append(create_menu(_('Visualize Change'),self.vdiff_change))m.append(create_menu(_('Di_splay Change'),self.show_status))m.append(create_menu(_('Diff to local'),self.vdiff_local))m.append_sep()m.append(create_menu(_('_Copy hash'),self.copy_hash))ifself.bfile:ifself.currevid>=len(self.repo)-self.npreviews:m.append_sep()m.append(create_menu(_('Pull to here'),self.pull_to))menu=m.create_menu()menu.show_all()returnmenuifself.repo[self.currevid].node()inself.outgoing:m.append_sep()m.append(create_menu(_('Push to here'),self.push_to))m.append_sep()m.append(create_menu(_('_Update...'),self.checkout))cmenu_merge=create_menu(_('_Merge with...'),self.domerge)m.append(cmenu_merge)m.append_sep()m.append(create_menu(_('_Export Patch...'),self.export_patch))m.append(create_menu(_('E_mail Patch...'),self.email_patch))m.append(create_menu(_('_Bundle rev:tip...'),self.bundle_rev_to_tip))m.append_sep()m.append(create_menu(_('Add/Remove _Tag...'),self.add_tag))cmenu_backout=create_menu(_('Backout Revision...'),self.backout_rev)m.append(cmenu_backout)m.append(create_menu(_('_Revert'),self.revert))m.append(create_menu(_('_Archive...'),self.archive))# disable/enable menus as requiredparents=self.repo.parents()iflen(parents)>1:can_merge=Falsecan_backout=Falseelse:pctx=parents[0]cctx=self.repo[self.currevid]actx=cctx.ancestor(pctx)can_merge=actx!=pctxorpctx.branch()!=cctx.branch()can_backout=actx==cctxcmenu_merge.set_sensitive(can_merge)cmenu_backout.set_sensitive(can_backout)# need transplant extension for transplant commandif'transplant'inself.exs:m.append(create_menu(_('Transp_lant to local'),self.transplant_rev))# need mq extension for strip commandif'mq'inself.exs:cmenu_qimport=create_menu(_('qimport'),self.qimport_rev)cmenu_strip=create_menu(_('Strip Revision...'),self.strip_rev)try:ctx=self.repo[self.currevid]qbase=self.repo['qbase']actx=ctx.ancestor(qbase)ifself.repo['qparent']==ctx:cmenu_qimport.set_sensitive(True)cmenu_strip.set_sensitive(False)elifactx==qbaseoractx==ctx:# we're in the mq revision range or the mq# is a descendant of uscmenu_qimport.set_sensitive(False)cmenu_strip.set_sensitive(False)except:passm.append_sep()m.append(cmenu_qimport)m.append(cmenu_strip)menu=m.create_menu()menu.show_all()returnmenudefrestore_single_sel(self,widget,*args):self.tree.get_selection().set_mode(gtk.SELECTION_SINGLE)self.tree.get_selection().select_path(self.origsel)self.revrange=Nonedeftree_diff_context_menu(self):m=gtklib.MenuItems()m.append(create_menu(_('_Diff with selected'),self.diff_revs))m.append(create_menu(_('Visual Diff with selected'),self.vdiff_selected))ifself.bfile:menu=m.create_menu()menu.connect_after('selection-done',self.restore_single_sel)menu.show_all()returnmenum.append_sep()m.append(create_menu(_('Email from here to selected...'),self.email_revs))m.append(create_menu(_('Bundle from here to selected...'),self.bundle_revs))m.append(create_menu(_('Export Patches from here to selected...'),self.export_revs))m.append_sep()cmenu_merge=create_menu(_('_Merge with...'),self.domerge)m.append(cmenu_merge)m.append_sep()# disable/enable menus as requiredparents=self.repo.parents()iflen(parents)>1:can_merge=Falseelse:rev0,rev1=self.revrangec0,c1=self.repo[rev0],self.repo[rev1]can_merge=c0.branch()!=c1.branch()orc0.ancestor(c1)!=c1cmenu_merge.set_sensitive(can_merge)# need transplant extension for transplant commandif'transplant'inself.exs:m.append(create_menu(_('Transplant Revision range to local'),self.transplant_revs))# need rebase extension for rebase commandif'rebase'inself.exs:m.append(create_menu(_('Rebase on top of selected'),self.rebase_selected))# need MQ extension for qimport commandif'mq'inself.exs:m.append(create_menu(_('qimport from here to selected'),self.qimport_revs))menu=m.create_menu()menu.connect_after('selection-done',self.restore_single_sel)menu.show_all()returnmenudefget_body(self):self.gorev_dialog=Noneself.stbar=gtklib.StatusBar()self.limit=self.get_graphlimit(None)# Allocate TreeView instance to use internallylimit=self.limitifself.opts['limit']:limit=self.get_graphlimit(self.opts['limit'])self.graphview=LogTreeView(self.repo,limit,self.stbar)# Allocate ChangeSet instance to use internallyself.changeview=changeset.ChangeSet(self.ui,self.repo,self.cwd,[],self.opts,self.stbar)self.changeview.display(False)self.changeview.glog_parent=self# Add extra toolbar buttonssep=gtk.SeparatorToolItem()sep.set_expand(True)sep.set_draw(False)loadnext=self.make_toolbutton(gtk.STOCK_GO_DOWN,_('Load more'),self.more_clicked,tip=_('load more revisions'),name='load-more')loadall=self.make_toolbutton(gtk.STOCK_GOTO_BOTTOM,_('Load all'),self.load_all_clicked,tip=_('load all revisions'),name='load-all')tbar=self.changeview.get_tbbuttons()tbar+=[sep,loadnext,loadall]fortbuttonintbar:self.toolbar.insert(tbutton,-1)# PyGtk 2.6 and below did not automatically register typesifgobject.pygtk_version<(2,8,0):gobject.type_register(LogTreeView)self.tree=self.graphview.treeviewself.graphview.connect('revision-selected',self.selection_changed)self.graphview.connect('revisions-loaded',self.revisions_loaded)self.tree.connect('popup-menu',self.tree_popup_menu)self.tree.connect('button-press-event',self.tree_button_press)self.tree.connect('row-activated',self.tree_row_act)accelgroup=gtk.AccelGroup()self.add_accel_group(accelgroup)mod=gtklib.get_thg_modifier()key,modifier=gtk.accelerator_parse(mod+'d')self.tree.add_accelerator('thg-diff',accelgroup,key,modifier,gtk.ACCEL_VISIBLE)self.tree.connect('thg-diff',self.thgdiff)key,modifier=gtk.accelerator_parse(mod+'p')self.tree.add_accelerator('thg-parent',accelgroup,key,modifier,gtk.ACCEL_VISIBLE)self.tree.connect('thg-parent',self.thgparent)key,modifier=gtk.accelerator_parse(mod+'g')self.tree.add_accelerator('thg-revision',accelgroup,key,modifier,gtk.ACCEL_VISIBLE)self.tree.connect('thg-revision',self.thgnavigate)self.connect('thg-refresh',self.thgrefresh)# synch barself.syncbox=gtklib.SlimToolbar(self.tooltips)syncbox=self.syncboxincoming=syncbox.append_stock(gtk.STOCK_GO_DOWN,_('Download and view incoming changesets'))pull=syncbox.append_stock(gtk.STOCK_GOTO_BOTTOM,_('Pull incoming changesets'))outgoing=syncbox.append_stock(gtk.STOCK_GO_UP,_('Determine and mark outgoing changesets'))push=syncbox.append_stock(gtk.STOCK_GOTO_TOP,_('Push outgoing changesets'))email=syncbox.append_stock(gtk.STOCK_GOTO_LAST,_('Email outgoing changesets'))conf=syncbox.append_stock(gtk.STOCK_PREFERENCES,_('Configure aliases and after pull behavior'))stop=syncbox.append_stock(gtk.STOCK_STOP,_('Stop current transaction'))stop.set_sensitive(False)self.stop_button=stop## target path comboboxurllist=gtk.ListStore(str,str)urlcombo=gtk.ComboBoxEntry(urllist,0)cell=gtk.CellRendererText()urlcombo.pack_end(cell,False)urlcombo.add_attribute(cell,'text',1)self.urlcombo=urlcomboself.pathentry=urlcombo.get_child()syncbox.append_widget(urlcombo,expand=True)foralias,pathinself.repo.ui.configitems('paths'):path=url.hidepassword(path)urllist.append([hglib.toutf(path),hglib.toutf(alias)])ifalias=='default':urlcombo.set_active(len(urllist)-1)incoming.connect('clicked',self.incoming_clicked)pull.connect('clicked',self.pull_clicked)outgoing.connect('clicked',self.outgoing_clicked)push.connect('clicked',self.push_clicked)conf.connect('clicked',self.conf_clicked,urlcombo)email.connect('clicked',self.email_clicked)syncbox.append_widget(gtk.Label(_('After Pull:')))ppulldata=[('none',_('Nothing')),('update',_('Update'))]ppull=self.repo.ui.config('tortoisehg','postpull','none')if'fetch'inself.exsor'fetch'==ppull:ppulldata.append(('fetch',_('Fetch')))if'rebase'inself.exsor'rebase'==ppull:ppulldata.append(('rebase',_('Rebase')))self.ppullcombo=gtk.combo_box_new_text()ppullcombo=self.ppullcombofor(index,(name,label))inenumerate(ppulldata):ppullcombo.insert_text(index,label)for(index,(name,label))inenumerate(ppulldata):ifppull==name:pos=indexbreak;else:pos=[indexfor(index,(name,label))inenumerate(ppulldata)ifname=='none'][0]ppullcombo.set_active(pos)self.ppullcombo=ppullcomboself.ppulldata=ppulldatasyncbox.append_widget(ppullcombo)# filter barself.filterbox=gtklib.SlimToolbar()filterbox=self.filterboxall=gtk.RadioButton(None,_('All'))all.set_active(True)all.connect('toggled',self.filter_selected,'all')filterbox.append_widget(all,padding=0)tagged=gtk.RadioButton(all,_('Tagged'))tagged.connect('toggled',self.filter_selected,'tagged')filterbox.append_widget(tagged,padding=0)ancestry=gtk.RadioButton(all,_('Ancestry'))ancestry.connect('toggled',self.filter_selected,'ancestry')filterbox.append_widget(ancestry,padding=0)self.ancestrybutton=ancestryparents=gtk.RadioButton(all,_('Parents'))parents.connect('toggled',self.filter_selected,'parents')filterbox.append_widget(parents,padding=0)heads=gtk.RadioButton(all,_('Heads'))heads.connect('toggled',self.filter_selected,'heads')filterbox.append_widget(heads,padding=0)merges=gtk.RadioButton(all,_('Merges'))merges.connect('toggled',self.filter_selected,'only_merges')filterbox.append_widget(merges,padding=0)hidemerges=gtk.CheckButton(_('Hide Merges'))hidemerges.connect('toggled',self.filter_selected,'no_merges')filterbox.append_widget(hidemerges,padding=0)self.hidemerges=hidemergesbranches=gtk.RadioButton(all,_('Branch'))branches.connect('toggled',self.filter_selected,'branch')branches.set_sensitive(False)filterbox.append_widget(branches,padding=0)self.branchbutton=branchesbranchcombo=gtk.combo_box_new_text()fornameinself.get_live_branches():branchcombo.append_text(hglib.toutf(name))branchcombo.connect('changed',self.select_branch)self.lastbranchrow=Nonefilterbox.append_widget(branchcombo,padding=0)self.branchcombo=branchcomboself.custombutton=gtk.RadioButton(all,_('Custom'))self.custombutton.set_sensitive(False)filterbox.append_widget(self.custombutton,padding=0)filtercombo=gtk.combo_box_new_text()filtercombo_entries=(_('Rev Range'),_('File Patterns'),_('Keywords'),_('Date'),_('User'))forfinfiltercombo_entries:filtercombo.append_text(f)if(self.filter_mode>=len(filtercombo_entries)orself.filter_mode<0):self.filter_mode=1filtercombo.set_active(self.filter_mode)self.filtercombo=filtercombofilterbox.append_widget(filtercombo,padding=0)entry=gtk.Entry()entry.connect('activate',self.filter_entry_activated,filtercombo)self.filterentry=entryfilterbox.append_widget(entry,expand=True,padding=0)midpane=gtk.VBox()midpane.pack_start(syncbox,False)midpane.pack_start(filterbox,False)midpane.pack_start(self.graphview)midpane.show_all()# MQ widgetif'mq'inself.exs:# create MQWidgetself.mqwidget=thgmq.MQWidget(self.repo,self.stbar.set_right3_text,accelgroup,self.tooltips)self.mqwidget.connect('patch-selected',self.patch_selected)self.mqwidget.connect('repo-invalidated',self.repo_invalidated)defwrapframe(widget):frame=gtk.Frame()frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)frame.add(widget)returnframeself.mqpaned=gtk.HPaned()self.mqpaned.add1(wrapframe(self.mqwidget))self.mqpaned.add2(wrapframe(midpane))midpane=self.mqpaned# Add ChangeSet instance to bottom half of vpaneself.changeview.graphview=self.graphviewself.hpaned=self.changeview.get_body()self.vpaned=gtk.VPaned()self.vpaned.pack1(midpane,True,False)self.vpaned.pack2(self.hpaned)gtklib.idle_add_single_call(self.realize_settings)vbox=gtk.VBox()vbox.pack_start(self.vpaned,True,True)returnvboxdefget_extras(self):returnself.stbardefapply_clicked(self,button):ppullcombo,ppulldata=self.ppullcombo,self.ppulldatasel=ppullcombo.get_active_text()ppull=[namefor(name,label)inppulldataifsel==label][0]ifppull=='fetch':cmd=['fetch','--message','merge']# load the fetch extension explicitlyextensions.load(self.ui,'fetch',None)else:cmd=['pull']ifppull=='update':cmd.append('--update')elifppull=='rebase':cmd.append('--rebase')# load the rebase extension explicitlyextensions.load(self.ui,'rebase',None)cmdline=['hg']+cmd+[self.bfile]dlg=hgcmd.CmdDialog(cmdline)dlg.show_all()dlg.run()dlg.hide()self.remove_overlay('--rebase'incmd)defremove_overlay(self,resettip):self.bfile=Noneself.npreviews=0self.urlcombo.set_active(self.origurl)self.repo=hg.repository(self.ui,path=self.repo.root)self.graphview.set_repo(self.repo,self.stbar)self.changeview.repo=self.repoself.changeview.bfile=Noneifresettip:self.origtip=len(self.repo)self.reload_log()self.toolbar.remove(self.toolbar.get_nth_item(0))self.toolbar.remove(self.toolbar.get_nth_item(0))self.cmd_set_sensitive('accept',False)self.cmd_set_sensitive('reject',False)forwinself.incoming_disabled:w.set_sensitive(True)forcmdinself.incoming_disabled_cmds:self.cmd_set_sensitive(cmd,True)defreject_clicked(self,button):self.remove_overlay(False)defincoming_clicked(self,toolbutton):defcleanup():try:shutil.rmtree(self.bundledir)exceptOSError:passpath=hglib.fromutf(self.pathentry.get_text()).strip()ifnotpath:gdialog.Prompt(_('No remote path specified'),_('Please enter or select a remote path'),self).run()self.pathentry.grab_focus()returnifnotself.bundledir:self.bundledir=tempfile.mkdtemp(prefix='thg-incoming-')atexit.register(cleanup)bfile=pathforbadcharin(':','*','\\','?','#'):bfile=bfile.replace(badchar,'')bfile=bfile.replace('/','_')bfile=os.path.join(self.bundledir,bfile)+'.hg'cmdline=['hg','incoming','--bundle',bfile]cmdline+=self.get_proxy_args()cmdline+=[path]dlg=hgcmd.CmdDialog(cmdline,text='hg incoming')dlg.show_all()dlg.run()dlg.hide()ifdlg.return_code()==0andos.path.isfile(bfile):self.set_bundlefile(bfile)defset_bundlefile(self,bfile):self.origurl=self.urlcombo.get_active()self.pathentry.set_text(bfile)# create apply/reject toolbar buttonsapply=gtk.ToolButton(gtk.STOCK_APPLY)apply.set_tooltip(self.tooltips,_('Accept incoming previewed changesets'))apply.set_label(_('Accept'))apply.show()reject=gtk.ToolButton(gtk.STOCK_DIALOG_ERROR)reject.set_tooltip(self.tooltips,_('Reject incoming previewed changesets'))reject.set_label(_('Reject'))reject.show()apply.connect('clicked',self.apply_clicked)reject.connect('clicked',self.reject_clicked)self.toolbar.insert(reject,0)self.toolbar.insert(apply,0)self.cmd_set_sensitive('accept',True)self.cmd_set_sensitive('reject',True)cmds=('incoming','outgoing','push','pull','email','refresh','synchronize','mq','add-bundle')self.incoming_disabled_cmds=[]forcmdincmds:self.cmd_set_sensitive(cmd,False)self.incoming_disabled_cmds.append(cmd)self.incoming_disabled=[]defdisable_child(w):ifw!=self.ppullcomboandw.get_property('sensitive'):w.set_sensitive(False)self.incoming_disabled.append(w)self.syncbox.foreach(disable_child)self.bfile=bfileoldtip=len(self.repo)self.repo=hg.repository(self.ui,path=bfile)self.graphview.set_repo(self.repo,self.stbar)self.changeview.repo=self.repoself.changeview.bfile=bfileself.npreviews=len(self.repo)-oldtipself.reload_log()defadd_bundle_clicked(self,button):result=gtklib.NativeSaveFileDialogWrapper(title=_('Open Bundle'),open=True).run()ifresult:self.set_bundlefile(result)defpull_clicked(self,toolbutton):ppullcombo,ppulldata=self.ppullcombo,self.ppulldatasel=ppullcombo.get_active_text()ppull=[namefor(name,label)inppulldataifsel==label][0]ifppull=='fetch':cmd=['fetch','--message','merge']# load the fetch extension explicitlyextensions.load(self.ui,'fetch',None)else:cmd=['pull']ifppull=='update':cmd.append('--update')elifppull=='rebase':cmd.append('--rebase')# load the rebase extension explicitlyextensions.load(self.ui,'rebase',None)path=hglib.fromutf(self.pathentry.get_text()).strip()ifnotpath:gdialog.Prompt(_('No remote path specified'),_('Please enter or select a remote path'),self).run()self.pathentry.grab_focus()returncmdline=['hg']+cmd+self.get_proxy_args()+[path]dlg=hgcmd.CmdDialog(cmdline,text=' '.join(['hg']+cmd))dlg.show_all()dlg.run()dlg.hide()ifdlg.return_code()==0:self.repo.invalidate()if'--rebase'incmd:self.origtip=len(self.repo)self.reload_log()eliflen(self.repo)>self.origtip:self.reload_log()defoutgoing_clicked(self,toolbutton):path=hglib.fromutf(self.pathentry.get_text()).strip()ifnotpath:gdialog.Prompt(_('No remote path specified'),_('Please enter or select a remote path'),self).run()self.pathentry.grab_focus()returnq=Queue.Queue()cmd=[q,'outgoing','--quiet','--template','{node}\n']cmd+=self.get_proxy_args()cmd+=[path]defthreadfunc(q,*args):try:hglib.hgcmd_toq(q,*args)except(util.Abort,hglib.RepoError),e:self.stbar.set_status_text(_('Abort: %s')%str(e))defout_wait():whileq.qsize():hash=q.get(0).strip()try:node=self.repo[hash].node()outgoing.append(node)except:passifthread.isAlive():returnTrueelse:self.stbar.end()self.outgoing=outgoingself.reload_log()self.stop_button.disconnect(stop_handler)self.stop_button.set_sensitive(False)defstop_clicked(button):thread.terminate()outgoing=[]thread=thread2.Thread(target=threadfunc,args=cmd)thread.start()self.stbar.begin()stop_handler=self.stop_button.connect('clicked',stop_clicked)self.stop_button.set_sensitive(True)gobject.timeout_add(50,out_wait)defemail_clicked(self,toolbutton):path=hglib.fromutf(self.pathentry.get_text()).strip()ifnotpath:gdialog.Prompt(_('No repository selected'),_('Select a peer repository to compare with'),self).run()self.pathentry.grab_focus()returnopts=['--outgoing',path]dlg=hgemail.EmailDialog(self.repo.root,opts)self.show_dialog(dlg)defpush_clicked(self,toolbutton):remote_path=hglib.fromutf(self.pathentry.get_text()).strip()foralias,pathinself.repo.ui.configitems('paths'):ifremote_path==alias:remote_path=pathelifremote_path==url.hidepassword(path):remote_path=pathifnotremote_path:gdialog.Prompt(_('No remote path specified'),_('Please enter or select a remote path'),self).run()self.pathentry.grab_focus()returncmdline=['hg','push']+self.get_proxy_args()ifself.forcepush:cmdline+=['--force']cmdline+=[remote_path]dlg=hgcmd.CmdDialog(cmdline,text=' '.join(cmdline[:-1]))dlg.show_all()dlg.run()dlg.hide()ifdlg.return_code()==0andself.outgoing:self.outgoing=[]self.reload_log()defconf_clicked(self,toolbutton,combo):newpath=hglib.fromutf(self.pathentry.get_text()).strip()foralias,pathinself.repo.ui.configitems('paths'):ifnewpathin(path,url.hidepassword(path)):newpath=Nonebreakdlg=thgconfig.ConfigDialog(True)dlg.show_all()ifnewpath:dlg.new_path(newpath,'default')else:dlg.focus_field('tortoisehg.postpull')dlg.run()dlg.hide()self.refreshui()urllist=combo.get_model()urllist.clear()foralias,pathinself.repo.ui.configitems('paths'):path=url.hidepassword(path)urllist.append([hglib.toutf(path),hglib.toutf(alias)])ifalias=='default':combo.set_active(len(urllist)-1)defrealize_settings(self):self.vpaned.set_position(self.setting_vpos)self.hpaned.set_position(self.setting_hpos)ifhasattr(self,'mqpaned')andself.mqtb.get_active():self.mqpaned.set_position(self.setting_mqhpos)defthgdiff(self,treeview):'ctrl-d handler'self.vdiff_change(None)defthgparent(self,treeview):'ctrl-p handler'parent=self.repo['.'].rev()self.graphview.set_revision_id(parent)defthgnavigate(self,treeview):'ctrl-g handler'self.show_goto_dialog()defget_live_branches(self):live=[]dblist=self.repo.ui.config('tortoisehg','deadbranch','')deadbranches=[x.strip()forxindblist.split(',')]fornameinself.repo.branchtags().keys():ifnamenotindeadbranches:live.append(name)returnlivedefselect_branch(self,combo):row=combo.get_active()ifrow>=0androw!=self.lastbranchrow:self.filter='branch'self.lastbranchrow=rowself.branchbutton.set_active(True)self.branchbutton.set_sensitive(True)self.reload_log(branch=combo.get_model()[row][0])else:self.lastbranchrow=Noneself.branchbutton.set_sensitive(False)defshow_goto_dialog(self):'Launch a modeless goto revision dialog'defgoto_rev_(rev):self.goto_rev(rev)defresponse_(dialog,response_id):dialog.hide()defdelete_event(dialog,event,data=None):# return True to prevent the dialog from being destroyedreturnTruedlg=gorev.GotoRevDialog(goto_rev_)dlg.connect('response',response_)dlg.connect('delete-event',delete_event)dlg.set_modal(False)dlg.show()self.gorev_dialog=dlgdefgoto_rev(self,revision):rid=self.repo[revision].rev()self.graphview.set_revision_id(rid,load=True)defstrip_rev(self,menuitem):defstrip_completed():self.repo.invalidate()self.reload_log()self.changeview._buffer.set_text('')self.changeview._filelist.clear()rev=self.curreviddialog=thgstrip.StripDialog(rev)dialog.set_notify_func(strip_completed)self.show_dialog(dialog)defshow_dialog(self,dlg):dlg.set_transient_for(self)dlg.show_all()dlg.present()ifgtk.pygtk_version<(2,12,0):# Workaround for old PyGTK (< 2.12.0) issue.# See background of this: f668034aeda3dlg.set_transient_for(None)defbackout_rev(self,menuitem):oldlen=len(self.repo)hash=str(self.repo[self.currevid])parents=[x.node()forxinself.repo.parents()]defcinotify(dlg):'User comitted the merge'dlg.ready=Falsedlg.hide()self.reload_log()defrefresh(*args):self.repo.invalidate()iflen(self.repo)!=oldlen:self.reload_log()iflen(self.repo.parents())!=len(parents):# User auto-merged the backoutfromtortoisehg.hgtkimportcommitdlg=commit.run(ui.ui())dlg.set_transient_for(self)dlg.set_modal(True)dlg.set_notify_func(cinotify,dlg)dlg.display()dlg=backout.BackoutDialog(hash)dlg.connect('destroy',refresh)self.show_dialog(dlg)defrevert(self,menuitem):rev=self.currevidres=gdialog.Confirm(_('Confirm Revert All Files'),[],self,_('Revert all files to revision %d?\nThis will overwrite your ''local changes')%rev).run()ifres!=gtk.RESPONSE_YES:returncmdline=['hg','revert','--verbose','--all','--rev',str(rev)]dlg=hgcmd.CmdDialog(cmdline)dlg.show_all()dlg.run()dlg.hide()defvdiff_change(self,menuitem,pats=[]):opts={'change':str(self.currevid),'bundle':self.bfile}self._do_diff(pats,opts)defvdiff_local(self,menuitem,pats=[]):opts={'rev':[str(self.currevid)],'bundle':self.bfile}self._do_diff(pats,{'rev':[str(self.currevid)]})defdiff_revs(self,menuitem):rev0,rev1=self.revrangestatopts=self.merge_opts(commands.table['^status|st'][1],('include','exclude','git'))statopts['rev']=['%u:%u'%(rev0,rev1)]statopts['modified']=Truestatopts['added']=Truestatopts['removed']=Truedialog=status.GStatus(self.ui,self.repo,self.cwd,self.pats,statopts)dialog.display()returnTruedefvdiff_selected(self,menuitem):strrevs=[str(r)forrinself.revrange]self._do_diff(self.pats,{'rev':strrevs})defemail_revs(self,menuitem):revrange=list(self.revrange)revrange.sort()opts=['--rev',str(revrange[0])+':'+str(revrange[1])]dlg=hgemail.EmailDialog(self.repo.root,opts)self.show_dialog(dlg)defexport_revs(self,menuitem):result=gtklib.NativeFolderSelectDialog(title=_('Save patches to'),initial=self.repo.root).run()ifresult:revs=list(self.revrange)revs.sort()rev='%d:%d'%(revs[0],revs[1])# In case new export args are added in the future, merge the# hg defaultsopts=self.merge_opts(commands.table['^export'][1],())opts['output']=os.path.join(result,'%b_rev%R.patch')defdohgexport():commands.export(self.ui,self.repo,rev,**opts)s,o=self._hg_call_wrapper('Export',dohgexport,False)defbundle_revs(self,menuitem):revrange=list(self.revrange)revrange.sort()parent=self.repo[revrange[0]].parents()[0].rev()# Special case for revision 0's parent.ifparent==-1:parent='null'filename="%s_rev%d_to_rev%s.hg"%(os.path.basename(self.repo.root),revrange[0],revrange[1])result=gtklib.NativeSaveFileDialogWrapper(title=_('Write bundle to'),initial=self.repo.root,filename=filename).run()ifresult:cmdline=['hg','bundle','--base',str(parent),'--rev',str(revrange[1]),result]dlg=hgcmd.CmdDialog(cmdline)dlg.show_all()dlg.run()dlg.hide()defqimport_rev(self,menuitem):"""QImport selected revision."""rev=str(self.currevid)self.qimport_revs(menuitem,rev)defqimport_revs(self,menuitem,rev=None):"""QImport revision range."""ifrev==None:revs=list(self.revrange)revs.sort()rev='%s:%s'%(str(revs[0]),str(revs[1]))cmdline=['hg','qimport','--rev',rev]dialog=hgcmd.CmdDialog(cmdline)dialog.show_all()dialog.run()dialog.hide()self.repo.invalidate()self.reload_log()self.changeview._buffer.set_text('')self.changeview._filelist.clear()self.enable_mqpanel()defrebase_selected(self,menuitem):"""Rebase revision on top of selection (1st on top of 2nd)."""revs=self.revrangeres=gdialog.Confirm(_('Confirm Rebase Revision'),[],self,_('Rebase revision %d on top of %d?')%(revs[0],revs[1])).run()ifres!=gtk.RESPONSE_YES:returncmdline=['hg','rebase','--source',str(revs[0]),'--dest',str(revs[1])]dialog=hgcmd.CmdDialog(cmdline)dialog.show_all()dialog.run()dialog.hide()self.repo.invalidate()self.reload_log()self.changeview._buffer.set_text('')self.changeview._filelist.clear()deftransplant_revs(self,menuitem):"""Transplant revision range on top of current revision."""revs=list(self.revrange)revs.sort()cmdline=['hg','transplant','%d:%d'%(revs[0],revs[1])]dialog=hgcmd.CmdDialog(cmdline)dialog.show_all()dialog.run()dialog.hide()self.repo.invalidate()self.reload_log()self.changeview._buffer.set_text('')self.changeview._filelist.clear()defadd_tag(self,menuitem):# save tag info for detecting new tags addedoldtags=self.repo.tagslist()oldlen=len(self.repo)rev=self.curreviddefrefresh(*args):self.repo.invalidate()iflen(self.repo)!=oldlen:self.reload_log()else:newtags=self.repo.tagslist()ifnewtags!=oldtags:self.refresh_model()dialog=tagadd.TagAddDialog(self.repo,rev=str(rev))dialog.connect('destroy',refresh)self.show_dialog(dialog)defshow_status(self,menuitem):rev=self.currevidstatopts=self.merge_opts(commands.table['^status|st'][1],('include','exclude','git'))ifself.changeview.parent_toggle.get_active():parent=self.repo[rev].parents()[1].rev()else:parent=self.repo[rev].parents()[0].rev()statopts['rev']=[str(parent),str(rev)]statopts['modified']=Truestatopts['added']=Truestatopts['removed']=Truedialog=status.GStatus(self.ui,self.repo,self.cwd,self.pats,statopts)dialog.display()defpush_to(self,menuitem):remote_path=hglib.fromutf(self.pathentry.get_text()).strip()foralias,pathinself.repo.ui.configitems('paths'):ifremote_path==alias:remote_path=pathelifremote_path==url.hidepassword(path):remote_path=pathifnotremote_path:gdialog.Prompt(_('No remote path specified'),_('Please enter or select a remote path'),self).run()self.pathentry.grab_focus()returnnode=self.repo[self.currevid].node()cmdline=['hg','push','--rev',str(self.currevid),remote_path]dlg=hgcmd.CmdDialog(cmdline,text='hg push')dlg.show_all()dlg.run()dlg.hide()ifdlg.return_code()==0andself.outgoing:d=self.outgoing.index(node)self.outgoing=self.outgoing[d+1:]self.reload_log()defpull_to(self,menuitem):cmdline=['hg','pull','--rev',str(self.currevid),self.bfile]dlg=hgcmd.CmdDialog(cmdline)dlg.show_all()dlg.run()dlg.hide()curtip=len(hg.repository(self.ui,self.repo.root))self.repo=hg.repository(self.ui,path=self.bfile)self.graphview.set_repo(self.repo,self.stbar)self.changeview.repo=self.repoself.npreviews=len(self.repo)-curtipself.reload_log()defcopy_hash(self,menuitem):hash=self.repo[self.currevid].hex()clipboard=gtk.Clipboard()clipboard.set_text(hash)defexport_patch(self,menuitem):rev=self.currevidfilename="%s_rev%s.patch"%(os.path.basename(self.repo.root),rev)result=gtklib.NativeSaveFileDialogWrapper(title=_('Save patch to'),initial=self.repo.root,filename=filename).run()ifresult:ifos.path.exists(result):res=gdialog.Confirm(_('Confirm Overwrite'),[],self,_('The file "%s" already exists!\n\n''Do you want to overwrite it?')%result).run()ifres!=gtk.RESPONSE_YES:returnos.remove(result)# In case new export args are added in the future, merge the# hg defaultsexportOpts=self.merge_opts(commands.table['^export'][1],())exportOpts['output']=resultdefdohgexport():commands.export(self.ui,self.repo,str(rev),**exportOpts)success,outtext=self._hg_call_wrapper("Export",dohgexport,False)defbundle_rev_to_tip(self,menuitem):try:rev=self.currevidparent=self.repo[rev].parents()[0].rev()# Special case for revision 0's parent.ifparent==-1:parent='null'except(ValueError,hglib.LookupError):returnfilename="%s_rev%d_to_tip.hg"%(os.path.basename(self.repo.root),rev)result=gtklib.NativeSaveFileDialogWrapper(title=_('Write bundle to'),initial=self.repo.root,filename=filename).run()ifresult:ifos.path.exists(result):res=gdialog.Confirm(_('Confirm Overwrite'),[],self,_('The file "%s" already exists!\n\n''Do you want to overwrite it?')%result).run()ifres!=gtk.RESPONSE_YES:returnos.remove(result)cmdline=['hg','bundle','--base',str(parent),result]dlg=hgcmd.CmdDialog(cmdline)dlg.show_all()dlg.run()dlg.hide()defemail_patch(self,menuitem):rev=self.curreviddlg=hgemail.EmailDialog(self.repo.root,['--rev',str(rev)])self.show_dialog(dlg)defcheckout(self,menuitem):rev=self.currevidparents=[x.node()forxinself.repo.parents()]dialog=update.UpdateDialog(rev)dialog.set_notify_func(self.checkout_completed,parents)self.show_dialog(dialog)defcheckout_completed(self,oldparents):self.repo.invalidate()self.repo.dirstate.invalidate()newparents=[x.node()forxinself.repo.parents()]ifnotoldparents==newparents:self.refresh_model()defdomerge(self,menuitem):defmerge_notify(args):oldparents,repolen=argsself.repo.invalidate()self.repo.dirstate.invalidate()iflen(self.repo)!=repolen:self.reload_log()elifnotoldparents==self.repo.parents():self.refresh_model()# update parents for the next nofifyingargs[0]=self.repo.parents()ifself.revrange:rev0,rev1=self.revrangeelse:rev0,rev1=self.repo['.'].rev(),self.currevidargs=[self.repo.parents(),len(self.repo)]dlg=merge.MergeDialog(rev0,rev1)dlg.set_notify_func(merge_notify,*args)merge_notify(args)# could have immediately switched parentsself.show_dialog(dlg)defarchive(self,menuitem):rev=self.currevidparents=[x.node()forxinself.repo.parents()]dlg=archive.ArchiveDialog(rev)self.show_dialog(dlg)deftransplant_rev(self,menuitem):"""Transplant selection on top of current revision."""rev=self.currevidcmdline=['hg','transplant',str(rev)]dialog=hgcmd.CmdDialog(cmdline)dialog.show_all()dialog.run()dialog.hide()self.repo.invalidate()self.reload_log()self.changeview._buffer.set_text('')self.changeview._filelist.clear()defthgrefresh(self,window):self.reload_log()defrefresh_clicked(self,toolbutton,data=None):self.reload_log()returnTruedefenable_mqpanel(self,enable=None):ifnothasattr(self,'mqpaned'):returnifenableisNone:enable=self.setting_mqvisandself.mqwidget.has_patch()oldpos=self.mqpaned.get_position()self.mqpaned.set_position(enableandself.setting_mqhposor0)ifnotenableandoldpos:self.setting_mqhpos=oldpos# set the state of MQ toolbuttonifhasattr(self,'mqtb'):self.mqtb.handler_block_by_func(self.mq_clicked)self.cmd_set_active('mq',enable)self.mqtb.handler_unblock_by_func(self.mq_clicked)self.cmd_set_sensitive('mq',self.mqwidget.has_mq())defmq_clicked(self,widget,data=None):self.enable_mqpanel(widget.get_active())deftree_button_press(self,tree,event):ifevent.button==3andnot(event.state&(gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK)):path=tree.get_path_at_pos(int(event.x),int(event.y))ifnotpath:returnFalsecrow=path[0](model,pathlist)=tree.get_selection().get_selected_rows()ifpathlist==[]:returnFalsesrow=pathlist[0]ifsrow==crow:self.tree_popup_menu(tree,event.button,event.time)else:tree.get_selection().set_mode(gtk.SELECTION_MULTIPLE)tree.get_selection().select_path(crow)self.origsel=srowrev0=self.graphview.get_revid_at_path(srow)rev1=self.graphview.get_revid_at_path(crow)self.revrange=(rev0,rev1)self.tree_popup_menu_diff(tree,event.button,event.time)returnTruereturnFalsedeftree_popup_menu(self,treeview,button=0,time=0):menu=self.tree_context_menu()menu.popup(None,None,None,button,time)returnTruedeftree_popup_menu_diff(self,treeview,button=0,time=0):menu=self.tree_diff_context_menu()menu.popup(None,None,None,button,time)returnTruedeftree_row_act(self,tree,path,column):'Default action is the first entry in the context menu'self.tree_context_menu().get_children()[0].activate()returnTruedefrun(ui,*pats,**opts):cmdoptions={'follow':False,'follow-first':False,'copies':False,'keyword':[],'limit':0,'rev':[],'removed':False,'no_merges':False,'date':None,'only_merges':None,'prune':[],'git':False,'verbose':False,'include':[],'exclude':[],'filehist':None,'canonpats':[]}cmdoptions.update(opts)pats=hglib.canonpaths(pats)+cmdoptions['canonpats']returnGLog(ui,None,None,pats,cmdoptions)
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.