Changeset - 3782a6d698af
COPYING
Show inline comments
 
@@ -123,97 +123,97 @@ entire whole, and thus to each and every
 

	
 
Thus, it is not the intent of this section to claim rights or contest
 
your rights to work written entirely by you; rather, the intent is to
 
exercise the right to control the distribution of derivative or
 
collective works based on the Program.
 

	
 
In addition, mere aggregation of another work not based on the Program
 
with the Program (or with a work based on the Program) on a volume of
 
a storage or distribution medium does not bring the other work under
 
the scope of this License.
 

	
 
  3. You may copy and distribute the Program (or a work based on it,
 
under Section 2) in object code or executable form under the terms of
 
Sections 1 and 2 above provided that you also do one of the following:
 

	
 
    a) Accompany it with the complete corresponding machine-readable
 
    source code, which must be distributed under the terms of Sections
 
    1 and 2 above on a medium customarily used for software interchange; or,
 

	
 
    b) Accompany it with a written offer, valid for at least three
 
    years, to give any third party, for a charge no more than your
 
    cost of physically performing source distribution, a complete
 
    machine-readable copy of the corresponding source code, to be
 
    distributed under the terms of Sections 1 and 2 above on a medium
 
    customarily used for software interchange; or,
 

	
 
    c) Accompany it with the information you received as to the offer
 
    to distribute corresponding source code.  (This alternative is
 
    allowed only for noncommercial distribution and only if you
 
    received the program in object code or executable form with such
 
    an offer, in accord with Subsection b above.)
 

	
 
The source code for a work means the preferred form of the work for
 
making modifications to it.  For an executable work, complete source
 
code means all the source code for all modules it contains, plus any
 
associated interface definition files, plus the scripts used to
 
control compilation and installation of the executable.  However, as a
 
special exception, the source code distributed need not include
 
anything that is normally distributed (in either source or binary
 
form) with the major components (compiler, kernel, and so on) of the
 
operating system on which the executable runs, unless that component
 
itself accompanies the executable.
 

	
 
If distribution of executable or object code is made by offering
 
access to copy from a designated place, then offering equivalent
 
access to copy the source code from the same place counts as
 
distribution of the source code, even though third parties are not
 
compelled to copy the source along with the object code.
 

 

	
 
  4. You may not copy, modify, sublicense, or distribute the Program
 
except as expressly provided under this License.  Any attempt
 
otherwise to copy, modify, sublicense or distribute the Program is
 
void, and will automatically terminate your rights under this License.
 
However, parties who have received copies, or rights, from you under
 
this License will not have their licenses terminated so long as such
 
parties remain in full compliance.
 

	
 
  5. You are not required to accept this License, since you have not
 
signed it.  However, nothing else grants you permission to modify or
 
distribute the Program or its derivative works.  These actions are
 
prohibited by law if you do not accept this License.  Therefore, by
 
modifying or distributing the Program (or any work based on the
 
Program), you indicate your acceptance of this License to do so, and
 
all its terms and conditions for copying, distributing or modifying
 
the Program or works based on it.
 

	
 
  6. Each time you redistribute the Program (or any work based on the
 
Program), the recipient automatically receives a license from the
 
original licensor to copy, distribute or modify the Program subject to
 
these terms and conditions.  You may not impose any further
 
restrictions on the recipients' exercise of the rights granted herein.
 
You are not responsible for enforcing compliance by third parties to
 
this License.
 

	
 
  7. If, as a consequence of a court judgment or allegation of patent
 
infringement or for any other reason (not limited to patent issues),
 
conditions are imposed on you (whether by court order, agreement or
 
otherwise) that contradict the conditions of this License, they do not
 
excuse you from the conditions of this License.  If you cannot
 
distribute so as to satisfy simultaneously your obligations under this
 
License and any other pertinent obligations, then as a consequence you
 
may not distribute the Program at all.  For example, if a patent
 
license would not permit royalty-free redistribution of the Program by
 
all those who receive copies directly or indirectly through you, then
 
the only way you could satisfy both it and this License would be to
 
refrain entirely from distribution of the Program.
 

	
 
If any portion of this section is held invalid or unenforceable under
 
any particular circumstance, the balance of the section is intended to
 
apply and the section as a whole is intended to apply in other
 
circumstances.
 

	
 
It is not the purpose of this section to induce you to infringe any
 
patents or other property right claims or to contest validity of any
 
such claims; this section has the sole purpose of protecting the
 
integrity of the free software distribution system, which is
 
implemented by public license practices.  Many people have made
 
@@ -233,97 +233,97 @@ may add an explicit geographical distrib
 
those countries, so that distribution is permitted only in or among
 
countries not thus excluded.  In such case, this License incorporates
 
the limitation as if written in the body of this License.
 

	
 
  9. The Free Software Foundation may publish revised and/or new versions
 
of the General Public License from time to time.  Such new versions will
 
be similar in spirit to the present version, but may differ in detail to
 
address new problems or concerns.
 

	
 
Each version is given a distinguishing version number.  If the Program
 
specifies a version number of this License which applies to it and "any
 
later version", you have the option of following the terms and conditions
 
either of that version or of any later version published by the Free
 
Software Foundation.  If the Program does not specify a version number of
 
this License, you may choose any version ever published by the Free Software
 
Foundation.
 

	
 
  10. If you wish to incorporate parts of the Program into other free
 
programs whose distribution conditions are different, write to the author
 
to ask for permission.  For software which is copyrighted by the Free
 
Software Foundation, write to the Free Software Foundation; we sometimes
 
make exceptions for this.  Our decision will be guided by the two goals
 
of preserving the free status of all derivatives of our free software and
 
of promoting the sharing and reuse of software generally.
 

	
 
			    NO WARRANTY
 

	
 
  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
 
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
 
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
 
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 
REPAIR OR CORRECTION.
 

	
 
  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 
POSSIBILITY OF SUCH DAMAGES.
 

	
 
		     END OF TERMS AND CONDITIONS
 

 

	
 
	    How to Apply These Terms to Your New Programs
 

	
 
  If you develop a new program, and you want it to be of the greatest
 
