##// END OF EJS Templates
changed for pylons 0.1 / 1.0...
marcink -
r43:2e1247e6 default
parent child Browse files
Show More
@@ -0,0 +1,87 b''
1 import logging
2
3 from pylons import request, response, session, tmpl_context as c, url, app_globals as g
4 from pylons.controllers.util import abort, redirect
5
6 from pylons_app.lib.base import BaseController, render
7 import os
8 from mercurial import ui, hg
9 from mercurial.error import RepoError
10 from ConfigParser import ConfigParser
11 log = logging.getLogger(__name__)
12
13 class AdminController(BaseController):
14
15
16 def __before__(self):
17 c.staticurl = g.statics
18
19 def index(self):
20 # Return a rendered template
21 return render('/admin.html')
22
23
24 def manage_hgrc(self):
25 pass
26
27 def hgrc(self, dirname):
28 filename = os.path.join(dirname, '.hg', 'hgrc')
29 return filename
30
31 def add_repo(self, new_repo):
32
33
34 #extra check it can be add since it's the command
35 if new_repo == 'add':
36 c.msg = 'you basstard ! this repo is a command'
37 c.new_repo = ''
38 return render('add.html')
39
40 new_repo = new_repo.replace(" ", "_")
41 new_repo = new_repo.replace("-", "_")
42
43 try:
44 self._create_repo(new_repo)
45 c.new_repo = new_repo
46 c.msg = 'added repo'
47 except Exception as e:
48 c.new_repo = 'Exception when adding: %s' % new_repo
49 c.msg = str(e)
50
51 return render('add.html')
52
53 def _check_repo(self, repo_name):
54 p = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
55 config_path = os.path.join(p, 'hgwebdir.config')
56
57 cp = ConfigParser()
58
59 cp.read(config_path)
60 repos_path = cp.get('paths', '/').replace("**", '')
61
62 if not repos_path:
63 raise Exception('Could not read config !')
64
65 self.repo_path = os.path.join(repos_path, repo_name)
66
67 try:
68 r = hg.repository(ui.ui(), self.repo_path)
69 hg.verify(r)
70 #here we hnow that repo exists it was verified
71 log.info('%s repo is already created', repo_name)
72 raise Exception('Repo exists')
73 except RepoError:
74 log.info('%s repo is free for creation', repo_name)
75 #it means that there is no valid repo there...
76 return True
77
78
79 def _create_repo(self, repo_name):
80 if repo_name in [None, '', 'add']:
81 raise Exception('undefined repo_name of repo')
82
83 if self._check_repo(repo_name):
84 log.info('creating repo %s in %s', repo_name, self.repo_path)
85 cmd = """mkdir %s && hg init %s""" \
86 % (self.repo_path, self.repo_path)
87 os.popen(cmd)
@@ -0,0 +1,51 b''
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <link rel="icon" href="${c.staticurl}hgicon.png" type="image/png" />
6 <meta name="robots" content="index, nofollow"/>
7 <link rel="stylesheet" href="${c.staticurl}style-monoblue.css" type="text/css" />
8 <title>Mercurial repositories Admin</title>
9 </head>
10
11 <body>
12 <div id="container">
13 <div class="page-header">
14 <h1><a href="/">Home</a> / Admin</h1>
15 <ul class="page-nav">
16 </ul>
17 </div>
18 <table cellspacing="0">
19 <tr>
20 <td>${h.link_to(u'Create "ccc" repository',h.url('admin_add_repo',new_repo='ccc'))}</td>
21 </tr>
22 <tr>
23 <td>${h.link_to(u'Create "ccc" repository',h.url('admin_add_repo',new_repo='ccc'))}</td>
24 </tr>
25 <tr>
26 <td>${h.link_to(u'Create "ccc" repository',h.url('admin_add_repo',new_repo='ccc'))}</td>
27 </tr>
28 <tr>
29 <td><h2>${c.new_repo}</h2></td>
30 </tr>
31 </table>
32 <div class="page-footer">
33 Mercurial Repository: admin
34 </div>
35
36 <div id="powered-by">
37 <p>
38 <a href="http://mercurial.selenic.com/" title="Mercurial">
39 <img src="${c.staticurl}hglogo.png" width="75" height="90" alt="mercurial"></a>
40 </p>
41 </div>
42
43 <div id="corner-top-left"></div>
44 <div id="corner-top-right"></div>
45 <div id="corner-bottom-left"></div>
46 <div id="corner-bottom-right"></div>
47
48 </div>
49 </body>
50 </html>
51 No newline at end of file
@@ -0,0 +1,7 b''
1 from pylons_app.tests import *
2
3 class TestAdminController(TestController):
4
5 def test_index(self):
6 response = self.app.get(url(controller='admin', action='index'))
7 # Test response...
@@ -1,43 +1,68 b''
1 1 """Pylons environment configuration"""
2 2 import logging
3 3 import os
4 4
5 5 from mako.lookup import TemplateLookup
6 from pylons.configuration import PylonsConfig
6 7 from pylons.error import handle_mako_error
7 from pylons import config
8 from sqlalchemy import engine_from_config
8 9
9 10 import pylons_app.lib.app_globals as app_globals
10 11 import pylons_app.lib.helpers
11 12 from pylons_app.config.routing import make_map
13 from pylons_app.model import init_model
12 14
13 15 log = logging.getLogger(__name__)
14 16
15 17 def load_environment(global_conf, app_conf):
16 18 """Configure the Pylons environment via the ``pylons.config``
17 19 object
18 20 """
21 config = PylonsConfig()
22
19 23 # Pylons paths
20 24 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
21 25 paths = dict(root=root,
22 26 controllers=os.path.join(root, 'controllers'),
23 27 static_files=os.path.join(root, 'public'),
24 28 templates=[os.path.join(root, 'templates')])
25 29
26 30 # Initialize config with the basic options
27 config.init_app(global_conf, app_conf, package='pylons_app',
28 template_engine='mako', paths=paths)
31 config.init_app(global_conf, app_conf, package='pylons_app', paths=paths)
29 32
30 config['routes.map'] = make_map()
31 config['pylons.app_globals'] = app_globals.Globals()
33 config['routes.map'] = make_map(config)
34 config['pylons.app_globals'] = app_globals.Globals(config)
32 35 config['pylons.h'] = pylons_app.lib.helpers
36
37 # Setup cache object as early as possible
38 import pylons
39 pylons.cache._push_object(config['pylons.app_globals'].cache)
40
33 41
34 42 # Create the Mako TemplateLookup, with the default auto-escaping
35 43 config['pylons.app_globals'].mako_lookup = TemplateLookup(
36 44 directories=paths['templates'],
37 45 error_handler=handle_mako_error,
38 46 module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
39 47 input_encoding='utf-8', default_filters=['escape'],
40 48 imports=['from webhelpers.html import escape'])
41 49
50 #sets the c attribute access when don't existing attribute ar accessed
51 config['pylons.strict_tmpl_context'] = False
52
53 #MULTIPLE DB configs
54 # Setup the SQLAlchemy database engine
55 # if config['debug']:
56 # #use query time debugging.
57 # from pylons_app.lib.timer_proxy import TimerProxy
58 # sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
59 # proxy=TimerProxy())
60 # else:
61 # sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
62
63 #init_model(sa_engine_db1)
64
42 65 # CONFIGURATION OPTIONS HERE (note: all config options will override
43 66 # any Pylons config options)
67
68 return config
@@ -1,68 +1,70 b''
1 1 """Pylons middleware initialization"""
2 from beaker.middleware import CacheMiddleware, SessionMiddleware
2 from beaker.middleware import SessionMiddleware
3 3 from paste.cascade import Cascade
4 4 from paste.registry import RegistryManager
5 5 from paste.urlparser import StaticURLParser
6 6 from paste.deploy.converters import asbool
7 from pylons import config
8 7 from pylons.middleware import ErrorHandler, StatusCodeRedirect
9 8 from pylons.wsgiapp import PylonsApp
10 9 from routes.middleware import RoutesMiddleware
11 10 from paste.auth.basic import AuthBasicHandler
12 11 from pylons_app.config.environment import load_environment
13 12 from pylons_app.lib.auth import authfunc
14 13
15 def make_app(global_conf, full_stack=True, **app_conf):
14 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
16 15 """Create a Pylons WSGI application and return it
17 16
18 17 ``global_conf``
19 18 The inherited configuration for this application. Normally from
20 19 the [DEFAULT] section of the Paste ini file.
21 20
22 21 ``full_stack``
23 22 Whether or not this application provides a full WSGI stack (by
24 23 default, meaning it handles its own exceptions and errors).
25 24 Disable full_stack when this application is "managed" by
26 25 another WSGI middleware.
27 26
28 27 ``app_conf``
29 28 The application's local configuration. Normally specified in
30 29 the [app:<name>] section of the Paste ini file (where <name>
31 30 defaults to main).
32 31
33 32 """
34 33 # Configure the Pylons environment
35 load_environment(global_conf, app_conf)
34 config = load_environment(global_conf, app_conf)
35
36 36
37 37 # The Pylons WSGI app
38 app = PylonsApp()
38 app = PylonsApp(config=config)
39 39
40 40 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
41 41
42 42 # Routing/Session/Cache Middleware
43 43 app = RoutesMiddleware(app, config['routes.map'])
44 44 app = SessionMiddleware(app, config)
45 app = CacheMiddleware(app, config)
46 45 app = AuthBasicHandler(app, config['repos_name'] + ' mercurial repository', authfunc)
47 46
48 47 if asbool(full_stack):
49 48 # Handle Python exceptions
50 49 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
51 50
52 51 # Display error documents for 401, 403, 404 status codes (and
53 52 # 500 when debug is disabled)
54 53 if asbool(config['debug']):
55 54 #don't handle 404, since mercurial does it for us.
56 app = StatusCodeRedirect(app, [400, 401, 403, 500])
55 app = StatusCodeRedirect(app, [400, 401, 403])
57 56 else:
58 57 app = StatusCodeRedirect(app, [400, 401, 403, 500])
59 58
60 59 # Establish the Registry for this application
61 60 app = RegistryManager(app)
62 61
63 # Static files (If running in production, and Apache or another web
64 # server is handling this static content, remove the following 3 lines)
65 static_app = StaticURLParser(config['pylons.paths']['static_files'])
66 app = Cascade([static_app, app])
62 if asbool(static_files):
63 # Serve static files
64 static_app = StaticURLParser(config['pylons.paths']['static_files'])
65 app = Cascade([static_app, app])
66
67 app.config = config
68
67 69 return app
68 70
@@ -1,28 +1,30 b''
1 1 """Routes configuration
2 2
3 3 The more specific and detailed routes should be defined first so they
4 4 may take precedent over the more generic routes. For more information
5 5 refer to the routes manual at http://routes.groovie.org/docs/
6 6 """
7 from pylons import config
8 7 from routes import Mapper
9 8
10 def make_map():
9 def make_map(config):
11 10 """Create, configure and return the routes Mapper"""
12 map = Mapper(directory = config['pylons.paths']['controllers'],
13 always_scan = config['debug'])
11 map = Mapper(directory=config['pylons.paths']['controllers'],
12 always_scan=config['debug'])
14 13 map.minimization = False
14 map.explicit = False
15 15
16 16 # The ErrorController route (handles 404/500 error pages); it should
17 17 # likely stay at the top, ensuring it can always be resolved
18 map.connect('/error/{action}', controller = 'error')
19 map.connect('/error/{action}/{id}', controller = 'error')
18 map.connect('/error/{action}', controller='error')
19 map.connect('/error/{action}/{id}', controller='error')
20 20
21 21 # CUSTOM ROUTES HERE
22 map.connect('hg_add', '/add/{new_repo:[a-z0-9\. _-]*}',
23 controller = 'hg', action = 'add_repo')
24 map.connect('hg', '/{path_info:.*}',
25 controller = 'hg', action = "view",
26 path_info = '/')
22 with map.submapper(path_prefix='/_admin', controller='admin') as m:
23 m.connect('admin_home', '/', action='index')#main page
24 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', action='add_repo')
25 m.connect('admin_manage_users', '/manage_users', action='index')
26
27 map.connect('hg', '/{path_info:.*}', controller='hg',
28 action="view", path_info='/')
27 29
28 30 return map
@@ -1,134 +1,41 b''
1 1 #!/usr/bin/python
2 2 # -*- coding: utf-8 -*-
3 3 import logging
4 import os
5 from pylons_app.lib.base import BaseController, render
4 from pylons_app.lib.base import BaseController
6 5 from pylons import tmpl_context as c, app_globals as g, session, request, config
7 6 from pylons_app.lib import helpers as h
8 7 from mako.template import Template
9 from mercurial import ui, hg
10 from mercurial.error import RepoError
11 from ConfigParser import ConfigParser
12 8 from pylons.controllers.util import abort
13 9
14 10 log = logging.getLogger(__name__)
15 11
16 12 class HgController(BaseController):
17 13
18 14 def __before__(self):
19 15 c.repos_prefix = config['repos_name']
20 16
21 17 def view(self, *args, **kwargs):
22 18 response = g.hgapp(request.environ, self.start_response)
23 19
24 20 http_accept = request.environ.get('HTTP_ACCEPT', False)
25 21 if not http_accept:
26 22 return abort(status_code=400, detail='no http accept in header')
27 23
28 24 #for mercurial protocols and raw files we can't wrap into mako
29 25 if http_accept.find("mercurial") != -1 or \
30 26 request.environ['PATH_INFO'].find('raw-file') != -1:
31 27 return response
32 28 try:
33 29 tmpl = u''.join(response)
34 30 template = Template(tmpl, lookup=request.environ['pylons.pylons']\
35 31 .config['pylons.app_globals'].mako_lookup)
36 32
37 33 except (RuntimeError, UnicodeDecodeError):
38 34 log.info('disabling unicode due to encoding error')
39 35 response = g.hgapp(request.environ, self.start_response)
40 36 tmpl = ''.join(response)
41 37 template = Template(tmpl, lookup=request.environ['pylons.pylons']\
42 38 .config['pylons.app_globals'].mako_lookup, disable_unicode=True)
43 39
44 40
45 41 return template.render(g=g, c=c, session=session, h=h)
46
47
48 def manage_hgrc(self):
49 pass
50
51 def hgrc(self, dirname):
52 filename = os.path.join(dirname, '.hg', 'hgrc')
53 return filename
54
55 def add_repo(self, new_repo):
56 c.staticurl = g.statics
57
58 #extra check it can be add since it's the command
59 if new_repo == 'add':
60 c.msg = 'you basstard ! this repo is a command'
61 c.new_repo = ''
62 return render('add.html')
63
64 new_repo = new_repo.replace(" ", "_")
65 new_repo = new_repo.replace("-", "_")
66
67 try:
68 self._create_repo(new_repo)
69 c.new_repo = new_repo
70 c.msg = 'added repo'
71 except Exception as e:
72 c.new_repo = 'Exception when adding: %s' % new_repo
73 c.msg = str(e)
74
75 return render('add.html')
76
77 def _check_repo(self, repo_name):
78 p = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
79 config_path = os.path.join(p, 'hgwebdir.config')
80
81 cp = ConfigParser()
82
83 cp.read(config_path)
84 repos_path = cp.get('paths', '/').replace("**", '')
85
86 if not repos_path:
87 raise Exception('Could not read config !')
88
89 self.repo_path = os.path.join(repos_path, repo_name)
90
91 try:
92 r = hg.repository(ui.ui(), self.repo_path)
93 hg.verify(r)
94 #here we hnow that repo exists it was verified
95 log.info('%s repo is already created', repo_name)
96 raise Exception('Repo exists')
97 except RepoError:
98 log.info('%s repo is free for creation', repo_name)
99 #it means that there is no valid repo there...
100 return True
101
102
103 def _create_repo(self, repo_name):
104 if repo_name in [None, '', 'add']:
105 raise Exception('undefined repo_name of repo')
106
107 if self._check_repo(repo_name):
108 log.info('creating repo %s in %s', repo_name, self.repo_path)
109 cmd = """mkdir %s && hg init %s""" \
110 % (self.repo_path, self.repo_path)
111 os.popen(cmd)
112
113 #def _make_app():
114 # #for single a repo
115 # #return hgweb("/path/to/repo", "Name")
116 # repos = "hgwebdir.config"
117 # return hgwebdir(repos)
118 #
119
120 # def view(self, environ, start_response):
121 # #the following is only needed when using hgwebdir
122 # app = _make_app()
123 # #return wsgi_app(environ, start_response)
124 # response = app(request.environ, self.start_response)
125 #
126 # if environ['PATH_INFO'].find("static") != -1:
127 # return response
128 # else:
129 # #wrap the murcurial response in a mako template.
130 # template = Template("".join(response),
131 # lookup = environ['pylons.pylons']\
132 # .config['pylons.g'].mako_lookup)
133 #
134 # return template.render(g = g, c = c, session = session, h = h)
@@ -1,72 +1,76 b''
1 1 """The application's Globals object"""
2 2 #uncomment the following if you want to serve a single repo
3 3 #from mercurial.hgweb.hgweb_mod import hgweb
4 4 from mercurial.hgweb.hgwebdir_mod import hgwebdir
5 5 from mercurial import templater
6 6 from mercurial.hgweb.request import wsgiapplication
7 7 from mercurial import ui, config
8 8 import os
9 from beaker.cache import CacheManager
10 from beaker.util import parse_cache_config_options
11
9 12 class Globals(object):
10 13
11 14 """Globals acts as a container for objects available throughout the
12 15 life of the application
13 16
14 17 """
15 18
16 def __init__(self):
19 def __init__(self, config):
17 20 """One instance of Globals is created during application
18 21 initialization and is available during requests via the
19 22 'app_globals' variable
20 23
21 24 """
22 25 #two ways of building the merc app i don't know
23 26 #the fastest one but belive the wsgiapp is better
24 27 #self.hgapp = self.make_web_app()
28 self.cache = CacheManager(**parse_cache_config_options(config))
25 29 self.hgapp = wsgiapplication(self.make_web_app)
26 30
27 31
28 32 def make_web_app(self):
29 33 repos = "hgwebdir.config"
30 34 baseui = ui.ui()
31 35 cfg = config.config()
32 36 cfg.read(repos)
33 37 paths = cfg.items('paths')
34 38 self.check_repo_dir(paths)
35 39 self.set_statics(cfg)
36 40
37 41 for k, v in cfg.items('web'):
38 42 baseui.setconfig('web', k, v)
39 43 #magic trick to make our custom template dir working
40 44 templater.path.append(cfg.get('web', 'templates', None))
41 45
42 46 #baseui.setconfig('web', 'description', '')
43 47 #baseui.setconfig('web', 'name', '')
44 48 #baseui.setconfig('web', 'contact', '')
45 49 #baseui.setconfig('web', 'allow_archive', '')
46 50 #baseui.setconfig('web', 'style', 'monoblue_plain')
47 51 #baseui.setconfig('web', 'baseurl', '')
48 52 #baseui.setconfig('web', 'staticurl', '')
49 53
50 54 hgwebapp = hgwebdir(paths, baseui=baseui)
51 55 return hgwebapp
52 56
53 57
54 58 def set_statics(self, cfg):
55 59 '''
56 60 set's the statics for use in mako templates
57 61 @param cfg:
58 62 '''
59 63 self.statics = cfg.get('web', 'staticurl', '/static')
60 64 if not self.statics.endswith('/'):
61 65 self.statics += '/'
62 66
63 67
64 68 def check_repo_dir(self, paths):
65 69 repos_path = paths[0][1].split('/')
66 70 if repos_path[-1] in ['*', '**']:
67 71 repos_path = repos_path[:-1]
68 72 if repos_path[0] != '/':
69 73 repos_path[0] = '/'
70 74 if not os.path.isdir(os.path.join(*repos_path)):
71 75 raise Exception('Not a valid repository in %s' % paths[0][1])
72 76
@@ -1,49 +1,48 b''
1 1 """Helper functions
2 2
3 3 Consists of functions to typically be used within templates, but also
4 4 available to Controllers. This module is available to both as 'h'.
5 5 """
6 from routes import redirect_to, url_for
7
6 from pylons import url
8 7 from webhelpers.html import (literal, HTML, escape)
9 8 from webhelpers.html.tools import (auto_link, button_to, highlight, js_obfuscate
10 9 , mail_to, strip_links, strip_tags, tag_re)
11 10 from webhelpers.html.tags import (auto_discovery_link, checkbox, css_classes,
12 11 end_form, file, form, hidden, image,
13 12 javascript_link, link_to, link_to_if,
14 13 link_to_unless, ol, required_legend,
15 14 select, stylesheet_link,
16 15 submit, text, textarea, title, ul, xml_declaration)
17 16 from webhelpers.text import (chop_at, collapse, convert_accented_entities,
18 17 convert_misc_characters, convert_misc_entities,
19 18 lchop, plural, rchop, remove_formatting, replace_whitespace,
20 19 urlify)
21 20
22 21 from webhelpers.pylonslib import Flash as _Flash
23 22 from webhelpers.pylonslib.secure_form import secure_form
24 23
25 24 #Custom helper here :)
26 25 class _Link(object):
27 26 '''
28 27 Make a url based on label and url with help of url_for
29 28 @param label:name of link if not defined url is used
30 29 @param url: the url for link
31 30 '''
32 31
33 def __call__(self, label = '', *url, **urlargs):
32 def __call__(self, label='', *url_, **urlargs):
34 33 if label is None or '':
35 34 label = url
36 link_fn = link_to(label, url_for(*url, **urlargs))
35 link_fn = link_to(label, url(*url_, **urlargs))
37 36 return link_fn
38 37
39 38
40 39 class _GetError(object):
41 40
42 41 def __call__(self, field_name, form_errors):
43 42 tmpl = """<span class="error_msg">%s</span>"""
44 43 if form_errors and form_errors.has_key(field_name):
45 44 return literal(tmpl % form_errors.get(field_name))
46 45
47 46 link = _Link()
48 47 flash = _Flash()
49 48 get_error = _GetError()
@@ -1,38 +1,41 b''
1 1 ## -*- coding: utf-8 -*-
2 2 {header}
3 3 <title>{repo|escape}: Mercurial repository not found</title>
4 4 </head>
5 5
6 6 <body>
7 7 <div id="container">
8 8 <div class="page-header">
9 9 <h1>Not found: {repo|escape}</h1>
10 10
11 11 <div style="height: 50px">
12 12 </div>
13 13 </div>
14 14
15 15 <h2 class="no-link no-border">Not Found</h2>
16 16 <p class="normal">The specified repository "{repo|escape}" is unknown, sorry.</p>
17 <p class="normal"><a href="/add/{repo|escape}">Create "{repo|escape}" repository </a></p>
17 <p class="normal">
18 <a href="/_admin/add_repo/{repo|escape}">Create "{repo|escape}" repository</a>
19
20 </p>
18 21 <p class="normal">Go back to the <a href="{url}">main repository list page</a>.</p>
19 22 <div class="page-footer">
20 23 <p>Mercurial Repository: {repo|escape}</p>
21 24 </div>
22 25
23 26 <div id="powered-by">
24 27 <p><a href="http://mercurial.selenic.com/" title="Mercurial"><img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a></p>
25 28
26 29 </div>
27 30
28 31 <div id="corner-top-left"></div>
29 32 <div id="corner-top-right"></div>
30 33 <div id="corner-bottom-left"></div>
31 34 <div id="corner-bottom-right"></div>
32 35
33 36 </div>
34 37
35 38 </body>
36 39 </html>
37 40
38 41
General Comments 0
You need to be logged in to leave comments. Login now