changeset 4459:296b37f6fcdc

pull requests: load repo branch info on demand after changing repo Visiting a lot of repositories for no reason takes time.
author Mads Kiilerich <madski@unity3d.com>
date Thu, 21 Aug 2014 23:46:55 +0200
parents 23def9978ec3
children 6cb077e99873
files kallithea/config/routing.py kallithea/controllers/pullrequests.py kallithea/templates/pullrequests/pullrequest.html
diffstat 3 files changed, 90 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/config/routing.py	Thu Aug 21 23:46:55 2014 +0200
+++ b/kallithea/config/routing.py	Thu Aug 21 23:46:55 2014 +0200
@@ -688,6 +688,11 @@
                  action='index', conditions=dict(function=check_repo,
                                                  method=["GET"]))
 
+    rmap.connect('pullrequest_repo_info',
+                 '/{repo_name:.*?}/pull-request-repo-info',
+                 controller='pullrequests', action='repo_info',
+                 conditions=dict(function=check_repo, method=["GET"]))
+
     rmap.connect('pullrequest',
                  '/{repo_name:.*?}/pull-request/new', controller='pullrequests',
                  action='create', conditions=dict(function=check_repo,
--- a/kallithea/controllers/pullrequests.py	Thu Aug 21 23:46:55 2014 +0200
+++ b/kallithea/controllers/pullrequests.py	Thu Aug 21 23:46:55 2014 +0200
@@ -245,9 +245,9 @@
                                    'repository.admin')
     def index(self):
         org_repo = c.db_repo
-
+        org_scm_instance = org_repo.scm_instance
         try:
-            org_repo.scm_instance.get_changeset()
+            org_scm_instance.get_changeset()
         except EmptyRepositoryError, e:
             h.flash(h.literal(_('There are no changesets yet')),
                     category='warning')
@@ -259,45 +259,26 @@
         #other_rev = request.POST.get('rev_start')
         branch = request.GET.get('branch')
 
-        c.org_repos = []
-        c.org_repos.append((org_repo.repo_name, org_repo.repo_name))
+        c.org_repos = [(org_repo.repo_name, org_repo.repo_name)]
         c.default_org_repo = org_repo.repo_name
-        c.org_refs, c.default_org_ref = self._get_repo_refs(org_repo.scm_instance, rev=org_rev, branch=branch)
-
-        c.other_repos = []
-        other_repos_info = {}
-
-        def add_other_repo(repo, branch_rev=None):
-            if repo.repo_name in other_repos_info: # shouldn't happen
-                return
-            c.other_repos.append((repo.repo_name, repo.repo_name))
-            other_refs, selected_other_ref = self._get_repo_refs(repo.scm_instance, branch_rev=branch_rev)
-            other_repos_info[repo.repo_name] = {
-                'user': dict(user_id=repo.user.user_id,
-                             username=repo.user.username,
-                             firstname=repo.user.firstname,
-                             lastname=repo.user.lastname,
-                             gravatar_link=h.gravatar_url(repo.user.email, 14)),
-                'description': repo.description.split('\n', 1)[0],
-                'revs': h.select('other_ref', selected_other_ref, other_refs, class_='refs')
-            }
+        c.org_refs, c.default_org_ref = self._get_repo_refs(org_scm_instance, rev=org_rev, branch=branch)
 
         # add org repo to other so we can open pull request against peer branches on itself
-        add_other_repo(org_repo, branch_rev=org_rev)
-        c.default_other_repo = org_repo.repo_name
+        c.other_repos = [(org_repo.repo_name, '%s (self)' % org_repo.repo_name)]
+
+        # add parent of this fork also and select it
+        if org_repo.parent:
+            c.other_repos.append((org_repo.parent.repo_name, '%s (parent)' % org_repo.parent.repo_name))
+            c.other_repo = org_repo.parent
+            c.other_refs, c.default_other_ref = self._get_repo_refs(org_repo.parent.scm_instance)
+        else:
+            c.other_repo = org_repo
+            c.other_refs, c.default_other_ref = self._get_repo_refs(org_scm_instance) # without rev and branch
 
         # gather forks and add to this list ... even though it is rare to
         # request forks to pull from their parent
         for fork in org_repo.forks:
-            add_other_repo(fork)
-
-        # add parents of this fork also, but only if it's not empty
-        if org_repo.parent and org_repo.parent.scm_instance.revisions:
-            add_other_repo(org_repo.parent)
-            c.default_other_repo = org_repo.parent.repo_name
-
-        c.default_other_repo_info = other_repos_info[c.default_other_repo]
-        c.other_repos_info = json.dumps(other_repos_info)
+            c.other_repos.append((fork.repo_name, fork.repo_name))
 
         return render('/pullrequests/pullrequest.html')
 
@@ -305,6 +286,25 @@
     @NotAnonymous()
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
+    @jsonify
+    def repo_info(self, repo_name):
+        repo = RepoModel()._get_repo(repo_name)
+        refs, selected_ref = self._get_repo_refs(repo.scm_instance)
+        return {
+            'description': repo.description.split('\n', 1)[0],
+            'selected_ref': selected_ref,
+            'refs': refs,
+            'user': dict(user_id=repo.user.user_id,
+                         username=repo.user.username,
+                         firstname=repo.user.firstname,
+                         lastname=repo.user.lastname,
+                         gravatar_link=h.gravatar_url(repo.user.email, 14)),
+            }
+
+    @LoginRequired()
+    @NotAnonymous()
+    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
+                                   'repository.admin')
     def create(self, repo_name):
         repo = RepoModel()._get_repo(repo_name)
         try:
