Changeset - 8fb1abd4178a
[Not reviewed]
default
1 3 1
Marcin Kuzminski - 16 years ago 2010-04-09 03:00:20
marcin@python-blog.com
Added hg model,implemented removal of repos, added HgModel for fetching repos(with generator)
5 files changed with 104 insertions and 51 deletions:
0 comments (0 inline, 0 general)
pylons_app/controllers/hg.py
Show inline comments
 
#!/usr/bin/python
 
# -*- coding: utf-8 -*-
 
import logging
 
import os
 
from pylons_app.lib.base import BaseController
 
from pylons import tmpl_context as c, app_globals as g, session, request, config
 
from pylons_app.lib import helpers as h
 
from mako.template import Template
 
from pylons.controllers.util import abort
 
from pylons_app.lib.base import BaseController, render
 
try:
 
    from vcs.backends.hg import get_repositories
 
except ImportError:
 
    print 'You have to import vcs module'
 
from mercurial.util import matchdate, Abort, makedate
 
from mercurial.hgweb.common import get_contact
 
from mercurial.templatefilters import age
 
from operator import itemgetter
 

	
 
from pylons_app.model.hg_model import HgModel
 
log = logging.getLogger(__name__)
 

	
 
class HgController(BaseController):
 

	
 
    def __before__(self):
 
        c.repos_prefix = config['repos_name']
 
        c.staticurl = g.statics
 

	
 
    def index(self):
 
        c.repos_list = []
 
        hg_model = HgModel()
 
        c.repos_list = list(hg_model.get_repos())
 
        c.current_sort = request.GET.get('sort', 'name')
 
        
 
        def get_mtime(spath):
 
            cl_path = os.path.join(spath, "00changelog.i")
 
            if os.path.exists(cl_path):
 
                return os.stat(cl_path).st_mtime
 
            else:
 
                return os.stat(spath).st_mtime   
 
        
 
        def archivelist(ui, nodeid, url):
 
            allowed = g.baseui.configlist("web", "allow_archive", untrusted=True)
 
            for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
 
                if i[0] in allowed or ui.configbool("web", "allow" + i[0],
 
                                                    untrusted=True):
 
                    yield {"type" : i[0], "extension": i[1],
 
                           "node": nodeid, "url": url}
 

	
 
        for name, r in get_repositories(g.paths[0][0], g.paths[0][1]).items():
 
            last_change = (get_mtime(r.spath), makedate()[1])
 
            tip = r.changectx('tip')
 
            tmp_d = {}
 
            tmp_d['name'] = name
 
            tmp_d['name_sort'] = tmp_d['name']
 
            tmp_d['description'] = r.ui.config('web', 'description', 'Unknown', untrusted=True)
 
            tmp_d['description_sort'] = tmp_d['description']
 
            tmp_d['last_change'] = age(last_change)
 
            tmp_d['last_change_sort'] = last_change[1] - last_change[0]
 
            tmp_d['tip'] = str(tip)
 
            tmp_d['tip_sort'] = tip.rev()
 
            tmp_d['rev'] = tip.rev()
 
            tmp_d['contact'] = get_contact(r.ui.config)
 
            tmp_d['contact_sort'] = get_contact(r.ui.config)
 
            tmp_d['repo_archives'] = archivelist(r.ui, "tip", 'sa')
 
            
 
            c.repos_list.append(tmp_d)
 
        
 
        cs = c.current_sort
 
        c.cs_slug = cs.replace('-', '')
 
        sortables = ['name', 'description', 'last_change', 'tip', 'contact']
 
        
 
        if cs and c.cs_slug in sortables:
 
            sort_key = c.cs_slug + '_sort'
 
            if cs.startswith('-'):
 
                c.repos_list.sort(key=itemgetter(sort_key), reverse=True)
 
            else:
 
                c.repos_list.sort(key=itemgetter(sort_key), reverse=False)
 
            
 
        return render('/index.html')
 

	
 
    def view(self, *args, **kwargs):
 
        #TODO: reimplement this not tu use hgwebdir
 
        response = g.hgapp(request.environ, self.start_response)
 
        
 
        http_accept = request.environ.get('HTTP_ACCEPT', False)
 
        if not http_accept:
 
            return abort(status_code=400, detail='no http accept in header')
 
        
 
        #for mercurial protocols and raw files we can't wrap into mako
 
        if http_accept.find("mercurial") != -1 or \
 
        request.environ['PATH_INFO'].find('raw-file') != -1:
 
                    return response
 
        try:
 
            tmpl = u''.join(response)
 
            template = Template(tmpl, lookup=request.environ['pylons.pylons']\
 
                            .config['pylons.app_globals'].mako_lookup)
 
                        
 
        except (RuntimeError, UnicodeDecodeError):
 
            log.info('disabling unicode due to encoding error')
 
            response = g.hgapp(request.environ, self.start_response)
 
            tmpl = ''.join(response)
 
            template = Template(tmpl, lookup=request.environ['pylons.pylons']\
 
                            .config['pylons.app_globals'].mako_lookup, disable_unicode=True)
 

	
 

	
 
        return template.render(g=g, c=c, session=session, h=h)
