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.
Newer hgext/pager.py calls this method of stdout. We need to implement this function and return False else the pager extension breaks our web server dialog.
# serve.py - TortoiseHg dialog to start web server## Copyright 2007 Steve Borho <steve@borho.org># Copyright 2007 TK Soh <teekaysoh@gmail.com>## This software may be used and distributed according to the terms of the# GNU General Public License version 2, incorporated herein by reference.importgtkimportgobjectimporthttplibimportosimportpangoimportQueueimportsocketimportsysimportthreadingimporttimefrommercurialimporthg,ui,commands,cmdutil,utilfrommercurial.hgwebimportserverfromthgutil.i18nimport_fromthgutilimporthglib,pathsfromhggtkimportdialog,gdialog,gtklib,thgconfiggservice=NoneclassServeDialog(gtk.Window):""" Dialog to run web server"""def__init__(self,webdir_conf):""" Initialize the Dialog """gtk.Window.__init__(self,gtk.WINDOW_TOPLEVEL)gtklib.set_tortoise_icon(self,'proxy.ico')gtklib.set_tortoise_keys(self)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=paths.find_root()self._webdirconf=webdir_confself._get_config()self.set_default_size(500,300)# toolbarself.tbar=gtk.Toolbar()self.tooltips=gtk.Tooltips()self._button_start=self._toolbutton(gtk.STOCK_MEDIA_PLAY,_('Start'),self._on_start_clicked,tip=_('Start server'))self._button_stop=self._toolbutton(gtk.STOCK_MEDIA_STOP,_('Stop'),self._on_stop_clicked,tip=_('Stop server'))self._button_browse=self._toolbutton(gtk.STOCK_HOME,_('Browse'),self._on_browse_clicked,tip=_('Launch browser to view repository'))self._button_conf=self._toolbutton(gtk.STOCK_PREFERENCES,_('Configure'),self._on_conf_clicked,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.textbuffer=self.textview.get_buffer() vbox.pack_start(scrolledwindow, True, True)
self._set_button_states()
+ def isatty(self):+ 'hgext/pager.py calls this method of stdout'+ return False+ def _get_config(self):
try:
repo = hg.repository(ui.ui(), path=self._root)
excepthglib.RepoError:self.destroy()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(_('Serve %s - %s')%(hglib.toutf(self._webdirconf),hglib.toutf(self.webname)))else:self.set_title(_('Serve - ')+hglib.toutf(self.webname))def_toolbutton(self,stock,label,handler,menu=None,userdata=None,tip=None):ifmenu:tbutton=gtk.MenuToolButton(stock)tbutton.set_menu(menu)else:tbutton=gtk.ToolButton(stock)iftip:tbutton.set_tooltip(self.tooltips,tip)tbutton.set_label(label)tbutton.connect('clicked',handler,userdata)returntbuttondef_delete(self,widget,event):ifnotself.should_live():self.destroy()else:returnTruedefshould_live(self):returnnotself._server_stopped()def_server_stopped(self):''' check if server is running, or to terminate if running '''ifgserviceandnotgservice.stopped:ret=gdialog.Confirm(_('Confirm Really Exit?'),[],self,_('Server process is still running\n''Exiting will stop the server.')).run()ifret==gtk.RESPONSE_YES:self._stop_server()returnTrueelse:returnFalseelse: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):dlg=thgconfig.ConfigDialog(True)dlg.show_all()dlg.focus_field('web.name')dlg.run()dlg.hide()self._get_config()def_start_server(self):defthreadfunc(path,q,*args):try:hglib.hgcmd_toq(path,q,*args)exceptutil.Abort,e:self._write(_('Abort: %s\n')%str(e))# gather input datatry:port=int(self._port_input.get_text())except:try:port=int(self.defport)except:port=8000dialog.error_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=threadfunc,args=args)thread.start()whileTrue:time.sleep(0.1)ifgserviceandhasattr(gservice,'httpd'):breakifnotthread.isAlive():return# 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:baseui=repoandrepo.baseuioruirepoui=repoandrepo.ui!=baseuiandrepo.uiorNoneoptlist=("name templates style address port prefix ipv6"" accesslog errorlog webdir_conf certificate")foroinoptlist.split():ifopts[o]:baseui.setconfig("web",o,str(opts[o]))ifrepoui:repoui.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(ui,*pats,**opts):returnServeDialog(opts.get('webdir_conf'))
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.