You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by he...@apache.org on 2015/04/01 23:10:30 UTC

[13/45] allura git commit: [#7830] ticket:729 Move actual merge to background task

[#7830] ticket:729 Move actual merge to background task


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b0a908cd
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b0a908cd
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b0a908cd

Branch: refs/heads/hss/7072
Commit: b0a908cd291dd99068edd550897fc11cf6ce40ff
Parents: 121ebed
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Feb 19 12:14:52 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Mar 20 20:40:29 2015 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/repository.py         | 11 +--
 Allura/allura/model/repository.py               | 27 ++++---
 Allura/allura/tasks/repo_tasks.py               | 15 ++++
 Allura/allura/templates/repo/merge_request.html | 82 +++++++++++++++++---
 4 files changed, 107 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b0a908cd/Allura/allura/controllers/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 78bff44..8d8cfff 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -366,6 +366,7 @@ class MergeRequestController(object):
         return dict(
             downstream_app=downstream_app,
             req=self.req,
+            status=self.req.merge_task_status(),
             page=page,
             limit=limit,
             count=self.req.discussion_thread.post_count)
@@ -447,13 +448,13 @@ class MergeRequestController(object):
         require_access(c.app, 'write')
         if self.req.status != 'open' or not self.req.can_merge():
             raise exc.HTTPNotFound
-        ok = self.req.merge()
-        if ok:
-            flash('Merged successfully', 'ok')
-        else:
-            flash('Merge failed. Please, merge manually', 'error')
+        self.req.merge()
         redirect(self.req.url())
 
+    @expose('json:')
+    def merge_task_status(self):
+        return {'status': self.req.merge_task_status()}
+
 
 class RefsController(object):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/b0a908cd/Allura/allura/model/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/repository.py b/Allura/allura/model/repository.py
index 5e4a171..d866598 100644
--- a/Allura/allura/model/repository.py
+++ b/Allura/allura/model/repository.py
@@ -23,7 +23,7 @@ import string
 import re
 from subprocess import Popen, PIPE
 from hashlib import sha1
-from datetime import datetime
+from datetime import datetime, timedelta
 from time import time
 from collections import defaultdict, OrderedDict
 from urlparse import urljoin
@@ -818,16 +818,21 @@ class MergeRequest(VersionedArtifact, ActivityObject):
         return result
 
     def merge(self):
-        if not self.app.forkable:
-            return False
-        try:
-            self.app.repo.merge(self)
-        except:
-            log.exception("Can't merge merge request %s", self.url())
-            return False
-        self.status = 'merged'
-        session(self).flush(self)
-        return True
+        in_progress = self.merge_task_status() in ['ready', 'busy']
+        if self.app.forkable and not in_progress:
+            from allura.tasks import repo_tasks
+            repo_tasks.merge.post(self._id)
+
+    def merge_task_status(self):
+        task = MonQTask.query.find({
+            'state': {'$in': ['busy', 'complete', 'error', 'ready']},  # needed to use index
+            'task_name': 'allura.tasks.repo_tasks.merge',
+            'args': [self._id],
+            'time_queue': {'$gt': datetime.utcnow() - timedelta(days=1)}, # constrain on index further
+        }).sort('_id', -1).limit(1).first()
+        if task:
+            return task.state
+        return None
 
 
 # Basic commit information

http://git-wip-us.apache.org/repos/asf/allura/blob/b0a908cd/Allura/allura/tasks/repo_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/repo_tasks.py b/Allura/allura/tasks/repo_tasks.py
index 61cac83..e50f9d2 100644
--- a/Allura/allura/tasks/repo_tasks.py
+++ b/Allura/allura/tasks/repo_tasks.py
@@ -20,6 +20,7 @@ import logging
 import traceback
 
 from pylons import tmpl_context as c, app_globals as g
+from ming.odm import session
 
 from allura.lib.decorators import task
 from allura.lib.repository import RepositoryApp
@@ -152,3 +153,17 @@ def tarball(revision, path):
         log.warn(
             'Skipped creation of snapshot: %s:%s because revision is not specified' %
             (c.project.shortname, c.app.config.options.mount_point))
+
+
+@task
+def merge(merge_request_id):
+    from allura import model as M
+    log = logging.getLogger(__name__)
+    mr = M.MergeRequest.query.get(_id=merge_request_id)
+    try:
+        mr.app.repo.merge(mr)
+    except:
+        log.exception("Can't merge merge request %s", mr.url())
+        return
+    mr.status = 'merged'
+    session(mr).flush(mr)

http://git-wip-us.apache.org/repos/asf/allura/blob/b0a908cd/Allura/allura/templates/repo/merge_request.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/repo/merge_request.html b/Allura/allura/templates/repo/merge_request.html
index 060b5b9..1520270 100644
--- a/Allura/allura/templates/repo/merge_request.html
+++ b/Allura/allura/templates/repo/merge_request.html
@@ -33,6 +33,19 @@ Merge Request #{{req.request_number}}: {{req.summary}} ({{req.status}})
 {% endblock %}
 
 {% block content %}
+  <div class="grid-19">
+    <div id="task_status">
+      {% if status == 'complete' %}
+        <h2 class="complete">Merged</h2>
+      {% else %}
+        <img src="{{g.forge_static('images/spinner.gif')}}" class="spinner" style="display:none"/>
+        <h2 class="busy ready">Merging...</h2>
+        <h2 class="complete">Merged</h2>
+        <h2 class="fail">Something went wrong. Please, merge manually</h2>
+      {% endif %}
+    </div>
+  </div>
+
   {% if req.downstream_repo %}
     <p>
       <a href="{{req.creator_url}}">{{req.creator_name}}</a>
@@ -49,7 +62,7 @@ Merge Request #{{req.request_number}}: {{req.summary}} ({{req.status}})
       <div class="grid-19">
         <form action="merge" method="POST">
           {{ lib.csrf_token() }}
-          <input type="submit" value="Merge"{% if not can_merge %}disabled="disabled"{% endif %}>
+          <input type="submit" value="Merge"{% if not can_merge or status in ('ready', 'busy') %}disabled="disabled"{% endif %}>
           {% if can_merge %}
             <div class="merge-ok">
               Merge request has no conflicts. You can merge automatically.
@@ -68,14 +81,16 @@ Merge Request #{{req.request_number}}: {{req.summary}} ({{req.status}})
     <div class="grid-19"><a href="#discussion_holder">Discuss</a></div>
 
     {% if h.has_access(c.app, 'write')() %}
-       <div class="grid-19">To merge the commits, please execute the following commands in your working
-         copy: </div>
-       <div class="grid-19"><textarea
-          style="width:80%; height:60px;"
-          readonly
-          >{{ c.app.repo.merge_command(req) | safe }}</textarea></div>
-      {{ c.mr_dispose_form.display(action="save", value=dict(status=req.status)) }}
-       <br style="clear:both">
+      <div class="grid-19">
+        To merge the commits, please execute the following commands in your working copy:
+      </div>
+      <div class="grid-19">
+        <textarea style="width:80%; height:60px;" readonly>{{ c.app.repo.merge_command(req) | safe }}</textarea>
+      </div>
+      {% if status not in ('ready', 'busy') %}
+        {{ c.mr_dispose_form.display(action="save", value=dict(status=req.status)) }}
+        <br style="clear:both">
+      {% endif %}
     {% endif %}
   {% else %}
     <p>
@@ -83,12 +98,10 @@ Merge Request #{{req.request_number}}: {{req.summary}} ({{req.status}})
       <a href="{{req.creator_url}}">{{req.creator_name}}</a>
       is deleted
     </p>
-
     <div>{{g.markdown.convert(req.description)}}</div>
-
     {% if h.has_access(c.app, 'write')() %}
       {{ c.mr_dispose_form.display(action="save", value=dict(status=req.status)) }}
-       <br style="clear:both">
+      <br style="clear:both">
     {% endif %}
   {% endif %}
 
@@ -111,5 +124,50 @@ Merge Request #{{req.request_number}}: {{req.summary}} ({{req.status}})
 <style type="text/css">
   .merge-ok { color: green; }
   .merge-conflicts { color: red; }
+
+  #task_status { margin: 0 10px; }
+  #task_status h2 { display: none; }
+  #task_status .{{ status }} { display: inline-block; }
+  #task_status h2.complete { color: #C6D880; }
+  #task_status h2.busy, #task_status h2.busy { color: #003565; }
+  #task_status h2.fail { color: #f33; }
 </style>
 {% endblock %}
+
+{% block extra_js %}
+{{ super() }}
+<script type="text/javascript">
+$(function() {
+    {% if status in ('ready', 'busy') %}
+        $('.spinner').show();
+        var delay = 500;
+        function check_status() {
+          $.get("{{request.path.rstrip('/') + '/merge_task_status'}}", function(data) {
+                if (data.status === 'complete') {
+                    $('.spinner').hide();
+                    $('#task_status h2').hide();
+                    $('#task_status h2.complete').show();
+                    location.reload();
+                } else {
+                    if (data.status === 'ready' || data.status === 'busy') {
+                        // keep waiting
+                        $('#task_status h2').hide();
+                        $('#task_status h2.busy').show();
+                    } else {
+                        // something went wrong
+                        $('.spinner').hide();
+                        $('#task_status h2').hide();
+                        $('#task_status h2.fail').show();
+                    }
+                    if (delay < 60000){
+                        delay = delay * 2;
+                    }
+                    window.setTimeout(check_status, delay);
+                }
+            });
+        }
+        window.setTimeout(check_status, delay);
+    {% endif %}
+});
+</script>
+{% endblock %}