possible use to the public, the best way to achieve this is to make it
 
free software which everyone can redistribute and change under these terms.
 

	
 
  To do so, attach the following notices to the program.  It is safest
 
to attach them to the start of each source file to most effectively
 
convey the exclusion of warranty; and each file should have at least
 
the "copyright" line and a pointer to where the full notice is found.
 

	
 
    <one line to give the program's name and a brief idea of what it does.>
 
    Copyright (C) <year>  <name of author>
 

	
 
    This program is free software; you can redistribute it and/or modify
 
    it under the terms of the GNU General Public License as published by
 
    the Free Software Foundation; either version 2 of the License, or
 
    (at your option) any later version.
 

	
 
    This program is distributed in the hope that it will be useful,
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
    GNU General Public License for more details.
 

	
 
    You should have received a copy of the GNU General Public License
 
    along with this program; if not, write to the Free Software
 
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 

	
 

	
 
Also add information on how to contact you by electronic and paper mail.
 

	
 
If the program is interactive, make it output a short notice like this
 
when it starts in an interactive mode:
 

	
 
    Gnomovision version 69, Copyright (C) year  name of author
 
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 
    This is free software, and you are welcome to redistribute it
 
    under certain conditions; type `show c' for details.
 

	
 
The hypothetical commands `show w' and `show c' should show the appropriate
 
parts of the General Public License.  Of course, the commands you use may
 
be called something other than `show w' and `show c'; they could even be
 
mouse-clicks or menu items--whatever suits your program.
 

	
 
You should also get your employer (if you work as a programmer) or your
 
school, if any, to sign a "copyright disclaimer" for the program, if
 
necessary.  Here is a sample; alter the names:
 

	
pylons_app/__init__.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# Hg app, a web based mercurial repository managment based on pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 9, 2010
 
Hg app, a web based mercurial repository managment based on pylons
 
@author: marcink
 
"""
 

	
 
VERSION = (0, 7, 6, 'beta')
 

	
 
__version__ = '.'.join((str(each) for each in VERSION[:4]))
 

	
 
def get_version():
 
    """
 
    Returns shorter version (digit parts only) as string.
 
    """
 
    return '.'.join((str(each) for each in VERSION[:3]))
pylons_app/config/environment.py
Show inline comments
 
"""Pylons environment configuration"""
 
from mako.lookup import TemplateLookup
 
from pylons.configuration import PylonsConfig
 
from pylons.error import handle_mako_error
 
from pylons_app.config.routing import make_map
 
from pylons_app.lib.auth import set_available_permissions
 
from pylons_app.lib.utils import repo2db_mapper
 
from pylons_app.model import init_model
 
from sqlalchemy import engine_from_config
 
import logging
 
import os
 
import pylons_app.lib.app_globals as app_globals
 
import pylons_app.lib.helpers
 

	
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
def load_environment(global_conf, app_conf):
 
    """Configure the Pylons environment via the ``pylons.config``
 
    object
 
    """
 
    config = PylonsConfig()
 
    
 
    # Pylons paths
 
    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
    paths = dict(root=root,
 
                 controllers=os.path.join(root, 'controllers'),
 
                 static_files=os.path.join(root, 'public'),
 
                 templates=[os.path.join(root, 'templates')])
 

	
 
    # Initialize config with the basic options
 
    config.init_app(global_conf, app_conf, package='pylons_app', paths=paths)
 

	
 
    config['routes.map'] = make_map(config)
 
    config['pylons.app_globals'] = app_globals.Globals(config)
 
    config['pylons.h'] = pylons_app.lib.helpers
 
    
 
    # Setup cache object as early as possible
 
    import pylons
 
    pylons.cache._push_object(config['pylons.app_globals'].cache)
 
    
 

	
 
    # Create the Mako TemplateLookup, with the default auto-escaping
 
    config['pylons.app_globals'].mako_lookup = TemplateLookup(
 
        directories=paths['templates'],
 
        error_handler=handle_mako_error,
 
        module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
 
        input_encoding='utf-8', default_filters=['escape'],
 
        imports=['from webhelpers.html import escape'])
 

	
 
    #sets the c attribute access when don't existing attribute ar accessed
 
    #sets the c attribute access when don't existing attribute are accessed
 
    config['pylons.strict_tmpl_context'] = True
 
    
 
    #MULTIPLE DB configs
 
    # Setup the SQLAlchemy database engine
 
    if config['debug']:
 
        #use query time debugging.
 
        from pylons_app.lib.timerproxy import TimerProxy
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
 
                                                            proxy=TimerProxy())
 
    else:
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
 

	
 
    init_model(sa_engine_db1)
 

	
 
    repo2db_mapper()
 
    set_available_permissions(config)
 
    # CONFIGURATION OPTIONS HERE (note: all config options will override
 
    # any Pylons config options)
 
    
 
    return config
pylons_app/controllers/admin.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# admin controller for pylons 
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 7, 2010
 
admin controller for pylons
 
@author: marcink
 
"""
 
import logging
 
from pylons import request, response, session, tmpl_context as c, url, app_globals as g
 
from pylons.controllers.util import abort, redirect
 
from pylons import request, response, session, tmpl_context as c
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model import meta
 
from pylons_app.model.db import UserLog
 
from webhelpers.paginate import Page
 
from pylons_app.lib.auth import LoginRequired
 

	
 
log = logging.getLogger(__name__)
 

	
 
class AdminController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        user = session['hg_app_user']
 
        c.admin_user = user.is_admin
 
        c.admin_username = user.username
 
        super(AdminController, self).__before__()
 
        
 
    def index(self):
 
        sa = meta.Session
 
                         
 
        users_log = sa.query(UserLog).order_by(UserLog.action_date.desc())
 
        p = int(request.params.get('page', 1))
 
        c.users_log = Page(users_log, page=p, items_per_page=10)
 
        c.log_data = render('admin/admin_log.html')
 
        if request.params.get('partial'):
 
            return c.log_data
 
        return render('admin/admin.html')    
 
                
pylons_app/controllers/branches.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# branches controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 21, 2010
 