pylons_app/controllers/repos.py
Show inline comments
 
import logging
 

	
 
import os
 
from pylons import request, response, session, tmpl_context as c, url, app_globals as g
 
from pylons.controllers.util import abort, redirect
 
from pylons_app.lib import auth
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model import meta
 
from pylons_app.model.db import Users, UserLogs
 
from pylons_app.lib.auth import authenticate
 

	
 
from pylons_app.model.hg_model import HgModel
 
from operator import itemgetter
 
import shutil
 
log = logging.getLogger(__name__)
 

	
 
class ReposController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('repo', 'repos')
 
    
 
    @authenticate
 
    def __before__(self):
 
        c.staticurl = g.statics
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        self.sa = meta.Session
 
                
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        hg_model = HgModel()
 
        c.repos_list = list(hg_model.get_repos())
 
        c.repos_list.sort(key=itemgetter('name'))
 
        return render('/repos.html')
 
    
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        # url('repos')
 

	
 
    def new(self, format='html'):
 
        """GET /repos/new: Form to create a new item"""
 
        # url('new_repo')
 

	
 
    def update(self, id):
 
        """PUT /repos/id: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
        #    h.form(url('repo', id=ID),
 
        #           method='put')
 
        # url('repo', id=ID)
 

	
 
    def delete(self, id):
 
        """DELETE /repos/id: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
        #    h.form(url('repo', id=ID),
 
        #           method='delete')
 
        # url('repo', id=ID)
 
        from datetime import datetime
 
        path = g.paths[0][1].replace('*', '')
 
        rm_path = os.path.join(path, id)
 
        log.info("Removing %s", rm_path)
 
        shutil.move(os.path.join(rm_path, '.hg'), os.path.join(rm_path, 'rm__.hg'))
 
        shutil.move(rm_path, os.path.join(path, 'rm__%s-%s' % (datetime.today(), id)))
 
        return redirect(url('repos'))
 
        
 

	
 
    def show(self, id, format='html'):
 
        """GET /repos/id: Show a specific item"""
 
        # url('repo', id=ID)
 
        return render('/repos_show.html')
 
    def edit(self, id, format='html'):
 
        """GET /repos/id/edit: Form to edit an existing item"""
 
        # url('edit_repo', id=ID)
pylons_app/dbmodel/__init__.py
Show inline comments
 
deleted file
pylons_app/model/hg_model.py
Show inline comments
 
new file 100644
 
#!/usr/bin/env python
 
# encoding: utf-8
 
#
 
# Copyright (c) 2010 marcink.  All rights reserved.
 
#
 
'''
 
Created on Apr 9, 2010
 

	
 
@author: marcink
 
'''
 
import os
 
from pylons_app.lib.base import BaseController
 
from pylons import tmpl_context as c, app_globals as g, session, request, config
 
from pylons_app.lib import helpers as h
 
from mako.template import Template
 
