changeset 530:a08f610e545e

Implemented server side forks added ability to pass session to user/repo models
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 01 Oct 2010 00:16:09 +0200
parents 3a567e329fb6
children 6fc59ac322ca
files pylons_app/config/routing.py pylons_app/controllers/settings.py pylons_app/lib/celerylib/tasks.py pylons_app/model/db.py pylons_app/model/forms.py pylons_app/model/repo_model.py pylons_app/model/user_model.py pylons_app/templates/settings/repo_fork.html
diffstat 8 files changed, 99 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/pylons_app/config/routing.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/config/routing.py	Fri Oct 01 00:16:09 2010 +0200
@@ -171,7 +171,11 @@
                 controller='settings', action='index',
                 conditions=dict(function=check_repo))
 
+    map.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
+                controller='settings', action='fork_create',
+                conditions=dict(function=check_repo, method=["POST"]))
     map.connect('repo_fork_home', '/{repo_name:.*}/fork',
                 controller='settings', action='fork',
-                conditions=dict(function=check_repo))    
+                conditions=dict(function=check_repo))
+        
     return map
--- a/pylons_app/controllers/settings.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/controllers/settings.py	Fri Oct 01 00:16:09 2010 +0200
@@ -29,7 +29,7 @@
 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
 from pylons_app.lib.base import BaseController, render
 from pylons_app.lib.utils import invalidate_cache
-from pylons_app.model.forms import RepoSettingsForm
+from pylons_app.model.forms import RepoSettingsForm, RepoForkForm
 from pylons_app.model.repo_model import RepoModel
 import formencode
 import logging
@@ -140,5 +140,33 @@
                       ' in order to rescan repositories') % repo_name,
                       category='error')
         
-            return redirect(url('hg_home'))         
+            return redirect(url('hg_home'))
+        
         return render('settings/repo_fork.html')
+    
+    
+    
+    def fork_create(self, repo_name):
+        repo_model = RepoModel()
+        c.repo_info = repo_model.get(repo_name)
+        _form = RepoForkForm()()
+        form_result = {}
+        try:
+            form_result = _form.to_python(dict(request.POST))
+            form_result.update({'repo_name':repo_name})
+            repo_model.create_fork(form_result, c.hg_app_user)
+            h.flash(_('fork %s repository as %s task added') \
+                      % (repo_name, form_result['fork_name']),
+                    category='success')
+                                                             
+        except formencode.Invalid as errors:
+            c.new_repo = errors.value['fork_name']
+            r = render('settings/repo_fork.html')
+            
+            return htmlfill.render(
+                r,
+                defaults=errors.value,
+                errors=errors.error_dict or {},
+                prefix_error=False,
+                encoding="UTF-8")   
+        return redirect(url('hg_home'))
--- a/pylons_app/lib/celerylib/tasks.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/lib/celerylib/tasks.py	Fri Oct 01 00:16:09 2010 +0200
@@ -271,6 +271,24 @@
         return False
     return True
 
+@task
+def create_repo_fork(form_data, cur_user):
+    import os
+    from pylons_app.lib.utils import invalidate_cache
+    from pylons_app.model.repo_model import RepoModel
+    sa = get_session()
+    rm = RepoModel(sa)
+    
+    rm.create(form_data, cur_user, just_db=True, fork=True)
+    
+    repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
+    repo_path = os.path.join(repos_path, form_data['repo_name'])
+    repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
+    
+    MercurialRepository(str(repo_fork_path), True, clone_url=str(repo_path))
+    #invalidate_cache('cached_repo_list')
+
+    
 def __get_codes_stats(repo_name):
     LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
                     'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el', 'erl',
--- a/pylons_app/model/db.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/model/db.py	Fri Oct 01 00:16:09 2010 +0200
@@ -81,8 +81,10 @@
     user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=False, default=None)
     private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
     description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
+    fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
     
     user = relation('User')
+    fork = relation('Repository', remote_side=repo_id)
     repo_to_perm = relation('RepoToPerm', cascade='all')
     
     def __repr__(self):
--- a/pylons_app/model/forms.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/model/forms.py	Fri Oct 01 00:16:09 2010 +0200
@@ -307,6 +307,16 @@
         chained_validators = [ValidPerms]
     return _RepoForm
 
