Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix #26 fix #6
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
  • Loading branch information
Kwpolska committed Jan 13, 2015
1 parent dff1f99 commit c756145
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 29 deletions.
10 changes: 10 additions & 0 deletions comet/data/comet_assets/css/comet.css
Expand Up @@ -6,6 +6,9 @@
/* global styles */

.save-btn, .save-icon {
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}

Expand All @@ -19,6 +22,13 @@
margin-top: 22px;
}

.build-status-caption {
-webkit-transition: all 0.6s ease;
-moz-transition: all 0.6s ease;
-o-transition: all 0.6s ease;
transition: all 0.6s ease;
}

/* edit */

#post-meta-line, #toolbar, #post-meta-panel, #content-area {
Expand Down
75 changes: 75 additions & 0 deletions comet/data/templates/jinja/comet_rebuild.tmpl
@@ -0,0 +1,75 @@
{# -*- coding: utf-8 -*- #}
{% extends 'base.tmpl' %}
{% block content %}
<div class="page-header">
<h1 class="build-status-caption"><i class="build-status-icon fa fa-fw fa-cog"></i> Rebuild</h1>
</div>

<div class="progress">
<div class="progress-bar progress-bar-striped active" id="progressbar" role="progressbar" aria-valuenow="0" aria-valuemin"0" aria-valuemax="100" style="width: 0%;">
0%
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">
<a data-toggle="collapse" href="#collapseOutput" aria-expanded="false" aria-controls="collapseOutput"><i class="fa fa-bars"></i> Advanced information</a>
</h3></div>
<div class="panel-body collapse" id="collapseOutput">
<h4>Build</h4>
<pre><code id="outputb">Working...</code></pre>

<h4>Unused files removed</h4>
<pre><code id="outputo">Working...</code></pre>
</div>
</div>

{% endblock %}

{% block extra_js %}
<script>
function set_bar(current, max) {
max = max;
perc = 100 * current / max;
pb.attr('aria-valuenow', Math.ceil(perc));
pb.attr('style', 'width: ' + perc + '%');
pb.html(Math.ceil(perc) + '%');
if (current == max) {
pb.removeClass('active');
}
}

$(document).ready(function() {
pb = $('#progressbar');
fs = $('.build-status-icon');
fsc = $('.build-status-caption');
outb = $('#outputb');
outo = $('#outputo');
var intID = setInterval(function() {
$.ajax({
"url": "/api/rebuild",
"dataType": "json",
}).done(function(data) {
outb.html(data.build.out);
outo.html(data.orphans.out);
set_bar(data.build.milestone, data.build.total + 1);
of = (data.orphans.status === true);
if (of) {
set_bar(1, 1);
pb.addClass('progress-bar-success');
fs.removeClass('fa-cog');
fs.addClass('fa-check');
fsc.addClass('text-success');
clearInterval(intID);
}
if (data.build.status === false || data.orphans.status === false) {
pb.addClass('progress-bar-danger');
fs.removeClass('fa-cog');
fs.addClass('fa-times');
fsc.addClass('text-danger');
}
});
}, 500);
});
</script>
{% endblock %}
75 changes: 75 additions & 0 deletions comet/data/templates/mako/comet_rebuild.tmpl
@@ -0,0 +1,75 @@
## -*- coding: utf-8 -*-
<%inherit file="base.tmpl"/>
<%block name="content">
<div class="page-header">
<h1 class="build-status-caption"><i class="build-status-icon fa fa-fw fa-cog"></i> Rebuild</h1>
</div>

<div class="progress">
<div class="progress-bar progress-bar-striped active" id="progressbar" role="progressbar" aria-valuenow="0" aria-valuemin"0" aria-valuemax="100" style="width: 0%;">
0%
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">
<a data-toggle="collapse" href="#collapseOutput" aria-expanded="false" aria-controls="collapseOutput"><i class="fa fa-bars"></i> Advanced information</a>
</h3></div>
<div class="panel-body collapse" id="collapseOutput">
<h4>Build</h4>
<pre><code id="outputb">Working...</code></pre>

<h4>Unused files removed</h4>
<pre><code id="outputo">Working...</code></pre>
</div>
</div>

</%block>

<%block name="extra_js">
<script>
function set_bar(current, max) {
max = max;
perc = 100 * current / max;
pb.attr('aria-valuenow', Math.ceil(perc));
pb.attr('style', 'width: ' + perc + '%');
pb.html(Math.ceil(perc) + '%');
if (current == max) {
pb.removeClass('active');
}
}

$(document).ready(function() {
pb = $('#progressbar');
fs = $('.build-status-icon');
fsc = $('.build-status-caption');
outb = $('#outputb');
outo = $('#outputo');
var intID = setInterval(function() {
$.ajax({
"url": "/api/rebuild",
"dataType": "json",
}).done(function(data) {
outb.html(data.build.out);
outo.html(data.orphans.out);
set_bar(data.build.milestone, data.build.total + 1);
of = (data.orphans.status === true);
if (of) {
set_bar(1, 1);
pb.addClass('progress-bar-success');
fs.removeClass('fa-cog');
fs.addClass('fa-check');
fsc.addClass('text-success');
clearInterval(intID);
}
if (data.build.status === false || data.orphans.status === false) {
pb.addClass('progress-bar-danger');
fs.removeClass('fa-cog');
fs.addClass('fa-times');
fsc.addClass('text-danger');
}
});
}, 500);
});
</script>
</%block>
100 changes: 100 additions & 0 deletions comet/tasks.py
@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*-

# Comet CMS v0.6.0
# Copyright © 2014-2015 Chris Warrick, Roberto Alsina, Henry Hirsch et al.

# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the
# Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the
# Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice
# shall be included in all copies or substantial portions of
# the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
# OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import subprocess
import os
from rq import get_current_job
from sys import executable
from redis import StrictRedis


def build(dbdata, sitedir):
"""Build a site."""
oldcwd = os.getcwd()
os.chdir(sitedir)
db = StrictRedis(**dbdata)
job = get_current_job(db)
job.meta.update({'out': '', 'milestone': 0, 'total': 1, 'return': None,
'status': None})
job.save()
p = subprocess.Popen([executable, '-m', 'nikola', 'build'],
stderr=subprocess.PIPE)

milestones = {
'done!': 0,
'render_posts': 0,
'render_pages': 0,
'generate_rss': 0,
'render_indexes': 0,
'sitemap': 0
}
out = []

while p.poll() is None:
nl = p.stderr.readline()
for k in milestones:
if k in nl:
milestones[k] = 1
out.append(nl)
job.meta.update({'milestone': sum(milestones.values()), 'total':
len(milestones), 'out': ''.join(out), 'return': None,
'status': None})
job.save()

out += p.stderr.readlines()

out = ''.join(out)
job.meta.update({'milestone': len(milestones), 'total': len(milestones),
'out': ''.join(out), 'return': p.returncode, 'status':
p.returncode == 0})
job.save()
os.chdir(oldcwd)
return p.returncode


def orphans(dbdata, sitedir):
"""Remove all orphans in the site."""
oldcwd = os.getcwd()
os.chdir(sitedir)
db = StrictRedis(**dbdata)
job = get_current_job(db)
job.meta.update({'out': '', 'return': None, 'status': None})
job.save()
p = subprocess.Popen([executable, '-m', 'nikola', 'orphans'],
stdout=subprocess.PIPE)
p.wait()
files = [l.strip() for l in p.stdout.readlines()]
for f in files:
if f:
os.unlink(f)

out = '\n'.join(files)
job.meta.update({'out': ''.join(out), 'return': p.returncode, 'status':
p.returncode == 0})
job.save()
os.chdir(oldcwd)
return p.returncode
13 changes: 9 additions & 4 deletions comet/utils.py
Expand Up @@ -106,6 +106,7 @@ def ask_yesno(query, default=None):
# Loop if no answer and no default.
return ask_yesno(query, default)


class SiteProxy(object):
"""A proxy for accessing the site in a multiprocessing-safe manner."""

Expand All @@ -123,7 +124,7 @@ def __init__(self, db, site, logger):
self._all_posts = []
self._pages = []

self.reload_site()
self.scan_posts()

def reload_site(self):
"""Reload the site from the database."""
Expand All @@ -150,7 +151,9 @@ def reload_site(self):

def _read_indexlist(self, name):
"""Read a list of indexes."""
setattr(self, '_' + name, [self._timeline[int(i)] for i in self.db.lrange('site:{0}'.format(name), 0, -1)])
setattr(self, '_' + name, [self._timeline[int(i)] for i in
self.db.lrange('site:{0}'.format(name), 0,
-1)])

def _write_indexlist(self, name):
"""Write a list of indexes."""
Expand All @@ -160,7 +163,8 @@ def _write_indexlist(self, name):

def scan_posts(self, really=True, ignore_quit=False, quiet=True):
"""Rescan the site."""
while self.db.exists('site:lock') and int(self.db.get('site:lock')) != 0:
while (self.db.exists('site:lock')
and int(self.db.get('site:lock')) != 0):
self.logger.info("Waiting for DB lock...")
time.sleep(0.5)
self.db.incr('site:lock')
Expand All @@ -171,7 +175,8 @@ def scan_posts(self, really=True, ignore_quit=False, quiet=True):

timeline = []
for post in self._site.timeline:
data = [post.source_path, post.folder, post.is_post, post._template_name, post.compiler.name]
data = [post.source_path, post.folder, post.is_post,
post._template_name, post.compiler.name]
timeline.append(json.dumps(data))
self.db.delete('site:timeline')
self.db.rpush('site:timeline', *timeline)
Expand Down

0 comments on commit c756145

Please sign in to comment.