branches controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c, app_globals as g
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class BranchesController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(BranchesController, self).__before__()
 
    
 
    def index(self):
 
        hg_model = HgModel()
 
        c.repo_info = hg_model.get_repo(c.repo_name)
 
        c.repo_branches = c.repo_info.branches
 
                
 
        return render('branches/branches.html')
pylons_app/controllers/changelog.py
Show inline comments
 
from mercurial.graphmod import revisions as graph_rev, colored, CHANGESET
 
from mercurial.node import short
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# changelog controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 21, 2010
 
changelog controller for pylons
 
@author: marcink
 
"""
 
from pylons import request, session, tmpl_context as c
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.filters import age as _age, person
 
from pylons_app.model.hg_model import _full_changelog_cached
 
from simplejson import dumps
 
from webhelpers.paginate import Page
 
import logging
 
log = logging.getLogger(__name__)     
 

	
 
class ChangelogController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(ChangelogController, self).__before__()
 
                
 
    def index(self):
 
        limit = 100
 
        default = 20
 
        if request.params.get('size'):
 
            try:
 
                int_size = int(request.params.get('size'))
 
            except ValueError:
 
                int_size = default
 
            int_size = int_size if int_size <= limit else limit 
 
            c.size = int_size
 
            session['changelog_size'] = c.size
 
            session.save()
 
        else:
 
            c.size = session.get('changelog_size', default)
 

	
 
        changesets = _full_changelog_cached(c.repo_name)
 
            
 
        p = int(request.params.get('page', 1))
 
        c.pagination = Page(changesets, page=p, item_count=len(changesets),
 
                            items_per_page=c.size)
 
            
 
        #self._graph(c.repo, c.size,p)
 
        
 
        return render('changelog/changelog.html')
 

	
 

	
 
    def _graph(self, repo, size, p):
 
        revcount = size
 
        if not repo.revisions:return dumps([]), 0
 
        
 
        max_rev = repo.revisions[-1]
 
        offset = 1 if p == 1 else  ((p - 1) * revcount)
 
        rev_start = repo.revisions[(-1 * offset)]
 
        c.bg_height = 120
 
        
 
        revcount = min(max_rev, revcount)
 
        rev_end = max(0, rev_start - revcount)
 
        dag = graph_rev(repo.repo, rev_start, rev_end)
 
        pass
 
#        revcount = size
 
#        if not repo.revisions:return dumps([]), 0
 
#        
 
#        max_rev = repo.revisions[-1]
 
#        offset = 1 if p == 1 else  ((p - 1) * revcount)
 
#        rev_start = repo.revisions[(-1 * offset)]
 
#        c.bg_height = 120
 
#        
 
#        revcount = min(max_rev, revcount)
 
#        rev_end = max(0, rev_start - revcount)
 
#        dag = graph_rev(repo.repo, rev_start, rev_end)
 
#        
 
#        c.dag = tree = list(colored(dag))
 
#        canvasheight = (len(tree) + 1) * c.bg_height - 27
 
#        data = []
 
#        for (id, type, ctx, vtx, edges) in tree:
 
#            if type != CHANGESET:
 
#                continue
 
#            node = short(ctx.node())
 
#            age = _age(ctx.date())
 
#            desc = ctx.description()
 
#            user = person(ctx.user())
 
#            branch = ctx.branch()
 
#            branch = branch, repo.repo.branchtags().get(branch) == ctx.node()
 
#            data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
 
#    
 
#        c.jsdata = dumps(data) 
 
#        c.canvasheight = canvasheight 
 
        
 
        c.dag = tree = list(colored(dag))
 
        canvasheight = (len(tree) + 1) * c.bg_height - 27
 
        data = []
 
        for (id, type, ctx, vtx, edges) in tree:
 
            if type != CHANGESET:
 
                continue
 
            node = short(ctx.node())
 
            age = _age(ctx.date())
 
            desc = ctx.description()
 
            user = person(ctx.user())
 
            branch = ctx.branch()
 
            branch = branch, repo.repo.branchtags().get(branch) == ctx.node()
 
            data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
 
    
 
        c.jsdata = dumps(data) 
 
        c.canvasheight = canvasheight 
 

	
pylons_app/controllers/changeset.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# changeset controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 25, 2010
 
changeset controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
from vcs.utils import diffs as differ
 
import logging
 
from vcs.nodes import FileNode
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ChangesetController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(ChangesetController, self).__before__()
 
        
 
    def index(self, revision):
 
        hg_model = HgModel()
 
        c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
 
        c.changeset_old = c.changeset.parents[0]
 
        c.changes = []
 
        
 
                
 
        for node in c.changeset.added:
 
            filenode_old = FileNode(node.path, '')
 
            f_udiff = differ.get_udiff(filenode_old, node)
 
            diff = differ.DiffProcessor(f_udiff).as_html()
 
            c.changes.append(('added', node, diff))
 
            
 
        for node in c.changeset.changed:
 
            filenode_old = c.changeset_old.get_node(node.path)
 
            f_udiff = differ.get_udiff(filenode_old, node)
 
            diff = differ.DiffProcessor(f_udiff).as_html()
 
            c.changes.append(('changed', node, diff))
 
            
 
        for node in c.changeset.removed:
 
            c.changes.append(('removed', node, None))            
 
            
 
        return render('changeset/changeset.html')
pylons_app/controllers/feed.py
Show inline comments
 
#!/usr/bin/python
 
# -*- coding: utf-8 -*-
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# feed controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 23, 2010
 
feed controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c, url, response
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import _full_changelog_cached
 
from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
class FeedController(BaseController):
 
    
 
    #secure it or not ?
 
    def __before__(self):
 
        super(FeedController, self).__before__()
 
        #common values for feeds
 
        self.description = 'Changes on %s repository'
 
        self.title = "%s feed"
 
        self.language = 'en-us'
 
        self.ttl = "5"
 
        self.feed_nr = 10
 

	
 
    def atom(self, repo_name):
 
        """Produce an atom-1.0 feed via feedgenerator module"""
 
        feed = Atom1Feed(title=self.title % repo_name,
 
                         link=url('summary_home', repo_name=repo_name, qualified=True),
 
                         description=self.description % repo_name,
 
                         language=self.language,
 
                         ttl=self.ttl)
 
        
 
        
 
        for cnt, cs in enumerate(_full_changelog_cached(repo_name)):
 
            if cnt > self.feed_nr:
 
                break
 
            feed.add_item(title=cs.message,
 
                          link=url('changeset_home', repo_name=repo_name,
 
                                   revision=cs.raw_id, qualified=True),
 
                                   description=str(cs.date))
 
        
 
        response.content_type = feed.mime_type
 
        return feed.writeString('utf-8')
 

	
 
    
 
    def rss(self, repo_name):
 
        """Produce an rss2 feed via feedgenerator module"""
 
        feed = Rss201rev2Feed(title=self.title % repo_name,
 
                         link=url('summary_home', repo_name=repo_name, qualified=True),
 
                         description=self.description % repo_name,
 
                         language=self.language,
 
                         ttl=self.ttl)
 
        
pylons_app/controllers/files.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# files controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 21, 2010
 
files controller for pylons
 
@author: marcink
 
"""
 