--- a/kallithea/templates/pullrequests/pullrequest.html	Thu Aug 21 23:46:55 2014 +0200
+++ b/kallithea/templates/pullrequests/pullrequest.html	Thu Aug 21 23:46:55 2014 +0200
@@ -53,7 +53,7 @@
                     <div>
                         <div>
                             <div style="padding:5px 3px 3px 3px;">
-                            <b>${_('Origin repository')}:</b> ${c.db_repo.description}
+                            <b>${_('Origin repository')}:</b> <span id="org_repo_desc">${c.db_repo.description.split('\n')[0]}</span>
                             </div>
                             <div>
                             ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref',c.default_org_ref,c.org_refs,class_='refs')}
@@ -68,10 +68,11 @@
                     <div style="border-top: 1px solid #EEE; margin: 5px 0px 0px 0px">
                         <div>
                             ## filled with JS
-                            <div id="other_repo_desc" style="padding:5px 3px 3px 3px;">
+                            <div style="padding:5px 3px 3px 3px;">
+                            <b>${_('Destination repository')}:</b> <span id="other_repo_desc">${c.other_repo.description.split('\n')[0]}</span>
                             </div>
                             <div>
-                            ${h.select('other_repo',c.default_other_repo,c.other_repos,class_='refs')}:${c.default_other_repo_info['revs']}
+                            ${h.select('other_repo',c.other_repo.repo_name,c.other_repos,class_='refs')}:${h.select('other_ref',c.default_other_ref,c.other_refs,class_='refs')}
                             </div>
                             <div style="padding:5px 3px 3px 3px;">
                             <b>${_('Revision')}:</b> <span id="other_rev_span">-</span>
@@ -98,13 +99,13 @@
               ## members goes here !
               <div>
                 <ul id="review_members" class="group_members">
-                %for member in [c.default_other_repo_info['user']]:
-                  <li id="reviewer_${member['user_id']}">
+                %for member in [c.other_repo.user]:
+                  <li id="reviewer_${member.user_id}">
                     <div class="reviewers_member">
-                      <div class="gravatar"><img alt="gravatar" src="${member['gravatar_link']}"/> </div>
-                      <div style="float:left">${member['firstname']} ${member['lastname']} (${_('owner')})</div>
-                      <input type="hidden" value="${member['user_id']}" name="review_members" />
-                      <span class="action_button" style="padding: 3px" onclick="removeReviewMember(${member['user_id']})" title="${_('Remove reviewer')}>
+                      <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email, 14)}"/> </div>
+                      <div style="float:left">${member.firstname} ${member.lastname} (${_('owner')})</div>
+                      <input type="hidden" value="${member.user_id}" name="review_members" />
+                      <span class="action_button" style="padding: 3px" onclick="removeReviewMember(${member.user_id})" title="${_('Remove reviewer')}>
                           <i class="icon-remove-sign" style="color: #FF4444;"></i>
                       </span>
                     </div>
