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.
# changeset.py - Changeset dialog for TortoiseHg## 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.importosimportreimportgtkimportgobjectimportpangoimportQueuefrommercurialimportcmdutil,util,patch,mdifffromtortoisehg.util.i18nimport_fromtortoisehg.utilimportshlib,hglib,pathsfromtortoisehg.hgtkimportcsinfo,gdialog,gtklib,hgcmd,statusbarclassChangeSet(gdialog.GDialog):'GTK+ based dialog for displaying repository logs'def__init__(self,ui,repo,cwd,pats,opts,stbar=None):gdialog.GDialog.__init__(self,ui,repo,cwd,pats,opts)self.stbar=stbarself.glog_parent=Noneself.bfile=None# initialize changeset/issue tracker link regex and dictmatch=r'(\b[0-9a-f]{12}(?:[0-9a-f]{28})?\b)'issue=repo.ui.config('tortoisehg','issue.regex')ifissue:match=r'%s|(%s)'%(match,issue)self.bodyre=re.compile(match)self.issuedict=dict()defget_title(self):title=_('%s changeset ')%self.get_reponame()rev=self.opts['rev']ifisinstance(rev,str):title+=revelse:title+=rev[0]returntitledefget_icon(self):return'menushowchanged.ico'defget_tbbuttons(self):return[]defparent_toggled(self,button):self.load_details(self.currev)defprepare_display(self):self.currow=Noneself.graphview=Noneself.glog_parent=Nonenode0,node1=cmdutil.revpair(self.repo,self.opts.get('rev'))self.load_details(self.repo.changelog.rev(node0))defsave_settings(self):settings=gdialog.GDialog.save_settings(self)settings['changeset']=self._hpaned.get_position()returnsettingsdefload_settings(self,settings):gdialog.GDialog.load_settings(self,settings)ifsettingsand'changeset'insettings:self._setting_hpos=settings['changeset']else:self._setting_hpos=-1defset_repo(self,repo):self.repo=repoself.summarypanel.update(repo=repo)defclear_cache(self):self.summarypanel.info.clear_cache()defclear(self):self._buffer.set_text('')self._filelist.clear()self.summarybox.hide()defdiff_other_parent(self):returnself.parent_button.get_active()defload_details(self,rev):'Load selected changeset details into buffer and filelist'oldrev=hasattr(self,'currev')andself.currevorNoneself.currev=revctx=self.repo[rev]ifnotctx:returnparents=ctx.parents()title=self.get_title()ifparents:iflen(parents)==2:# deferred adding of parent check buttonifnotself.parent_button.parent:self.parent_box.pack_start(self.parent_button,False,False)self.parent_box.pack_start(gtk.HSeparator(),False,False)self.parent_box.show_all()# show parent boxself.parent_box.show()# uncheck the check buttonifrev!=oldrev:self.parent_button.handler_block_by_func(self.parent_toggled)self.parent_button.set_active(False)self.parent_button.handler_unblock_by_func(self.parent_toggled)# determine title and current parentifself.diff_other_parent():title+=':'+str(parents[1].rev())parent=parents[1].node()else:title+=':'+str(parents[0].rev())parent=parents[0].node()# clear cache for highlighting parent correctlyself.clear_cache()else:# hide parent boxself.parent_box.hide()parent=parents[0].node()else:parent=self.repo[-1]# update dialog titleself.set_title(title)ifself.clipboard:self.clipboard.set_text(str(ctx))pats=self.patsifself.graphview:(path,focus)=self.graphview.treeview.get_cursor()ifpath:wfile=self.graphview.get_wfile_at_path(path)ifwfile:pats.append(wfile)self._filelist.clear()self._filelist.append(('*',_('[All Files]'),''))modified,added,removed=self.repo.status(parent,ctx.node())[:3]selrow=Noneforfinmodified:iffinpats:selrow=len(self._filelist)self._filelist.append(('M',hglib.toutf(f),f))forfinadded:iffinpats:selrow=len(self._filelist)self._filelist.append(('A',hglib.toutf(f),f))forfinremoved:iffinpats:selrow=len(self._filelist)self._filelist.append(('R',hglib.toutf(f),f))self.curnodes=(parent,ctx.node())ifselrowisnotNone:self._filesel.select_path((selrow,))eliflen(self._filelist)>1:self._filesel.select_path((1,))else:self._filesel.select_path((0,))self.reset_scroll_pos()defload_patch_details(self,patchfile):'Load specified patch details into buffer and file list'self._filelist.clear()self._filelist.append(('*',_('[All Files]'),''))# append files & collect hunksself.currev=-1self.curphunks={}self.curpatch=patchfilepf=open(self.curpatch)defget_path(a,b):type=(a=='/dev/null')and'A'or'M'type=(b=='/dev/null')and'R'ortyperawpath=(b!='/dev/null')andboraifnot(rawpath.startswith('a/')orrawpath.startswith('b/')):returntype,rawpathreturntype,rawpath.split('/',1)[-1]hunks=[]files=[]map={'MODIFY':'M','ADD':'A','DELETE':'R','RENAME':'','COPY':''}try:try:forstate,valuesinpatch.iterhunks(self.ui,pf):ifstate=='git':forminvalues:f=m.pathself._filelist.append((map[m.op],hglib.toutf(f),f))files.append(f)elifstate=='file':type,path=get_path(values[0],values[1])self.curphunks[path]=hunks=['diff']ifpathnotinfiles:self._filelist.append((type,hglib.toutf(path),path))files.append(path)elifstate=='hunk':hunks.extend([l.rstrip('\r\n')forlinvalues.hunk])else:raise_('unknown hunk type: %s')%stateexceptpatch.NoHunks:passfinally:pf.close()# select first fileiflen(self._filelist)>1:self._filesel.select_path((1,))else:self._filesel.select_path((0,))self.reset_scroll_pos()deffilelist_rowchanged(self,sel):model,path=sel.get_selected()ifnotpath:returnstatus,file_utf8,file=model[path]ifself.currev!=-1:self.curfile=fileself.generate_change_header()ifself.curfile:self.append_diff(self.curfile)else:for_,_,finmodel:self.append_diff(f)else:self.generate_patch_header()iffile:self.append_patch_diff(file)else:self.append_all_patch_diffs()defreset_scroll_pos(self):adj=self.diffscroller.get_vadjustment()adj.set_value(0)adj=self.diffscroller.get_hadjustment()adj.set_value(0)defgenerate_change_header(self):self.summarypanel.update(self.currev,self.csetstyle)self.summarybox.show()desc=self.summarypanel.get_data('desc')self.set_commitlog(desc)defgenerate_patch_header(self):self.summarypanel.update(self.curpatch,self.patchstyle)self.summarybox.show()desc=self.summarypanel.get_data('desc')self.set_commitlog(desc)defset_commitlog(self,desc):'Append commit log after clearing buffer'buf=self._bufferbuf.set_text('')eob=buf.get_end_iter()desc=desc.rstrip('\n\r')pos=0self.issuedict.clear()forminself.bodyre.finditer(desc):a,b=m.span()ifa>pos:buf.insert(eob,desc[pos:a])pos=bgroups=m.groups()link=groups[0]iflink:buf.insert_with_tags_by_name(eob,link,'csetlink')else:link=groups[1]iflen(groups)>2:self.issuedict[link]=groups[1:]buf.insert_with_tags_by_name(eob,link,'issuelink')ifpos<len(desc):buf.insert(eob,desc[pos:])buf.insert(eob,'\n\n')defappend_diff(self,wfile):ifnotwfile:returnbuf,rev=self._buffer,self.currevn1,n2=self.curnodeseob=buf.get_end_iter()offset=eob.get_offset()try:fctx=self.repo[rev].filectx(wfile)excepthglib.LookupError:fctx=Noneiffctxandfctx.size()>hglib.getmaxdiffsize(self.repo.ui):lines=['diff',_(' %s is larger than the specified max diff size')%wfile]else:lines=[]m=cmdutil.matchfiles(self.repo,[wfile])opts=mdiff.diffopts(git=True,nodates=True)try:forsinpatch.diff(self.repo,n1,n2,match=m,opts=opts):lines.extend(s.splitlines())except(hglib.RepoLookupError,hglib.RepoError,hglib.LookupError),e:err=_('Repository Error: %s, refresh suggested')%str(e)lines=['diff','',err]tags,lines=self.prepare_diff(lines,offset,wfile)forlinlines:buf.insert(eob,l)# inserts the tagsforname,p0,p1intags:i0=buf.get_iter_at_offset(p0)i1=buf.get_iter_at_offset(p1)buf.apply_tag_by_name(name,i0,i1)sob,eob=buf.get_bounds()pos=buf.get_iter_at_offset(offset)buf.apply_tag_by_name('diff',pos,eob)returnTruedefappend_patch_diff(self,patchfile):ifnotpatchfile:return# append diffsbuf=self._buffereob=buf.get_end_iter()offset=eob.get_offset()lines=self.curphunks[patchfile]tags,lines=self.prepare_diff(lines,offset,patchfile)forlineinlines:buf.insert(eob,line)# insert the tagsforname,p0,p1intags:i0=buf.get_iter_at_offset(p0)i1=buf.get_iter_at_offset(p1)buf.apply_tag_by_name(name,i0,i1)sob,eob=buf.get_bounds()pos=buf.get_iter_at_offset(offset)buf.apply_tag_by_name('diff',pos,eob)defappend_all_patch_diffs(self):model=self._filelistiflen(model)>1:forst,fu,fninmodel:self.append_patch_diff(fn)else:self._buffer.insert(self._buffer.get_end_iter(),'\n'+_('[no hunks to display]'))defprepare_diff(self,difflines,offset,fname):'Borrowed from hgview; parses changeset diffs'defaddtag(name,offset,length):iftagsandtags[-1][0]==nameandtags[-1][2]==offset:tags[-1][2]+=lengthelse:tags.append([name,offset,offset+length])add,rem=0,0forlindifflines[1:]:ifl.startswith('+'):add+=1elifl.startswith('-'):rem+=1outlines=[]tags=[]txt=hglib.toutf('=== (+%d,-%d) %s ===\n'%(add,rem,fname))addtag('greybg',offset,len(txt))outlines.append(txt)offset+=len(txt.decode('utf-8'))forl1indifflines[1:]:l=hglib.toutf(l1)ifl.startswith('--- '):continueifl.startswith('+++ '):continueifl.startswith('@@'):tag='blue'elifl.startswith('+'):tag='green'l=hglib.diffexpand(l)elifl.startswith('-'):tag='red'l=hglib.diffexpand(l)else:tag='black'l=hglib.diffexpand(l)l=l+"\n"length=len(l.decode('utf-8'))addtag(tag,offset,length)outlines.append(l)offset+=lengthreturntags,outlinesdeflink_event(self,label,event,revnum):revnum=int(revnum)ifself.graphview:self.graphview.set_revision_id(revnum,load=True)else:self.load_details(revnum)deffile_context_menu(self):defcreate_menu(label,callback):menuitem=gtk.MenuItem(label,True)menuitem.connect('activate',callback)menuitem.set_border_width(1)returnmenuitemmenu=gtklib.MenuItems()menu.append(create_menu(_('_Visual Diff'),self.diff_file_rev))menu.append(create_menu(_('Diff to _local'),self.diff_to_local))menu.append_sep()menu.append(create_menu(_('_View at Revision'),self.view_file_rev))self.save_menu=create_menu(_('_Save at Revision...'),self.save_file_rev)menu.append(self.save_menu)menu.append_sep()menu.append(create_menu(_('_File History'),self.file_history))self.ann_menu=create_menu(_('_Annotate File'),self.ann_file)menu.append(self.ann_menu)menu.append_sep()menu.append(create_menu(_('_Revert File Contents'),self.revert_file))menu=menu.create_menu()menu.show_all()returnmenudefget_body(self):embedded=bool(self.stbar)use_expander=embeddedandself.ui.configbool('tortoisehg','changeset-expander')self.curfile=''ifself.repo.ui.configbool('tortoisehg','copyhash'):sel=(os.name=='nt')and'CLIPBOARD'or'PRIMARY'self.clipboard=gtk.Clipboard(selection=sel)else:self.clipboard=Noneself.filemenu=self.file_context_menu()details_frame_parent=gtk.VBox()# changeset framedetails_frame=gtk.Frame()details_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)scroller=gtk.ScrolledWindow()scroller.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)details_frame.add(scroller)self.diffscroller=scrollerdetails_box=gtk.VBox()scroller.add_with_viewport(details_box)scroller.child.set_shadow_type(gtk.SHADOW_NONE)## changeset paneldefrevid_markup(revid,**kargs):opts=dict(face='monospace',size='9000')opts.update(kargs)returngtklib.markup(revid,**opts)defdata_func(widget,item,ctx):defsummary_line(desc):desc=hglib.tounicode(desc.replace('\0','').split('\n')[0])returnhglib.toutf(desc[:80])defrevline_data(ctx,hl=False,branch=None):ifisinstance(ctx,basestring):returnctxdesc=ctx.description()return(str(ctx.rev()),str(ctx),summary_line(desc),hl,branch)ifitem=='cset':returnrevline_data(ctx)elifitem=='branch':value=hglib.toutf(ctx.branch())returnvalue!='default'andvalueorNoneelifitem=='parents':pindex=self.diff_other_parent()and1or0pctxs=ctx.parents()parents=[]forpctxinpctxs:highlight=len(pctxs)==2andpctx==pctxs[pindex]branch=Noneifhasattr(pctx,'branch')andpctx.branch()!=ctx.branch():branch=pctx.branch()parents.append(revline_data(pctx,highlight,branch))returnparentselifitem=='children':children=[]forcctxinctx.children():branch=Noneifhasattr(cctx,'branch')andcctx.branch()!=ctx.branch():branch=cctx.branch()children.append(revline_data(cctx,branch=branch))returnchildrenelifitem=='transplant':ts=widget.get_data('transplant',usepreset=True)ifnotts:returnNonetry:tctx=self.repo[ts]returnrevline_data(tctx)except(hglib.LookupError,hglib.RepoLookupError,hglib.RepoError):returntselifitem=='patch':ifhasattr(ctx,'_patchname'):desc=ctx.description()return(ctx._patchname,str(ctx),summary_line(desc))returnNoneraisecsinfo.UnknownItem(item)deflabel_func(widget,item):ifitem=='cset':return_('Changeset:')elifitem=='parents':return_('Parent:')elifitem=='children':return_('Child:')elifitem=='patch':return_('Patch:')raisecsinfo.UnknownItem(item)defmarkup_func(widget,item,value):defrevline_markup(revnum,revid,summary,highlight=None,branch=None):revnum=gtklib.markup(revnum)summary=gtklib.markup(summary)ifrevid:revid=revid_markup(revid)ifbranch:return'%s (%s) %s%s'%(revnum,revid,branch,summary)return'%s (%s) %s'%(revnum,revid,summary)else:ifbranch:return'%s - %s%s'%(revnum,branch,summary)return'%s - %s'%(revnum,summary)ifitemin('cset','transplant','patch'):ifisinstance(value,basestring):returnrevid_markup(value)returnrevline_markup(*value)elifitemin('parents','children'):csets=[]forcsetinvalue:ifisinstance(cset,basestring):csets.append(revid_markup(cset))else:csets.append(revline_markup(*cset))returncsetsraisecsinfo.UnknownItem(item)defwidget_func(widget,item,markups):deflinkwidget(revnum,revid,summary,highlight=None,branch=None):# revision labelopts=dict(underline='single',foreground='#0000FF')ifhighlight:opts['weight']='bold'rev='%s (%s)'%(gtklib.markup(revnum,**opts),revid_markup(revid,**opts))revlabel=gtk.Label()revlabel.set_markup(rev)revlabel.set_selectable(True)revlabel.connect('button-release-event',self.link_event,revnum)# summary & branch labelsum=gtklib.markup(summary)ifbranch:sum=gtklib.markup(branch,color='black',background='#aaffaa')+' '+sumsumlabel=gtk.Label()sumlabel.set_markup(sum)sumlabel.set_selectable(True)box=gtk.HBox()box.pack_start(revlabel,False,False)box.pack_start(sumlabel,True,True,4)returnboxdefgenwidget(param):ifisinstance(param,basestring):label=gtk.Label()label.set_markup(param)label.set_selectable(True)returnlabelreturnlinkwidget(*param)ifitemin('parents','children'):csets=widget.get_data(item)return[genwidget(cset)forcsetincsets]elifitem=='transplant':cset=widget.get_data(item)returngenwidget(cset)raisecsinfo.UnknownItem(item)custom=csinfo.custom(data=data_func,label=label_func,markup=markup_func,widget=widget_func)self.csetstyle=csinfo.panelstyle(contents=('cset','branch','user','dateage','parents','children','tags','transplant'),selectable=True)self.patchstyle=csinfo.panelstyle(contents=('patch','branch','user','dateage','parents'),selectable=True)ifuse_expander:self.csetstyle['expander']=Trueself.patchstyle['expander']=Trueself.summarypanel=csinfo.create(self.repo,custom=custom)## summary box (summarypanel + separator)self.summarybox=gtk.VBox()ifuse_expander:# don't scroll summaryboxdetails_frame_parent.pack_start(self.summarybox,False,False)else:# scroll summaryboxdetails_box.pack_start(self.summarybox,False,False)self.summarybox.pack_start(self.summarypanel,False,False)self.summarybox.pack_start(gtk.HSeparator(),False,False)## changeset diffdetails_text=gtk.TextView()details_text.set_wrap_mode(gtk.WRAP_NONE)details_text.connect('populate-popup',self.add_to_popup)details_text.set_editable(False)details_text.modify_font(pango.FontDescription(self.fontcomment))details_box.pack_start(details_text)self._buffer=gtk.TextBuffer()self.setup_tags()details_text.set_buffer(self._buffer)self.textview=details_text## file listfilelist_tree=gtk.TreeView()filelist_tree.set_headers_visible(False)filesel=filelist_tree.get_selection()filesel.connect('changed',self.filelist_rowchanged)self._filesel=fileselfilelist_tree.connect('button-release-event',self.file_button_release)filelist_tree.connect('popup-menu',self.file_popup_menu)filelist_tree.connect('row-activated',self.file_row_act)filelist_tree.set_search_equal_func(self.search_filelist)filelist_tree.modify_font(pango.FontDescription(self.fontlist))accelgroup=gtk.AccelGroup()ifself.glog_parent:self.glog_parent.add_accel_group(accelgroup)else:self.add_accel_group(accelgroup)mod=gtklib.get_thg_modifier()key,modifier=gtk.accelerator_parse(mod+'d')filelist_tree.add_accelerator('thg-diff',accelgroup,key,modifier,gtk.ACCEL_VISIBLE)filelist_tree.connect('thg-diff',self.thgdiff)self._filelist=gtk.ListStore(gobject.TYPE_STRING,# MAR statusgobject.TYPE_STRING,# filename (utf-8 encoded)gobject.TYPE_STRING,# filename)filelist_tree.set_model(self._filelist)column=gtk.TreeViewColumn()filelist_tree.append_column(column)iconcell=gtk.CellRendererPixbuf()filecell=gtk.CellRendererText()column.pack_start(iconcell,expand=False)column.pack_start(filecell,expand=False)column.add_attribute(filecell,'text',1)iconw,iconh=gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR)defget_pixbuf(iconfilename):iconpath=paths.get_tortoise_icon(iconfilename) return gtk.gdk.pixbuf_new_from_file_at_size(
iconpath, iconw, iconh)
- addedpixbuf = get_pixbuf('menuadd.ico')
- removedpixbuf = get_pixbuf('menudelete.ico')
+ addedpixbuf = get_pixbuf('fileadd.ico')
+ removedpixbuf = get_pixbuf('filedelete.ico')
+ modifiedpixbuf = get_pixbuf('filemodify.ico') def cell_seticon(column, cell, model, iter):
state = model.get_value(iter, 0)
pixbuf=Noneifstate=='A': pixbuf = addedpixbuf
elif state == 'R':
pixbuf = removedpixbuf
+ elif state == 'M':+ pixbuf = modifiedpixbuf cell.set_property('pixbuf', pixbuf)
column.set_cell_data_func(iconcell, cell_seticon)
list_frame=gtk.Frame()list_frame.set_shadow_type(gtk.SHADOW_ETCHED_IN)scroller=gtk.ScrolledWindow()scroller.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)scroller.add(filelist_tree)flbox=gtk.VBox()list_frame.add(flbox)self.parent_box=gtk.VBox()flbox.pack_start(self.parent_box,False,False)flbox.pack_start(scroller)btn=gtk.CheckButton(_('Diff to second Parent'))btn.connect('toggled',self.parent_toggled)# don't pack btn yet to keep it initially invisibleself.parent_button=btnself._hpaned=gtk.HPaned()self._hpaned.pack1(list_frame,True,True)self._hpaned.pack2(details_frame_parent,True,True)self._hpaned.set_position(self._setting_hpos)details_frame_parent.pack_start(details_frame,True,True)ifembedded:# embedded by changelog browserreturnself._hpanedelse:# add status bar for main appvbox=gtk.VBox()vbox.pack_start(self._hpaned,True,True)self.stbar=statusbar.StatusBar()self.stbar.show()vbox.pack_start(gtk.HSeparator(),False,False)vbox.pack_start(self.stbar,False,False)returnvboxdefsearch_filelist(self,model,column,key,iter):'case insensitive filename search'key=key.lower()ifkeyinmodel.get_value(iter,1).lower():returnFalsereturnTruedefsetup_tags(self):'Creates the tags to be used inside the TextView'defmake_texttag(name,**kwargs):'Helper function generating a TextTag'tag=gtk.TextTag(name)forkey,valueinkwargs.iteritems():key=key.replace("_","-")try:tag.set_property(key,value)exceptTypeError:print"Warning the property %s is unsupported in"%keyprint"this version of pygtk"returntagtag_table=self._buffer.get_tag_table()tag_table.add(make_texttag('diff',font=self.fontdiff))tag_table.add(make_texttag('blue',foreground='blue'))tag_table.add(make_texttag('red',foreground='red'))tag_table.add(make_texttag('green',foreground='darkgreen'))tag_table.add(make_texttag('black',foreground='black'))tag_table.add(make_texttag('greybg',paragraph_background='grey',weight=pango.WEIGHT_BOLD))tag_table.add(make_texttag('yellowbg',background='yellow'))issuelink_tag=make_texttag('issuelink',foreground='blue',underline=pango.UNDERLINE_SINGLE)issuelink_tag.connect('event',self.issuelink_event)tag_table.add(issuelink_tag)csetlink_tag=make_texttag('csetlink',foreground='blue',underline=pango.UNDERLINE_SINGLE)csetlink_tag.connect('event',self.csetlink_event)tag_table.add(csetlink_tag)defissuelink_event(self,tag,widget,event,liter):ifevent.type!=gtk.gdk.BUTTON_RELEASE:returntext=self.get_link_text(tag,widget,liter)ifnottext:returnlink=self.repo.ui.config('tortoisehg','issue.link')iflink:groups=self.issuedict.get(text,[text])link,num=re.subn(r'\{(\d+)\}',lambdam:groups[int(m.group(1))],link)ifnotnum:link+=textshlib.browse_url(link)defcsetlink_event(self,tag,widget,event,liter):ifevent.type!=gtk.gdk.BUTTON_RELEASE:returntext=self.get_link_text(tag,widget,liter)ifnottext:returntry:rev=self.repo[text].rev()ifself.graphview:self.graphview.set_revision_id(rev,load=True)else:self.load_details(rev)exceptRepoError:passdefget_link_text(self,tag,widget,liter):text_buffer=widget.get_buffer()beg=liter.copy()whilenotbeg.begins_tag(tag):beg.backward_char()end=liter.copy()whilenotend.ends_tag(tag):end.forward_char()text=text_buffer.get_text(beg,end)returntextdeffile_button_release(self,widget,event):ifevent.button==3andnot(event.state&(gtk.gdk.SHIFT_MASK|gtk.gdk.CONTROL_MASK)):self.file_popup_menu(widget,event.button,event.time)returnFalsedeffile_popup_menu(self,treeview,button=0,time=0):ifnotself.curfile:returnself.filemenu.popup(None,None,None,button,time)# If the filelog entry this changeset references does not link# back to this changeset, it means this changeset did not# actually change the contents of this file, and thus the file# cannot be annotated at this revision (since this changeset# does not appear in the filelog)ctx=self.repo[self.currev]try:fctx=ctx.filectx(self.curfile)has_filelog=fctx.filelog().linkrev(fctx.filerev())==ctx.rev()excepthglib.LookupError:has_filelog=Falseself.ann_menu.set_sensitive(has_filelog)self.save_menu.set_sensitive(has_filelog)returnTruedefthgdiff(self,treeview):# Do not steal ctrl-d from changelog treeviewifnottreeview.is_focus()andself.glog_parent:w=self.glog_parent.get_focus()ifisinstance(w,gtk.TreeView):w.emit('thg-diff')returnFalseifnotself.curfile:returnFalseopts={'change':str(self.currev),'bundle':self.bfile}self._do_diff([self.curfile],opts)deffile_row_act(self,tree,path,column):self.diff_file_rev(None)returnTruedefsave_file_rev(self,menuitem):wfile=util.localpath(self.curfile)wfile,ext=os.path.splitext(os.path.basename(wfile))ifwfile:filename="%s@%d%s"%(wfile,self.currev,ext)else:filename="%s@%d"%(ext,self.currev)result=gtklib.NativeSaveFileDialogWrapper(title=_("Save file to"),initial=self.cwd,filename=filename).run()ifresult:q=Queue.Queue()hglib.hgcmd_toq(q,'cat','--rev',str(self.currev),'--output',hglib.fromutf(result),self.curfile)defdiff_to_local(self,menuitem):ifnotself.curfile:returnopts={'rev':[str(self.currev)],'bundle':self.bfile}self._do_diff([self.curfile],opts)defdiff_file_rev(self,menuitem):'User selected visual diff file from the file list context menu'ifnotself.curfile:returnrev=self.currevopts={'change':str(rev),'bundle':self.bfile}parents=self.repo[rev].parents()iflen(parents)==2:ifself.diff_other_parent():parent=parents[1].rev()else:parent=parents[0].rev()opts['rev']=[str(parent),str(rev)]self._do_diff([self.curfile],opts)defview_file_rev(self,menuitem):'User selected view file revision from the file list context menu'ifnotself.curfile:returnrev=self.currevparents=[x.rev()forxinself.repo[rev].parents()]iflen(parents)==0:parent=rev-1else:parent=parents[0]pair='%u:%u'%(parent,rev)self._node1,self._node2=cmdutil.revpair(self.repo,[pair])self._view_files([self.curfile],False)defann_file(self,menuitem):'User selected annotate file from the file list context menu'fromtortoisehg.hgtkimportdataminerev=self.currevdialog=datamine.DataMineDialog(self.ui,self.repo,self.cwd,[],{})dialog.display()dialog.close_current_page()dialog.add_annotate_page(self.curfile,str(rev))deffile_history(self,menuitem):'User selected file history from file list context menu'ifself.glog_parent:# If this changeset browser is embedded in glog, send# send this event to the main appopts={'pats':[self.curfile]}self.glog_parent.filtercombo.set_active(1)self.glog_parent.filterentry.set_text(self.curfile)self.glog_parent.custombutton.set_active(True)self.glog_parent.filter='custom'self.glog_parent.reload_log(**opts)else:# Else launch our own glog instancefromtortoisehg.hgtkimporthistorydlg=history.run(self.ui,filehist=self.curfile)dlg.display()defrevert_file(self,menuitem):'User selected file revert from the file list context menu'rev=self.currevdialog=gdialog.Confirm(_('Confirm revert file to old revision'),[],self,_('Revert %s to contents at revision %d?')%(self.curfile,rev))ifdialog.run()==gtk.RESPONSE_NO:returncmdline=['hg','revert','--verbose','--rev',str(rev),self.curfile]dlg=hgcmd.CmdDialog(cmdline)dlg.run()dlg.hide()shlib.shell_notify([self.repo.wjoin(self.curfile)])defadd_to_popup(self,textview,menu):menu_items=(('----',None),(_('Toggle _Wordwrap'),self.toggle_wordwrap),)forlabel,handlerinmenu_items:iflabel=='----':menuitem=gtk.SeparatorMenuItem()else:menuitem=gtk.MenuItem(label)ifhandler:menuitem.connect('activate',handler)menu.append(menuitem)menu.show_all()deftoggle_wordwrap(self,sender):ifself.textview.get_wrap_mode()!=gtk.WRAP_NONE:self.textview.set_wrap_mode(gtk.WRAP_NONE)else:self.textview.set_wrap_mode(gtk.WRAP_WORD)
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.