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.
## TortoiseHg dialog to start web server## Copyright (C) 2007 Steve Borho <steve@borho.org># Copyright (C) 2007 TK Soh <teekaysoh@gmail.com>#importpygtkpygtk.require("2.0")importgtkimportgobjectimporthttplibimportosimportpangoimportQueueimportsocketimportsysimportthreadingimporttimeimporthglibfromdialogimportquestion_dialog,error_dialogfrommercurial.i18nimport_frommercurialimporthg,ui,commands,cmdutil,utilfrommercurial.hgwebimportserverfrommercurial.i18nimport_fromshlibimportset_tortoise_icongservice=NoneclassServeDialog(gtk.Window):""" Dialog to run web server"""def__init__(self,cwd='',root='',webdir_conf=''):""" Initialize the Dialog """gtk.Window.__init__(self,gtk.WINDOW_TOPLEVEL)set_tortoise_icon(self,'proxy.ico')self.connect('delete-event',self._delete)# Pipe stderr, stdout to self.writeself._queue=Queue.Queue()sys.stdout=selfsys.stderr=self# Override mercurial.commands.serve() with our own version# that supports being stoppedcommands.table.update(thg_serve_cmd)self._url=Noneself._root=rootself._webdirconf=webdir_confifcwd:os.chdir(cwd)self._get_config()self.set_default_size(500,300) # toolbar
self.tbar = gtk.Toolbar()
+ self.tooltips = gtk.Tooltips() self._button_start = self._toolbutton(gtk.STOCK_MEDIA_PLAY,
_('Start'),
self._on_start_clicked,
- _('Start server'))
+tip=_('Start server'))
self._button_stop = self._toolbutton(gtk.STOCK_MEDIA_STOP,
_('Stop'),
self._on_stop_clicked,
- _('Stop server'))
+tip=_('Stop server'))
self._button_browse = self._toolbutton(gtk.STOCK_HOME,
_('Browse'),
self._on_browse_clicked,
- _('Launch browser'))
+tip=_('Launch browser to view repository'))
self._button_conf = self._toolbutton(gtk.STOCK_PREFERENCES,
_('Configure'),
self._on_conf_clicked,
- _('Configure web settings'))
+tip=_('Configure web settings'))
tbuttons = [
self._button_start,
self._button_stop,gtk.SeparatorToolItem(),self._button_browse,gtk.SeparatorToolItem(),self._button_conf,]forbtnintbuttons:self.tbar.insert(btn,-1)vbox=gtk.VBox()self.add(vbox)vbox.pack_start(self.tbar,False,False,2)# revision inputrevbox=gtk.HBox()lbl=gtk.Label(_('HTTP Port:'))lbl.set_property('width-chars',16)lbl.set_alignment(0,0.5)self._port_input=gtk.Entry()self._port_input.set_text(self.defport)revbox.pack_start(lbl,False,False)revbox.pack_start(self._port_input,False,False)vbox.pack_start(revbox,False,False,2)scrolledwindow=gtk.ScrolledWindow()scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)self.textview=gtk.TextView(buffer=None)self.textview.set_editable(False)self.textview.modify_font(pango.FontDescription('Monospace'))scrolledwindow.add(self.textview)self.textview.set_editable(False)self.textbuffer=self.textview.get_buffer()vbox.pack_start(scrolledwindow,True,True)self._set_button_states()def_get_config(self):try:repo=hg.repository(ui.ui(),path=self._root)excepthglib.RepoError:print_('no repository found')gtk.main_quit()self.defport=repo.ui.config('web','port')or'8000'self.webname=repo.ui.config('web','name')or \
os.path.basename(self._root)ifself._webdirconf:self.set_title("hg serve %s - %s"%(self._webdirconf,self.webname)) else:
self.set_title("hg serve - " + self.webname)
- def _toolbutton(self, stock, label, handler, menu=None, userdata=None):
+ def _toolbutton(self, stock, label, handler, menu=None,
+ userdata=None, tip=None):
if menu:
tbutton = gtk.MenuToolButton(stock)
tbutton.set_menu(menu)
else:
tbutton = gtk.ToolButton(stock)
+ if tip:+ tbutton.set_tooltip(self.tooltips, tip)+ tbutton.set_label(label)
tbutton.connect('clicked', handler, userdata)
return tbutton
def_delete(self,widget,event):ifself._server_stopped():gtk.main_quit()else:returnTruedef_server_stopped(self):''' check if server is running, or to terminate if running '''ifgserviceandnotgservice.stopped:ifquestion_dialog(self,_('Really Exit?'),_('Server process is still running\n''Exiting will stop the server.'))!=gtk.RESPONSE_YES:returnFalseelse:self._stop_server()returnTrueelse:returnTruedef_set_button_states(self):ifgserviceandnotgservice.stopped:self._button_start.set_sensitive(False)self._button_stop.set_sensitive(True)self._button_browse.set_sensitive(True)self._button_conf.set_sensitive(False)else:self._button_start.set_sensitive(True)self._button_stop.set_sensitive(False)self._button_browse.set_sensitive(False)self._button_conf.set_sensitive(True)def_on_start_clicked(self,*args):self._start_server()self._set_button_states()def_on_stop_clicked(self,*args):self._stop_server()def_on_browse_clicked(self,*args):''' launch default browser to view repo '''ifself._url:defstart_browser():ifos.name=='nt':try:importwin32api,win32conwin32api.ShellExecute(0,"open",self._url,None,"",win32con.SW_SHOW)except:# Firefox likes to create exceptions at launch,# the user doesn't need to be bothered by thempasselse:importgconfclient=gconf.client_get_default()browser=client.get_string('/desktop/gnome/url-handlers/http/command')+'&'os.system(browser%self._url)threading.Thread(target=start_browser).start()def_on_conf_clicked(self,*args):fromthgconfigimportConfigDialogdlg=ConfigDialog(self._root,True)dlg.show_all()dlg.focus_field('web.name')dlg.run()dlg.hide()self._get_config()def_start_server(self):# gather input datatry:port=int(self._port_input.get_text())except:try:port=int(self.defport)except:port=8000error_dialog(self,_('Invalid port 2048..65535'),_('Defaulting to ')+self.defport)globalgservicegservice=Noneargs=[self._root,self._queue,'serve','--port',str(port)]ifself._webdirconf:args.append('--webdir-conf='+self._webdirconf)else:args.append('--name')args.append(self.webname)thread=threading.Thread(target=hglib.hgcmd_toq,args=args)thread.start()whilenotgserviceornothasattr(gservice,'httpd'):time.sleep(0.1)# gservice.httpd.fqaddr turned out to be unreliable, so use# loopback addr directlyself._url='http://127.0.0.1:%d/'%(port)gobject.timeout_add(10,self.process_queue)def_stop_server(self):ifgserviceandnotgservice.stopped:gservice.stop()defflush(self,*args):passdefwrite(self,msg):self._queue.put(msg)def_write(self,msg,append=True):msg=hglib.toutf(msg)ifappend:enditer=self.textbuffer.get_end_iter()self.textbuffer.insert(enditer,msg)else:self.textbuffer.set_text(msg)defprocess_queue(self):""" Handle all the messages currently in the queue (if any). """whileself._queue.qsize():try:msg=self._queue.get(0)self._write(msg)exceptQueue.Empty:passifgserviceandgservice.stopped:self._set_button_states()returnFalse# Stop polling this functionelse:returnTruedefthg_serve(ui,repo,**opts):classservice:definit(self):self.stopped=Trueutil.set_signal_handler()try:parentui=ui.parentuioruioptlist=("name templates style address port prefix ipv6"" accesslog errorlog webdir_conf certificate")foroinoptlist.split():ifopts[o]:parentui.setconfig("web",o,str(opts[o]))if(repoisnotNone)and(repo.ui!=parentui):repo.ui.setconfig("web",o,str(opts[o]))self.httpd=server.create_server(ui,repo)exceptsocket.error,inst:raiseutil.Abort(_('cannot start server: ')+inst.args[1])ifself.httpd.prefix:prefix=self.httpd.prefix.strip('/')+'/'else:prefix=''port=':%d'%self.httpd.portifport==':80':port=''ui.status(_('listening at http://%s%s/%s (%s:%d)\n')%(self.httpd.fqaddr,port,prefix,self.httpd.addr,self.httpd.port))defstop(self):self.stopped=True# issue request to trigger handle_request() and quitaddr='%s:%d'%(self.httpd.fqaddr,self.httpd.port)conn=httplib.HTTPConnection(addr)conn.request("GET","/")res=conn.getresponse()res.read()conn.close()defrun(self):self.stopped=Falsewhilenotself.stopped:self.httpd.handle_request()self.httpd.server_close()# release portglobalgservicegservice=service()cmdutil.service(opts,initfn=gservice.init,runfn=gservice.run)thg_serve_cmd={"^serve":(thg_serve,[('A','accesslog','',_('name of access log file to write to')),('d','daemon',None,_('run server in background')),('','daemon-pipefds','',_('used internally by daemon mode')),('E','errorlog','',_('name of error log file to write to')),('p','port',0,_('port to use (default: 8000)')),('a','address','',_('address to use')),('','prefix','',_('prefix path to serve from (default: server root)')),('n','name','',_('name to show in web pages (default: working dir)')),('','webdir-conf','',_('name of the webdir config file'' (serve more than one repo)')),('','pid-file','',_('name of file to write process ID to')),('','stdio',None,_('for remote clients')),('t','templates','',_('web templates to use')),('','style','',_('template style to use')),('6','ipv6',None,_('use IPv6 in addition to IPv4')),('','certificate','',_('SSL certificate file'))],_('hg serve [OPTION]...'))}defrun(cwd='',root='',webdir_conf='',**opts):dialog=ServeDialog(cwd,root,webdir_conf)dialog.show_all()gtk.gdk.threads_init()gtk.gdk.threads_enter()gtk.main()gtk.gdk.threads_leave()if__name__=="__main__":opts={}opts['cwd']=os.getcwd()iflen(sys.argv)==2andsys.argv[1].endswith('.conf'):opts['webdir_conf']=sys.argv[1]else:opts['root']=len(sys.argv)>1andsys.argv[1]or''run(**opts)
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.