from mercurial import archival
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
from vcs.exceptions import RepositoryError, ChangesetError
 
from vcs.utils import diffs as differ
 
import logging
 
import tempfile
 

	
 
        
 
log = logging.getLogger(__name__)
 

	
 
class FilesController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(FilesController, self).__before__()
 

	
 
    def index(self, repo_name, revision, f_path):
 
        hg_model = HgModel()
 
        c.repo = repo = hg_model.get_repo(c.repo_name)
 
        revision = request.POST.get('at_rev', None) or revision
 
        
 
        def get_next_rev(cur):
 
            max_rev = len(c.repo.revisions) - 1
 
            r = cur + 1
 
            if r > max_rev:
 
                r = max_rev
 
            return r
 
            
 
        def get_prev_rev(cur):
 
            r = cur - 1
 
            return r
 

	
 
        c.f_path = f_path
 
     
 
        
 
        try:
 
            cur_rev = repo.get_changeset(revision).revision
 
            prev_rev = repo.get_changeset(get_prev_rev(cur_rev)).raw_id
 
            next_rev = repo.get_changeset(get_next_rev(cur_rev)).raw_id
 
                    
 
            c.url_prev = url('files_home', repo_name=c.repo_name,
 
                             revision=prev_rev, f_path=f_path) 
 
            c.url_next = url('files_home', repo_name=c.repo_name,
 
                             revision=next_rev, f_path=f_path)   
 
                    
pylons_app/controllers/graph.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# graph controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 21, 2010
 
graph controller for pylons
 
@author: marcink
 
"""
 
from mercurial.graphmod import revisions as graph_rev, colored, CHANGESET
 
from mercurial.node import short
 
from pylons import request, response, session, tmpl_context as c, url, config, \
 
    app_globals as g
 
from pylons.controllers.util import abort, redirect
 
from pylons import request, tmpl_context as c
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.filters import age as _age, person
 
from pylons_app.lib.utils import get_repo_slug
 
from pylons_app.model.hg_model import HgModel
 
from simplejson import dumps
 
from webhelpers.paginate import Page
 
import logging
 

	
 
        
 
        
 

	
 
log = logging.getLogger(__name__)
 

	
 
class GraphController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(GraphController, self).__before__()
 
        
 
    def index(self):
 
        # Return a rendered template
 
        hg_model = HgModel()
 
        if request.POST.get('size'):
 
            c.size = int(request.params.get('size', 20))
 
        else:
 
            c.size = int(request.params.get('size', 20))
 
        c.jsdata, c.canvasheight = self.graph(hg_model.get_repo(c.repo_name), c.size)
 
        
 
        return render('/graph.html')
 

	
 

	
 
    def graph(self, repo, size):
 
        revcount = size
 
        p = int(request.params.get('page', 1))
 
        c.pagination = Page(repo.revisions, page=p, item_count=len(repo.revisions), items_per_page=revcount)
 
        if not repo.revisions:return dumps([]), 0
 
        
 
        max_rev = repo.revisions[-1]
 
        offset = 1 if p == 1 else  ((p - 1) * revcount)
 
        rev_start = repo.revisions[(-1 * offset)]
 
        bg_height = 39
 
        
 
        revcount = min(max_rev, revcount)
 
        rev_end = max(0, rev_start - revcount)
 
        dag = graph_rev(repo.repo, rev_start, rev_end)
 
        tree = list(colored(dag))
 
        canvasheight = (len(tree) + 1) * bg_height - 27
 
        data = []
 
        for (id, type, ctx, vtx, edges) in tree:
 
            if type != CHANGESET:
 
                continue
 
            node = short(ctx.node())
 
            age = _age(ctx.date())
 
            desc = ctx.description()
 
            user = person(ctx.user())
 
            branch = ctx.branch()
 
            branch = branch, repo.repo.branchtags().get(branch) == ctx.node()
 
            data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
 
    
pylons_app/controllers/hg.py
Show inline comments
 
#!/usr/bin/python
 
# -*- coding: utf-8 -*-
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# hg controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on February 18, 2010
 
hg controller for pylons
 
@author: marcink
 
"""
 
from operator import itemgetter
 
from pylons import tmpl_context as c, request, config
 
from pylons import tmpl_context as c, request
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
class HgController(BaseController):
 

	
 
    @LoginRequired()
 
    def __before__(self):
 
        super(HgController, self).__before__()
 
        
 
    def index(self):
 
        c.current_sort = request.GET.get('sort', 'name')
 
        cs = c.current_sort
 
        c.cs_slug = cs.replace('-', '')
 
        sortables = ['name', 'description', 'last_change', 'tip', 'contact']
 
        cached_repo_list = HgModel().get_repos()
 
        if cs and c.cs_slug in sortables:
 
            sort_key = c.cs_slug + '_sort'
 
            if cs.startswith('-'):
 
                c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key), reverse=True)
 
            else:
 
                c.repos_list = sorted(cached_repo_list, key=itemgetter(sort_key), reverse=False)
 
            
 
        return render('/index.html')
pylons_app/controllers/login.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# login controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 22, 2010
 
login controller for pylons
 
