From 15ceff77fef19819cba43e866938311aeffd0732 Mon Sep 17 00:00:00 2001 From: eliott Date: Sat, 29 Dec 2007 15:34:02 -0800 Subject: Modified render_template and renamed it to render_response (consistent with archweb_pub conventions). Moved pkgmaint_guide to a template. --- data/pkgmaint_guide.txt | 164 -------------------- devel/views.py | 87 +++++------ lib/utils.py | 34 +++++ news/views.py | 116 +++++++-------- packages/views.py | 296 ++++++++++++++++++------------------- public/views.py | 52 +++---- templates/devel/pkgmaint_guide.txt | 164 ++++++++++++++++++++ todolists/views.py | 77 +++++----- utils.py | 69 --------- wiki/views.py | 82 +++++----- 10 files changed, 553 insertions(+), 588 deletions(-) delete mode 100644 data/pkgmaint_guide.txt create mode 100644 lib/utils.py create mode 100644 templates/devel/pkgmaint_guide.txt delete mode 100644 utils.py diff --git a/data/pkgmaint_guide.txt b/data/pkgmaint_guide.txt deleted file mode 100644 index 85106ea..0000000 --- a/data/pkgmaint_guide.txt +++ /dev/null @@ -1,164 +0,0 @@ -============================================================================= - THE QUICK AND DIRTY ON HOW TO BE A PACKAGE MAINTAINER -============================================================================= - questions to jvinet@zeroflux.org - -1. Follow Package Guidelines - - Package guidelines can be found in the Arch Linux documentation. - Please follow them closely. - -2. How To Use CVS - - The example commands below assume the module 'extra'. - - 2.1 Make sure your CVSROOT environment variable is set properly. If the - CVS repository is on the same box: - # export CVSROOT=/home/cvs-extra - - If you want to access the repository from the different box via SSH: - # export CVS_RSH=ssh - # export CVSROOT=:ext:user@cvs.archlinux.org:/home/cvs-extra - - 2.2 Checkout the repository. This will download the entire repository to - your local machine: - # cvs co extra - - 2.3 Updating the repository. This syncs your local repository with the - master. You should do this often, especially if other people could be - working on the same repository. - # cd extra - # cvs -q update -d - - 2.4 Adding files/directories to the repository. When you want to add a new - package you should create a directory under the respective category and - place the new PKGBUILD in it. For example, to add fvwm to the repo: - # cd extra/x11 - # mkdir fvwm - # cd fvwm - # cp /var/abs/PKGBUILD.proto ./PKGBUILD - - # cd .. - # cvs add fvwm - # cvs add fvwm/PKGBUILD - - 2.5 Committing changes. Files are not written to the master repository until - you commit. Never forget to commit! - # cd extra - # cvs commit - - This will find all modified files, then throw you into vi where you can - add a log message describing your changes. Save and exit from vi when - you're done and cvs will update the files in the master repository. - - 2.6 Removing files. If you need to remove a file (eg, an old patch that - isn't needed anymore), you can do the following: - # cd extra/x11/fvwm - # rm old.patch - # cvs remove old.patch - # cvs commit -m "removed old.patch" old.patch - also remove the CURRENT/STABLE tags from the file so it does not appear - in ABS any more: - # cvs tag -d CURRENT old.patch - - Don't forget to commit afterwards! Remember that no changes are made - to the master until you commit. - - 2.7 Removing directories cannot be done easily. If you really need to - remove a directory, email the sysadmin (Judd) and I'll help you out. - - 2.8 Tagging files. Every file in CVS has tags associated with it, which - allows us to select certain versions of scripts. The db generation - scripts will only look at files that are tagged as CURRENT, so you need - to tag all files after you commit them: - # cd extra/x11/fvwm - # cvs tag -c -F -R CURRENT - - NOTE: When tagging, you should be sure to ONLY tag the updated files, - not the entire repository. Otherwise, if parts of your checkout are - out-of-date, you may actually be tagging an OLDER version of a file, - reversing someone else's tag procedure. - -3. The Process - - 3.1 Checkout/update your local repository from cvs.archlinux.org - 3.2 Make any changes you need to - 3.3 Put your new packages in your local staging directory on archlinux.org. - Suggested syntax is: - scp name-ver-rel.pkg.tar.gz you@archlinux.org:staging/extra/add - 3.4 Commit your changes (section 2.5) - 3.5 Update the CURRENT tags to new revisions (section 2.8) - 3.6 Log in to archlinux.org and run the /arch/db-extra script, which - will re-generate the sync db and place it in /home/ftp/extra, then - move the new/updated packages from your staging directory to the - FTP tree. - 3.7 Remove any older versions of packages from /home/ftp/extra to - save diskspace, they should be noted when the db generation script - finishes. - - Make sure you do things in this order, mixing them up can break things - temporarily. For example, if you remove older versions from the ftp - tree before you update the database or update the database before - uploading new packages, arch users trying to download the package at - that time will get "file not found" errors. - -4. Staging Directories - - As mentioned in Section 3, packages need to be uploaded to the proper - staging directory before running a db generation script. The staging - area (located in your home dir) looks like so: - - staging - |-- arch - | |-- add - | `-- del - |-- extra - | |-- add - | `-- del - |-- testing - | |-- add - | `-- del - `-- unstable - |-- add - `-- del - - As you can see, each repository has two staging directories: "add" and - "del". When you want to add or update a package, you'll place it in the - "add" directory for the repository you're working in. Then run the db-gen - script. - - When you want to remove a package, you will move the package OUT OF the FTP - directory (eg, /home/ftp/extra/os/i686/) and INTO the "del" directory for - the repository you're working in. Once moved, you can run the db-gen - script -- it will see that the file has left the FTP tree and will remove - it from the package database. - -5. Miscellaneous Stuff - - 5.1 If you are creating a daemon you need to include an rc.d startup - script for it. Look at /var/abs/daemons/esd for a simple example. - 5.2 Please include a line that says '# $Id: pkgmaint_guide.txt,v 1.3 2006/10/05 20:52:01 judd Exp $' at the top of each - PKGBUILD. This will be parsed by cvs during a commit, and replaced - with user/timestamp data. - 5.3 Please do some rudimentary checks of the package before making it - 'live'. Try installing it and see if there are any file conflicts. - Check for dependencies by running 'ldd' against the binaries and - looking through the .so files it requires. For example, - 'ldd /usr/bin/gvim' returns a big list of libs, one of which is - libgtk-x11-2.0.so.0, so gtk2 should be one of the dependencies for - gvim. Also, namcap is available in the extra repository. Running it - against a package will print dependancy warnings as well as possible - configuration problems. Namcap is not the final word, if ldd or - runtime show otherwise, believe them instead. - 5.4 When creating a package description for a package, do not include - the package name in a self-referencing way, as it is redundant. - For example, "Nedit is a text editor for X11" could be simplified to - "A text editor for X11". Also try to keep the descriptions to ~80 - characters or less. - 5.5 When entering cvs log messages for new/upgraded packages, please use - these tags so they can be easily parsed for changelog generation: - if the package is upgrade use: 'upgpkg: pkgname newpkgver' - if the package is new use: 'newpkg: pkgname newpkgver' - - -$Id: pkgmaint_guide.txt,v 1.3 2006/10/05 20:52:01 judd Exp $ diff --git a/devel/views.py b/devel/views.py index d31dd10..206d1fa 100644 --- a/devel/views.py +++ b/devel/views.py @@ -2,7 +2,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.core import validators -from archweb_dev.utils import render_template +from archweb_dev.utils import render_response from archweb_dev.packages.models import Package from archweb_dev.todolists.models import Todolist, TodolistPkg from archweb_dev.settings import DATA_DIR @@ -11,57 +11,58 @@ from archweb_dev.public.models import UserProfile @login_required def index(request): - try: - thismaint = User.objects.get(username=request.user.username) - except User.DoesNotExist: - # weird, we don't have a maintainer record for this logged-in user - thismaint = None + try: + thismaint = User.objects.get(username=request.user.username) + except User.DoesNotExist: + # weird, we don't have a maintainer record for this logged-in user + thismaint = None - # get a list of incomplete package todo lists - todos = Todolist.objects.get_incomplete() - # get flagged-package stats for all maintainers - stats = Package.objects.get_flag_stats() - if thismaint: - # get list of flagged packages for this maintainer - pkgs = Package.objects.filter(maintainer=thismaint.id).filter(needupdate=True).order_by('repo', 'pkgname') - else: - pkgs = None + # get a list of incomplete package todo lists + todos = Todolist.objects.get_incomplete() + # get flagged-package stats for all maintainers + stats = Package.objects.get_flag_stats() + if thismaint: + # get list of flagged packages for this maintainer + pkgs = Package.objects.filter(maintainer=thismaint.id).filter(needupdate=True).order_by('repo', 'pkgname') + else: + pkgs = None - return render_template('devel/index.html', request, - {'stats':stats, 'pkgs':pkgs, 'todos':todos, 'maint':thismaint}) + return render_response(request, 'devel/index.html', + {'stats':stats, 'pkgs':pkgs, 'todos':todos, 'maint':thismaint}) @login_required #@is_maintainer def change_notify(request): - maint = User.objects.get(username=request.user.username) - notify = request.POST.get('notify', 'no') - try: - maint.get_profile().notify = notify == 'yes' - except UserProfile.DoesNotExist: - UserProfile(user_id=maint.id ,notify=notify == 'yes').save() - maint.get_profile().save() - return HttpResponseRedirect('/devel/') + maint = User.objects.get(username=request.user.username) + notify = request.POST.get('notify', 'no') + try: + maint.get_profile().notify = notify == 'yes' + except UserProfile.DoesNotExist: + UserProfile(user_id=maint.id ,notify=notify == 'yes').save() + maint.get_profile().save() + return HttpResponseRedirect('/devel/') @login_required def change_profile(request): - errors = {} - if request.POST: - passwd1, passwd2 = request.POST['passwd'], request.POST['passwd2'] - email = request.POST['email'] - # validate - if passwd1 != passwd2: - errors['password'] = [' Passwords do not match. '] - validate(errors, 'Email', email, validators.isValidEmail, False, request) - # apply changes - if not errors: - request.user.email = email - if passwd1: - request.user.set_password(passwd1) - request.user.save() - return HttpResponseRedirect('/devel/') - return render_template('devel/profile.html', request, {'errors':errors,'email':request.user.email}) + errors = {} + if request.POST: + passwd1, passwd2 = request.POST['passwd'], request.POST['passwd2'] + email = request.POST['email'] + # validate + if passwd1 != passwd2: + errors['password'] = [' Passwords do not match. '] + validate(errors, 'Email', email, validators.isValidEmail, False, request) + # apply changes + if not errors: + request.user.email = email + if passwd1: + request.user.set_password(passwd1) + request.user.save() + return HttpResponseRedirect('/devel/') + return render_response(request, 'devel/profile.html', {'errors':errors,'email':request.user.email}) @login_required def guide(request): - return HttpResponse(file(DATA_DIR + '/pkgmaint_guide.txt').read(), - mimetype='text/plain') + return render_response(request, 'devel/pkgmaint_guide.txt', {'errors':errors,'email':request.user.email}) + return HttpResponse(file(DATA_DIR + '/pkgmaint_guide.txt').read(), + mimetype='text/plain') diff --git a/lib/utils.py b/lib/utils.py new file mode 100644 index 0000000..59df963 --- /dev/null +++ b/lib/utils.py @@ -0,0 +1,34 @@ +from django.core import validators +from django.conf import settings +from django.core.cache import cache +from django.shortcuts import render_to_response +from django.template import RequestContext + +def validate(errdict, fieldname, fieldval, validator, blankallowed, request): + """ + A helper function that allows easy access to Django's validators without + going through a Manipulator object. Will return a dict of all triggered + errors. + """ + if blankallowed and not fieldval: + return + alldata = ' '.join(request.POST.values()) + ' '.join(request.GET.values()) + try: + validator(fieldval, alldata) + except validators.ValidationError, e: + if not errdict.has_key(fieldname): + errdict[fieldname] = [] + errdict[fieldname].append(e) + +def prune_cache(django_page_url): + if not settings.CACHE: + return + cache_prefix = 'views.decorators.cache.cache_page.' + cache_prefix += settings.CACHE_MIDDLEWARE_KEY_PREFIX + '.' + cache_postfix = '.d41d8cd98f00b204e9800998ecf8427e' + cache.delete('%s%s%s' % (cache_prefix,django_page_url,cache_postfix)) + +def render_response(req, *args, **kwargs): + kwargs['context_instance'] = RequestContext(req) + return render_to_response(*args, **kwargs) + diff --git a/news/views.py b/news/views.py index 5ceb331..4e4b4f0 100644 --- a/news/views.py +++ b/news/views.py @@ -3,80 +3,80 @@ from django.shortcuts import get_object_or_404 from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.models import User from django import forms -from archweb_dev.utils import render_template +from archweb_dev.lib.utils import render_response from archweb_dev.news.models import News from datetime import date def view(request, newsid): - news = get_object_or_404(News, id=newsid) - return render_template('news/view.html', request, {'news':news}) + news = get_object_or_404(News, id=newsid) + return render_response(request, 'news/view.html', {'news':news}) def list(request): - news = News.objects.order_by('-postdate', '-id') - return render_template('news/list.html', request, {'news':news}) + news = News.objects.order_by('-postdate', '-id') + return render_response(request, 'news/list.html', {'news':news}) @user_passes_test(lambda u: u.has_perm('news.add_news')) def add(request): - try: - m = User.objects.get(username=request.user.username) - except User.DoesNotExist: - return render_template('error_page.html', request, - {'errmsg': 'Cannot find a maintainer record for you! No posting allowed.'}) + try: + m = User.objects.get(username=request.user.username) + except User.DoesNotExist: + return render_response(request, 'error_page.html', + {'errmsg': 'Cannot find a maintainer record for you! No posting allowed.'}) - manipulator = News.AddManipulator() - if request.POST: - data = request.POST.copy() - # add in the author ID - data['author'] = m.id - errors = manipulator.get_validation_errors(data) - if not errors: - manipulator.do_html2python(data) - manipulator.save(data) - return HttpResponseRedirect('/news/') - else: - errors = {} - data = {} + manipulator = News.AddManipulator() + if request.POST: + data = request.POST.copy() + # add in the author ID + data['author'] = m.id + errors = manipulator.get_validation_errors(data) + if not errors: + manipulator.do_html2python(data) + manipulator.save(data) + return HttpResponseRedirect('/news/') + else: + errors = {} + data = {} - form = forms.FormWrapper(manipulator, data, errors) - return render_template('news/add.html', request, {'form': form}) + form = forms.FormWrapper(manipulator, data, errors) + return render_response(request, 'news/add.html', {'form': form}) @user_passes_test(lambda u: u.has_perm('news.delete_news')) def delete(request, newsid): - news = get_object_or_404(News, id=newsid) - #if news.author.id != request.user.id: - # return render_template('error_page.html', request, {'errmsg': 'You do not own this news item'}) - if request.POST: - news.delete() - return HttpResponseRedirect('/news/') - return render_template('news/delete.html', request) + news = get_object_or_404(News, id=newsid) + #if news.author.id != request.user.id: + # return render_response(request, 'error_page.html', {'errmsg': 'You do not own this news item'}) + if request.POST: + news.delete() + return HttpResponseRedirect('/news/') + return render_response(request, 'news/delete.html') @user_passes_test(lambda u: u.has_perm('news.change_news')) def edit(request, newsid): - try: - m = User.objects.get(username=request.user.username) - except User.DoesNotExist: - return render_template('error_page.html', request, - {'errmsg': 'Cannot find a maintainer record for you! No posting allowed.'}) - try: - manipulator = News.ChangeManipulator(newsid) - except News.DoesNotExist: - raise Http404 + try: + m = User.objects.get(username=request.user.username) + except User.DoesNotExist: + return render_response(request, 'error_page.html', + {'errmsg': 'Cannot find a maintainer record for you! No posting allowed.'}) + try: + manipulator = News.ChangeManipulator(newsid) + except News.DoesNotExist: + raise Http404 - news = manipulator.original_object -# if news.author != m: -# return render_template('error_page.html', request, {'errmsg': 'You do not own this news item'}) - if request.POST: - data = request.POST.copy() - # add in the author ID - data['author'] = news.author.id - errors = manipulator.get_validation_errors(data) - if not errors: - manipulator.do_html2python(data) - manipulator.save(data) - return HttpResponseRedirect('/news/') - else: - errors = {} - data = news.__dict__ + news = manipulator.original_object +# if news.author != m: +# return render_response(request, 'error_page.html', {'errmsg': 'You do not own this news item'}) + if request.POST: + data = request.POST.copy() + # add in the author ID + data['author'] = news.author.id + errors = manipulator.get_validation_errors(data) + if not errors: + manipulator.do_html2python(data) + manipulator.save(data) + return HttpResponseRedirect('/news/') + else: + errors = {} + data = news.__dict__ - form = forms.FormWrapper(manipulator, data, errors) - return render_template('news/add.html', request, {'form': form, 'news':news}) + form = forms.FormWrapper(manipulator, data, errors) + return render_response(request, 'news/add.html', {'form': form, 'news':news}) diff --git a/packages/views.py b/packages/views.py index 7b1ae1f..aaf4dee 100644 --- a/packages/views.py +++ b/packages/views.py @@ -5,168 +5,168 @@ from django.template import Context, loader from django.core import validators from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User -from archweb_dev.utils import validate, render_template +from archweb_dev.lib.utils import validate, render_response from datetime import datetime from archweb_dev.packages.models import Package, PackageFile, Repo, Category def update(request): - if request.POST.has_key('adopt'): - mode = 'adopt' - message = 'Adoption was successful' - if request.POST.has_key('disown'): - mode = 'disown' - message = 'Disown was successful' - try: - maint = User.objects.get(username=request.user.username) - except User.DoesNotExist: - return render_template('error_page.html', request, {'errmsg':'No maintainer record found! Are you a maintainer?'}) - ids = request.POST.getlist('pkgid') - for id in ids: - pkg = Package.objects.get(id=id) - if mode == 'adopt' and pkg.maintainer_id == 0: - pkg.maintainer = maint - elif mode == 'disown' and pkg.maintainer == maint: - pkg.maintainer_id = 0 - else: - message = "You are not the current maintainer" - pkg.save() - return render_template('status_page.html', request, {'message':message}) + if request.POST.has_key('adopt'): + mode = 'adopt' + message = 'Adoption was successful' + if request.POST.has_key('disown'): + mode = 'disown' + message = 'Disown was successful' + try: + maint = User.objects.get(username=request.user.username) + except User.DoesNotExist: + return render_response(request, 'error_page.html', {'errmsg':'No maintainer record found! Are you a maintainer?'}) + ids = request.POST.getlist('pkgid') + for id in ids: + pkg = Package.objects.get(id=id) + if mode == 'adopt' and pkg.maintainer_id == 0: + pkg.maintainer = maint + elif mode == 'disown' and pkg.maintainer == maint: + pkg.maintainer_id = 0 + else: + message = "You are not the current maintainer" + pkg.save() + return render_response(request, 'status_page.html', {'message':message}) def details(request, pkgid=0, name='', repo=''): - if pkgid == 0: - p = Package.objects.filter(pkgname=name) - if repo: p = p.filter(repo__name__exact=repo) - # if more then one result, send to the search view - if len(p) > 1: return search(request, name) - if len(p) < 1: return render_template('error_page.html', request, - {'errmsg': 'No matching packages.'}) - pkgid = p[0].id - - pkg = get_object_or_404(Package, id=pkgid) - return render_template('packages/details.html', request, {'pkg':pkg}) + if pkgid == 0: + p = Package.objects.filter(pkgname=name) + if repo: p = p.filter(repo__name__exact=repo) + # if more then one result, send to the search view + if len(p) > 1: return search(request, name) + if len(p) < 1: return render_response(request, 'error_page.html', + {'errmsg': 'No matching packages.'}) + pkgid = p[0].id + + pkg = get_object_or_404(Package, id=pkgid) + return render_response(request, 'packages/details.html', {'pkg':pkg}) def search(request, query=''): - if request.GET.has_key('q'): - # take the q GET var over the one passed on the URL - query = request.GET['q'].strip() - - # fetch the form vars - repo = request.GET.get('repo', 'all') - category = request.GET.get('category', 'all') - lastupdate = request.GET.get('lastupdate', '') - limit = int(request.GET.get('limit', '50')) - skip = int(request.GET.get('skip', '0')) - sort = request.GET.get('sort', '') - maint = request.GET.get('maint', 'all') - - # build the form lists - repos = Repo.objects.order_by('name') - cats = Category.objects.order_by('category') - # copy GET data over and add the lists - c = request.GET.copy() - c['repos'], c['categories'] = repos, cats - c['limit'], c['skip'] = limit, skip - c['lastupdate'] = lastupdate - c['sort'] = sort - # 'q' gets renamed to 'query', so it's not in GET - c['query'] = query - - # validate - errors = {} - validate(errors, 'Last Update', lastupdate, validators.isValidANSIDate, True, request) - validate(errors, 'Page Limit', str(limit), validators.isOnlyDigits, True, request) - validate(errors, 'Page Skip', str(skip), validators.isOnlyDigits, True, request) - if errors: - c['errors'] = errors - return render_template('packages/search.html', request, c) - - if query: - res1 = Package.objects.filter(pkgname__icontains=query) - res2 = Package.objects.filter(pkgdesc__icontains=query) - results = res1 | res2 - else: - results = Package.objects.all() - if repo != 'all': results = results.filter(repo__name__exact=repo) - if category != 'all': results = results.filter(category__category__exact=category) - if maint != 'all': results = results.filter(maintainer=maint) - if lastupdate: results = results.filter(last_update__gte=datetime(int(lastupdate[0:4]),int(lastupdate[5:7]),int(lastupdate[8:10]))) - # select_related() shouldn't be needed -- we're working around a Django bug - #results = results.select_related().order_by('repos.name', 'category', 'pkgname') - - # sort results - if sort == '': - results = results.order_by('repo', 'category', 'pkgname') - else: - # duplicate sort fields shouldn't hurt anything - results = results.order_by(sort, 'repo', 'category', 'pkgname') - - qs = request.GET.copy() - # build pagination urls - if results.count() > (skip + limit): - qs['skip'] = skip + limit - c['nextpage'] = '?' + qs.urlencode() - if skip > 0: - qs['skip'] = max(0, skip - limit) - c['prevpage'] = '?' + qs.urlencode() - # pass the querystring to the template so we can build sort queries - c['querystring'] = request.GET - - # if only there's only one result, pass right to the package details view - if results.count() == 1: return details(request, results[0].id) - # limit result set - if limit > 0: results = results[skip:(skip+limit)] - - c['results'] = results - return render_template('packages/search.html', request, c) + if request.GET.has_key('q'): + # take the q GET var over the one passed on the URL + query = request.GET['q'].strip() + + # fetch the form vars + repo = request.GET.get('repo', 'all') + category = request.GET.get('category', 'all') + lastupdate = request.GET.get('lastupdate', '') + limit = int(request.GET.get('limit', '50')) + skip = int(request.GET.get('skip', '0')) + sort = request.GET.get('sort', '') + maint = request.GET.get('maint', 'all') + + # build the form lists + repos = Repo.objects.order_by('name') + cats = Category.objects.order_by('category') + # copy GET data over and add the lists + c = request.GET.copy() + c['repos'], c['categories'] = repos, cats + c['limit'], c['skip'] = limit, skip + c['lastupdate'] = lastupdate + c['sort'] = sort + # 'q' gets renamed to 'query', so it's not in GET + c['query'] = query + + # validate + errors = {} + validate(errors, 'Last Update', lastupdate, validators.isValidANSIDate, True, request) + validate(errors, 'Page Limit', str(limit), validators.isOnlyDigits, True, request) + validate(errors, 'Page Skip', str(skip), validators.isOnlyDigits, True, request) + if errors: + c['errors'] = errors + return render_response(request, 'packages/search.html', c) + + if query: + res1 = Package.objects.filter(pkgname__icontains=query) + res2 = Package.objects.filter(pkgdesc__icontains=query) + results = res1 | res2 + else: + results = Package.objects.all() + if repo != 'all': results = results.filter(repo__name__exact=repo) + if category != 'all': results = results.filter(category__category__exact=category) + if maint != 'all': results = results.filter(maintainer=maint) + if lastupdate: results = results.filter(last_update__gte=datetime(int(lastupdate[0:4]),int(lastupdate[5:7]),int(lastupdate[8:10]))) + # select_related() shouldn't be needed -- we're working around a Django bug + #results = results.select_related().order_by('repos.name', 'category', 'pkgname') + + # sort results + if sort == '': + results = results.order_by('repo', 'category', 'pkgname') + else: + # duplicate sort fields shouldn't hurt anything + results = results.order_by(sort, 'repo', 'category', 'pkgname') + + qs = request.GET.copy() + # build pagination urls + if results.count() > (skip + limit): + qs['skip'] = skip + limit + c['nextpage'] = '?' + qs.urlencode() + if skip > 0: + qs['skip'] = max(0, skip - limit) + c['prevpage'] = '?' + qs.urlencode() + # pass the querystring to the template so we can build sort queries + c['querystring'] = request.GET + + # if only there's only one result, pass right to the package details view + if results.count() == 1: return details(request, results[0].id) + # limit result set + if limit > 0: results = results[skip:(skip+limit)] + + c['results'] = results + return render_response(request, 'packages/search.html', c) def files(request, pkgid): - pkg = get_object_or_404(Package, id=pkgid) - files = PackageFile.objects.filter(pkg=pkgid) - return render_template('packages/files.html', request, {'pkg':pkg,'files':files}) + pkg = get_object_or_404(Package, id=pkgid) + files = PackageFile.objects.filter(pkg=pkgid) + return render_response(request, 'packages/files.html', {'pkg':pkg,'files':files}) def flaghelp(request): - return render_template('packages/flaghelp.html', request) + return render_response(request, 'packages/flaghelp.html') def flag(request, pkgid): - pkg = get_object_or_404(Package, id=pkgid) - context = {'pkg': pkg} - if request.POST.has_key('confirmemail'): - email = request.POST['confirmemail'] - if request.POST.has_key('usermessage'): - message = request.POST['usermessage'] - else: - message = None - # validate - errors = {} - validate(errors, 'Email Address', email, validators.isValidEmail, False, request) - if errors: - context['errors'] = errors - return render_template('packages/flag.html', request, context) - - context['confirmemail'] = email - pkg.needupdate = 1 - pkg.save() - if pkg.maintainer_id > 0: - # send notification email to the maintainer - t = loader.get_template('packages/outofdate.txt') - c = Context({ - 'email': request.POST['confirmemail'], - 'message': message, - 'pkgname': pkg.pkgname, - 'weburl': 'http://www.archlinux.org/packages/' + str(pkg.id) + '/' - }) - send_mail('arch: Package [%s] marked out-of-date' % pkg.pkgname, - t.render(c), - 'Arch Website Notification ', - [pkg.maintainer.email], - fail_silently=True) - return render_template('packages/flag.html', request, context) + pkg = get_object_or_404(Package, id=pkgid) + context = {'pkg': pkg} + if request.POST.has_key('confirmemail'): + email = request.POST['confirmemail'] + if request.POST.has_key('usermessage'): + message = request.POST['usermessage'] + else: + message = None + # validate + errors = {} + validate(errors, 'Email Address', email, validators.isValidEmail, False, request) + if errors: + context['errors'] = errors + return render_response(request, 'packages/flag.html', context) + + context['confirmemail'] = email + pkg.needupdate = 1 + pkg.save() + if pkg.maintainer_id > 0: + # send notification email to the maintainer + t = loader.get_template('packages/outofdate.txt') + c = Context({ + 'email': request.POST['confirmemail'], + 'message': message, + 'pkgname': pkg.pkgname, + 'weburl': 'http://www.archlinux.org/packages/' + str(pkg.id) + '/' + }) + send_mail('arch: Package [%s] marked out-of-date' % pkg.pkgname, + t.render(c), + 'Arch Website Notification ', + [pkg.maintainer.email], + fail_silently=True) + return render_response(request, 'packages/flag.html', context) @login_required def unflag(request, pkgid): - pkg = get_object_or_404(Package, id=pkgid) - if pkg.maintainer.username != request.user.username: - return render_template('error_page.html', request, {'errmsg': 'You do not own this package.'}) - pkg.needupdate = 0 - pkg.save() - return HttpResponseRedirect('/packages/%d/' % (pkg.id)) + pkg = get_object_or_404(Package, id=pkgid) + if pkg.maintainer.username != request.user.username: + return render_response(request, 'error_page.html', {'errmsg': 'You do not own this package.'}) + pkg.needupdate = 0 + pkg.save() + return HttpResponseRedirect('/packages/%d/' % (pkg.id)) diff --git a/public/views.py b/public/views.py index 6c69831..2cda74b 100644 --- a/public/views.py +++ b/public/views.py @@ -1,5 +1,5 @@ from django.http import HttpResponse -from archweb_dev.utils import render_template +from archweb_dev.lib.utils import render_response from django.contrib.auth.models import User from archweb_dev.packages.models import Package, Repo from archweb_dev.news.models import News @@ -7,53 +7,53 @@ from archweb_dev.settings import DATA_DIR from archweb_dev.public.models import Donator, Mirror def index(request): - # get the most recent 10 news items - news = News.objects.order_by('-postdate', '-id')[:10] - pkgs = Package.objects.exclude(repo__name__exact='Testing').order_by('-last_update')[:15] - repos = Repo.objects.order_by('name') - return render_template('public/index.html', request, {'news_updates':news,'pkg_updates':pkgs,'repos':repos}) + # get the most recent 10 news items + news = News.objects.order_by('-postdate', '-id')[:10] + pkgs = Package.objects.exclude(repo__name__exact='Testing').order_by('-last_update')[:15] + repos = Repo.objects.order_by('name') + return render_response(request, 'public/index.html', {'news_updates':news,'pkg_updates':pkgs,'repos':repos}) def about(request): - return render_template('public/about.html', request) + return render_response(request, 'public/about.html') def art(request): - return render_template('public/art.html', request) + return render_response(request, 'public/art.html') def cvs(request): - return render_template('public/cvs.html', request) + return render_response(request, 'public/cvs.html') def developers(request): - devs = User.objects.order_by('username') - return render_template('public/developers.html', request, {'devs':devs}) + devs = User.objects.order_by('username') + return render_response(request, 'public/developers.html', {'devs':devs}) def donate(request): - donor_count = Donator.objects.count() - splitval = donor_count / 4 - slice1 = Donator.objects.all()[:splitval] - slice2 = Donator.objects.all()[(splitval):(splitval*2)] - slice3 = Donator.objects.all()[(splitval*2):(donor_count-splitval)] - slice4 = Donator.objects.all()[(donor_count-splitval):donor_count] - return render_template('public/donate.html', request, - {'slice1':slice1,'slice2':slice2,'slice3':slice3,'slice4':slice4}) + donor_count = Donator.objects.count() + splitval = donor_count / 4 + slice1 = Donator.objects.all()[:splitval] + slice2 = Donator.objects.all()[(splitval):(splitval*2)] + slice3 = Donator.objects.all()[(splitval*2):(donor_count-splitval)] + slice4 = Donator.objects.all()[(donor_count-splitval):donor_count] + return render_response(request, 'public/donate.html', + {'slice1':slice1,'slice2':slice2,'slice3':slice3,'slice4':slice4}) def download(request): - mirrors = Mirror.objects.order_by('country', 'domain') - return render_template('public/download.html', request, {'mirrors':mirrors}) + mirrors = Mirror.objects.order_by('country', 'domain') + return render_response(request, 'public/download.html', {'mirrors':mirrors}) def irc(request): - return render_template('public/irc.html', request) + return render_response(request, 'public/irc.html') def moreforums(request): - return render_template('public/moreforums.html', request) + return render_response(request, 'public/moreforums.html') def press(request): - return render_template('public/press.html', request) + return render_response(request, 'public/press.html') def projects(request): - return render_template('public/projects.html', request) + return render_response(request, 'public/projects.html') def robots(request): return HttpResponse("User-agent: *\nDisallow: /\n", mimetype="text/plain") def denied(request): - return render_template('public/denied.html', request) + return render_response(request, 'public/denied.html') diff --git a/templates/devel/pkgmaint_guide.txt b/templates/devel/pkgmaint_guide.txt new file mode 100644 index 0000000..85106ea --- /dev/null +++ b/templates/devel/pkgmaint_guide.txt @@ -0,0 +1,164 @@ +============================================================================= + THE QUICK AND DIRTY ON HOW TO BE A PACKAGE MAINTAINER +============================================================================= + questions to jvinet@zeroflux.org + +1. Follow Package Guidelines + + Package guidelines can be found in the Arch Linux documentation. + Please follow them closely. + +2. How To Use CVS + + The example commands below assume the module 'extra'. + + 2.1 Make sure your CVSROOT environment variable is set properly. If the + CVS repository is on the same box: + # export CVSROOT=/home/cvs-extra + + If you want to access the repository from the different box via SSH: + # export CVS_RSH=ssh + # export CVSROOT=:ext:user@cvs.archlinux.org:/home/cvs-extra + + 2.2 Checkout the repository. This will download the entire repository to + your local machine: + # cvs co extra + + 2.3 Updating the repository. This syncs your local repository with the + master. You should do this often, especially if other people could be + working on the same repository. + # cd extra + # cvs -q update -d + + 2.4 Adding files/directories to the repository. When you want to add a new + package you should create a directory under the respective category and + place the new PKGBUILD in it. For example, to add fvwm to the repo: + # cd extra/x11 + # mkdir fvwm + # cd fvwm + # cp /var/abs/PKGBUILD.proto ./PKGBUILD + + # cd .. + # cvs add fvwm + # cvs add fvwm/PKGBUILD + + 2.5 Committing changes. Files are not written to the master repository until + you commit. Never forget to commit! + # cd extra + # cvs commit + + This will find all modified files, then throw you into vi where you can + add a log message describing your changes. Save and exit from vi when + you're done and cvs will update the files in the master repository. + + 2.6 Removing files. If you need to remove a file (eg, an old patch that + isn't needed anymore), you can do the following: + # cd extra/x11/fvwm + # rm old.patch + # cvs remove old.patch + # cvs commit -m "removed old.patch" old.patch + also remove the CURRENT/STABLE tags from the file so it does not appear + in ABS any more: + # cvs tag -d CURRENT old.patch + + Don't forget to commit afterwards! Remember that no changes are made + to the master until you commit. + + 2.7 Removing directories cannot be done easily. If you really need to + remove a directory, email the sysadmin (Judd) and I'll help you out. + + 2.8 Tagging files. Every file in CVS has tags associated with it, which + allows us to select certain versions of scripts. The db generation + scripts will only look at files that are tagged as CURRENT, so you need + to tag all files after you commit them: + # cd extra/x11/fvwm + # cvs tag -c -F -R CURRENT + + NOTE: When tagging, you should be sure to ONLY tag the updated files, + not the entire repository. Otherwise, if parts of your checkout are + out-of-date, you may actually be tagging an OLDER version of a file, + reversing someone else's tag procedure. + +3. The Process + + 3.1 Checkout/update your local repository from cvs.archlinux.org + 3.2 Make any changes you need to + 3.3 Put your new packages in your local staging directory on archlinux.org. + Suggested syntax is: + scp name-ver-rel.pkg.tar.gz you@archlinux.org:staging/extra/add + 3.4 Commit your changes (section 2.5) + 3.5 Update the CURRENT tags to new revisions (section 2.8) + 3.6 Log in to archlinux.org and run the /arch/db-extra script, which + will re-generate the sync db and place it in /home/ftp/extra, then + move the new/updated packages from your staging directory to the + FTP tree. + 3.7 Remove any older versions of packages from /home/ftp/extra to + save diskspace, they should be noted when the db generation script + finishes. + + Make sure you do things in this order, mixing them up can break things + temporarily. For example, if you remove older versions from the ftp + tree before you update the database or update the database before + uploading new packages, arch users trying to download the package at + that time will get "file not found" errors. + +4. Staging Directories + + As mentioned in Section 3, packages need to be uploaded to the proper + staging directory before running a db generation script. The staging + area (located in your home dir) looks like so: + + staging + |-- arch + | |-- add + | `-- del + |-- extra + | |-- add + | `-- del + |-- testing + | |-- add + | `-- del + `-- unstable + |-- add + `-- del + + As you can see, each repository has two staging directories: "add" and + "del". When you want to add or update a package, you'll place it in the + "add" directory for the repository you're working in. Then run the db-gen + script. + + When you want to remove a package, you will move the package OUT OF the FTP + directory (eg, /home/ftp/extra/os/i686/) and INTO the "del" directory for + the repository you're working in. Once moved, you can run the db-gen + script -- it will see that the file has left the FTP tree and will remove + it from the package database. + +5. Miscellaneous Stuff + + 5.1 If you are creating a daemon you need to include an rc.d startup + script for it. Look at /var/abs/daemons/esd for a simple example. + 5.2 Please include a line that says '# $Id: pkgmaint_guide.txt,v 1.3 2006/10/05 20:52:01 judd Exp $' at the top of each + PKGBUILD. This will be parsed by cvs during a commit, and replaced + with user/timestamp data. + 5.3 Please do some rudimentary checks of the package before making it + 'live'. Try installing it and see if there are any file conflicts. + Check for dependencies by running 'ldd' against the binaries and + looking through the .so files it requires. For example, + 'ldd /usr/bin/gvim' returns a big list of libs, one of which is + libgtk-x11-2.0.so.0, so gtk2 should be one of the dependencies for + gvim. Also, namcap is available in the extra repository. Running it + against a package will print dependancy warnings as well as possible + configuration problems. Namcap is not the final word, if ldd or + runtime show otherwise, believe them instead. + 5.4 When creating a package description for a package, do not include + the package name in a self-referencing way, as it is redundant. + For example, "Nedit is a text editor for X11" could be simplified to + "A text editor for X11". Also try to keep the descriptions to ~80 + characters or less. + 5.5 When entering cvs log messages for new/upgraded packages, please use + these tags so they can be easily parsed for changelog generation: + if the package is upgrade use: 'upgpkg: pkgname newpkgver' + if the package is new use: 'newpkg: pkgname newpkgver' + + +$Id: pkgmaint_guide.txt,v 1.3 2006/10/05 20:52:01 judd Exp $ diff --git a/todolists/views.py b/todolists/views.py index 757a35a..225da15 100644 --- a/todolists/views.py +++ b/todolists/views.py @@ -2,7 +2,7 @@ from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404 from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.models import User -from archweb_dev.utils import render_template +from archweb_dev.lib.utils import render_response from archweb_dev.todolists.models import Todolist, TodolistPkg from archweb_dev.packages.models import Package @@ -13,52 +13,51 @@ IntegrityError = django.db.backend.Database.IntegrityError @login_required #@is_maintainer def flag(request, listid, pkgid): - list = get_object_or_404(Todolist, id=listid) - pkg = get_object_or_404(TodolistPkg, id=pkgid) - pkg.complete = not pkg.complete - pkg.save() - return HttpResponseRedirect('/todo/%s/' % (listid)) + list = get_object_or_404(Todolist, id=listid) + pkg = get_object_or_404(TodolistPkg, id=pkgid) + pkg.complete = not pkg.complete + pkg.save() + return HttpResponseRedirect('/todo/%s/' % (listid)) @login_required def view(request, listid): - list = get_object_or_404(Todolist, id=listid) - pkgs = TodolistPkg.objects.filter(list=list.id).order_by('pkg') - return render_template('todolists/view.html', request, {'list':list,'pkgs':pkgs}) + list = get_object_or_404(Todolist, id=listid) + pkgs = TodolistPkg.objects.filter(list=list.id).order_by('pkg') + return render_response(request, 'todolists/view.html', {'list':list,'pkgs':pkgs}) @login_required def list(request): - lists = Todolist.objects.order_by('-date_added') - for l in lists: - l.complete = TodolistPkg.objects.filter(list=l.id,complete=False).count() == 0 - return render_template('todolists/list.html', request, {'lists':lists}) + lists = Todolist.objects.order_by('-date_added') + for l in lists: + l.complete = TodolistPkg.objects.filter(list=l.id,complete=False).count() == 0 + return render_response(request, 'todolists/list.html', {'lists':lists}) @login_required #@is_maintainer @user_passes_test(lambda u: u.has_perm('todolists.add_todolist')) def add(request): - if request.POST: - try: - m = User.objects.get(username=request.user.username) - except User.DoesNotExist: - return render_template('error_page.html', request, - {'errmsg': 'Cannot find a maintainer record for you!'}) - # create the list - todo = Todolist( - creator = m, - name = request.POST.get('name'), - description = request.POST.get('description')) - todo.save() - # now link in packages - for p in request.POST.get('packages').split("\n"): - for pkg in Package.objects.filter(pkgname=p.strip()): - todopkg = TodolistPkg( - list = todo, - pkg = pkg) - try: - todopkg.save() - except IntegrityError, (num, desc): - if num == 1062: # duplicate entry aka dupe package on list - pass - return HttpResponseRedirect('/todo/') - - return render_template('todolists/add.html', request) + if request.POST: + try: + m = User.objects.get(username=request.user.username) + except User.DoesNotExist: + return render_response(request, 'error_page.html', + {'errmsg': 'Cannot find a maintainer record for you!'}) + # create the list + todo = Todolist( + creator = m, + name = request.POST.get('name'), + description = request.POST.get('description')) + todo.save() + # now link in packages + for p in request.POST.get('packages').split("\n"): + for pkg in Package.objects.filter(pkgname=p.strip()): + todopkg = TodolistPkg( + list = todo, + pkg = pkg) + try: + todopkg.save() + except IntegrityError, (num, desc): + if num == 1062: # duplicate entry aka dupe package on list + pass + return HttpResponseRedirect('/todo/') + return render_response(request, 'todolists/add.html') diff --git a/utils.py b/utils.py deleted file mode 100644 index 1769471..0000000 --- a/utils.py +++ /dev/null @@ -1,69 +0,0 @@ -from django.core import validators -from django.template import RequestContext -from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect -from string import * -import sgmllib - -#from archweb_dev.packages.models import Maintainer -#from archweb_dev.settings import BADPRIVS_URL -#def is_maintainer(view_func, badprivs_url=BADPRIVS_URL): -# """ -# Decorator for views that checks that the logged-in user has a corresponding -# record in the Maintainers table. If not, the user is forwarded to a -# "bad-privileges" page. -# """ -# def _dec(view_func): -# def _checkuser(request, *args, **kwargs): -# try: -# m = Maintainer.objects.get(username=request.user.username) -# except Maintainer.DoesNotExist: -# return HttpResponseRedirect(badprivs_url) -# return view_func(request, *args, **kwargs) -# -# return _checkuser -# return _dec(view_func) - -def render_template(template, request, context=None): - """ - A shortcut to render_to_response with a RequestContext. Also includes - request.path in the context, so both 'path' and 'user' are accessible to - the template. - """ - if context: - context['path'] = request.path - return render_to_response(template, context_instance=RequestContext(request, context)) - else: - return render_to_response(template, context_instance=RequestContext(request)) - -def validate(errdict, fieldname, fieldval, validator, blankallowed, request): - """ - A helper function that allows easy access to Django's validators without - going through a Manipulator object. Will return a dict of all triggered - errors. - """ - if blankallowed and not fieldval: - return - alldata = ' '.join(request.POST.values()) + ' '.join(request.GET.values()) - try: - validator(fieldval, alldata) - except validators.ValidationError, e: - if not errdict.has_key(fieldname): errdict[fieldname] = [] - errdict[fieldname].append(e) - - -# XXX: unused right now, probably not needed -class Stripper(sgmllib.SGMLParser): - """Helper class to strip HTML tags""" - def __init__(self): - sgmllib.SGMLParser.__init__(self) - - def strip(self, some_html): - """Strips all HTML tags and leading/trailing whitespace""" - self.theString = "" - self.feed(some_html) - self.close() - return self.theString - - def handle_data(self, data): - self.theString += data diff --git a/wiki/views.py b/wiki/views.py index 4e4444a..9f7bd78 100644 --- a/wiki/views.py +++ b/wiki/views.py @@ -3,59 +3,59 @@ # from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth.decorators import login_required -from archweb_dev.utils import render_template +from archweb_dev.lib.utils import render_response from archweb_dev.wiki.models import Wikipage @login_required def index(request): - """Return a list of all wiki pages""" - pages = Wikipage.objects.all().order_by('title') - return render_template('wiki/home.html', request, {'pages':pages}) + """Return a list of all wiki pages""" + pages = Wikipage.objects.all().order_by('title') + return render_response(request, 'wiki/home.html', {'pages':pages}) def main(request): - """Return the Index wiki page""" - return HttpResponseRedirect("/wiki/WikiIndex/") + """Return the Index wiki page""" + return HttpResponseRedirect("/wiki/WikiIndex/") @login_required def page(request, title): - """Display page, or redirect to root if page doesn't exist yet""" - try: - page = Wikipage.objects.get(title__exact=title) - return render_template('wiki/page.html', request, {'page':page}) - except Wikipage.DoesNotExist: - return HttpResponseRedirect("/wiki/edit/%s/" % title) + """Display page, or redirect to root if page doesn't exist yet""" + try: + page = Wikipage.objects.get(title__exact=title) + return render_response(request, 'wiki/page.html', {'page':page}) + except Wikipage.DoesNotExist: + return HttpResponseRedirect("/wiki/edit/%s/" % title) @login_required def edit(request, title): - """Process submitted page edits (POST) or display editing form (GET)""" - if request.POST: - try: - page = Wikipage.objects.get(title__exact=title) - except Wikipage.DoesNotExist: - # Must be a new one; let's create it - page = Wikipage(title=title) - page.content = request.POST['content'] - page.title = request.POST['title'] - page.last_author = request.user - page.save() - return HttpResponseRedirect("/wiki/" + page.title + "/") - else: - try: - page = Wikipage.objects.get(title__exact=title) - except Wikipage.DoesNotExist: - # create a dummy page object -- note that it is not saved! - page = Wikipage(title=title) - page.body = "" - return render_template('wiki/edit.html', request, {'page':page}) + """Process submitted page edits (POST) or display editing form (GET)""" + if request.POST: + try: + page = Wikipage.objects.get(title__exact=title) + except Wikipage.DoesNotExist: + # Must be a new one; let's create it + page = Wikipage(title=title) + page.content = request.POST['content'] + page.title = request.POST['title'] + page.last_author = request.user + page.save() + return HttpResponseRedirect("/wiki/" + page.title + "/") + else: + try: + page = Wikipage.objects.get(title__exact=title) + except Wikipage.DoesNotExist: + # create a dummy page object -- note that it is not saved! + page = Wikipage(title=title) + page.body = "" + return render_response(request, 'wiki/edit.html', {'page':page}) @login_required def delete(request): - """Delete a page""" - if request.POST: - title = request.POST['title'] - try: - page = Wikipage.objects.get(title__exact=title) - except Wikipage.DoesNotExist: - return HttpResponseRedirect("/wiki/") - page.delete() - return HttpResponseRedirect("/wiki/") + """Delete a page""" + if request.POST: + title = request.POST['title'] + try: + page = Wikipage.objects.get(title__exact=title) + except Wikipage.DoesNotExist: + return HttpResponseRedirect("/wiki/") + page.delete() + return HttpResponseRedirect("/wiki/") -- cgit v1.2.3-24-g4f1b