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 | """Pylons environment configuration""" |
|
1 | """Pylons environment configuration""" | |
2 | import logging |
|
2 | import logging | |
3 | import os |
|
3 | import os | |
4 |
|
4 | |||
5 | from mako.lookup import TemplateLookup |
|
5 | from mako.lookup import TemplateLookup | |
|
6 | from pylons.configuration import PylonsConfig | |||
6 | from pylons.error import handle_mako_error |
|
7 | from pylons.error import handle_mako_error | |
7 |
from |
|
8 | from sqlalchemy import engine_from_config | |
8 |
|
9 | |||
9 | import pylons_app.lib.app_globals as app_globals |
|
10 | import pylons_app.lib.app_globals as app_globals | |
10 | import pylons_app.lib.helpers |
|
11 | import pylons_app.lib.helpers | |
11 | from pylons_app.config.routing import make_map |
|
12 | from pylons_app.config.routing import make_map | |
|
13 | from pylons_app.model import init_model | |||
12 |
|
14 | |||
13 | log = logging.getLogger(__name__) |
|
15 | log = logging.getLogger(__name__) | |
14 |
|
16 | |||
15 | def load_environment(global_conf, app_conf): |
|
17 | def load_environment(global_conf, app_conf): | |
16 | """Configure the Pylons environment via the ``pylons.config`` |
|
18 | """Configure the Pylons environment via the ``pylons.config`` | |
17 | object |
|
19 | object | |
18 | """ |
|
20 | """ | |
|
21 | config = PylonsConfig() | |||
|
22 | ||||
19 | # Pylons paths |
|
23 | # Pylons paths | |
20 | root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|
24 | root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
21 | paths = dict(root=root, |
|
25 | paths = dict(root=root, | |
22 | controllers=os.path.join(root, 'controllers'), |
|
26 | controllers=os.path.join(root, 'controllers'), | |
23 | static_files=os.path.join(root, 'public'), |
|
27 | static_files=os.path.join(root, 'public'), | |
24 | templates=[os.path.join(root, 'templates')]) |
|
28 | templates=[os.path.join(root, 'templates')]) | |
25 |
|
29 | |||
26 | # Initialize config with the basic options |
|
30 | # Initialize config with the basic options | |
27 | config.init_app(global_conf, app_conf, package='pylons_app', |
|
31 | config.init_app(global_conf, app_conf, package='pylons_app', paths=paths) | |
28 | template_engine='mako', paths=paths) |
|
|||
29 |
|
32 | |||
30 | config['routes.map'] = make_map() |
|
33 | config['routes.map'] = make_map(config) | |
31 | config['pylons.app_globals'] = app_globals.Globals() |
|
34 | config['pylons.app_globals'] = app_globals.Globals(config) | |
32 | config['pylons.h'] = pylons_app.lib.helpers |
|
35 | config['pylons.h'] = pylons_app.lib.helpers | |
33 |
|
36 | |||
|
37 | # Setup cache object as early as possible | |||
|
38 | import pylons | |||
|
39 | pylons.cache._push_object(config['pylons.app_globals'].cache) | |||
|
40 | ||||
|
41 | ||||
34 | # Create the Mako TemplateLookup, with the default auto-escaping |
|
42 | # Create the Mako TemplateLookup, with the default auto-escaping | |
35 | config['pylons.app_globals'].mako_lookup = TemplateLookup( |
|
43 | config['pylons.app_globals'].mako_lookup = TemplateLookup( | |
36 | directories=paths['templates'], |
|
44 | directories=paths['templates'], | |
37 | error_handler=handle_mako_error, |
|
45 | error_handler=handle_mako_error, | |
38 | module_directory=os.path.join(app_conf['cache_dir'], 'templates'), |
|
46 | module_directory=os.path.join(app_conf['cache_dir'], 'templates'), | |
39 | input_encoding='utf-8', default_filters=['escape'], |
|
47 | input_encoding='utf-8', default_filters=['escape'], | |
40 | imports=['from webhelpers.html import escape']) |
|
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 | # CONFIGURATION OPTIONS HERE (note: all config options will override |
|
65 | # CONFIGURATION OPTIONS HERE (note: all config options will override | |
43 | # any Pylons config options) |
|
66 | # any Pylons config options) | |
|
67 | ||||
|
68 | return config |
@@ -1,68 +1,70 b'' | |||||
1 | """Pylons middleware initialization""" |
|
1 | """Pylons middleware initialization""" | |
2 |
from beaker.middleware import |
|
2 | from beaker.middleware import SessionMiddleware | |
3 | from paste.cascade import Cascade |
|
3 | from paste.cascade import Cascade | |
4 | from paste.registry import RegistryManager |
|
4 | from paste.registry import RegistryManager | |
5 | from paste.urlparser import StaticURLParser |
|
5 | from paste.urlparser import StaticURLParser | |
6 | from paste.deploy.converters import asbool |
|
6 | from paste.deploy.converters import asbool | |
7 | from pylons import config |
|
|||
8 | from pylons.middleware import ErrorHandler, StatusCodeRedirect |
|
7 | from pylons.middleware import ErrorHandler, StatusCodeRedirect | |
9 | from pylons.wsgiapp import PylonsApp |
|
8 | from pylons.wsgiapp import PylonsApp | |
10 | from routes.middleware import RoutesMiddleware |
|
9 | from routes.middleware import RoutesMiddleware | |
11 | from paste.auth.basic import AuthBasicHandler |
|
10 | from paste.auth.basic import AuthBasicHandler | |
12 | from pylons_app.config.environment import load_environment |
|
11 | from pylons_app.config.environment import load_environment | |
13 | from pylons_app.lib.auth import authfunc |
|
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 | """Create a Pylons WSGI application and return it |
|
15 | """Create a Pylons WSGI application and return it | |
17 |
|
16 | |||
18 | ``global_conf`` |
|
17 | ``global_conf`` | |
19 | The inherited configuration for this application. Normally from |
|
18 | The inherited configuration for this application. Normally from | |
20 | the [DEFAULT] section of the Paste ini file. |
|
19 | the [DEFAULT] section of the Paste ini file. | |
21 |
|
20 | |||
22 | ``full_stack`` |
|
21 | ``full_stack`` | |
23 | Whether or not this application provides a full WSGI stack (by |
|
22 | Whether or not this application provides a full WSGI stack (by | |
24 | default, meaning it handles its own exceptions and errors). |
|
23 | default, meaning it handles its own exceptions and errors). | |
25 | Disable full_stack when this application is "managed" by |
|
24 | Disable full_stack when this application is "managed" by | |
26 | another WSGI middleware. |
|
25 | another WSGI middleware. | |
27 |
|
26 | |||
28 | ``app_conf`` |
|
27 | ``app_conf`` | |
29 | The application's local configuration. Normally specified in |
|
28 | The application's local configuration. Normally specified in | |
30 | the [app:<name>] section of the Paste ini file (where <name> |
|
29 | the [app:<name>] section of the Paste ini file (where <name> | |
31 | defaults to main). |
|
30 | defaults to main). | |
32 |
|
31 | |||
33 | """ |
|
32 | """ | |
34 | # Configure the Pylons environment |
|
33 | # Configure the Pylons environment | |
35 | load_environment(global_conf, app_conf) |
|
34 | config = load_environment(global_conf, app_conf) | |
|
35 | ||||
36 |
|
36 | |||
37 | # The Pylons WSGI app |
|
37 | # The Pylons WSGI app | |
38 | app = PylonsApp() |
|
38 | app = PylonsApp(config=config) | |
39 |
|
39 | |||
40 | # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) |
|
40 | # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) | |
41 |
|
41 | |||
42 | # Routing/Session/Cache Middleware |
|
42 | # Routing/Session/Cache Middleware | |
43 | app = RoutesMiddleware(app, config['routes.map']) |
|
43 | app = RoutesMiddleware(app, config['routes.map']) | |
44 | app = SessionMiddleware(app, config) |
|
44 | app = SessionMiddleware(app, config) | |
45 | app = CacheMiddleware(app, config) |
|
|||
46 | app = AuthBasicHandler(app, config['repos_name'] + ' mercurial repository', authfunc) |
|
45 | app = AuthBasicHandler(app, config['repos_name'] + ' mercurial repository', authfunc) | |
47 |
|
46 | |||
48 | if asbool(full_stack): |
|
47 | if asbool(full_stack): | |
49 | # Handle Python exceptions |
|
48 | # Handle Python exceptions | |
50 | app = ErrorHandler(app, global_conf, **config['pylons.errorware']) |
|
49 | app = ErrorHandler(app, global_conf, **config['pylons.errorware']) | |
51 |
|
50 | |||
52 | # Display error documents for 401, 403, 404 status codes (and |
|
51 | # Display error documents for 401, 403, 404 status codes (and | |
53 | # 500 when debug is disabled) |
|
52 | # 500 when debug is disabled) | |
54 | if asbool(config['debug']): |
|
53 | if asbool(config['debug']): | |
55 | #don't handle 404, since mercurial does it for us. |
|
54 | #don't handle 404, since mercurial does it for us. | |
56 |
app = StatusCodeRedirect(app, [400, 401, 403 |
|
55 | app = StatusCodeRedirect(app, [400, 401, 403]) | |
57 | else: |
|
56 | else: | |
58 | app = StatusCodeRedirect(app, [400, 401, 403, 500]) |
|
57 | app = StatusCodeRedirect(app, [400, 401, 403, 500]) | |
59 |
|
58 | |||
60 | # Establish the Registry for this application |
|
59 | # Establish the Registry for this application | |
61 | app = RegistryManager(app) |
|
60 | app = RegistryManager(app) | |
62 |
|
61 | |||
63 | # Static files (If running in production, and Apache or another web |
|
62 | if asbool(static_files): | |
64 | # server is handling this static content, remove the following 3 lines) |
|
63 | # Serve static files | |
65 | static_app = StaticURLParser(config['pylons.paths']['static_files']) |
|
64 | static_app = StaticURLParser(config['pylons.paths']['static_files']) | |
66 | app = Cascade([static_app, app]) |
|
65 | app = Cascade([static_app, app]) | |
|
66 | ||||
|
67 | app.config = config | |||
|
68 | ||||
67 | return app |
|
69 | return app | |
68 |
|
70 |
@@ -1,28 +1,30 b'' | |||||
1 | """Routes configuration |
|
1 | """Routes configuration | |
2 |
|
2 | |||
3 | The more specific and detailed routes should be defined first so they |
|
3 | The more specific and detailed routes should be defined first so they | |
4 | may take precedent over the more generic routes. For more information |
|
4 | may take precedent over the more generic routes. For more information | |
5 | refer to the routes manual at http://routes.groovie.org/docs/ |
|
5 | refer to the routes manual at http://routes.groovie.org/docs/ | |
6 | """ |
|
6 | """ | |
7 | from pylons import config |
|
|||
8 | from routes import Mapper |
|
7 | from routes import Mapper | |
9 |
|
8 | |||
10 | def make_map(): |
|
9 | def make_map(config): | |
11 | """Create, configure and return the routes Mapper""" |
|
10 | """Create, configure and return the routes Mapper""" | |
12 |
map = Mapper(directory |
|
11 | map = Mapper(directory=config['pylons.paths']['controllers'], | |
13 |
always_scan |
|
12 | always_scan=config['debug']) | |
14 | map.minimization = False |
|
13 | map.minimization = False | |
|
14 | map.explicit = False | |||
15 |
|
15 | |||
16 | # The ErrorController route (handles 404/500 error pages); it should |
|
16 | # The ErrorController route (handles 404/500 error pages); it should | |
17 | # likely stay at the top, ensuring it can always be resolved |
|
17 | # likely stay at the top, ensuring it can always be resolved | |
18 |
map.connect('/error/{action}', controller |
|
18 | map.connect('/error/{action}', controller='error') | |
19 |
map.connect('/error/{action}/{id}', controller |
|
19 | map.connect('/error/{action}/{id}', controller='error') | |
20 |
|
20 | |||
21 | # CUSTOM ROUTES HERE |
|
21 | # CUSTOM ROUTES HERE | |
22 | map.connect('hg_add', '/add/{new_repo:[a-z0-9\. _-]*}', |
|
22 | with map.submapper(path_prefix='/_admin', controller='admin') as m: | |
23 | controller = 'hg', action = 'add_repo') |
|
23 | m.connect('admin_home', '/', action='index')#main page | |
24 | map.connect('hg', '/{path_info:.*}', |
|
24 | m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}', action='add_repo') | |
25 | controller = 'hg', action = "view", |
|
25 | m.connect('admin_manage_users', '/manage_users', action='index') | |
26 | path_info = '/') |
|
26 | ||
|
27 | map.connect('hg', '/{path_info:.*}', controller='hg', | |||
|
28 | action="view", path_info='/') | |||
27 |
|
29 | |||
28 | return map |
|
30 | return map |
@@ -1,134 +1,41 b'' | |||||
1 | #!/usr/bin/python |
|
1 | #!/usr/bin/python | |
2 | # -*- coding: utf-8 -*- |
|
2 | # -*- coding: utf-8 -*- | |
3 | import logging |
|
3 | import logging | |
4 | import os |
|
4 | from pylons_app.lib.base import BaseController | |
5 | from pylons_app.lib.base import BaseController, render |
|
|||
6 | from pylons import tmpl_context as c, app_globals as g, session, request, config |
|
5 | from pylons import tmpl_context as c, app_globals as g, session, request, config | |
7 | from pylons_app.lib import helpers as h |
|
6 | from pylons_app.lib import helpers as h | |
8 | from mako.template import Template |
|
7 | from mako.template import Template | |
9 | from mercurial import ui, hg |
|
|||
10 | from mercurial.error import RepoError |
|
|||
11 | from ConfigParser import ConfigParser |
|
|||
12 | from pylons.controllers.util import abort |
|
8 | from pylons.controllers.util import abort | |
13 |
|
9 | |||
14 | log = logging.getLogger(__name__) |
|
10 | log = logging.getLogger(__name__) | |
15 |
|
11 | |||
16 | class HgController(BaseController): |
|
12 | class HgController(BaseController): | |
17 |
|
13 | |||
18 | def __before__(self): |
|
14 | def __before__(self): | |
19 | c.repos_prefix = config['repos_name'] |
|
15 | c.repos_prefix = config['repos_name'] | |
20 |
|
16 | |||
21 | def view(self, *args, **kwargs): |
|
17 | def view(self, *args, **kwargs): | |
22 | response = g.hgapp(request.environ, self.start_response) |
|
18 | response = g.hgapp(request.environ, self.start_response) | |
23 |
|
19 | |||
24 | http_accept = request.environ.get('HTTP_ACCEPT', False) |
|
20 | http_accept = request.environ.get('HTTP_ACCEPT', False) | |
25 | if not http_accept: |
|
21 | if not http_accept: | |
26 | return abort(status_code=400, detail='no http accept in header') |
|
22 | return abort(status_code=400, detail='no http accept in header') | |
27 |
|
23 | |||
28 | #for mercurial protocols and raw files we can't wrap into mako |
|
24 | #for mercurial protocols and raw files we can't wrap into mako | |
29 | if http_accept.find("mercurial") != -1 or \ |
|
25 | if http_accept.find("mercurial") != -1 or \ | |
30 | request.environ['PATH_INFO'].find('raw-file') != -1: |
|
26 | request.environ['PATH_INFO'].find('raw-file') != -1: | |
31 | return response |
|
27 | return response | |
32 | try: |
|
28 | try: | |
33 | tmpl = u''.join(response) |
|
29 | tmpl = u''.join(response) | |
34 | template = Template(tmpl, lookup=request.environ['pylons.pylons']\ |
|
30 | template = Template(tmpl, lookup=request.environ['pylons.pylons']\ | |
35 | .config['pylons.app_globals'].mako_lookup) |
|
31 | .config['pylons.app_globals'].mako_lookup) | |
36 |
|
32 | |||
37 | except (RuntimeError, UnicodeDecodeError): |
|
33 | except (RuntimeError, UnicodeDecodeError): | |
38 | log.info('disabling unicode due to encoding error') |
|
34 | log.info('disabling unicode due to encoding error') | |
39 | response = g.hgapp(request.environ, self.start_response) |
|
35 | response = g.hgapp(request.environ, self.start_response) | |
40 | tmpl = ''.join(response) |
|
36 | tmpl = ''.join(response) | |
41 | template = Template(tmpl, lookup=request.environ['pylons.pylons']\ |
|
37 | template = Template(tmpl, lookup=request.environ['pylons.pylons']\ | |
42 | .config['pylons.app_globals'].mako_lookup, disable_unicode=True) |
|
38 | .config['pylons.app_globals'].mako_lookup, disable_unicode=True) | |
43 |
|
39 | |||
44 |
|
40 | |||
45 | return template.render(g=g, c=c, session=session, h=h) |
|
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 | """The application's Globals object""" |
|
1 | """The application's Globals object""" | |
2 | #uncomment the following if you want to serve a single repo |
|
2 | #uncomment the following if you want to serve a single repo | |
3 | #from mercurial.hgweb.hgweb_mod import hgweb |
|
3 | #from mercurial.hgweb.hgweb_mod import hgweb | |
4 | from mercurial.hgweb.hgwebdir_mod import hgwebdir |
|
4 | from mercurial.hgweb.hgwebdir_mod import hgwebdir | |
5 | from mercurial import templater |
|
5 | from mercurial import templater | |
6 | from mercurial.hgweb.request import wsgiapplication |
|
6 | from mercurial.hgweb.request import wsgiapplication | |
7 | from mercurial import ui, config |
|
7 | from mercurial import ui, config | |
8 | import os |
|
8 | import os | |
|
9 | from beaker.cache import CacheManager | |||
|
10 | from beaker.util import parse_cache_config_options | |||
|
11 | ||||
9 | class Globals(object): |
|
12 | class Globals(object): | |
10 |
|
13 | |||
11 | """Globals acts as a container for objects available throughout the |
|
14 | """Globals acts as a container for objects available throughout the | |
12 | life of the application |
|
15 | life of the application | |
13 |
|
16 | |||
14 | """ |
|
17 | """ | |
15 |
|
18 | |||
16 | def __init__(self): |
|
19 | def __init__(self, config): | |
17 | """One instance of Globals is created during application |
|
20 | """One instance of Globals is created during application | |
18 | initialization and is available during requests via the |
|
21 | initialization and is available during requests via the | |
19 | 'app_globals' variable |
|
22 | 'app_globals' variable | |
20 |
|
23 | |||
21 | """ |
|
24 | """ | |
22 | #two ways of building the merc app i don't know |
|
25 | #two ways of building the merc app i don't know | |
23 | #the fastest one but belive the wsgiapp is better |
|
26 | #the fastest one but belive the wsgiapp is better | |
24 | #self.hgapp = self.make_web_app() |
|
27 | #self.hgapp = self.make_web_app() | |
|
28 | self.cache = CacheManager(**parse_cache_config_options(config)) | |||
25 | self.hgapp = wsgiapplication(self.make_web_app) |
|
29 | self.hgapp = wsgiapplication(self.make_web_app) | |
26 |
|
30 | |||
27 |
|
31 | |||
28 | def make_web_app(self): |
|
32 | def make_web_app(self): | |
29 | repos = "hgwebdir.config" |
|
33 | repos = "hgwebdir.config" | |
30 | baseui = ui.ui() |
|
34 | baseui = ui.ui() | |
31 | cfg = config.config() |
|
35 | cfg = config.config() | |
32 | cfg.read(repos) |
|
36 | cfg.read(repos) | |
33 | paths = cfg.items('paths') |
|
37 | paths = cfg.items('paths') | |
34 | self.check_repo_dir(paths) |
|
38 | self.check_repo_dir(paths) | |
35 | self.set_statics(cfg) |
|
39 | self.set_statics(cfg) | |
36 |
|
40 | |||
37 | for k, v in cfg.items('web'): |
|
41 | for k, v in cfg.items('web'): | |
38 | baseui.setconfig('web', k, v) |
|
42 | baseui.setconfig('web', k, v) | |
39 | #magic trick to make our custom template dir working |
|
43 | #magic trick to make our custom template dir working | |
40 | templater.path.append(cfg.get('web', 'templates', None)) |
|
44 | templater.path.append(cfg.get('web', 'templates', None)) | |
41 |
|
45 | |||
42 | #baseui.setconfig('web', 'description', '') |
|
46 | #baseui.setconfig('web', 'description', '') | |
43 | #baseui.setconfig('web', 'name', '') |
|
47 | #baseui.setconfig('web', 'name', '') | |
44 | #baseui.setconfig('web', 'contact', '') |
|
48 | #baseui.setconfig('web', 'contact', '') | |
45 | #baseui.setconfig('web', 'allow_archive', '') |
|
49 | #baseui.setconfig('web', 'allow_archive', '') | |
46 | #baseui.setconfig('web', 'style', 'monoblue_plain') |
|
50 | #baseui.setconfig('web', 'style', 'monoblue_plain') | |
47 | #baseui.setconfig('web', 'baseurl', '') |
|
51 | #baseui.setconfig('web', 'baseurl', '') | |
48 | #baseui.setconfig('web', 'staticurl', '') |
|
52 | #baseui.setconfig('web', 'staticurl', '') | |
49 |
|
53 | |||
50 | hgwebapp = hgwebdir(paths, baseui=baseui) |
|
54 | hgwebapp = hgwebdir(paths, baseui=baseui) | |
51 | return hgwebapp |
|
55 | return hgwebapp | |
52 |
|
56 | |||
53 |
|
57 | |||
54 | def set_statics(self, cfg): |
|
58 | def set_statics(self, cfg): | |
55 | ''' |
|
59 | ''' | |
56 | set's the statics for use in mako templates |
|
60 | set's the statics for use in mako templates | |
57 | @param cfg: |
|
61 | @param cfg: | |
58 | ''' |
|
62 | ''' | |
59 | self.statics = cfg.get('web', 'staticurl', '/static') |
|
63 | self.statics = cfg.get('web', 'staticurl', '/static') | |
60 | if not self.statics.endswith('/'): |
|
64 | if not self.statics.endswith('/'): | |
61 | self.statics += '/' |
|
65 | self.statics += '/' | |
62 |
|
66 | |||
63 |
|
67 | |||
64 | def check_repo_dir(self, paths): |
|
68 | def check_repo_dir(self, paths): | |
65 | repos_path = paths[0][1].split('/') |
|
69 | repos_path = paths[0][1].split('/') | |
66 | if repos_path[-1] in ['*', '**']: |
|
70 | if repos_path[-1] in ['*', '**']: | |
67 | repos_path = repos_path[:-1] |
|
71 | repos_path = repos_path[:-1] | |
68 | if repos_path[0] != '/': |
|
72 | if repos_path[0] != '/': | |
69 | repos_path[0] = '/' |
|
73 | repos_path[0] = '/' | |
70 | if not os.path.isdir(os.path.join(*repos_path)): |
|
74 | if not os.path.isdir(os.path.join(*repos_path)): | |
71 | raise Exception('Not a valid repository in %s' % paths[0][1]) |
|
75 | raise Exception('Not a valid repository in %s' % paths[0][1]) | |
72 |
|
76 |
@@ -1,49 +1,48 b'' | |||||
1 | """Helper functions |
|
1 | """Helper functions | |
2 |
|
2 | |||
3 | Consists of functions to typically be used within templates, but also |
|
3 | Consists of functions to typically be used within templates, but also | |
4 | available to Controllers. This module is available to both as 'h'. |
|
4 | available to Controllers. This module is available to both as 'h'. | |
5 | """ |
|
5 | """ | |
6 | from routes import redirect_to, url_for |
|
6 | from pylons import url | |
7 |
|
||||
8 | from webhelpers.html import (literal, HTML, escape) |
|
7 | from webhelpers.html import (literal, HTML, escape) | |
9 | from webhelpers.html.tools import (auto_link, button_to, highlight, js_obfuscate |
|
8 | from webhelpers.html.tools import (auto_link, button_to, highlight, js_obfuscate | |
10 | , mail_to, strip_links, strip_tags, tag_re) |
|
9 | , mail_to, strip_links, strip_tags, tag_re) | |
11 | from webhelpers.html.tags import (auto_discovery_link, checkbox, css_classes, |
|
10 | from webhelpers.html.tags import (auto_discovery_link, checkbox, css_classes, | |
12 | end_form, file, form, hidden, image, |
|
11 | end_form, file, form, hidden, image, | |
13 | javascript_link, link_to, link_to_if, |
|
12 | javascript_link, link_to, link_to_if, | |
14 | link_to_unless, ol, required_legend, |
|
13 | link_to_unless, ol, required_legend, | |
15 | select, stylesheet_link, |
|
14 | select, stylesheet_link, | |
16 | submit, text, textarea, title, ul, xml_declaration) |
|
15 | submit, text, textarea, title, ul, xml_declaration) | |
17 | from webhelpers.text import (chop_at, collapse, convert_accented_entities, |
|
16 | from webhelpers.text import (chop_at, collapse, convert_accented_entities, | |
18 | convert_misc_characters, convert_misc_entities, |
|
17 | convert_misc_characters, convert_misc_entities, | |
19 | lchop, plural, rchop, remove_formatting, replace_whitespace, |
|
18 | lchop, plural, rchop, remove_formatting, replace_whitespace, | |
20 | urlify) |
|
19 | urlify) | |
21 |
|
20 | |||
22 | from webhelpers.pylonslib import Flash as _Flash |
|
21 | from webhelpers.pylonslib import Flash as _Flash | |
23 | from webhelpers.pylonslib.secure_form import secure_form |
|
22 | from webhelpers.pylonslib.secure_form import secure_form | |
24 |
|
23 | |||
25 | #Custom helper here :) |
|
24 | #Custom helper here :) | |
26 | class _Link(object): |
|
25 | class _Link(object): | |
27 | ''' |
|
26 | ''' | |
28 | Make a url based on label and url with help of url_for |
|
27 | Make a url based on label and url with help of url_for | |
29 | @param label:name of link if not defined url is used |
|
28 | @param label:name of link if not defined url is used | |
30 | @param url: the url for link |
|
29 | @param url: the url for link | |
31 | ''' |
|
30 | ''' | |
32 |
|
31 | |||
33 |
def __call__(self, label |
|
32 | def __call__(self, label='', *url_, **urlargs): | |
34 | if label is None or '': |
|
33 | if label is None or '': | |
35 | label = url |
|
34 | label = url | |
36 |
link_fn = link_to(label, url |
|
35 | link_fn = link_to(label, url(*url_, **urlargs)) | |
37 | return link_fn |
|
36 | return link_fn | |
38 |
|
37 | |||
39 |
|
38 | |||
40 | class _GetError(object): |
|
39 | class _GetError(object): | |
41 |
|
40 | |||
42 | def __call__(self, field_name, form_errors): |
|
41 | def __call__(self, field_name, form_errors): | |
43 | tmpl = """<span class="error_msg">%s</span>""" |
|
42 | tmpl = """<span class="error_msg">%s</span>""" | |
44 | if form_errors and form_errors.has_key(field_name): |
|
43 | if form_errors and form_errors.has_key(field_name): | |
45 | return literal(tmpl % form_errors.get(field_name)) |
|
44 | return literal(tmpl % form_errors.get(field_name)) | |
46 |
|
45 | |||
47 | link = _Link() |
|
46 | link = _Link() | |
48 | flash = _Flash() |
|
47 | flash = _Flash() | |
49 | get_error = _GetError() |
|
48 | get_error = _GetError() |
@@ -1,38 +1,41 b'' | |||||
1 | ## -*- coding: utf-8 -*- |
|
1 | ## -*- coding: utf-8 -*- | |
2 | {header} |
|
2 | {header} | |
3 | <title>{repo|escape}: Mercurial repository not found</title> |
|
3 | <title>{repo|escape}: Mercurial repository not found</title> | |
4 | </head> |
|
4 | </head> | |
5 |
|
5 | |||
6 | <body> |
|
6 | <body> | |
7 | <div id="container"> |
|
7 | <div id="container"> | |
8 | <div class="page-header"> |
|
8 | <div class="page-header"> | |
9 | <h1>Not found: {repo|escape}</h1> |
|
9 | <h1>Not found: {repo|escape}</h1> | |
10 |
|
10 | |||
11 | <div style="height: 50px"> |
|
11 | <div style="height: 50px"> | |
12 | </div> |
|
12 | </div> | |
13 | </div> |
|
13 | </div> | |
14 |
|
14 | |||
15 | <h2 class="no-link no-border">Not Found</h2> |
|
15 | <h2 class="no-link no-border">Not Found</h2> | |
16 | <p class="normal">The specified repository "{repo|escape}" is unknown, sorry.</p> |
|
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 | <p class="normal">Go back to the <a href="{url}">main repository list page</a>.</p> |
|
21 | <p class="normal">Go back to the <a href="{url}">main repository list page</a>.</p> | |
19 | <div class="page-footer"> |
|
22 | <div class="page-footer"> | |
20 | <p>Mercurial Repository: {repo|escape}</p> |
|
23 | <p>Mercurial Repository: {repo|escape}</p> | |
21 | </div> |
|
24 | </div> | |
22 |
|
25 | |||
23 | <div id="powered-by"> |
|
26 | <div id="powered-by"> | |
24 | <p><a href="http://mercurial.selenic.com/" title="Mercurial"><img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a></p> |
|
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 | </div> |
|
29 | </div> | |
27 |
|
30 | |||
28 | <div id="corner-top-left"></div> |
|
31 | <div id="corner-top-left"></div> | |
29 | <div id="corner-top-right"></div> |
|
32 | <div id="corner-top-right"></div> | |
30 | <div id="corner-bottom-left"></div> |
|
33 | <div id="corner-bottom-left"></div> | |
31 | <div id="corner-bottom-right"></div> |
|
34 | <div id="corner-bottom-right"></div> | |
32 |
|
35 | |||
33 | </div> |
|
36 | </div> | |
34 |
|
37 | |||
35 | </body> |
|
38 | </body> | |
36 | </html> |
|
39 | </html> | |
37 |
|
40 | |||
38 |
|
41 |
General Comments 0
You need to be logged in to leave comments.
Login now