from pylons.controllers.util import abort
 
from pylons_app.lib.base import BaseController, render
 
try:
 
    from vcs.backends.hg import get_repositories
 
except ImportError:
 
    print 'You have to import vcs module'
 
from mercurial.util import matchdate, Abort, makedate
 
from mercurial.hgweb.common import get_contact
 
from mercurial.templatefilters import age
 
from operator import itemgetter
 

	
 
class HgModel(object):
 
    """
 
    Mercurial Model
 
    """
 

	
 

	
 
    def __init__(self):
 
        """
 
        Constructor
 
        """
 
        
 

	
 
    def get_mtime(self, spath):
 
        cl_path = os.path.join(spath, "00changelog.i")
 
        if os.path.exists(cl_path):
 
            return os.stat(cl_path).st_mtime
 
        else:
 
            return os.stat(spath).st_mtime   
 
    
 
    def archivelist(self, ui, nodeid, url):
 
        allowed = g.baseui.configlist("web", "allow_archive", untrusted=True)
 
        for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
 
            if i[0] in allowed or ui.configbool("web", "allow" + i[0],
 
                                                untrusted=True):
 
                yield {"type" : i[0], "extension": i[1],
 
                       "node": nodeid, "url": url}
 

	
 
    def get_repos(self):
 
        for name, r in get_repositories(g.paths[0][0], g.paths[0][1]).items():
 
            last_change = (self.get_mtime(r.spath), makedate()[1])
 
            tip = r.changectx('tip')
 
            tmp_d = {}
 
            tmp_d['name'] = name
 
            tmp_d['name_sort'] = tmp_d['name']
 
            tmp_d['description'] = r.ui.config('web', 'description', 'Unknown', untrusted=True)
 
            tmp_d['description_sort'] = tmp_d['description']
 
            tmp_d['last_change'] = age(last_change)
 
            tmp_d['last_change_sort'] = last_change[1] - last_change[0]
 
            tmp_d['tip'] = str(tip)
 
            tmp_d['tip_sort'] = tip.rev()
 
            tmp_d['rev'] = tip.rev()
 
            tmp_d['contact'] = get_contact(r.ui.config)
 
            tmp_d['contact_sort'] = get_contact(r.ui.config)
 
            tmp_d['repo_archives'] = self.archivelist(r.ui, "tip", 'sa')
 
            
 
            yield tmp_d
pylons_app/templates/repos.html
Show inline comments
 
<%inherit file="base/base.html"/>
 
<%def name="title()">
 
    ${_('Repository managment')}
 
</%def>
 
<%def name="breadcrumbs()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    / 
 
    ${h.link_to(u'Admin',h.url('admin_home'))}
 
    /
 
    ${h.link_to(u'Repos managment',h.url('repos'))}
 
</%def>
 
<%def name="page_nav()">
 
	<li>${h.link_to(u'Home',h.url('/'))}</li>
 
	<li class="current">${_('Admin')}</li>
 
</%def>
 
<%def name="main()">
 
    <ul class="submenu">
 
        <li class="current_submenu">
 
            ${h.link_to(u'Repos',h.url('repos'))}
 
        </li>
 
        <li>
 
            ${h.link_to(u'Users',h.url('users'))}
 
        </li>
 
    </ul>
 
	<div>
 
        <h2>${_('Mercurial repos')}</h2>
 
        <table>
 
	        %for cnt,repo in enumerate(c.repos_list):
 
	 		<tr class="parity${cnt%2}">
 
			    <td><a href="/${repo['name']}">${repo['name']}</a></td>
 
		        <td>r${repo['rev']}:${repo['tip']}</td>
 
                <td>
 
                  ${h.form(url('repo', id=repo['name']),method='delete')}
 
                  	${h.submit('remove','remove',class_="submit",onclick="return confirm('Confirm to delete this repository');")}
 
                  ${h.end_form()}
 
     			</td>
 
			</tr>
 
			%endfor
 
		</table>
 
    </div>
 
</%def>    
 
\ No newline at end of file
0 comments (0 inline, 0 general)