@@ -143,39 +144,45 @@
   var _GROUPS_AC_DATA = ${c.user_groups_array|n};
   PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
 
-  var other_repos_info = ${c.other_repos_info|n};
+  pyroutes.register('pullrequest_repo_info', "${url('pullrequest_repo_info',repo_name='%(repo_name)s')}", ['repo_name']);
 
   var otherrepoChanged = function(){
-      var sel_box = YUQ('#pull_request_form #other_repo')[0];
-      var repo_name = sel_box.options[sel_box.selectedIndex].value;
-      var _tmpl = "<b>${_('Destination repository')}</b>: {0}".format(other_repos_info[repo_name]['description']);
-      YUD.get('other_repo_desc').innerHTML = _tmpl
-      // replace options of other_ref with the ones for the current other_repo
-      var other_ref_selector = YUD.get('other_ref');
-      var new_select = YUD.createElementFromMarkup(other_repos_info[repo_name]['revs']);
-      var new_selectedIndex = new_select.selectedIndex;
-      other_ref_selector.innerHTML = ""; // clear old options
-      while (new_select.length > 0){ // children will be popped when appened to other_ref_selector
-          other_ref_selector.appendChild(new_select.children[0]);
-      }
-      // browsers lost track of selected when appendChild was used
-      other_ref_selector.selectedIndex = new_selectedIndex;
+      var repo_name = $('#other_repo').val();
+      ajaxGET(pyroutes.url('pullrequest_repo_info', {"repo_name": repo_name}),
+          function(o){
+              var data = JSON.parse(o.responseText);
+              $('#other_repo_desc').html(data.description);
 
-      // reset && add the reviewer based on selected repo
-      var _data = other_repos_info[repo_name];
-      YUD.get('review_members').innerHTML = '';
-      addReviewMember(_data.user.user_id, _data.user.firstname,
-                      _data.user.lastname, _data.user.username,
-                      _data.user.gravatar_link);
+              // replace options of other_ref with the ones for the current other_repo
+              var $other_ref = $('#other_ref');
+              $other_ref.empty();
+              for(var i = 0; i < data.refs.length; i++)
+              {
+                var $optgroup = $('<optgroup/>').attr('label', data.refs[i][1]);
+                var options = data.refs[i][0];
+                var length = options.length;
+                for(var j = 0; j < length; j++)
+                {
+                  $optgroup.append($('<option/>').text(options[j][1]).val(options[j][0]));
+                }
+                $other_ref.append($optgroup);
+              }
+              $other_ref.val(data.selected_ref);
 
-      // (re)populate the select2 thingie
-      $("#other_ref").select2({
-          dropdownAutoWidth: true,
-      });
-      $("#other_ref").on("change", function(e){
-          loadPreview();
-      });
-  }
+              // reset && add the reviewer based on selected repo
+              YUD.get('review_members').innerHTML = '';
+              addReviewMember(data.user.user_id, data.user.firstname,
+                              data.user.lastname, data.user.username,
+                              data.user.gravatar_link);
+
+              // re-populate the select2 thingie
+              $("#other_ref").select2({
+                  dropdownAutoWidth: true,
+              });
+
+              loadPreview();
+          });
+  };
 
   var loadPreview = function(){
       //url template
@@ -236,10 +243,15 @@
       });
       $("#other_repo").on("change", function(e){
           otherrepoChanged();
+      });
+
+      $("#other_ref").select2({
+          dropdownAutoWidth: true,
+      });
+      $("#other_ref").on("change", function(e){
           loadPreview();
       });
 
-      otherrepoChanged();
       //lazy load overview after 0.5s
       setTimeout(loadPreview, 500);
   });