@author: marcink
 
"""
 
import logging
 
from formencode import htmlfill
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons_app.lib.base import BaseController, render
 
import formencode
 
from pylons_app.model.forms import LoginForm
 
from pylons_app.lib.auth import AuthUser
 

	
 
log = logging.getLogger(__name__)
 

	
 
class LoginController(BaseController):
 

	
 
    def __before__(self):
 
        super(LoginController, self).__before__()
 

	
 
    def index(self):
 
        #redirect if already logged in
 
        if c.hg_app_user.is_authenticated:
 
            return redirect(url('hg_home'))
 
        
 
        if request.POST:
 
            #import Login Form validator class
 
            login_form = LoginForm()
 
            try:
 
                c.form_result = login_form.to_python(dict(request.POST))
 
                return redirect(url('hg_home'))
 
                               
 
            except formencode.Invalid as errors:
 
                c.form_errors = errors.error_dict
 
                return htmlfill.render(
 
                    render('/login.html'),
 
                    defaults=errors.value,
 
                    encoding="UTF-8")
 
                        
 
        return render('/login.html')
 
    
 
    def logout(self):
 
        session['hg_app_user'] = AuthUser()
 
        session.save()
 
        log.info('Logging out and setting user as Empty')
 
        redirect(url('hg_home'))
pylons_app/controllers/permissions.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# permissions controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 27, 2010
 
permissions controller for pylons
 
@author: marcink
 
"""
 
import logging
 

	
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 

	
 
from pylons_app.lib.base import BaseController, render
 

	
 
log = logging.getLogger(__name__)
 

	
 
