diff options
-rw-r--r-- | README.md | 23 | ||||
-rw-r--r-- | devel/utils.py | 8 | ||||
-rw-r--r-- | main/utils.py | 15 | ||||
-rw-r--r-- | news/models.py | 7 | ||||
-rw-r--r-- | news/views.py | 6 | ||||
-rw-r--r-- | packages/views/search.py | 17 | ||||
-rw-r--r-- | releng/models.py | 6 | ||||
-rw-r--r-- | requirements.txt | 4 | ||||
-rw-r--r-- | requirements_prod.txt | 4 | ||||
-rw-r--r-- | sitestatic/archweb.js | 4 | ||||
-rw-r--r-- | templates/devel/index.html | 15 |
11 files changed, 68 insertions, 41 deletions
@@ -32,15 +32,15 @@ packages, you will probably want the following: 1. Run `virtualenv2`. - $ cd /path/to/archweb && virtualenv2 ./env/ + cd /path/to/archweb && virtualenv2 ./env/ 2. Activate the virtualenv. - $ source ./env/bin/activate + source ./env/bin/activate 2. Install dependencies through `pip`. - (archweb-env) $ pip install -r requirements.txt + pip install -r requirements.txt 3. Copy `local_settings.py.example` to `local_settings.py` and modify. Make sure to uncomment the appropriate database section (either sqlite or @@ -48,26 +48,29 @@ packages, you will probably want the following: 4. Sync the database to create it. - (archweb-env) $ ./manage.py syncdb + ./manage.py syncdb 5. Migrate changes. - (archweb-env) $ ./manage.py migrate + ./manage.py migrate 6. Load the fixtures to prepopulate some data. If you don't want some of the provided data, adjust the file glob accordingly. - (archweb-env) $ ./manage.py loaddata */fixtures/*.json + ./manage.py loaddata main/fixtures/*.json + ./manage.py loaddata devel/fixtures/*.json + ./manage.py loaddata mirrors/fixtures/*.json + ./manage.py loaddata releng/fixtures/*.json 7. Use the following commands to start a service instance - (archweb-env) $ ./manage.py runserver + ./manage.py runserver 8. To optionally populate the database with real data: - (archweb-env) $ wget ftp://ftp.archlinux.org/core/os/i686/core.db.tar.gz - (archweb-env) $ ./manage.py reporead i686 core.db.tar.gz - (archweb-env) $ ./manage.py syncisos + wget http://mirrors.kernel.org/archlinux/core/os/i686/core.db.tar.gz + ./manage.py reporead i686 core.db.tar.gz + ./manage.py syncisos Alter architecture and repo to get x86\_64 and packages from other repos if needed. diff --git a/devel/utils.py b/devel/utils.py index eaa7d07e..3326987a 100644 --- a/devel/utils.py +++ b/devel/utils.py @@ -6,13 +6,16 @@ from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db import connection from django.db.models import Count, Q +from devel.models import UserProfile from main.utils import cache_function from main.models import Package from packages.models import PackageRelation @cache_function(283) def get_annotated_maintainers(): - maintainers = User.objects.filter(is_active=True).order_by( + profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') + maintainers = User.objects.filter( + is_active=True, userprofile__id__in=profile_ids).order_by( 'first_name', 'last_name') # annotate the maintainers with # of maintained and flagged packages @@ -43,7 +46,8 @@ SELECT pr.user_id, COUNT(*), COUNT(p.flag_date) m.flagged_count = flag_count.get(m.id, 0) m.updated_count = update_count.get(m.id, 0) - return maintainers + # force non-QS context, otherwise pickling doesn't work + return list(maintainers) def ignore_does_not_exist(func): diff --git a/main/utils.py b/main/utils.py index cf156566..f94f314d 100644 --- a/main/utils.py +++ b/main/utils.py @@ -4,6 +4,8 @@ except ImportError: import pickle import hashlib +import markdown +from markdown.extensions import Extension from django.core.cache import cache from django.db import connections, router @@ -109,6 +111,19 @@ def database_vendor(model, mode='read'): return connections[database].vendor +class EscapeHtml(Extension): + def extendMarkdown(self, md, md_globals): + del md.preprocessors['html_block'] + del md.inlinePatterns['html'] + + +def parse_markdown(text, allow_html=False): + if allow_html: + return markdown.markdown(text, enable_attributes=False) + ext = [EscapeHtml()] + return markdown.markdown(text, extensions=ext, enable_attributes=False) + + def groupby_preserve_order(iterable, keyfunc): '''Take an iterable and regroup using keyfunc to determine whether items belong to the same group. The order of the iterable is preserved and diff --git a/news/models.py b/news/models.py index 985c1088..a66da8d4 100644 --- a/news/models.py +++ b/news/models.py @@ -1,11 +1,11 @@ -import markdown - from django.db import models from django.contrib.auth.models import User from django.contrib.sites.models import Site from django.utils.safestring import mark_safe from django.utils.timezone import now +from main.utils import parse_markdown + class News(models.Model): slug = models.SlugField(max_length=255, unique=True) @@ -22,8 +22,7 @@ class News(models.Model): return '/news/%s/' % self.slug def html(self): - return mark_safe(markdown.markdown( - self.content, safe_mode=self.safe_mode, enable_attributes=False)) + return mark_safe(parse_markdown(self.content, not self.safe_mode)) def __unicode__(self): return self.title diff --git a/news/views.py b/news/views.py index ca4fdf97..274ba75d 100644 --- a/news/views.py +++ b/news/views.py @@ -1,5 +1,3 @@ -import markdown - from django import forms from django.http import HttpResponse from django.shortcuts import get_object_or_404, redirect @@ -8,7 +6,7 @@ from django.views.generic import (DetailView, ListView, CreateView, UpdateView, DeleteView) from .models import News -from main.utils import find_unique_slug +from main.utils import find_unique_slug, parse_markdown class NewsForm(forms.ModelForm): @@ -62,7 +60,7 @@ def view_redirect(request, object_id): @require_POST def preview(request): data = request.POST.get('data', '') - markup = markdown.markdown(data, safe_mode=True, enable_attributes=False) + markup = parse_markdown(data) return HttpResponse(markup) # vim: set ts=4 sw=4 et: diff --git a/packages/views/search.py b/packages/views/search.py index 0b776d79..e4cd0423 100644 --- a/packages/views/search.py +++ b/packages/views/search.py @@ -6,6 +6,7 @@ from django.db.models import Q from django.http import HttpResponse from django.views.generic import ListView +from devel.models import UserProfile from main.models import Package, Arch, Repo from main.utils import empty_response, make_choice from ..models import PackageRelation @@ -36,14 +37,16 @@ class PackageSearchForm(forms.Form): self.fields['arch'].choices = make_choice( [arch.name for arch in Arch.objects.all()]) self.fields['q'].widget.attrs.update({"size": "30"}) - maints = User.objects.filter(is_active=True).order_by( + + profile_ids = UserProfile.allowed_repos.through.objects.values('userprofile_id') + people = User.objects.filter( + is_active=True, userprofile__id__in=profile_ids).order_by( 'first_name', 'last_name') - self.fields['maintainer'].choices = \ - [('', 'All'), ('orphan', 'Orphan')] + \ - [(m.username, m.get_full_name()) for m in maints] - self.fields['packager'].choices = \ - [('', 'All'), ('unknown', 'Unknown')] + \ - [(m.username, m.get_full_name()) for m in maints] + people = [('', 'All'), ('orphan', 'Orphan')] + \ + [(p.username, p.get_full_name()) for p in people] + + self.fields['maintainer'].choices = people + self.fields['packager'].choices = people def exact_matches(self): # only do exact match search if 'q' is sole parameter diff --git a/releng/models.py b/releng/models.py index 2f9216bd..a4af81ab 100644 --- a/releng/models.py +++ b/releng/models.py @@ -2,7 +2,6 @@ from base64 import b64decode from bencode import bdecode, bencode from datetime import datetime import hashlib -import markdown from pytz import utc from django.conf import settings @@ -12,7 +11,7 @@ from django.db.models.signals import pre_save from django.utils.safestring import mark_safe from main.fields import PositiveBigIntegerField -from main.utils import set_created_field +from main.utils import set_created_field, parse_markdown class IsoOption(models.Model): @@ -154,8 +153,7 @@ class Release(models.Model): return "magnet:?%s" % '&'.join(['%s=%s' % (k, v) for k, v in query]) def info_html(self): - return mark_safe(markdown.markdown( - self.info, safe_mode=True, enable_attributes=False)) + return mark_safe(parse_markdown(self.info)) def torrent(self): try: diff --git a/requirements.txt b/requirements.txt index e1acd2e9..2a5dba96 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,9 +2,9 @@ Django==1.7.1 IPy==0.81 Jinja2==2.7.3 -Markdown==2.4.1 +Markdown==2.5.2 bencode==1.0 -django-jinja==1.0.4 +django-jinja==1.0.5 django_countries==3.0.1 jsmin==2.0.11 pgpdump==1.5 diff --git a/requirements_prod.txt b/requirements_prod.txt index ef535eb8..6edfa17f 100644 --- a/requirements_prod.txt +++ b/requirements_prod.txt @@ -2,9 +2,9 @@ Django==1.7.1 IPy==0.81 Jinja2==2.7.3 -Markdown==2.4.1 +Markdown==2.5.2 bencode==1.0 -django-jinja==1.0.4 +django-jinja==1.0.5 django_countries==3.0.1 jsmin==2.0.11 pgpdump==1.5 diff --git a/sitestatic/archweb.js b/sitestatic/archweb.js index 43816c5b..dce9cd0c 100644 --- a/sitestatic/archweb.js +++ b/sitestatic/archweb.js @@ -303,12 +303,12 @@ function filter_packages() { var cells = $(this).children('td'); /* all this just to get the split version out of the table cell */ - var ver_a = cells.eq(2).find('span').text().match(pat); + var ver_a = cells.eq(2).text().match(pat); if (!ver_a) { return true; } - var ver_b = cells.eq(3).find('span').text().match(pat); + var ver_b = cells.eq(3).text().match(pat); if (!ver_b) { return true; } diff --git a/templates/devel/index.html b/templates/devel/index.html index 8ed9f9ac..0de285d5 100644 --- a/templates/devel/index.html +++ b/templates/devel/index.html @@ -157,8 +157,11 @@ </ul> </div>{# #dev-dashboard #} -<div id='stats-area'> - <p>Enable Javascript to get more useful info here.</p> +<div id="stats-area"> + <div class="box"> + <h2>Developer Stats</h2> + <p id="stats-message">Enable JavaScript to get more useful info here.</p> + </div> </div> {% endblock %} @@ -167,8 +170,12 @@ <script type="text/javascript" src="{% static "archweb.js" %}"></script> <script type="text/javascript"> $(document).ready(function() { - $("#stats-area").html('<p>Loading stats…</p>'); - $("#stats-area").load('stats/', function() { + $("#stats-message").html('Loading developer stats…'); + $("#stats-area").load('stats/', function(response, status, xhr) { + if (status === 'error' || status === 'timeout') { + $("#stats-message").html('Developer stats loading encountered an error. Sorry.'); + return; + } var settings = { widgets: ['zebra'], sortList: [[0,0]], |