+def RepoForkForm(edit=False, old_data={}):
+    class _RepoForkForm(formencode.Schema):
+        allow_extra_fields = True
+        filter_extra_fields = False
+        fork_name = All(UnicodeString(strip=True, min=1, not_empty=True), ValidRepoName(edit, old_data))
+        description = UnicodeString(strip=True, min=1, not_empty=True)
+        private = StringBoolean(if_missing=False)
+        
+    return _RepoForkForm
+
 def RepoSettingsForm(edit=False, old_data={}):
     class _RepoForm(formencode.Schema):
         allow_extra_fields = True
--- a/pylons_app/model/repo_model.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/model/repo_model.py	Fri Oct 01 00:16:09 2010 +0200
@@ -27,6 +27,7 @@
 from pylons_app.model.db import Repository, RepoToPerm, User, Permission
 from pylons_app.model.meta import Session
 from pylons_app.model.user_model import UserModel
+from pylons_app.lib.celerylib.tasks import create_repo_fork, run_task
 import logging
 import os
 import shutil
@@ -35,11 +36,15 @@
 
 class RepoModel(object):
     
-    def __init__(self):
-        self.sa = Session()
+    def __init__(self, sa=None):
+        if not sa:
+            self.sa = Session()
+        else:
+            self.sa = sa
     
     def get(self, id):
-        return self.sa.query(Repository).filter(Repository.repo_name == id).scalar()
+        return self.sa.query(Repository)\
+            .filter(Repository.repo_name == id).scalar()
         
     def get_users_js(self):
         
@@ -100,20 +105,32 @@
             self.sa.rollback()
             raise    
     
-    def create(self, form_data, cur_user, just_db=False):
+    def create(self, form_data, cur_user, just_db=False, fork=False):
         try:
-            repo_name = form_data['repo_name']
+            if fork:
+                repo_name = str(form_data['fork_name'])
+                org_name = str(form_data['repo_name'])
+                
+            else:
+                org_name = repo_name = str(form_data['repo_name'])
             new_repo = Repository()
             for k, v in form_data.items():
+                if k == 'repo_name':
+                    v = repo_name
                 setattr(new_repo, k, v)
                 
+            if fork:
+                parent_repo = self.sa.query(Repository)\
+                        .filter(Repository.repo_name == org_name).scalar()
+                new_repo.fork = parent_repo
+                            
             new_repo.user_id = cur_user.user_id
             self.sa.add(new_repo)
             
             #create default permission
             repo_to_perm = RepoToPerm()
             default = 'repository.read'
-            for p in UserModel().get_default().user_perms:
+            for p in UserModel(self.sa).get_default().user_perms:
                 if p.permission.permission_name.startswith('repository.'):
                     default = p.permission.permission_name
                     break
@@ -136,7 +153,10 @@
             log.error(traceback.format_exc())
             self.sa.rollback()
             raise    
-                     
+    
+    def create_fork(self, form_data, cur_user):
+        run_task(create_repo_fork, form_data, cur_user)
+                         
     def delete(self, repo):
         try:
             self.sa.delete(repo)
--- a/pylons_app/model/user_model.py	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/model/user_model.py	Fri Oct 01 00:16:09 2010 +0200
@@ -36,8 +36,11 @@
 
 class UserModel(object):
 
-    def __init__(self):
-        self.sa = Session() 
+    def __init__(self, sa=None):
+        if not sa:
+            self.sa = Session()
+        else:
+            self.sa = sa
     
     def get_default(self):
         return self.sa.query(User).filter(User.username == 'default').scalar()
--- a/pylons_app/templates/settings/repo_fork.html	Thu Sep 30 18:35:03 2010 +0200
+++ b/pylons_app/templates/settings/repo_fork.html	Fri Oct 01 00:16:09 2010 +0200
@@ -20,7 +20,7 @@
     <div class="title">
         ${self.breadcrumbs()}      
     </div>
-    ${h.form(url('repos'))}
+    ${h.form(url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
     <div class="form">
         <!-- fields -->
         <div class="fields">
@@ -49,7 +49,7 @@
                 </div>
              </div>
 	        <div class="buttons">
-	          ${h.submit('fork','fork this repository',class_="ui-button ui-widget ui-state-default ui-corner-all")}
+	          ${h.submit('','fork this repository',class_="ui-button ui-widget ui-state-default ui-corner-all")}
 	        </div>                                                          
         </div>
     </div>