class PermissionsController(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('permission', 'permissions')
 

	
 
    def index(self, format='html'):
 
        """GET /permissions: All items in the collection"""
 
        # url('permissions')
 
        return render('admin/permissions/permissions.html')
 

	
 
    def create(self):
 
        """POST /permissions: Create a new item"""
 
        # url('permissions')
 

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

	
 
    def update(self, id):
 
        """PUT /permissions/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('permission', id=ID),
 
        #           method='put')
 
        # url('permission', id=ID)
 

	
 
    def delete(self, id):
 
        """DELETE /permissions/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('permission', id=ID),
 
        #           method='delete')
 
        # url('permission', id=ID)
 

	
 
    def show(self, id, format='html'):
 
        """GET /permissions/id: Show a specific item"""
pylons_app/controllers/repos.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# repos controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 7, 2010
 
admin controller for pylons
 
@author: marcink
 
"""
 
import logging
 
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.auth import LoginRequired
 
from pylons.i18n.translation import _
 
from pylons_app.lib import helpers as h
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.filters import clean_repo
 
from pylons_app.lib.utils import check_repo, invalidate_cache
 
from pylons_app.model.hg_model import HgModel
 
import logging
 
import os
 
import shutil
 
from operator import itemgetter
 
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')
 
    @LoginRequired()
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(ReposController, self).__before__()
 
                
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        cached_repo_list = HgModel().get_repos()
 
        c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
 
        return render('admin/repos/repos.html')
 
    
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        # url('repos')
 
        name = request.POST.get('name')
 

	
 
        try:
 
            self._create_repo(name)
 
            #clear our cached list for refresh with new repo
 
            invalidate_cache('cached_repo_list')
 
            h.flash(_('created repository %s') % name, category='success')
 
        except Exception as e:
 
            log.error(e)
 
        
 
        return redirect('repos')
 
        
 
    def _create_repo(self, repo_name):        
 
        repo_path = os.path.join(g.base_path, repo_name)
 
        if check_repo(repo_name, g.base_path):
 
            log.info('creating repo %s in %s', repo_name, repo_path)
 
            from vcs.backends.hg import MercurialRepository
 
            MercurialRepository(repo_path, create=True)
 
                        
 

	
 
    def new(self, format='html'):
 
        """GET /repos/new: Form to create a new item"""
pylons_app/controllers/shortlog.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# shortlog controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 18, 2010
 
shortlog controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c, request
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
from webhelpers.paginate import Page
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ShortlogController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(ShortlogController, self).__before__()
 
        
 
    def index(self):
 
        hg_model = HgModel()
 
        p = int(request.params.get('page', 1))
 
        repo = hg_model.get_repo(c.repo_name)
 
        c.repo_changesets = Page(repo, page=p, items_per_page=20)
 
        c.shortlog_data = render('shortlog/shortlog_data.html')
 
        if request.params.get('partial'):
 
            return c.shortlog_data
 
        r = render('shortlog/shortlog.html')
 
        return r
pylons_app/controllers/summary.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# summary controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 18, 2010
 
summary controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c, request
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel, _full_changelog_cached
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class SummaryController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(SummaryController, self).__before__()
 
        
 
    def index(self):
 
        hg_model = HgModel()
 
        c.repo_info = hg_model.get_repo(c.repo_name)
 
        c.repo_changesets = _full_changelog_cached(c.repo_name)[:10]
 
        e = request.environ
 
        uri = u'%(protocol)s://%(user)s@%(host)s/%(repo_name)s' % {
 
                                        'protocol': e.get('wsgi.url_scheme'),
 
                                        'user':str(c.hg_app_user.username),
 
                                        'host':e.get('HTTP_HOST'),
 
                                        'repo_name':c.repo_name, }
 
        c.clone_repo_url = uri
 
        c.repo_tags = c.repo_info.tags[:10]
 
        c.repo_branches = c.repo_info.branches[:10]
 
        return render('summary/summary.html')
pylons_app/controllers/tags.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# tags controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 21, 2010
 
tags controller for pylons
 
@author: marcink
 
"""
 
from pylons import tmpl_context as c
 
from pylons_app.lib.auth import LoginRequired
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.hg_model import HgModel
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class TagsController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        super(TagsController, self).__before__()
 
        
 
    def index(self):
 
        hg_model = HgModel()
 
        c.repo_info = hg_model.get_repo(c.repo_name)
 
        c.repo_tags = c.repo_info.tags
 
        
 
        return render('tags/tags.html')
pylons_app/controllers/users.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# users controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 4, 2010
 
users controller for pylons
 
@author: marcink
 
"""
 
import logging
 
from formencode import htmlfill
 
from pylons import request, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 
from pylons_app.lib import helpers as h
 
from pylons_app.lib.auth import LoginRequired, CheckPermissionAll
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.model.db import User, UserLog
 
from pylons_app.model.forms import UserForm
 
from pylons_app.model.user_model import UserModel
 
import formencode
 
import logging
 

	
 
log = logging.getLogger(__name__)
 

	
 
class UsersController(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('user', 'users')
 
    @LoginRequired()
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(UsersController, self).__before__()
 
    
 

	
 
    def index(self, format='html'):
 
        """GET /users: All items in the collection"""
 
        # url('users')
 
        
 
        c.users_list = self.sa.query(User).all()     
 
        return render('admin/users/users.html')
 
    
 
    def create(self):
 
        """POST /users: Create a new item"""
 
        # url('users')
 
        
 
        user_model = UserModel()
 
        login_form = UserForm()()
 
        try:
 
            form_result = login_form.to_python(dict(request.POST))
 
            user_model.create(form_result)
 
            h.flash(_('created user %s') % form_result['username'], category='success')
 
            return redirect(url('users'))
 
                           
 
        except formencode.Invalid as errors:
 
            c.form_errors = errors.error_dict
 
            return htmlfill.render(
 
                 render('admin/users/user_add.html'),
 
                defaults=errors.value,
 
                encoding="UTF-8")
 
    
 
    def new(self, format='html'):
 
        """GET /users/new: Form to create a new item"""
 
        # url('new_user')
 
        return render('admin/users/user_add.html')
 

	
 
    def update(self, id):
 
        """PUT /users/id: Update an existing item"""
pylons_app/lib/auth.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# authentication and permission libraries
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 
"""
 
Created on April 4, 2010
 

	
 
@author: marcink
 
"""
 

	
 
from functools import wraps
 
from pylons import session, url, app_globals as g
 
from pylons.controllers.util import abort, redirect
 
from pylons_app.model import meta
 
from pylons_app.model.db import User
 
from sqlalchemy.exc import OperationalError
 
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 
import crypt
 
import logging
 
log = logging.getLogger(__name__)
 

	
 
def get_crypt_password(password):
 
    """
 
    Cryptographic function used for password hashing
 
    @param password: password to hash
 
    """
 
    return crypt.crypt(password, '6a')
 

	
 
def authfunc(environ, username, password):
 
    sa = meta.Session
 
    password_crypt = get_crypt_password(password)
 
    try:
 
        user = sa.query(User).filter(User.username == username).one()
 
    except (NoResultFound, MultipleResultsFound, OperationalError) as e:
 
        log.error(e)
 
        user = None
 
        
 
    if user:
 
        if user.active:
 
            if user.username == username and user.password == password_crypt:
 
                log.info('user %s authenticated correctly', username)
 
                return True
 
        else:
 
            log.error('user %s is disabled', username)
 
            
 
    return False
 

	
 
class  AuthUser(object):
 
    """
 
    A simple object that handles a mercurial username for authentication
 
    """
 
    username = 'None'
 
    is_authenticated = False
 
    is_admin = False
 
    permissions = set()
 
    group = set()
 
    
 
    def __init__(self):
pylons_app/lib/backup_manager.py
Show inline comments
 
'''BACKUP MANAGER'''
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# mercurial repository backup manager
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on Feb 28, 2010
 
Mercurial repositories backup manager
 
@author: marcink
 
"""
 

	
 

	
 
import logging
 
from mercurial import config
 
import tarfile
 
import os
 
import datetime
 
import sys
 
import subprocess
 
logging.basicConfig(level=logging.DEBUG,
 
                    format="%(asctime)s %(levelname)-5.5s %(message)s")
 

	
 
class BackupManager(object):
 
    def __init__(self, id_rsa_path, repo_conf):
 
        self.repos_path = None
 
        self.backup_file_name = None
 
        self.id_rsa_path = id_rsa_path
 
        self.check_id_rsa()
 
        cur_dir = os.path.realpath(__file__)
 
        dn = os.path.dirname
 
        self.backup_file_path = os.path.join(dn(dn(dn(cur_dir))), 'data')
 
        cfg = config.config()
 
        try:
 
            cfg.read(os.path.join(dn(dn(dn(cur_dir))), repo_conf))
 
        except IOError:
 
            logging.error('Could not read %s', repo_conf)
 
            sys.exit()
 
        self.set_repos_path(cfg.items('paths'))
 
        logging.info('starting backup for %s', self.repos_path)
 
        logging.info('backup target %s', self.backup_file_path)
 

	
 
        if not os.path.isdir(self.repos_path):
 
            raise Exception('Not a valid directory in %s' % self.repos_path)
 

	
 
    def check_id_rsa(self):
 
        if not os.path.isfile(self.id_rsa_path):
 
            logging.error('Could not load id_rsa key file in %s',
 
                          self.id_rsa_path)
 
            sys.exit()
 

	
 
    def set_repos_path(self, paths):
 
        repos_path = paths[0][1].split('/')
 
        if repos_path[-1] in ['*', '**']:
 
            repos_path = repos_path[:-1]
 
        if repos_path[0] != '/':
 
            repos_path[0] = '/'
 
        self.repos_path = os.path.join(*repos_path)
 

	
 
    def backup_repos(self):
 
        today = datetime.datetime.now().weekday() + 1
pylons_app/lib/db_manage.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# database managment for hg app
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 10, 2010
 
database managment and creation for hg app
 
@author: marcink
 
"""
 

	
 
from os.path import dirname as dn, join as jn
 
import os
 
import sys
 
ROOT = dn(dn(dn(os.path.realpath(__file__))))
 
sys.path.append(ROOT)
 

	
 
from pylons_app.lib.auth import get_crypt_password
 
from pylons_app.model import init_model
 
from pylons_app.model.db import User, Permission
 
from pylons_app.model.meta import Session, Base
 
from sqlalchemy.engine import create_engine
 
import logging
 

	
 
log = logging.getLogger('db manage')
 
log.setLevel(logging.DEBUG)
 
console_handler = logging.StreamHandler()
 
console_handler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)03d" 
 
                                    " %(levelname)-5.5s [%(name)s] %(message)s"))
 
log.addHandler(console_handler)
 

	
 
class DbManage(object):
 
    def __init__(self, log_sql):
 
        self.dbname = 'hg_app.db'
 
        dburi = 'sqlite:////%s' % jn(ROOT, self.dbname)
 
        engine = create_engine(dburi, echo=log_sql) 
 
        init_model(engine)
 
        self.sa = Session()
 
        self.db_exists = False
 
    
 
    def check_for_db(self, override):
 
        log.info('checking for exisiting db')
 
        if os.path.isfile(jn(ROOT, self.dbname)):
 
            self.db_exists = True
 
            log.info('database exisist')
 
            if not override:
 
                raise Exception('database already exists')
 

	
 
    def create_tables(self, override=False):
 
        """
 
        Create a auth database
 
        """
 
        self.check_for_db(override)
 
        if override:
 
            log.info("database exisist and it's going to be destroyed")
 
            if self.db_exists:
 
                os.remove(jn(ROOT, self.dbname))
 
        Base.metadata.create_all(checkfirst=override)
 
        log.info('Created tables for %s', self.dbname)
pylons_app/lib/filters.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# simple filters for hg apps html templates
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 12, 2010
 
simple filters for hg apps html templates
 
@author: marcink
 
"""
 

	
 
from mercurial import util
 
from mercurial.templatefilters import age as _age, person as _person
 
from string import punctuation
 

	
 
def clean_repo(repo_name):
 
    for x in punctuation:
 
        if x != '_':
 
            repo_name = repo_name.replace(x, '')
 
    repo_name = repo_name.lower().strip()
 
    return repo_name.replace(' ', '_')
 

	
 
age = lambda  x:_age(x)
 
capitalize = lambda x: x.capitalize()
 
date = lambda x: util.datestr(x)
 
email = util.email
 
person = lambda x: _person(x)
 
hgdate = lambda  x: "%d %d" % x
 
isodate = lambda  x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
 
isodatesec = lambda  x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
 
localdate = lambda  x: (x[0], util.makedate()[1])
 
rfc822date = lambda  x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
 
rfc3339date = lambda  x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
 
time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
pylons_app/lib/middleware/https_fixup.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# middleware to handle https correctly
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on May 23, 2010
 

	
 
@author: marcink
 
"""
 

	
 
class HttpsFixup(object):
 
    def __init__(self, app):
 
        self.application = app
 
    
 
    def __call__(self, environ, start_response):
 
        self.__fixup(environ)
 
        return self.application(environ, start_response)
 
    
 
    
 
    def __fixup(self, environ):
 
        """Function to fixup the environ as needed. In order to use this
 
        middleware you should set this header inside your 
 
        proxy ie. nginx, apache etc.
 
        """
 
        proto = environ.get('HTTP_X_URL_SCHEME')
 
            
 
        if proto == 'https':
 
            environ['wsgi.url_scheme'] = proto
 
        else:
 
            environ['wsgi.url_scheme'] = 'http'
 
        return None
pylons_app/lib/middleware/simplehg.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# middleware to handle mercurial api calls
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
#
 
# Copyright (c) 2010 marcink.  All rights reserved.
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on 2010-04-28
 

	
 
@author: marcink
 
SimpleHG middleware for handling mercurial protocol request (push/clone etc.)
 
It's implemented with basic auth function
 
"""
 
from datetime import datetime
 
from mercurial.hgweb import hgweb
 
from mercurial.hgweb.request import wsgiapplication
 
from paste.auth.basic import AuthBasicAuthenticator
 
from paste.httpheaders import REMOTE_USER, AUTH_TYPE
 
from pylons_app.lib.auth import authfunc
 
from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache
 
from pylons_app.model import meta
 
from pylons_app.model.db import UserLog, User
 
from webob.exc import HTTPNotFound
 
import logging
 
import os
 
log = logging.getLogger(__name__)
 

	
 
class SimpleHg(object):
 

	
 
    def __init__(self, application, config):
 
        self.application = application
 
        self.config = config
 
        #authenticate this mercurial request using 
 
        realm = '%s %s' % (config['hg_app_name'], 'mercurial repository')
 
        self.authenticate = AuthBasicAuthenticator(realm, authfunc)
 
        
 
    def __call__(self, environ, start_response):
 
        if not is_mercurial(environ):
 
            return self.application(environ, start_response)
 
        else:
 
            #===================================================================
 
            # AUTHENTICATE THIS MERCURIAL REQUEST
 
            #===================================================================
 
            username = REMOTE_USER(environ)
 
            if not username:
 
                result = self.authenticate(environ)
 
                if isinstance(result, str):
 
                    AUTH_TYPE.update(environ, 'basic')
 
                    REMOTE_USER.update(environ, result)
 
                else:
 
                    return result.wsgi_application(environ, start_response)
 
            
 
            try:
 
                repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
pylons_app/lib/utils.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# Utilities for hg app
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 18, 2010
 
Utilities for hg app
 
@author: marcink
 
"""
 

	
 
import os
 
import logging
 
from mercurial import ui, config, hg
 
from mercurial.error import RepoError
 
log = logging.getLogger(__name__)
 

	
 

	
 
def get_repo_slug(request):
 
    return request.environ['pylons.routes_dict'].get('repo_name')
 

	
 
def is_mercurial(environ):
 
    """
 
    Returns True if request's target is mercurial server - header
 
    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
 
    """
 
    http_accept = environ.get('HTTP_ACCEPT')
 
    if http_accept and http_accept.startswith('application/mercurial'):
 
        return True
 
    return False
 

	
 
def check_repo_dir(paths):
 
    repos_path = paths[0][1].split('/')
 
    if repos_path[-1] in ['*', '**']:
 
        repos_path = repos_path[:-1]
 
    if repos_path[0] != '/':
 
        repos_path[0] = '/'
 
    if not os.path.isdir(os.path.join(*repos_path)):
 
        raise Exception('Not a valid repository in %s' % paths[0][1])
 

	
 
def check_repo(repo_name, base_path):
 

	
 
    repo_path = os.path.join(base_path, repo_name)
 

	
 
    try:
 
        r = hg.repository(ui.ui(), repo_path)
 
        hg.verify(r)
 
        #here we hnow that repo exists it was verified
 
        log.info('%s repo is already created', repo_name)
 
        return False
 
        #raise Exception('Repo exists')
 
    except RepoError:
 
        log.info('%s repo is free for creation', repo_name)
 
        #it means that there is no valid repo there...
 
        return True
 
                
 
def make_ui(path=None, checkpaths=True):        
 
    """
 
    A funcion that will read python rc files and make an ui from read options
 
@@ -86,49 +112,49 @@ def make_ui(path=None, checkpaths=True):
 

	
 
    for section in sections:
 
        for k, v in cfg.items(section):
 
            baseui.setconfig(section, k, v)
 
    
 
    return baseui
 

	
 
def invalidate_cache(name, *args):
 
    """Invalidates given name cache"""
 
    
 
    from beaker.cache import region_invalidate
 
    log.info('INVALIDATING CACHE FOR %s', name)
 
    
 
    """propagate our arguments to make sure invalidation works. First
 
    argument has to be the name of cached func name give to cache decorator
 
    without that the invalidation would not work"""
 
    tmp = [name]
 
    tmp.extend(args)
 
    args = tuple(tmp)
 
    
 
    if name == 'cached_repo_list':
 
        from pylons_app.model.hg_model import _get_repos_cached
 
        region_invalidate(_get_repos_cached, None, *args)
 
        
 
    if name == 'full_changelog':
 
        from pylons_app.model.hg_model import _full_changelog_cached
 
        region_invalidate(_full_changelog_cached, None, *args)
 
        
 
from vcs.backends.base import BaseChangeset
 
from vcs.utils.lazy import LazyProperty
 
class EmptyChangeset(BaseChangeset):
 
    
 
    revision = -1
 

	
 
    @LazyProperty
 
    def raw_id(self):
 
        """
 
        Returns raw string identifing this changeset, useful for web
 
        representation.
 
        """
 
        return '0' * 12
 

	
 

	
 
def repo2db_mapper():
 
    """
 
    scann all dirs for .hgdbid
 
    if some dir doesn't have one generate one.
 
    """
 
    pass
 
\ No newline at end of file
 
    pass
pylons_app/model/hg_model.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
#
 
# Copyright (c) 2010 marcink.  All rights reserved.
 
# Model for hg app
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
#
 
'''
 
Created on Apr 9, 2010
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
# 
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 9, 2010
 
Model for hg app
 
@author: marcink
 
'''
 
"""
 

	
 
from beaker.cache import cache_region
 
from mercurial import ui
 
from mercurial.hgweb.hgwebdir_mod import findrepos
 
from pylons import app_globals as g
 
from vcs.exceptions import RepositoryError, VCSError
 
import logging
 
import os
 
import sys
 
log = logging.getLogger(__name__)
 

	
 
try:
 
    from vcs.backends.hg import MercurialRepository
 
except ImportError:
 
    sys.stderr.write('You have to import vcs module')
 
    raise Exception('Unable to import vcs')
 

	
 

	
 
@cache_region('long_term', 'cached_repo_list')
 
def _get_repos_cached():
 
    """
 
    return cached dict with repos
 
    """
 
    return HgModel.repo_scan(g.paths[0][0], g.paths[0][1], g.baseui)
 

	
 
@cache_region('long_term', 'full_changelog')
 
def _full_changelog_cached(repo_name):
 
    log.info('getting full changelog for %s', repo_name)
 
    return list(reversed(list(HgModel().get_repo(repo_name))))
 

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

	
 
    def __init__(self):
 
        """
 
        Constructor
 
        """
 
        pass
 
    
 
    @staticmethod
 
    def repo_scan(repos_prefix, repos_path, baseui):
 
        """
 
        Listing of repositories in given path. This path should not be a 
 
        repository itself. Return a dictionary of repository objects
 
        :param repos_path: path to directory it could take syntax with 
 
        * or ** for deep recursive displaying repositories
pylons_app/model/user_model.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# Model for users
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
 
 
# This program is free software; you can redistribute it and/or
 
# modify it under the terms of the GNU General Public License
 
# as published by the Free Software Foundation; version 2
 
# of the License or (at your opinion) any later version of the license.
 
#
 
# Copyright (c) 2010 marcink.  All rights reserved.
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program; if not, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
"""
 
Created on April 9, 2010
 
Model for users
 
@author: marcink
 
"""
 

	
 
from pylons_app.model.db import User
 
from pylons_app.model.meta import Session
 
'''
 
Created on Apr 9, 2010
 

	
 
@author: marcink
 
'''
 

	
 
class UserModel(object):
 

	
 
    def __init__(self):
 
        self.sa = Session() 
 
    
 
    def get_user(self, id):
 
        return self.sa.query(User).get(id)
 
    
 
    def create(self, form_data):
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except:
 
            self.sa.rollback()
 
            raise      
 
    
 
    def update(self, id, form_data):
 
        try:
 
            new_user = self.sa.query(User).get(id)
 
            for k, v in form_data.items():
 
                if k == 'new_password' and v != '':
 
                    
 
                    new_user.password = v
 
                else:
 
                    setattr(new_user, k, v)
 
                
 
            self.sa.add(new_user)
 
            self.sa.commit()
 
        except:
 
            self.sa.rollback()
 
            raise      
pylons_app/templates/admin/permissions/permissions.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Permissions administration')}
 
</%def>
 
<%def name="breadcrumbs()">
 
	${h.link_to(u'Admin',h.url('admin_home'))}
 
	 /  
 
	 ${_('Permissions')}
 
</%def>
 
<%def name="page_nav()">
 
	${self.menu('admin')}
 
	${self.submenu('permissions')}
 
</%def>
 
<%def name="main()">
 
	<div>
 
	<h2>${_('Permissions')}</h2>
 
	todo :) 
 
	</i>
 
    </div>
 
</%def>    
0 comments (0 inline, 0 general)