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.importosimportgtkimportgobjectimportpangoimportQueuefrommercurialimportcmdutil,context,util,ui,hg,patch,mdifffromthgutil.i18nimport_fromthgutil.hglibimport*fromthgutilimportshlibfromhggtkimportgdialog,gtklib,hgcmdclassChangeSet(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=Nonedefget_title(self):title=toutf(os.path.basename(self.repo.root))+' changeset 'rev=self.opts['rev']ifisinstance(rev,str):title+=revelse:title+=rev[0]returntitledefget_icon(self):return'menushowchanged.ico'defget_tbbuttons(self):self.parent_toggle=gtk.ToggleToolButton(gtk.STOCK_UNDO)self.parent_toggle.set_use_underline(True)self.parent_toggle.set_label(_('_Other parent'))self.parent_toggle.set_tooltip(self.tooltips,_('diff other parent'))self.parent_toggle.set_sensitive(False)self.parent_toggle.set_active(False)self.parent_toggle.connect('toggled',self.parent_toggled)return[self.parent_toggle]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=-1defload_details(self,rev):'Load selected changeset details into buffer and filelist'self.currev=revctx=self.repo[rev]ifnotctx:returnparents=ctx.parents()title=self.get_title()iflen(parents)==2:self.parent_toggle.set_sensitive(True)ifself.parent_toggle.get_active():title+=':'+str(parents[1].rev())else:title+=':'+str(parents[0].rev())else:self.parent_toggle.set_sensitive(False)ifself.parent_toggle.get_active():# Parent button must be pushed out, but this# will cause load_details to be called again# so we exit out to prevent recursion.self.parent_toggle.set_active(False)returnifself.clipboard:self.clipboard.set_text(str(ctx))self.set_title(title)ifself.parent_toggle.get_active():parent=parents[1].node()elifparents:parent=parents[0].node()else:parent=self.repo[-1]self._filelist.clear()self._filelist.append(('*',_('[All Files]'),''))modified,added,removed=self.repo.status(parent,ctx.node())[:3]forfinmodified:self._filelist.append(('M',toutf(f),f))forfinadded:self._filelist.append(('A',toutf(f),f))forfinremoved:self._filelist.append(('R',toutf(f),f))self.curnodes=(parent,ctx.node())iflen(self._filelist)>1:self._filesel.select_path((1,))else:self._filesel.select_path((0,))deffilelist_rowchanged(self,sel):model,path=sel.get_selected()ifnotpath:returnstatus,file_utf8,self.curfile=model[path]self.generate_change_header()ifself.curfile:self.append_diff(self.curfile)else:for_,_,finmodel:self.append_diff(f)defgenerate_change_header(self):buf,rev=self._buffer,self.currevdeftitle_line(title,text,tag):pad=' '*(12-len(title))utext=toutf(title+pad+text)buf.insert_with_tags_by_name(eob,utext,tag)buf.insert(eob,"\n")buf.set_text('')ctx=self.repo[rev]eob=buf.get_end_iter()date=displaytime(ctx.date())change=str(rev)+' ('+str(ctx)+')'tags=' '.join(ctx.tags())title_line(_('changeset:'),change,'changeset')ifctx.branch()!='default':title_line(_('branch:'),ctx.branch(),'greybg')title_line(_('user/date:'),ctx.user()+'\t'+date,'changeset')iflen(ctx.parents())==2andself.parent_toggle.get_active():parentindex=1else:parentindex=0forpctxinctx.parents():try:summary=pctx.description().splitlines()[0]summary=toutf(summary)except:summary=""change=str(pctx.rev())+' ('+str(pctx)+')'ifpctx.branch()!=ctx.branch():change+=' ['+toutf(pctx.branch())+']'title=_('parent:')title+=' '*(12-len(title))iflen(ctx.parents())==2andpctx==ctx.parents()[parentindex]:buf.insert_with_tags_by_name(eob,title,'parenthl')buf.insert_with_tags_by_name(eob,change,'linkhl')buf.insert_with_tags_by_name(eob,' '+summary,'parenthl')else:buf.insert_with_tags_by_name(eob,title,'parent')buf.insert_with_tags_by_name(eob,change,'link')buf.insert_with_tags_by_name(eob,' '+summary,'parent')buf.insert(eob,"\n")forcctxinctx.children():try:summary=cctx.description().splitlines()[0]summary=toutf(summary)except:summary=""change=str(cctx.rev())+' ('+str(cctx)+')'ifcctx.branch()!=ctx.branch():change+=' ['+toutf(cctx.branch())+']'title=_('child:')title+=' '*(12-len(title))buf.insert_with_tags_by_name(eob,title,'parent')buf.insert_with_tags_by_name(eob,change,'link')buf.insert_with_tags_by_name(eob,' '+summary,'parent')buf.insert(eob,"\n")iftags:title_line(_('tags:'),tags,'tag')log=toutf(ctx.description())buf.insert(eob,'\n'+log+'\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)exceptLookupError:fctx=Noneiffctxandfctx.size()>getmaxdiffsize(self.ui):lines=['diff','','',_(' %s is larger than the specified max diff size')%wfile]else:lines=[]matcher=cmdutil.matchfiles(self.repo,[wfile])opts=mdiff.diffopts(git=True,nodates=True)forsinpatch.diff(self.repo,n1,n2,match=matcher,opts=opts):lines.extend(s.splitlines())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('mono',pos,eob)returnTruedefprepare_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[3:]:ifl.startswith('+'):add+=1elifl.startswith('-'):rem+=1outlines=[]tags=[]txt=toutf('=== (+%d,-%d) %s ===\n'%(add,rem,fname))addtag('greybg',offset,len(txt))outlines.append(txt)offset+=len(txt.decode('utf-8'))forl1indifflines[3:]:l=toutf(l1)ifl.startswith('@@'):tag='blue'elifl.startswith('+'):tag='green'l=diffexpand(l)elifl.startswith('-'):tag='red'l=diffexpand(l)else:tag='black'l=diffexpand(l)l=l+"\n"length=len(l.decode('utf-8'))addtag(tag,offset,length)outlines.append(l)offset+=lengthreturntags,outlinesdeflink_event(self,tag,widget,event,liter):ifevent.type!=gtk.gdk.BUTTON_RELEASE:returntext=self.get_link_text(tag,widget,liter)ifnottext:returnlinkrev=long(text.split(' ')[0])ifself.graphview:self.graphview.set_revision_id(linkrev,load=True)else:self.load_details(linkrev)defget_link_text(self,tag,widget,liter):'handle clicking on a link in a textview'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_context_menu(self):defcreate_menu(label,callback):menuitem=gtk.MenuItem(label,True)menuitem.connect('activate',callback)menuitem.set_border_width(1)returnmenuitemmenu=gtk.Menu()menu.append(create_menu(_('_visual diff'),self.diff_file_rev))menu.append(create_menu(_('diff to _local'),self.diff_to_local))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(create_menu(_('_file history'),self.file_history))self.ann_menu=create_menu(_('_annotate file'),self.ann_file)menu.append(self.ann_menu)menu.append(create_menu(_('_revert file contents'),self.revert_file))menu.show_all()returnmenudefget_body(self):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=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)details_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))scroller.add(details_text)self._buffer=gtk.TextBuffer()self.setup_tags()details_text.set_buffer(self._buffer)self.textview=details_textfilelist_tree=gtk.TreeView()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)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(_('Stat'),gtk.CellRendererText(),text=0)filelist_tree.append_column(column)column=gtk.TreeViewColumn(_('Files'),gtk.CellRendererText(),text=1)filelist_tree.append_column(column)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)list_frame.add(scroller)self._hpaned=gtk.HPaned()self._hpaned.pack1(list_frame,True,True)self._hpaned.pack2(details_frame,True,True)self._hpaned.set_position(self._setting_hpos)ifself.stbar:# embedded by changelog browserreturnself._hpanedelse:# add status bar for main appvbox=gtk.VBox()vbox.pack_start(self._hpaned,True,True)self.stbar=gtklib.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('changeset',foreground='#000090',paragraph_background='#F0F0F0'))tag_table.add(make_texttag('date',foreground='#000090',paragraph_background='#F0F0F0'))tag_table.add(make_texttag('tag',foreground='#000090',paragraph_background='#F0F0F0'))tag_table.add(make_texttag('files',foreground='#5C5C5C',paragraph_background='#F0F0F0'))tag_table.add(make_texttag('parent',foreground='#000090',paragraph_background='#F0F0F0'))tag_table.add(make_texttag('parenthl',foreground='#000090',paragraph_background='#F0F0F0',weight=pango.WEIGHT_BOLD))tag_table.add(make_texttag('mono',family='Monospace'))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'))link_tag=make_texttag('link',foreground='blue',underline=pango.UNDERLINE_SINGLE)linkhl_tag=make_texttag('linkhl',foreground='blue',underline=pango.UNDERLINE_SINGLE,weight=pango.WEIGHT_BOLD)link_tag.connect('event',self.link_event)linkhl_tag.connect('event',self.link_event)tag_table.add(link_tag)tag_table.add(linkhl_tag)deffile_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()exceptLookupError: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:returnFalseself._do_diff([self.curfile],{'change':self.currev})deffile_row_act(self,tree,path,column):'Default action is the first entry in the context menu'self.filemenu.get_children()[0].activate()returnTruedefsave_file_rev(self,menuitem):wfile=util.localpath(self.curfile)wfile,ext=os.path.splitext(os.path.basename(wfile))filename="%s@%d%s"%(wfile,self.currev,ext)result=gtklib.NativeSaveFileDialogWrapper(Title=_("Save file to"),InitialDir=self.cwd,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)q=Queue.Queue()hgcmd_toq(self.repo.root,q,'cat','--rev',str(self.currev),'--output',fromutf(result),self.curfile)defdiff_to_local(self,menuitem):ifnotself.curfile:returnself._do_diff([self.curfile],{'rev':str(self.currev)})defdiff_file_rev(self,menuitem):'User selected visual diff file from the file list context menu'ifnotself.curfile:returnself._do_diff([self.curfile],{'change':str(self.currev)})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'fromhggtkimportdataminerev=self.currevdialog=datamine.DataMineDialog(self.ui,self.repo,self.cwd,[],{})dialog.display()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 app
opts = {'pats' : [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 instance
fromhggtkimporthistorydlg=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.