diff options
Diffstat (limited to 'apps')
74 files changed, 0 insertions, 11119 deletions
diff --git a/apps/__init__.py b/apps/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/apps/__init__.py +++ /dev/null diff --git a/apps/manage.py b/apps/manage.py deleted file mode 100755 index 04eac77..0000000 --- a/apps/manage.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "patchwork.settings.prod") - - from django.core.management import execute_from_command_line - - execute_from_command_line(sys.argv) diff --git a/apps/patchwork/__init__.py b/apps/patchwork/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/apps/patchwork/__init__.py +++ /dev/null diff --git a/apps/patchwork/admin.py b/apps/patchwork/admin.py deleted file mode 100644 index 5297903..0000000 --- a/apps/patchwork/admin.py +++ /dev/null @@ -1,50 +0,0 @@ -from django.contrib import admin -from patchwork.models import Project, Person, UserProfile, State, Patch, \ - Comment, Bundle - -class ProjectAdmin(admin.ModelAdmin): - list_display = ('name', 'linkname','listid', 'listemail') -admin.site.register(Project, ProjectAdmin) - -class PersonAdmin(admin.ModelAdmin): - list_display = ('__unicode__', 'has_account') - search_fields = ('name', 'email') - def has_account(self, person): - return bool(person.user) - has_account.boolean = True - has_account.admin_order_field = 'user' - has_account.short_description = 'Account' -admin.site.register(Person, PersonAdmin) - -class UserProfileAdmin(admin.ModelAdmin): - search_fields = ('user__username', 'user__first_name', 'user__last_name') -admin.site.register(UserProfile, UserProfileAdmin) - -class StateAdmin(admin.ModelAdmin): - list_display = ('name', 'action_required') -admin.site.register(State, StateAdmin) - -class PatchAdmin(admin.ModelAdmin): - list_display = ('name', 'submitter', 'project', 'state', 'date', - 'archived', 'is_pull_request') - list_filter = ('project', 'state', 'archived') - search_fields = ('name', 'submitter__name', 'submitter__email') - date_hierarchy = 'date' - def is_pull_request(self, patch): - return bool(patch.pull_url) - is_pull_request.boolean = True - is_pull_request.admin_order_field = 'pull_url' - is_pull_request.short_description = 'Pull' -admin.site.register(Patch, PatchAdmin) - -class CommentAdmin(admin.ModelAdmin): - list_display = ('patch', 'submitter', 'date') - search_fields = ('patch__name', 'submitter__name', 'submitter__email') - date_hierarchy = 'date' -admin.site.register(Comment, CommentAdmin) - -class BundleAdmin(admin.ModelAdmin): - list_display = ('name', 'owner', 'project', 'public') - list_filter = ('public', 'project') - search_fields = ('name', 'owner') -admin.site.register(Bundle, BundleAdmin) diff --git a/apps/patchwork/bin/__init__.py b/apps/patchwork/bin/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/apps/patchwork/bin/__init__.py +++ /dev/null diff --git a/apps/patchwork/bin/bash_completion b/apps/patchwork/bin/bash_completion deleted file mode 100644 index a120a76..0000000 --- a/apps/patchwork/bin/bash_completion +++ /dev/null @@ -1,29 +0,0 @@ -# Autocompletion for bash. - -_pwclient() { - local cur prev words cword split - - if declare -f _init_completion >/dev/null; then - _init_completion -s || return - else - cur=$(_get_cword) - prev=${COMP_WORDS[COMP_CWORD-1]} - fi - - case "${COMP_CWORD}" in - 0|1) return 0;; - esac - - projects="$(sed -r -e '/\[options\]/d;' \ - -e '/^\[(.+)\]$/!d;' \ - -e 's//\1/;' ~/.pwclientrc 2>/dev/null)" - - case "${prev}" in - -p) COMPREPLY=( $(compgen -W "${projects}" -- "${cur}" ) );; - esac - - return 0 -} -complete -F _pwclient pwclient - -# vim: ft=sh diff --git a/apps/patchwork/bin/parsemail-batch.sh b/apps/patchwork/bin/parsemail-batch.sh deleted file mode 100755 index 31ef4f0..0000000 --- a/apps/patchwork/bin/parsemail-batch.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -PATCHWORK_BINDIR=`dirname $0` - -if [ $# -ne 1 ] -then - echo "usage: $0 <dir>" >&2 - exit 1 -fi - -mail_dir="$1" - -echo "dir: $mail_dir" - -if [ ! -d "$mail_dir" ] -then - echo "$mail_dir should be a directory"? >&2 - exit 1 -fi - -ls -1rt "$mail_dir" | -while read line; -do - echo $line - $PATCHWORK_BINDIR/parsemail.sh < "$mail_dir/$line" -done diff --git a/apps/patchwork/bin/parsemail.py b/apps/patchwork/bin/parsemail.py deleted file mode 100755 index 19e6e57..0000000 --- a/apps/patchwork/bin/parsemail.py +++ /dev/null @@ -1,455 +0,0 @@ -#!/usr/bin/env python -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import sys -import re -import datetime -import time -import operator -import codecs -from email import message_from_file -try: - from email.header import Header, decode_header - from email.utils import parsedate_tz, mktime_tz -except ImportError: - # Python 2.4 compatibility - from email.Header import Header, decode_header - from email.Utils import parsedate_tz, mktime_tz - -from patchwork.parser import parse_patch -from patchwork.models import Patch, Project, Person, Comment, State, \ - get_default_initial_patch_state -from django.contrib.auth.models import User - -list_id_headers = ['List-ID', 'X-Mailing-List', 'X-list'] - -whitespace_re = re.compile('\s+') -def normalise_space(str): - return whitespace_re.sub(' ', str).strip() - -def clean_header(header): - """ Decode (possibly non-ascii) headers """ - - def decode(fragment): - (frag_str, frag_encoding) = fragment - if frag_encoding: - return frag_str.decode(frag_encoding) - return frag_str.decode() - - fragments = map(decode, decode_header(header)) - - return normalise_space(u' '.join(fragments)) - -def find_project(mail): - project = None - listid_res = [re.compile('.*<([^>]+)>.*', re.S), - re.compile('^([\S]+)$', re.S)] - - for header in list_id_headers: - if header in mail: - - for listid_re in listid_res: - match = listid_re.match(mail.get(header)) - if match: - break - - if not match: - continue - - listid = match.group(1) - - try: - project = Project.objects.get(listid = listid) - break - except: - pass - - return project - -def find_author(mail): - - from_header = clean_header(mail.get('From')) - (name, email) = (None, None) - - # tuple of (regex, fn) - # - where fn returns a (name, email) tuple from the match groups resulting - # from re.match().groups() - from_res = [ - # for "Firstname Lastname" <example@example.com> style addresses - (re.compile('"?(.*?)"?\s*<([^>]+)>'), (lambda g: (g[0], g[1]))), - - # for example@example.com (Firstname Lastname) style addresses - (re.compile('"?(.*?)"?\s*\(([^\)]+)\)'), (lambda g: (g[1], g[0]))), - - # everything else - (re.compile('(.*)'), (lambda g: (None, g[0]))), - ] - - for regex, fn in from_res: - match = regex.match(from_header) - if match: - (name, email) = fn(match.groups()) - break - - if email is None: - raise Exception("Could not parse From: header") - - email = email.strip() - if name is not None: - name = name.strip() - - new_person = False - - try: - person = Person.objects.get(email__iexact = email) - except Person.DoesNotExist: - person = Person(name = name, email = email) - new_person = True - - return (person, new_person) - -def mail_date(mail): - t = parsedate_tz(mail.get('Date', '')) - if not t: - return datetime.datetime.utcnow() - return datetime.datetime.utcfromtimestamp(mktime_tz(t)) - -def mail_headers(mail): - return reduce(operator.__concat__, - ['%s: %s\n' % (k, Header(v, header_name = k, \ - continuation_ws = '\t').encode()) \ - for (k, v) in mail.items()]) - -def find_pull_request(content): - git_re = re.compile('^The following changes since commit.*' + - '^are available in the git repository at:\n' - '^\s*([\S]+://[^\n]+)$', - re.DOTALL | re.MULTILINE) - match = git_re.search(content) - if match: - return match.group(1) - return None - -def try_decode(payload, charset): - try: - payload = unicode(payload, charset) - except UnicodeDecodeError: - return None - return payload - -def find_content(project, mail): - patchbuf = None - commentbuf = '' - pullurl = None - - for part in mail.walk(): - if part.get_content_maintype() != 'text': - continue - - payload = part.get_payload(decode=True) - subtype = part.get_content_subtype() - - if not isinstance(payload, unicode): - charset = part.get_content_charset() - - # Check that we have a charset that we understand. Otherwise, - # ignore it and fallback to our standard set. - if charset is not None: - try: - codec = codecs.lookup(charset) - except LookupError: - charset = None - - # If there is no charset or if it is unknown, then try some common - # charsets before we fail. - if charset is None: - try_charsets = ['utf-8', 'windows-1252', 'iso-8859-1'] - else: - try_charsets = [charset] - - for cset in try_charsets: - decoded_payload = try_decode(payload, cset) - if decoded_payload is not None: - break - payload = decoded_payload - - # Could not find a valid decoded payload. Fail. - if payload is None: - return (None, None) - - if subtype in ['x-patch', 'x-diff']: - patchbuf = payload - - elif subtype == 'plain': - c = payload - - if not patchbuf: - (patchbuf, c) = parse_patch(payload) - - if not pullurl: - pullurl = find_pull_request(payload) - - if c is not None: - commentbuf += c.strip() + '\n' - - patch = None - comment = None - - if pullurl or patchbuf: - name = clean_subject(mail.get('Subject'), [project.linkname]) - patch = Patch(name = name, pull_url = pullurl, content = patchbuf, - date = mail_date(mail), headers = mail_headers(mail)) - - if commentbuf: - if patch: - cpatch = patch - else: - cpatch = find_patch_for_comment(project, mail) - if not cpatch: - return (None, None) - comment = Comment(patch = cpatch, date = mail_date(mail), - content = clean_content(commentbuf), - headers = mail_headers(mail)) - - return (patch, comment) - -def find_patch_for_comment(project, mail): - # construct a list of possible reply message ids - refs = [] - if 'In-Reply-To' in mail: - refs.append(mail.get('In-Reply-To')) - - if 'References' in mail: - rs = mail.get('References').split() - rs.reverse() - for r in rs: - if r not in refs: - refs.append(r) - - for ref in refs: - patch = None - - # first, check for a direct reply - try: - patch = Patch.objects.get(project = project, msgid = ref) - return patch - except Patch.DoesNotExist: - pass - - # see if we have comments that refer to a patch - try: - comment = Comment.objects.get(patch__project = project, msgid = ref) - return comment.patch - except Comment.DoesNotExist: - pass - - - return None - -split_re = re.compile('[,\s]+') - -def split_prefixes(prefix): - """ Turn a prefix string into a list of prefix tokens - - >>> split_prefixes('PATCH') - ['PATCH'] - >>> split_prefixes('PATCH,RFC') - ['PATCH', 'RFC'] - >>> split_prefixes('') - [] - >>> split_prefixes('PATCH,') - ['PATCH'] - >>> split_prefixes('PATCH ') - ['PATCH'] - >>> split_prefixes('PATCH,RFC') - ['PATCH', 'RFC'] - >>> split_prefixes('PATCH 1/2') - ['PATCH', '1/2'] - """ - matches = split_re.split(prefix) - return [ s for s in matches if s != '' ] - -re_re = re.compile('^(re|fwd?)[:\s]\s*', re.I) -prefix_re = re.compile('^\[([^\]]*)\]\s*(.*)$') - -def clean_subject(subject, drop_prefixes = None): - """ Clean a Subject: header from an incoming patch. - - Removes Re: and Fwd: strings, as well as [PATCH]-style prefixes. By - default, only [PATCH] is removed, and we keep any other bracketed data - in the subject. If drop_prefixes is provided, remove those too, - comparing case-insensitively. - - >>> clean_subject('meep') - 'meep' - >>> clean_subject('Re: meep') - 'meep' - >>> clean_subject('[PATCH] meep') - 'meep' - >>> clean_subject('[PATCH] meep \\n meep') - 'meep meep' - >>> clean_subject('[PATCH RFC] meep') - '[RFC] meep' - >>> clean_subject('[PATCH,RFC] meep') - '[RFC] meep' - >>> clean_subject('[PATCH,1/2] meep') - '[1/2] meep' - >>> clean_subject('[PATCH RFC 1/2] meep') - '[RFC,1/2] meep' - >>> clean_subject('[PATCH] [RFC] meep') - '[RFC] meep' - >>> clean_subject('[PATCH] [RFC,1/2] meep') - '[RFC,1/2] meep' - >>> clean_subject('[PATCH] [RFC] [1/2] meep') - '[RFC,1/2] meep' - >>> clean_subject('[PATCH] rewrite [a-z] regexes') - 'rewrite [a-z] regexes' - >>> clean_subject('[PATCH] [RFC] rewrite [a-z] regexes') - '[RFC] rewrite [a-z] regexes' - >>> clean_subject('[foo] [bar] meep', ['foo']) - '[bar] meep' - >>> clean_subject('[FOO] [bar] meep', ['foo']) - '[bar] meep' - """ - - subject = clean_header(subject) - - if drop_prefixes is None: - drop_prefixes = [] - else: - drop_prefixes = [ s.lower() for s in drop_prefixes ] - - drop_prefixes.append('patch') - - # remove Re:, Fwd:, etc - subject = re_re.sub(' ', subject) - - subject = normalise_space(subject) - - prefixes = [] - - match = prefix_re.match(subject) - - while match: - prefix_str = match.group(1) - prefixes += [ p for p in split_prefixes(prefix_str) \ - if p.lower() not in drop_prefixes] - - subject = match.group(2) - match = prefix_re.match(subject) - - subject = normalise_space(subject) - - subject = subject.strip() - if prefixes: - subject = '[%s] %s' % (','.join(prefixes), subject) - - return subject - -sig_re = re.compile('^(-- |_+)\n.*', re.S | re.M) -def clean_content(str): - """ Try to remove signature (-- ) and list footer (_____) cruft """ - str = sig_re.sub('', str) - return str.strip() - -def get_state(state_name): - """ Return the state with the given name or the default State """ - if state_name: - try: - return State.objects.get(name__iexact=state_name) - except State.DoesNotExist: - pass - return get_default_initial_patch_state() - -def get_delegate(delegate_email): - """ Return the delegate with the given email or None """ - if delegate_email: - try: - return User.objects.get(email__iexact=delegate_email) - except User.DoesNotExist: - pass - return None - -def parse_mail(mail): - - # some basic sanity checks - if 'From' not in mail: - return 0 - - if 'Subject' not in mail: - return 0 - - if 'Message-Id' not in mail: - return 0 - - hint = mail.get('X-Patchwork-Hint', '').lower() - if hint == 'ignore': - return 0; - - project = find_project(mail) - if project is None: - print "no project found" - return 0 - - msgid = mail.get('Message-Id').strip() - - (author, save_required) = find_author(mail) - - (patch, comment) = find_content(project, mail) - - if patch: - # we delay the saving until we know we have a patch. - if save_required: - author.save() - save_required = False - patch.submitter = author - patch.msgid = msgid - patch.project = project - patch.state = get_state(mail.get('X-Patchwork-State', '').strip()) - patch.delegate = get_delegate( - mail.get('X-Patchwork-Delegate', '').strip()) - try: - patch.save() - except Exception, ex: - print str(ex) - - if comment: - if save_required: - author.save() - # looks like the original constructor for Comment takes the pk - # when the Comment is created. reset it here. - if patch: - comment.patch = patch - comment.submitter = author - comment.msgid = msgid - try: - comment.save() - except Exception, ex: - print str(ex) - - return 0 - -def main(args): - mail = message_from_file(sys.stdin) - return parse_mail(mail) - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/apps/patchwork/bin/parsemail.sh b/apps/patchwork/bin/parsemail.sh deleted file mode 100755 index 246c2a1..0000000 --- a/apps/patchwork/bin/parsemail.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -BIN_DIR=`dirname $0` -PATCHWORK_BASE=`readlink -e $BIN_DIR/../../..` - -PYTHONPATH="$PATCHWORK_BASE/apps":"$PATCHWORK_BASE/lib/python:$PYTHONPATH" \ - DJANGO_SETTINGS_MODULE=settings \ - "$PATCHWORK_BASE/apps/patchwork/bin/parsemail.py" - -exit 0 diff --git a/apps/patchwork/bin/patchwork-cron.py b/apps/patchwork/bin/patchwork-cron.py deleted file mode 100755 index 148e97c..0000000 --- a/apps/patchwork/bin/patchwork-cron.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -import sys -from patchwork.utils import send_notifications, do_expiry - -def main(args): - errors = send_notifications() - for (recipient, error) in errors: - print "Failed sending to %s: %s" % (recipient.email, ex) - - do_expiry() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - diff --git a/apps/patchwork/bin/pwclient b/apps/patchwork/bin/pwclient deleted file mode 100755 index 8d1f476..0000000 --- a/apps/patchwork/bin/pwclient +++ /dev/null @@ -1,744 +0,0 @@ -#!/usr/bin/env python -# -# Patchwork command line client -# Copyright (C) 2008 Nate Case <ncase@xes-inc.com> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import os -import sys -import xmlrpclib -import argparse -import string -import tempfile -import subprocess -import base64 -import ConfigParser -import shutil -import re - -# Default Patchwork remote XML-RPC server URL -# This script will check the PW_XMLRPC_URL environment variable -# for the URL to access. If that is unspecified, it will fallback to -# the hardcoded default value specified here. -DEFAULT_URL = "http://patchwork/xmlrpc/" -CONFIG_FILE = os.path.expanduser('~/.pwclientrc') - -class Filter: - """Filter for selecting patches.""" - def __init__(self): - # These fields refer to specific objects, so they are special - # because we have to resolve them to IDs before passing the - # filter to the server - self.state = "" - self.project = "" - - # The dictionary that gets passed to via XML-RPC - self.d = {} - - def add(self, field, value): - if field == 'state': - self.state = value - elif field == 'project': - self.project = value - else: - # OK to add directly - self.d[field] = value - - def resolve_ids(self, rpc): - """Resolve State, Project, and Person IDs based on filter strings.""" - if self.state != "": - id = state_id_by_name(rpc, self.state) - if id == 0: - sys.stderr.write("Note: No State found matching %s*, " \ - "ignoring filter\n" % self.state) - else: - self.d['state_id'] = id - - if self.project != None: - id = project_id_by_name(rpc, self.project) - if id == 0: - sys.stderr.write("Note: No Project found matching %s, " \ - "ignoring filter\n" % self.project) - else: - self.d['project_id'] = id - - def __str__(self): - """Return human-readable description of the filter.""" - return str(self.d) - -class BasicHTTPAuthTransport(xmlrpclib.SafeTransport): - - def __init__(self, username = None, password = None, use_https = False): - self.username = username - self.password = password - self.use_https = use_https - xmlrpclib.SafeTransport.__init__(self) - - def authenticated(self): - return self.username != None and self.password != None - - def send_host(self, connection, host): - xmlrpclib.Transport.send_host(self, connection, host) - if not self.authenticated(): - return - credentials = '%s:%s' % (self.username, self.password) - auth = 'Basic ' + base64.encodestring(credentials).strip() - connection.putheader('Authorization', auth) - - def make_connection(self, host): - if self.use_https: - fn = xmlrpclib.SafeTransport.make_connection - else: - fn = xmlrpclib.Transport.make_connection - return fn(self, host) - -def project_id_by_name(rpc, linkname): - """Given a project short name, look up the Project ID.""" - if len(linkname) == 0: - return 0 - projects = rpc.project_list(linkname, 0) - for project in projects: - if project['linkname'] == linkname: - return project['id'] - return 0 - -def state_id_by_name(rpc, name): - """Given a partial state name, look up the state ID.""" - if len(name) == 0: - return 0 - states = rpc.state_list(name, 0) - for state in states: - if state['name'].lower().startswith(name.lower()): - return state['id'] - return 0 - -def person_ids_by_name(rpc, name): - """Given a partial name or email address, return a list of the - person IDs that match.""" - if len(name) == 0: - return [] - people = rpc.person_list(name, 0) - return map(lambda x: x['id'], people) - -def list_patches(patches, format_str=None): - """Dump a list of patches to stdout.""" - if format_str: - format_field_re = re.compile("%{([a-z0-9_]+)}") - - def patch_field(matchobj): - fieldname = matchobj.group(1) - - if fieldname == "_msgid_": - # naive way to strip < and > from message-id - val = string.strip(str(patch["msgid"]), "<>") - else: - val = str(patch[fieldname]) - - return val - - for patch in patches: - print(format_field_re.sub(patch_field, format_str)) - else: - print("%-7s %-12s %s" % ("ID", "State", "Name")) - print("%-7s %-12s %s" % ("--", "-----", "----")) - for patch in patches: - print("%-7d %-12s %s" % (patch['id'], patch['state'], patch['name'])) - -def action_list(rpc, filter, submitter_str, delegate_str, format_str=None): - filter.resolve_ids(rpc) - - if submitter_str != None: - ids = person_ids_by_name(rpc, submitter_str) - if len(ids) == 0: - sys.stderr.write("Note: Nobody found matching *%s*\n" % \ - submitter_str) - else: - for id in ids: - person = rpc.person_get(id) - print "Patches submitted by %s <%s>:" % \ - (unicode(person['name']).encode("utf-8"), \ - unicode(person['email']).encode("utf-8")) - f = filter - f.add("submitter_id", id) - patches = rpc.patch_list(f.d) - list_patches(patches, format_str) - return - - if delegate_str != None: - ids = person_ids_by_name(rpc, delegate_str) - if len(ids) == 0: - sys.stderr.write("Note: Nobody found matching *%s*\n" % \ - delegate_str) - else: - for id in ids: - person = rpc.person_get(id) - print "Patches delegated to %s <%s>:" % \ - (person['name'], person['email']) - f = filter - f.add("delegate_id", id) - patches = rpc.patch_list(f.d) - list_patches(patches, format_str) - return - - patches = rpc.patch_list(filter.d) - list_patches(patches, format_str) - -def action_projects(rpc): - projects = rpc.project_list("", 0) - print("%-5s %-24s %s" % ("ID", "Name", "Description")) - print("%-5s %-24s %s" % ("--", "----", "-----------")) - for project in projects: - print("%-5d %-24s %s" % (project['id'], \ - project['linkname'], \ - project['name'])) - -def action_states(rpc): - states = rpc.state_list("", 0) - print("%-5s %s" % ("ID", "Name")) - print("%-5s %s" % ("--", "----")) - for state in states: - print("%-5d %s" % (state['id'], state['name'])) - -def action_info(rpc, patch_id): - patch = rpc.patch_get(patch_id) - s = "Information for patch id %d" % (patch_id) - print(s) - print('-' * len(s)) - for key, value in sorted(patch.iteritems()): - print("- %- 14s: %s" % (key, unicode(value).encode("utf-8"))) - -def action_get(rpc, patch_id): - patch = rpc.patch_get(patch_id) - s = rpc.patch_get_mbox(patch_id) - - if patch == {} or len(s) == 0: - sys.stderr.write("Unable to get patch %d\n" % patch_id) - sys.exit(1) - - base_fname = fname = os.path.basename(patch['filename']) - i = 0 - while os.path.exists(fname): - fname = "%s.%d" % (base_fname, i) - i += 1 - - try: - f = open(fname, "w") - except: - sys.stderr.write("Unable to open %s for writing\n" % fname) - sys.exit(1) - - try: - f.write(unicode(s).encode("utf-8")) - f.close() - print "Saved patch to %s" % fname - except: - sys.stderr.write("Failed to write to %s\n" % fname) - sys.exit(1) - -def action_apply(rpc, patch_id, apply_cmd=None): - patch = rpc.patch_get(patch_id) - if patch == {}: - sys.stderr.write("Error getting information on patch ID %d\n" % \ - patch_id) - sys.exit(1) - - if apply_cmd is None: - print "Applying patch #%d to current directory" % patch_id - apply_cmd = ['patch', '-p1'] - else: - print "Applying patch #%d using %s" % ( - patch_id, repr(' '.join(apply_cmd))) - - print "Description: %s" % patch['name'] - s = rpc.patch_get_mbox(patch_id) - if len(s) > 0: - proc = subprocess.Popen(apply_cmd, stdin = subprocess.PIPE) - proc.communicate(unicode(s).encode('utf-8')) - return proc.returncode - else: - sys.stderr.write("Error: No patch content found\n") - sys.exit(1) - -def action_update_patch(rpc, patch_id, state = None, archived = None, commit = None): - patch = rpc.patch_get(patch_id) - if patch == {}: - sys.stderr.write("Error getting information on patch ID %d\n" % \ - patch_id) - sys.exit(1) - - params = {} - - if state: - state_id = state_id_by_name(rpc, state) - if state_id == 0: - sys.stderr.write("Error: No State found matching %s*\n" % state) - sys.exit(1) - params['state'] = state_id - - if commit: - params['commit_ref'] = commit - - if archived: - params['archived'] = archived == 'yes' - - success = False - try: - success = rpc.patch_set(patch_id, params) - except xmlrpclib.Fault, f: - sys.stderr.write("Error updating patch: %s\n" % f.faultString) - - if not success: - sys.stderr.write("Patch not updated\n") - -def patch_id_from_hash(rpc, project, hash): - try: - patch = rpc.patch_get_by_project_hash(project, hash) - except xmlrpclib.Fault: - # the server may not have the newer patch_get_by_project_hash function, - # so fall back to hash-only. - patch = rpc.patch_get_by_hash(hash) - - if patch == {}: - sys.stderr.write("No patch has the hash provided\n") - sys.exit(1) - - patch_id = patch['id'] - # be super paranoid - try: - patch_id = int(patch_id) - except: - sys.stderr.write("Invalid patch ID obtained from server\n") - sys.exit(1) - return patch_id - -auth_actions = ['update'] - -# unfortunately we currently have to revert to this ugly hack.. -class _RecursiveHelpAction(argparse._HelpAction): - - def __call__(self, parser, namespace, values, option_string=None): - parser.print_help() - print - - subparsers_actions = [ - action for action in parser._actions - if isinstance(action, argparse._SubParsersAction) - ] - hash_n_id_actions = set(['hash', 'id', 'help']) - for subparsers_action in subparsers_actions: - for choice, subparser in subparsers_action.choices.items(): - # gross but the whole thing is.. - if (len(subparser._actions) == 3 \ - and set([a.dest for a in subparser._actions]) \ - == hash_n_id_actions) \ - or len(subparser._actions) == 0: - continue - print("command '{}'".format(choice)) - print(subparser.format_help()) - - parser.exit() - -def main(): - hash_parser = argparse.ArgumentParser(add_help=False, version=False) - hash_parser.add_argument( - '-h', metavar='HASH', dest='hash', action='store', - help='''Lookup by patch hash''' - ) - hash_parser.add_argument( - 'id', metavar='ID', nargs='*', action='store', type=int, - help='Patch ID', - ) - hash_parser.add_argument( - '-p', metavar='PROJECT', - help='''Lookup patch in project''' - ) - - filter_parser = argparse.ArgumentParser(add_help=False, version=False) - filter_parser.add_argument( - '-s', metavar='STATE', - help='''Filter by patch state (e.g., 'New', 'Accepted', etc.)''' - ) - filter_parser.add_argument( - '-a', choices=['yes','no'], - help='''Filter by patch archived state''' - ) - filter_parser.add_argument( - '-p', metavar='PROJECT', - help='''Filter by project name (see 'projects' for list)''' - ) - filter_parser.add_argument( - '-w', metavar='WHO', - help='''Filter by submitter (name, e-mail substring search)''' - ) - filter_parser.add_argument( - '-d', metavar='WHO', - help='''Filter by delegate (name, e-mail substring search)''' - ) - filter_parser.add_argument( - '-n', metavar='MAX#', - type=int, - help='''Restrict number of results''' - ) - filter_parser.add_argument( - '-m', metavar='MESSAGEID', - help='''Filter by Message-Id''' - ) - filter_parser.add_argument( - '-f', metavar='FORMAT', - help='''Print output in the given format. You can use tags matching ''' - '''fields, e.g. %%{id}, %%{state}, or %%{msgid}.''' - ) - filter_parser.add_argument( - 'patch_name', metavar='STR', nargs='?', - help='substring to search for patches by name', - ) - help_parser = argparse.ArgumentParser(add_help=False, version=False) - help_parser.add_argument( - '--help', action='help', help=argparse.SUPPRESS, - #help='''show this help message and exit''' - ) - - action_parser = argparse.ArgumentParser( - prog='pwclient', - add_help=False, - version=False, - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog='''(apply | get | info | view | update) (-h HASH | ID [ID ...])''', - ) - action_parser.add_argument( - '--help', - #action='help', - action=_RecursiveHelpAction, - help='''Print this help text''' - ) - - subparsers = action_parser.add_subparsers( - title='Commands', - metavar='' - ) - apply_parser = subparsers.add_parser( - 'apply', parents=[hash_parser, help_parser], - add_help=False, - help='''Apply a patch (in the current dir, using -p1)''' - ) - apply_parser.set_defaults(subcmd='apply') - git_am_parser = subparsers.add_parser( - 'git-am', parents=[hash_parser, help_parser], - add_help=False, - help='''Apply a patch to current git branch using "git am".''' - ) - git_am_parser.set_defaults(subcmd='git_am') - git_am_parser.add_argument( - '-s', '--signoff', - action='store_true', - help='''pass --signoff to git-am''' - ) - get_parser = subparsers.add_parser( - 'get', parents=[hash_parser, help_parser], - add_help=False, - help='''Download a patch and save it locally''' - ) - get_parser.set_defaults(subcmd='get') - info_parser = subparsers.add_parser( - 'info', parents=[hash_parser, help_parser], - add_help=False, - help='''Display patchwork info about a given patch ID''' - ) - info_parser.set_defaults(subcmd='info') - projects_parser = subparsers.add_parser( - 'projects', - add_help=False, - help='''List all projects''' - ) - projects_parser.set_defaults(subcmd='projects') - states_parser = subparsers.add_parser( - 'states', - add_help=False, - help='''Show list of potential patch states''' - ) - states_parser.set_defaults(subcmd='states') - view_parser = subparsers.add_parser( - 'view', parents=[hash_parser, help_parser], - add_help=False, - help='''View a patch''' - ) - view_parser.set_defaults(subcmd='view') - update_parser = subparsers.add_parser( - 'update', parents=[hash_parser, help_parser], - add_help=False, - help='''Update patch''', - epilog='''Using a COMMIT-REF allows for only one ID to be specified''', - ) - update_parser.add_argument( - '-c', metavar='COMMIT-REF', - help='''commit reference hash''' - ) - update_parser.add_argument( - '-s', metavar='STATE', - required=True, - help='''Set patch state (e.g., 'Accepted', 'Superseded' etc.)''' - ) - update_parser.add_argument( - '-a', choices=['yes', 'no'], - help='''Set patch archived state''' - ) - update_parser.set_defaults(subcmd='update') - list_parser = subparsers.add_parser("list", - add_help=False, - #aliases=['search'], - parents=[filter_parser, help_parser], - help='''List patches, using the optional filters specified - below and an optional substring to search for patches - by name''' - ) - list_parser.set_defaults(subcmd='list') - search_parser = subparsers.add_parser("search", - add_help=False, - parents=[filter_parser, help_parser], - help='''Alias for "list"''' - ) - # Poor man's argparse aliases: - # We register the "search" parser but effectively use "list" for the - # help-text. - search_parser.set_defaults(subcmd='list') - if len(sys.argv) < 2: - action_parser.print_help() - sys.exit(0) - - args = action_parser.parse_args() - args = dict(vars(args)) - action = args.get('subcmd') - - if args.get('hash') and len(args.get('id')): - # mimic mutual exclusive group - sys.stderr.write("Error: [-h HASH] and [ID [ID ...]] " + - "are mutually exlusive\n") - locals()[action + '_parser'].print_help() - sys.exit(1) - - # set defaults - filt = Filter() - commit_str = None - url = DEFAULT_URL - - archived_str = args.get('a') - state_str = args.get('s') - project_str = args.get('p') - submitter_str = args.get('w') - delegate_str = args.get('d') - format_str = args.get('f') - hash_str = args.get('hash') - patch_ids = args.get('id') - msgid_str = args.get('m') - if args.get('c'): - # update multiple IDs with a single commit-hash does not make sense - if action == 'update' and patch_ids and len(patch_ids) > 1: - sys.stderr.write( - "Declining update with COMMIT-REF on multiple IDs\n" - ) - update_parser.print_help() - sys.exit(1) - commit_str = args.get('c') - - if args.get('n') != None: - try: - filt.add("max_count", args.get('n')) - except: - sys.stderr.write("Invalid maximum count '%s'\n" % args.get('n')) - action_parser.print_help() - sys.exit(1) - - do_signoff = args.get('signoff') - - # grab settings from config files - config = ConfigParser.ConfigParser() - config.read([CONFIG_FILE]) - - if not config.has_section('options'): - sys.stderr.write('~/.pwclientrc is in the old format. Migrating it...') - - old_project = config.get('base','project') - - new_config = ConfigParser.ConfigParser() - new_config.add_section('options') - - new_config.set('options','default',old_project) - new_config.add_section(old_project) - - new_config.set(old_project,'url',config.get('base','url')) - if config.has_option('auth', 'username'): - new_config.set(old_project,'username',config.get('auth','username')) - if config.has_option('auth', 'password'): - new_config.set(old_project,'password',config.get('auth','password')) - - old_config_file = CONFIG_FILE + '.orig' - shutil.copy2(CONFIG_FILE,old_config_file) - - with open(CONFIG_FILE, 'wb') as fd: - new_config.write(fd) - - sys.stderr.write(' Done.\n') - sys.stderr.write('Your old ~/.pwclientrc was saved to %s\n' % old_config_file) - sys.stderr.write('and was converted to the new format. You may want to\n') - sys.stderr.write('inspect it before continuing.\n') - sys.exit(1) - - if not project_str: - try: - project_str = config.get('options', 'default') - except: - sys.stderr.write("No default project configured in ~/.pwclientrc\n") - action_parser.print_help() - sys.exit(1) - - if not config.has_section(project_str): - sys.stderr.write("No section for project %s\n" % project_str) - sys.exit(1) - if not config.has_option(project_str, 'url'): - sys.stderr.write("No URL for project %s\n" % project_str) - sys.exit(1) - if not do_signoff and config.has_option('options', 'signoff'): - do_signoff = config.getboolean('options', 'signoff') - if not do_signoff and config.has_option(project_str, 'signoff'): - do_signoff = config.getboolean(project_str, 'signoff') - - url = config.get(project_str, 'url') - - transport = None - if action in auth_actions: - if config.has_option(project_str, 'username') and \ - config.has_option(project_str, 'password'): - - use_https = url.startswith('https') - - transport = BasicHTTPAuthTransport( \ - config.get(project_str, 'username'), - config.get(project_str, 'password'), - use_https) - - else: - sys.stderr.write(("The %s action requires authentication, " - "but no username or password\nis configured\n") % action) - sys.exit(1) - - if project_str: - filt.add("project", project_str) - - if state_str: - filt.add("state", state_str) - - if archived_str: - filt.add("archived", archived_str == 'yes') - - if msgid_str: - filt.add("msgid", msgid_str) - - try: - rpc = xmlrpclib.Server(url, transport = transport) - except: - sys.stderr.write("Unable to connect to %s\n" % url) - sys.exit(1) - - # It should be safe to assume hash_str is not zero, but who knows.. - if hash_str != None: - patch_ids = [patch_id_from_hash(rpc, project_str, hash_str)] - - # helper for non_empty() to print correct helptext - h = locals()[action + '_parser'] - - # Require either hash_str or IDs for - def non_empty(h, patch_ids): - """Error out if no patch IDs were specified""" - if patch_ids == None or len(patch_ids) < 1: - sys.stderr.write("Error: Missing Argument! " + - "Either [-h HASH] or [ID [ID ...]] are required\n") - if h: - h.print_help() - sys.exit(1) - return patch_ids - - if action == 'list' or action == 'search': - if args.get('patch_name') != None: - filt.add("name__icontains", args.get('patch_name')) - action_list(rpc, filt, submitter_str, delegate_str, format_str) - - elif action.startswith('project'): - action_projects(rpc) - - elif action.startswith('state'): - action_states(rpc) - - elif action == 'view': - pager = os.environ.get('PAGER') - if pager: - pager = subprocess.Popen( - pager.split(), stdin=subprocess.PIPE - ) - if pager: - i = list() - for patch_id in non_empty(h, patch_ids): - s = rpc.patch_get_mbox(patch_id) - if len(s) > 0: - i.append(unicode(s).encode("utf-8")) - if len(i) > 0: - pager.communicate(input="\n".join(i)) - pager.stdin.close() - else: - for patch_id in non_empty(h, patch_ids): - s = rpc.patch_get_mbox(patch_id) - if len(s) > 0: - print unicode(s).encode("utf-8") - - elif action == 'info': - for patch_id in non_empty(h, patch_ids): - action_info(rpc, patch_id) - - elif action == 'get': - for patch_id in non_empty(h, patch_ids): - action_get(rpc, patch_id) - - elif action == 'apply': - for patch_id in non_empty(h, patch_ids): - ret = action_apply(rpc, patch_id) - if ret: - sys.stderr.write("Apply failed with exit status %d\n" % ret) - sys.exit(1) - - elif action == 'git_am': - cmd = ['git', 'am'] - if do_signoff: - cmd.append('-s') - for patch_id in non_empty(h, patch_ids): - ret = action_apply(rpc, patch_id, cmd) - if ret: - sys.stderr.write("'git am' failed with exit status %d\n" % ret) - sys.exit(1) - - elif action == 'update': - for patch_id in non_empty(h, patch_ids): - action_update_patch(rpc, patch_id, state = state_str, - archived = archived_str, commit = commit_str - ) - - else: - sys.stderr.write("Unknown action '%s'\n" % action) - action_parser.print_help() - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/apps/patchwork/bin/rehash.py b/apps/patchwork/bin/rehash.py deleted file mode 100755 index c44e49b..0000000 --- a/apps/patchwork/bin/rehash.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from patchwork.models import Patch -import sys - -if __name__ == '__main__': - if len(sys.argv) > 1: - patches = Patch.objects.filter(id__in = sys.argv[1:]) - else: - patches = Patch.objects.all() - - for patch in patches: - print patch.id, patch.name - patch.hash = None - patch.save() diff --git a/apps/patchwork/bin/update-patchwork-status.py b/apps/patchwork/bin/update-patchwork-status.py deleted file mode 100755 index 2da5d23..0000000 --- a/apps/patchwork/bin/update-patchwork-status.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -import sys -import subprocess -from optparse import OptionParser - -def commits(options, revlist): - cmd = ['git', 'rev-list', revlist] - proc = subprocess.Popen(cmd, stdout = subprocess.PIPE, cwd = options.repodir) - - revs = [] - - for line in proc.stdout.readlines(): - revs.append(line.strip()) - - return revs - -def commit(options, rev): - cmd = ['git', 'diff', '%(rev)s^..%(rev)s' % {'rev': rev}] - proc = subprocess.Popen(cmd, stdout = subprocess.PIPE, cwd = options.repodir) - - buf = proc.communicate()[0] - - return buf - - -def main(args): - parser = OptionParser(usage = '%prog [options] revspec') - parser.add_option("-p", "--project", dest = "project", action = 'store', - help="use project PROJECT", metavar="PROJECT") - parser.add_option("-d", "--dir", dest = "repodir", action = 'store', - help="use git repo in DIR", metavar="DIR") - - (options, args) = parser.parse_args(args[1:]) - - if len(args) != 1: - parser.error("incorrect number of arguments") - - revspec = args[0] - revs = commits(options, revspec) - - for rev in revs: - print rev - print commit(options, rev) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) - - diff --git a/apps/patchwork/context_processors.py b/apps/patchwork/context_processors.py deleted file mode 100644 index f4ab5a9..0000000 --- a/apps/patchwork/context_processors.py +++ /dev/null @@ -1,32 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from patchwork.models import Bundle -from patchwork.utils import order_map, get_order - -def bundle(request): - user = request.user - if not user.is_authenticated(): - return {} - return {'bundles': Bundle.objects.filter(owner = user)} - - -def patchlists(request): - diff --git a/apps/patchwork/filters.py b/apps/patchwork/filters.py deleted file mode 100644 index 8c9690e..0000000 --- a/apps/patchwork/filters.py +++ /dev/null @@ -1,471 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from patchwork.models import Person, State -from django.utils.safestring import mark_safe -from django.utils.html import escape -from django.contrib.auth.models import User -from urllib import quote - -class Filter(object): - def __init__(self, filters): - self.filters = filters - self.applied = False - self.forced = False - - def name(self): - """The 'name' of the filter, to be displayed in the filter UI""" - return self.name - - def condition(self): - """The current condition of the filter, to be displayed in the - filter UI""" - return self.key - - def key(self): - """The key for this filter, to appear in the querystring. A key of - None will remove the param=ley pair from the querystring.""" - return None - - def set_status(self, *kwargs): - """Views can call this to force a specific filter status. For example, - a user's todo page needs to setup the delegate filter to show - that user's delegated patches""" - pass - - def parse(self, dict): - if self.param not in dict.keys(): - return - self._set_key(dict[self.param]) - - def url_without_me(self): - return self.filters.querystring_without_filter(self) - - def form_function(self): - return 'function(form) { return "unimplemented" }' - - def form(self): - if self.forced: - return mark_safe('<input type="hidden" value="%s">%s' % (self.param, - self.condition())) - return self.condition() - return self._form() - - def kwargs(self): - return {} - - def __str__(self): - return '%s: %s' % (self.name, self.kwargs()) - - -class SubmitterFilter(Filter): - param = 'submitter' - def __init__(self, filters): - super(SubmitterFilter, self).__init__(filters) - self.name = 'Submitter' - self.person = None - self.person_match = None - - def _set_key(self, str): - self.person = None - self.person_match = None - submitter_id = None - try: - submitter_id = int(str) - except ValueError: - pass - except: - return - - if submitter_id: - self.person = Person.objects.get(id = int(str)) - self.applied = True - return - - - people = Person.objects.filter(name__icontains = str) - - if not people: - return - - self.person_match = str - self.applied = True - - def kwargs(self): - if self.person: - user = self.person.user - if user: - return {'submitter__in': - Person.objects.filter(user = user).values('pk').query} - return {'submitter': self.person} - - if self.person_match: - return {'submitter__name__icontains': self.person_match} - return {} - - def condition(self): - if self.person: - return self.person.name - elif self.person_match: - return self.person_match - return '' - - def _form(self): - name = '' - if self.person: - name = self.person.name - return mark_safe(('<input onKeyUp="submitter_field_change(this)" ' + - 'name="submitter" id="submitter_input" ' + - 'value="%s"> ' % escape(name)) + - '<select id="submitter_select" ' + - 'disabled="true"></select>') - - def key(self): - if self.person: - return self.person.id - return self.person_match - -class StateFilter(Filter): - param = 'state' - any_key = '*' - action_req_str = 'Action Required' - - def __init__(self, filters): - super(StateFilter, self).__init__(filters) - self.name = 'State' - self.state = None - self.applied = True - - def _set_key(self, str): - self.state = None - - if str == self.any_key: - self.applied = False - return - - try: - self.state = State.objects.get(id=int(str)) - except: - return - - self.applied = True - - def kwargs(self): - if self.state is not None: - return {'state': self.state} - else: - return {'state__in': \ - State.objects.filter(action_required = True) \ - .values('pk').query} - - def condition(self): - if self.state: - return self.state.name - return self.action_req_str - - def key(self): - if self.state is not None: - return self.state.id - if not self.applied: - return '*' - return None - - def _form(self): - str = '<select name="%s">' % self.param - - selected = '' - if not self.applied: - selected = 'selected' - str += '<option %s value="%s">any</option>' % (selected, self.any_key) - - selected = '' - if self.applied and self.state == None: - selected = 'selected' - str += '<option %s value="">%s</option>' % \ - (selected, self.action_req_str) - - for state in State.objects.all(): - selected = '' - if self.state and self.state == state: - selected = ' selected="true"' - - str += '<option value="%d" %s>%s</option>' % \ - (state.id, selected, state.name) - str += '</select>' - return mark_safe(str); - - def form_function(self): - return 'function(form) { return form.x.value }' - - def url_without_me(self): - qs = self.filters.querystring_without_filter(self) - if qs != '?': - qs += '&' - return qs + '%s=%s' % (self.param, self.any_key) - -class SearchFilter(Filter): - param = 'q' - def __init__(self, filters): - super(SearchFilter, self).__init__(filters) - self.name = 'Search' - self.param = 'q' - self.search = None - - def _set_key(self, str): - str = str.strip() - if str == '': - return - self.search = str - self.applied = True - - def kwargs(self): - return {'name__icontains': self.search} - - def condition(self): - return self.search - - def key(self): - return self.search - - def _form(self): - value = '' - if self.search: - value = escape(self.search) - return mark_safe('<input name="%s" value="%s">' %\ - (self.param, value)) - - def form_function(self): - return mark_safe('function(form) { return form.x.value }') - -class ArchiveFilter(Filter): - param = 'archive' - def __init__(self, filters): - super(ArchiveFilter, self).__init__(filters) - self.name = 'Archived' - self.archive_state = False - self.applied = True - self.param_map = { - True: 'true', - False: '', - None: 'both' - } - self.description_map = { - True: 'Yes', - False: 'No', - None: 'Both' - } - - def _set_key(self, str): - self.archive_state = False - self.applied = True - for (k, v) in self.param_map.iteritems(): - if str == v: - self.archive_state = k - if self.archive_state == None: - self.applied = False - - def kwargs(self): - if self.archive_state == None: - return {} - return {'archived': self.archive_state} - - def condition(self): - return self.description_map[self.archive_state] - - def key(self): - if self.archive_state == False: - return None - return self.param_map[self.archive_state] - - def _form(self): - s = '' - for b in [False, True, None]: - label = self.description_map[b] - selected = '' - if self.archive_state == b: - selected = 'checked="true"' - s += ('<input type="radio" name="%(param)s" ' + \ - '%(selected)s value="%(value)s">%(label)s' + \ - ' ') % \ - {'label': label, - 'param': self.param, - 'selected': selected, - 'value': self.param_map[b] - } - return mark_safe(s) - - def url_without_me(self): - qs = self.filters.querystring_without_filter(self) - if qs != '?': - qs += '&' - return qs + 'archive=both' - - -class DelegateFilter(Filter): - param = 'delegate' - no_delegate_key = '-' - no_delegate_str = 'Nobody' - AnyDelegate = 1 - - def __init__(self, filters): - super(DelegateFilter, self).__init__(filters) - self.name = 'Delegate' - self.param = 'delegate' - self.delegate = None - - def _set_key(self, str): - if str == self.no_delegate_key: - self.applied = True - self.delegate = None - return - - applied = False - try: - self.delegate = User.objects.get(id = str) - self.applied = True - except: - pass - - def kwargs(self): - if not self.applied: - return {} - return {'delegate': self.delegate} - - def condition(self): - if self.delegate: - return self.delegate.profile.name() - return self.no_delegate_str - - def _form(self): - delegates = User.objects.filter(profile__maintainer_projects = - self.filters.project) - - str = '<select name="delegate">' - - selected = '' - if not self.applied: - selected = 'selected' - - str += '<option %s value="">------</option>' % selected - - selected = '' - if self.applied and self.delegate is None: - selected = 'selected' - - str += '<option %s value="%s">%s</option>' % \ - (selected, self.no_delegate_key, self.no_delegate_str) - - for d in delegates: - selected = '' - if d == self.delegate: - selected = ' selected' - - str += '<option %s value="%s">%s</option>' % (selected, - d.id, d.profile.name()) - str += '</select>' - - return mark_safe(str) - - def key(self): - if self.delegate: - return self.delegate.id - if self.applied: - return self.no_delegate_key - return None - - def set_status(self, *args, **kwargs): - if 'delegate' in kwargs: - self.applied = self.forced = True - self.delegate = kwargs['delegate'] - if self.AnyDelegate in args: - self.applied = False - self.forced = True - -filterclasses = [SubmitterFilter, \ - StateFilter, - SearchFilter, - ArchiveFilter, - DelegateFilter] - -class Filters: - - def __init__(self, request): - self._filters = map(lambda c: c(self), filterclasses) - self.dict = request.GET - self.project = None - - for f in self._filters: - f.parse(self.dict) - - def set_project(self, project): - self.project = project - - def filter_conditions(self): - kwargs = {} - for f in self._filters: - if f.applied: - kwargs.update(f.kwargs()) - return kwargs - - def apply(self, queryset): - kwargs = self.filter_conditions() - if not kwargs: - return queryset - return queryset.filter(**kwargs) - - def params(self): - return [ (f.param, f.key()) for f in self._filters \ - if f.key() is not None ] - - def querystring(self, remove = None): - params = dict(self.params()) - - for (k, v) in self.dict.iteritems(): - if k not in params: - params[k] = v - - if remove is not None: - if remove.param in params.keys(): - del params[remove.param] - - pairs = params.iteritems() - - def sanitise(s): - if not isinstance(s, basestring): - s = unicode(s) - return quote(s.encode('utf-8')) - - return '?' + '&'.join(['%s=%s' % (sanitise(k), sanitise(v)) - for (k, v) in pairs]) - - def querystring_without_filter(self, filter): - return self.querystring(filter) - - def applied_filters(self): - return filter(lambda x: x.applied, self._filters) - - def available_filters(self): - return self._filters - - def set_status(self, filterclass, *args, **kwargs): - for f in self._filters: - if isinstance(f, filterclass): - f.set_status(*args, **kwargs) - return diff --git a/apps/patchwork/fixtures/default_projects.xml b/apps/patchwork/fixtures/default_projects.xml deleted file mode 100644 index c67fa56..0000000 --- a/apps/patchwork/fixtures/default_projects.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - - <!-- some default projects --> - <object pk="1" model="patchwork.project"> - <field type="CharField" name="linkname">cbe-oss-dev</field> - <field type="CharField" name="name">Cell Broadband Engine development</field> - <field type="CharField" name="listid">cbe-oss-dev.ozlabs.org</field> - <field type="CharField" name="listemail">cbe-oss-dev@ozlabs.org</field> - </object> - <object pk="2" model="patchwork.project"> - <field type="CharField" name="linkname">linuxppc-dev</field> - <field type="CharField" name="name">Linux PPC development</field> - <field type="CharField" name="listid">linuxppc-dev.ozlabs.org</field> - <field type="CharField" name="listemail">linuxppc-dev@ozlabs.org</field> - </object> - -</django-objects> diff --git a/apps/patchwork/fixtures/initial_data.xml b/apps/patchwork/fixtures/initial_data.xml deleted file mode 100644 index 86e1105..0000000 --- a/apps/patchwork/fixtures/initial_data.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<django-objects version="1.0"> - - <!-- default states --> - <object pk="1" model="patchwork.state"> - <field type="CharField" name="name">New</field> - <field type="IntegerField" name="ordering">0</field> - <field type="BooleanField" name="action_required">True</field> - </object> - <object pk="2" model="patchwork.state"> - <field type="CharField" name="name">Under Review</field> - <field type="IntegerField" name="ordering">1</field> - <field type="BooleanField" name="action_required">True</field> - </object> - <object pk="3" model="patchwork.state"> - <field type="CharField" name="name">Accepted</field> - <field type="IntegerField" name="ordering">2</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="4" model="patchwork.state"> - <field type="CharField" name="name">Rejected</field> - <field type="IntegerField" name="ordering">3</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="5" model="patchwork.state"> - <field type="CharField" name="name">RFC</field> - <field type="IntegerField" name="ordering">4</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="6" model="patchwork.state"> - <field type="CharField" name="name">Not Applicable</field> - <field type="IntegerField" name="ordering">5</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="7" model="patchwork.state"> - <field type="CharField" name="name">Changes Requested</field> - <field type="IntegerField" name="ordering">6</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="8" model="patchwork.state"> - <field type="CharField" name="name">Awaiting Upstream</field> - <field type="IntegerField" name="ordering">7</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="9" model="patchwork.state"> - <field type="CharField" name="name">Superseded</field> - <field type="IntegerField" name="ordering">8</field> - <field type="BooleanField" name="action_required">False</field> - </object> - <object pk="10" model="patchwork.state"> - <field type="CharField" name="name">Deferred</field> - <field type="IntegerField" name="ordering">9</field> - <field type="BooleanField" name="action_required">False</field> - </object> -</django-objects> diff --git a/apps/patchwork/forms.py b/apps/patchwork/forms.py deleted file mode 100644 index 0327958..0000000 --- a/apps/patchwork/forms.py +++ /dev/null @@ -1,237 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from django.contrib.auth.models import User -from django import forms - -from patchwork.models import Patch, State, Bundle, UserProfile - -class RegistrationForm(forms.Form): - first_name = forms.CharField(max_length = 30, required = False) - last_name = forms.CharField(max_length = 30, required = False) - username = forms.RegexField(regex = r'^\w+$', max_length=30, - label=u'Username') - email = forms.EmailField(max_length=100, label=u'Email address') - password = forms.CharField(widget=forms.PasswordInput(), - label='Password') - - def clean_username(self): - value = self.cleaned_data['username'] - try: - user = User.objects.get(username__iexact = value) - except User.DoesNotExist: - return self.cleaned_data['username'] - raise forms.ValidationError('This username is already taken. ' + \ - 'Please choose another.') - - def clean_email(self): - value = self.cleaned_data['email'] - try: - user = User.objects.get(email__iexact = value) - except User.DoesNotExist: - return self.cleaned_data['email'] - raise forms.ValidationError('This email address is already in use ' + \ - 'for the account "%s".\n' % user.username) - - def clean(self): - return self.cleaned_data - -class LoginForm(forms.Form): - username = forms.CharField(max_length = 30) - password = forms.CharField(widget = forms.PasswordInput) - -class BundleForm(forms.ModelForm): - name = forms.RegexField(regex = r'^[^/]+$', max_length=50, label=u'Name', - error_messages = {'invalid': 'Bundle names can\'t contain slashes'}) - - class Meta: - model = Bundle - fields = ['name', 'public'] - -class CreateBundleForm(BundleForm): - def __init__(self, *args, **kwargs): - super(CreateBundleForm, self).__init__(*args, **kwargs) - - class Meta: - model = Bundle - fields = ['name'] - - def clean_name(self): - name = self.cleaned_data['name'] - count = Bundle.objects.filter(owner = self.instance.owner, \ - name = name).count() - if count > 0: - raise forms.ValidationError('A bundle called %s already exists' \ - % name) - return name - -class DeleteBundleForm(forms.Form): - name = 'deletebundleform' - form_name = forms.CharField(initial = name, widget = forms.HiddenInput) - bundle_id = forms.IntegerField(widget = forms.HiddenInput) - -class DelegateField(forms.ModelChoiceField): - def __init__(self, project, *args, **kwargs): - queryset = User.objects.filter(profile__in = \ - UserProfile.objects \ - .filter(maintainer_projects = project) \ - .values('pk').query) - super(DelegateField, self).__init__(queryset, *args, **kwargs) - - -class PatchForm(forms.ModelForm): - def __init__(self, instance = None, project = None, *args, **kwargs): - if (not project) and instance: - project = instance.project - if not project: - raise Exception("meep") - super(PatchForm, self).__init__(instance = instance, *args, **kwargs) - self.fields['delegate'] = DelegateField(project, required = False) - - class Meta: - model = Patch - fields = ['state', 'archived', 'delegate'] - -class UserProfileForm(forms.ModelForm): - class Meta: - model = UserProfile - fields = ['primary_project', 'patches_per_page'] - -class OptionalDelegateField(DelegateField): - no_change_choice = ('*', 'no change') - to_field_name = None - - def __init__(self, no_change_choice = None, *args, **kwargs): - self.filter = None - if (no_change_choice): - self.no_change_choice = no_change_choice - super(OptionalDelegateField, self). \ - __init__(initial = self.no_change_choice[0], *args, **kwargs) - - def _get_choices(self): - choices = list( - super(OptionalDelegateField, self)._get_choices()) - choices.append(self.no_change_choice) - return choices - - choices = property(_get_choices, forms.ChoiceField._set_choices) - - def is_no_change(self, value): - return value == self.no_change_choice[0] - - def clean(self, value): - if value == self.no_change_choice[0]: - return value - return super(OptionalDelegateField, self).clean(value) - -class OptionalModelChoiceField(forms.ModelChoiceField): - no_change_choice = ('*', 'no change') - to_field_name = None - - def __init__(self, no_change_choice = None, *args, **kwargs): - self.filter = None - if (no_change_choice): - self.no_change_choice = no_change_choice - super(OptionalModelChoiceField, self). \ - __init__(initial = self.no_change_choice[0], *args, **kwargs) - - def _get_choices(self): - choices = list( - super(OptionalModelChoiceField, self)._get_choices()) - choices.append(self.no_change_choice) - return choices - - choices = property(_get_choices, forms.ChoiceField._set_choices) - - def is_no_change(self, value): - return value == self.no_change_choice[0] - - def clean(self, value): - if value == self.no_change_choice[0]: - return value - return super(OptionalModelChoiceField, self).clean(value) - -class MultipleBooleanField(forms.ChoiceField): - no_change_choice = ('*', 'no change') - def __init__(self, *args, **kwargs): - super(MultipleBooleanField, self).__init__(*args, **kwargs) - self.choices = [self.no_change_choice] + \ - [(True, 'Archived'), (False, 'Unarchived')] - - def is_no_change(self, value): - return value == self.no_change_choice[0] - - # TODO: Check whether it'd be worth to use a TypedChoiceField here; I - # think that'd allow us to get rid of the custom valid_value() and - # to_python() methods. - def valid_value(self, value): - if value in [v1 for (v1, v2) in self.choices]: - return True - return False - - def to_python(self, value): - if value is None or self.is_no_change(value): - return self.no_change_choice[0] - elif value == 'True': - return True - elif value == 'False': - return False - else: - raise ValueError('Unknown value: %s' % value) - -class MultiplePatchForm(forms.Form): - action = 'update' - state = OptionalModelChoiceField(queryset = State.objects.all()) - archived = MultipleBooleanField() - - def __init__(self, project, *args, **kwargs): - super(MultiplePatchForm, self).__init__(*args, **kwargs) - self.fields['delegate'] = OptionalDelegateField(project = project, - required = False) - - def save(self, instance, commit = True): - opts = instance.__class__._meta - if self.errors: - raise ValueError("The %s could not be changed because the data " - "didn't validate." % opts.object_name) - data = self.cleaned_data - # Update the instance - for f in opts.fields: - if not f.name in data: - continue - - field = self.fields.get(f.name, None) - if not field: - continue - - if field.is_no_change(data[f.name]): - continue - - setattr(instance, f.name, data[f.name]) - - if commit: - instance.save() - return instance - -class EmailForm(forms.Form): - email = forms.EmailField(max_length = 200) - -UserPersonLinkForm = EmailForm -OptinoutRequestForm = EmailForm diff --git a/apps/patchwork/models.py b/apps/patchwork/models.py deleted file mode 100644 index 54b8656..0000000 --- a/apps/patchwork/models.py +++ /dev/null @@ -1,386 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django.db import models -from django.contrib.auth.models import User -from django.core.urlresolvers import reverse -from django.contrib.sites.models import Site -from django.conf import settings -from patchwork.parser import hash_patch - -import re -import datetime, time -import random - -class Person(models.Model): - email = models.CharField(max_length=255, unique = True) - name = models.CharField(max_length=255, null = True, blank = True) - user = models.ForeignKey(User, null = True, blank = True, - on_delete = models.SET_NULL) - - def __unicode__(self): - if self.name: - return u'%s <%s>' % (self.name, self.email) - else: - return self.email - - def link_to_user(self, user): - self.name = user.profile.name() - self.user = user - - class Meta: - verbose_name_plural = 'People' - -class Project(models.Model): - linkname = models.CharField(max_length=255, unique=True) - name = models.CharField(max_length=255, unique=True) - listid = models.CharField(max_length=255, unique=True) - listemail = models.CharField(max_length=200) - web_url = models.CharField(max_length=2000, blank=True) - scm_url = models.CharField(max_length=2000, blank=True) - webscm_url = models.CharField(max_length=2000, blank=True) - send_notifications = models.BooleanField(default=False) - - def __unicode__(self): - return self.name - - def is_editable(self, user): - if not user.is_authenticated(): - return False - return self in user.profile.maintainer_projects.all() - - class Meta: - ordering = ['linkname'] - - -class UserProfile(models.Model): - user = models.OneToOneField(User, unique = True, related_name='profile') - primary_project = models.ForeignKey(Project, null = True, blank = True) - maintainer_projects = models.ManyToManyField(Project, - related_name = 'maintainer_project') - send_email = models.BooleanField(default = False, - help_text = 'Selecting this option allows patchwork to send ' + - 'email on your behalf') - patches_per_page = models.PositiveIntegerField(default = 100, - null = False, blank = False, - help_text = 'Number of patches to display per page') - - def name(self): - if self.user.first_name or self.user.last_name: - names = filter(bool, [self.user.first_name, self.user.last_name]) - return u' '.join(names) - return self.user.username - - def contributor_projects(self): - submitters = Person.objects.filter(user = self.user) - return Project.objects.filter(id__in = - Patch.objects.filter( - submitter__in = submitters) - .values('project_id').query) - - def sync_person(self): - pass - - def n_todo_patches(self): - return self.todo_patches().count() - - def todo_patches(self, project = None): - - # filter on project, if necessary - if project: - qs = Patch.objects.filter(project = project) - else: - qs = Patch.objects - - qs = qs.filter(archived = False) \ - .filter(delegate = self.user) \ - .filter(state__in = - State.objects.filter(action_required = True) - .values('pk').query) - return qs - - def __unicode__(self): - return self.name() - -def _user_saved_callback(sender, created, instance, **kwargs): - try: - profile = instance.profile - except UserProfile.DoesNotExist: - profile = UserProfile(user = instance) - profile.save() - -models.signals.post_save.connect(_user_saved_callback, sender = User) - -class State(models.Model): - name = models.CharField(max_length = 100) - ordering = models.IntegerField(unique = True) - action_required = models.BooleanField(default = True) - - def __unicode__(self): - return self.name - - class Meta: - ordering = ['ordering'] - -class HashField(models.CharField): - __metaclass__ = models.SubfieldBase - - def __init__(self, algorithm = 'sha1', *args, **kwargs): - self.algorithm = algorithm - try: - import hashlib - def _construct(string = ''): - return hashlib.new(self.algorithm, string) - self.construct = _construct - self.n_bytes = len(hashlib.new(self.algorithm).hexdigest()) - except ImportError: - modules = { 'sha1': 'sha', 'md5': 'md5'} - - if algorithm not in modules.keys(): - raise NameError("Unknown algorithm '%s'" % algorithm) - - self.construct = __import__(modules[algorithm]).new - - self.n_bytes = len(self.construct().hexdigest()) - - kwargs['max_length'] = self.n_bytes - super(HashField, self).__init__(*args, **kwargs) - - def db_type(self, connection=None): - return 'char(%d)' % self.n_bytes - -def get_default_initial_patch_state(): - return State.objects.get(ordering=0) - -class Patch(models.Model): - project = models.ForeignKey(Project) - msgid = models.CharField(max_length=255) - name = models.CharField(max_length=255) - date = models.DateTimeField(default=datetime.datetime.now) - submitter = models.ForeignKey(Person) - delegate = models.ForeignKey(User, blank = True, null = True) - state = models.ForeignKey(State, default=get_default_initial_patch_state) - archived = models.BooleanField(default = False) - headers = models.TextField(blank = True) - content = models.TextField(null = True, blank = True) - pull_url = models.CharField(max_length=255, null = True, blank = True) - commit_ref = models.CharField(max_length=255, null = True, blank = True) - hash = HashField(null = True, blank = True) - - def __unicode__(self): - return self.name - - def comments(self): - return Comment.objects.filter(patch = self) - - def save(self): - try: - s = self.state - except: - self.state = State.objects.get(ordering = 0) - - if self.hash is None and self.content is not None: - self.hash = hash_patch(self.content).hexdigest() - - super(Patch, self).save() - - def is_editable(self, user): - if not user.is_authenticated(): - return False - - if self.submitter.user == user or self.delegate == user: - return True - - return self.project.is_editable(user) - - def filename(self): - fname_re = re.compile('[^-_A-Za-z0-9\.]+') - str = fname_re.sub('-', self.name) - return str.strip('-') + '.patch' - - @models.permalink - def get_absolute_url(self): - return ('patchwork.views.patch.patch', (), {'patch_id': self.id}) - - class Meta: - verbose_name_plural = 'Patches' - ordering = ['date'] - unique_together = [('msgid', 'project')] - -class Comment(models.Model): - patch = models.ForeignKey(Patch) - msgid = models.CharField(max_length=255) - submitter = models.ForeignKey(Person) - date = models.DateTimeField(default = datetime.datetime.now) - headers = models.TextField(blank = True) - content = models.TextField() - - response_re = re.compile( \ - '^(Tested|Reviewed|Acked|Signed-off|Nacked|Reported)-by: .*$', - re.M | re.I) - - def patch_responses(self): - return ''.join([ match.group(0) + '\n' for match in - self.response_re.finditer(self.content)]) - - class Meta: - ordering = ['date'] - unique_together = [('msgid', 'patch')] - -class Bundle(models.Model): - owner = models.ForeignKey(User) - project = models.ForeignKey(Project) - name = models.CharField(max_length = 50, null = False, blank = False) - patches = models.ManyToManyField(Patch, through = 'BundlePatch') - public = models.BooleanField(default = False) - - def n_patches(self): - return self.patches.all().count() - - def ordered_patches(self): - return self.patches.order_by('bundlepatch__order') - - def append_patch(self, patch): - # todo: use the aggregate queries in django 1.1 - orders = BundlePatch.objects.filter(bundle = self).order_by('-order') \ - .values('order') - - if len(orders) > 0: - max_order = orders[0]['order'] - else: - max_order = 0 - - # see if the patch is already in this bundle - if BundlePatch.objects.filter(bundle = self, patch = patch).count(): - raise Exception("patch is already in bundle") - - bp = BundlePatch.objects.create(bundle = self, patch = patch, - order = max_order + 1) - bp.save() - - class Meta: - unique_together = [('owner', 'name')] - - def public_url(self): - if not self.public: - return None - site = Site.objects.get_current() - return 'http://%s%s' % (site.domain, - reverse('patchwork.views.bundle.bundle', - kwargs = { - 'username': self.owner.username, - 'bundlename': self.name - })) - - @models.permalink - def get_absolute_url(self): - return ('patchwork.views.bundle.bundle', (), { - 'username': self.owner.username, - 'bundlename': self.name, - }) - -class BundlePatch(models.Model): - patch = models.ForeignKey(Patch) - bundle = models.ForeignKey(Bundle) - order = models.IntegerField() - - class Meta: - unique_together = [('bundle', 'patch')] - ordering = ['order'] - -class EmailConfirmation(models.Model): - validity = datetime.timedelta(days = settings.CONFIRMATION_VALIDITY_DAYS) - type = models.CharField(max_length = 20, choices = [ - ('userperson', 'User-Person association'), - ('registration', 'Registration'), - ('optout', 'Email opt-out'), - ]) - email = models.CharField(max_length = 200) - user = models.ForeignKey(User, null = True) - key = HashField() - date = models.DateTimeField(default = datetime.datetime.now) - active = models.BooleanField(default = True) - - def deactivate(self): - self.active = False - self.save() - - def is_valid(self): - return self.date + self.validity > datetime.datetime.now() - - def save(self): - max = 1 << 32 - if self.key == '': - str = '%s%s%d' % (self.user, self.email, random.randint(0, max)) - self.key = self._meta.get_field('key').construct(str).hexdigest() - super(EmailConfirmation, self).save() - -class EmailOptout(models.Model): - email = models.CharField(max_length = 200, primary_key = True) - - def __unicode__(self): - return self.email - - @classmethod - def is_optout(cls, email): - email = email.lower().strip() - return cls.objects.filter(email = email).count() > 0 - -class PatchChangeNotification(models.Model): - patch = models.ForeignKey(Patch, primary_key = True) - last_modified = models.DateTimeField(default = datetime.datetime.now) - orig_state = models.ForeignKey(State) - -def _patch_change_callback(sender, instance, **kwargs): - # we only want notification of modified patches - if instance.pk is None: - return - - if instance.project is None or not instance.project.send_notifications: - return - - try: - orig_patch = Patch.objects.get(pk = instance.pk) - except Patch.DoesNotExist: - return - - # If there's no interesting changes, abort without creating the - # notification - if orig_patch.state == instance.state: - return - - notification = None - try: - notification = PatchChangeNotification.objects.get(patch = instance) - except PatchChangeNotification.DoesNotExist: - pass - - if notification is None: - notification = PatchChangeNotification(patch = instance, - orig_state = orig_patch.state) - - elif notification.orig_state == instance.state: - # If we're back at the original state, there is no need to notify - notification.delete() - return - - notification.last_modified = datetime.datetime.now() - notification.save() - -models.signals.pre_save.connect(_patch_change_callback, sender = Patch) diff --git a/apps/patchwork/paginator.py b/apps/patchwork/paginator.py deleted file mode 100644 index 31c0190..0000000 --- a/apps/patchwork/paginator.py +++ /dev/null @@ -1,88 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from django.core import paginator -from django.conf import settings - -DEFAULT_PATCHES_PER_PAGE = 100 -LONG_PAGE_THRESHOLD = 30 -LEADING_PAGE_RANGE_DISPLAYED = TRAILING_PAGE_RANGE_DISPLAYED = 10 -LEADING_PAGE_RANGE = TRAILING_PAGE_RANGE = 8 -NUM_PAGES_OUTSIDE_RANGE = 2 -ADJACENT_PAGES = 4 - -# parts from: -# http://blog.localkinegrinds.com/2007/09/06/digg-style-pagination-in-django/ - -class Paginator(paginator.Paginator): - def __init__(self, request, objects): - - patches_per_page = settings.DEFAULT_PATCHES_PER_PAGE - - if request.user.is_authenticated(): - patches_per_page = request.user.profile.patches_per_page - - n = request.META.get('ppp') - if n: - try: - patches_per_page = int(n) - except ValueError: - pass - - super(Paginator, self).__init__(objects, patches_per_page) - - try: - page_no = int(request.GET.get('page')) - self.current_page = self.page(int(page_no)) - except Exception: - page_no = 1 - self.current_page = self.page(page_no) - - self.leading_set = self.trailing_set = [] - - pages = self.num_pages - - if pages <= LEADING_PAGE_RANGE_DISPLAYED: - self.adjacent_set = [n for n in range(1, pages + 1) \ - if n > 0 and n <= pages] - elif page_no <= LEADING_PAGE_RANGE: - self.adjacent_set = [n for n in \ - range(1, LEADING_PAGE_RANGE_DISPLAYED + 1) \ - if n > 0 and n <= pages] - self.leading_set = [n + pages for n in \ - range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)] - elif page_no > pages - TRAILING_PAGE_RANGE: - self.adjacent_set = [n for n in \ - range(pages - TRAILING_PAGE_RANGE_DISPLAYED + 1, \ - pages + 1) if n > 0 and n <= pages] - self.trailing_set = [n + 1 for n in range(0, \ - NUM_PAGES_OUTSIDE_RANGE)] - else: - self.adjacent_set = [n for n in range(page_no - ADJACENT_PAGES, \ - page_no + ADJACENT_PAGES + 1) if n > 0 and n <= pages] - self.leading_set = [n + pages for n in \ - range(0, -NUM_PAGES_OUTSIDE_RANGE, -1)] - self.trailing_set = [n + 1 for n in \ - range(0, NUM_PAGES_OUTSIDE_RANGE)] - - - self.leading_set.reverse() - self.long_page = \ - len(self.current_page.object_list) >= LONG_PAGE_THRESHOLD diff --git a/apps/patchwork/parser.py b/apps/patchwork/parser.py deleted file mode 100644 index a51a7b6..0000000 --- a/apps/patchwork/parser.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env python -# -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -import re - -try: - import hashlib - sha1_hash = hashlib.sha1 -except ImportError: - import sha - sha1_hash = sha.sha - -_hunk_re = re.compile('^\@\@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? \@\@') -_filename_re = re.compile('^(---|\+\+\+) (\S+)') - -def parse_patch(text): - patchbuf = '' - commentbuf = '' - buf = '' - - # state specified the line we just saw, and what to expect next - state = 0 - # 0: text - # 1: suspected patch header (diff, ====, Index:) - # 2: patch header line 1 (---) - # 3: patch header line 2 (+++) - # 4: patch hunk header line (@@ line) - # 5: patch hunk content - # 6: patch meta header (rename from/rename to) - # - # valid transitions: - # 0 -> 1 (diff, ===, Index:) - # 0 -> 2 (---) - # 1 -> 2 (---) - # 2 -> 3 (+++) - # 3 -> 4 (@@ line) - # 4 -> 5 (patch content) - # 5 -> 1 (run out of lines from @@-specifed count) - # 1 -> 6 (rename from / rename to) - # 6 -> 2 (---) - # 6 -> 1 (other text) - # - # Suspected patch header is stored into buf, and appended to - # patchbuf if we find a following hunk. Otherwise, append to - # comment after parsing. - - # line counts while parsing a patch hunk - lc = (0, 0) - hunk = 0 - - - for line in text.split('\n'): - line += '\n' - - if state == 0: - if line.startswith('diff ') or line.startswith('===') \ - or line.startswith('Index: '): - state = 1 - buf += line - - elif line.startswith('--- '): - state = 2 - buf += line - - else: - commentbuf += line - - elif state == 1: - buf += line - if line.startswith('--- '): - state = 2 - - if line.startswith('rename from ') or line.startswith('rename to '): - state = 6 - - elif state == 2: - if line.startswith('+++ '): - state = 3 - buf += line - - elif hunk: - state = 1 - buf += line - - else: - state = 0 - commentbuf += buf + line - buf = '' - - elif state == 3: - match = _hunk_re.match(line) - if match: - - def fn(x): - if not x: - return 1 - return int(x) - - lc = map(fn, match.groups()) - - state = 4 - patchbuf += buf + line - buf = '' - - elif line.startswith('--- '): - patchbuf += buf + line - buf = '' - state = 2 - - elif hunk and line.startswith('\ No newline at end of file'): - # If we had a hunk and now we see this, it's part of the patch, - # and we're still expecting another @@ line. - patchbuf += line - - elif hunk: - state = 1 - buf += line - - else: - state = 0 - commentbuf += buf + line - buf = '' - - elif state == 4 or state == 5: - if line.startswith('-'): - lc[0] -= 1 - elif line.startswith('+'): - lc[1] -= 1 - elif line.startswith('\ No newline at end of file'): - # Special case: Not included as part of the hunk's line count - pass - else: - lc[0] -= 1 - lc[1] -= 1 - - patchbuf += line - - if lc[0] <= 0 and lc[1] <= 0: - state = 3 - hunk += 1 - else: - state = 5 - - elif state == 6: - if line.startswith('rename to ') or line.startswith('rename from '): - patchbuf += buf + line - buf = '' - - elif line.startswith('--- '): - patchbuf += buf + line - buf = '' - state = 2 - - else: - buf += line - state = 1 - - else: - raise Exception("Unknown state %d! (line '%s')" % (state, line)) - - commentbuf += buf - - if patchbuf == '': - patchbuf = None - - if commentbuf == '': - commentbuf = None - - return (patchbuf, commentbuf) - -def hash_patch(str): - # normalise spaces - str = str.replace('\r', '') - str = str.strip() + '\n' - - prefixes = ['-', '+', ' '] - hash = sha1_hash() - - for line in str.split('\n'): - - if len(line) <= 0: - continue - - hunk_match = _hunk_re.match(line) - filename_match = _filename_re.match(line) - - if filename_match: - # normalise -p1 top-directories - if filename_match.group(1) == '---': - filename = 'a/' - else: - filename = 'b/' - filename += '/'.join(filename_match.group(2).split('/')[1:]) - - line = filename_match.group(1) + ' ' + filename - - elif hunk_match: - # remove line numbers, but leave line counts - def fn(x): - if not x: - return 1 - return int(x) - line_nos = map(fn, hunk_match.groups()) - line = '@@ -%d +%d @@' % tuple(line_nos) - - elif line[0] in prefixes: - # if we have a +, - or context line, leave as-is - pass - - else: - # other lines are ignored - continue - - hash.update(line.encode('utf-8') + '\n') - - return hash - - -def main(args): - from optparse import OptionParser - - parser = OptionParser() - parser.add_option('-p', '--patch', action = 'store_true', - dest = 'print_patch', help = 'print parsed patch') - parser.add_option('-c', '--comment', action = 'store_true', - dest = 'print_comment', help = 'print parsed comment') - parser.add_option('-#', '--hash', action = 'store_true', - dest = 'print_hash', help = 'print patch hash') - - (options, args) = parser.parse_args() - - # decode from (assumed) UTF-8 - content = sys.stdin.read().decode('utf-8') - - (patch, comment) = parse_patch(content) - - if options.print_hash and patch: - print hash_patch(patch).hexdigest() - - if options.print_patch and patch: - print "Patch: ------\n" + patch - - if options.print_comment and comment: - print "Comment: ----\n" + comment - -if __name__ == '__main__': - import sys - sys.exit(main(sys.argv)) diff --git a/apps/patchwork/requestcontext.py b/apps/patchwork/requestcontext.py deleted file mode 100644 index 3b1afaf..0000000 --- a/apps/patchwork/requestcontext.py +++ /dev/null @@ -1,89 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django.template import RequestContext -from django.utils.html import escape -from django.contrib.sites.models import Site -from django.conf import settings -from patchwork.filters import Filters -from patchwork.models import Bundle, Project - -def bundle(request): - user = request.user - if not user.is_authenticated(): - return {} - return {'bundles': Bundle.objects.filter(owner = user)} - -def _params_as_qs(params): - return '&'.join([ '%s=%s' % (escape(k), escape(v)) for k, v in params ]) - -def _params_as_hidden_fields(params): - return '\n'.join([ '<input type="hidden" name="%s" value="%s"/>' % \ - (escape(k), escape(v)) for k, v in params ]) - -class PatchworkRequestContext(RequestContext): - def __init__(self, request, project = None, - dict = None, processors = None, - list_view = None, list_view_params = {}): - self._project = project - self.filters = Filters(request) - if processors is None: - processors = [] - processors.append(bundle) - super(PatchworkRequestContext, self). \ - __init__(request, dict, processors); - - self.update({ - 'filters': self.filters, - 'messages': [], - }) - if list_view: - params = self.filters.params() - for param in ['order', 'page']: - value = request.REQUEST.get(param, None) - if value: - params.append((param, value)) - self.update({ - 'list_view': { - 'view': list_view, - 'view_params': list_view_params, - 'params': params - }}) - - self.projects = Project.objects.all() - - self.update({ - 'project': self.project, - 'site': Site.objects.get_current(), - 'settings': settings, - 'other_projects': len(self.projects) > 1 - }) - - def _set_project(self, project): - self._project = project - self.filters.set_project(project) - self.update({'project': self._project}) - - def _get_project(self): - return self._project - - project = property(_get_project, _set_project) - - def add_message(self, message): - self['messages'].append(message) diff --git a/apps/patchwork/settings/__init__.py b/apps/patchwork/settings/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/apps/patchwork/settings/__init__.py +++ /dev/null diff --git a/apps/patchwork/settings/base.py b/apps/patchwork/settings/base.py deleted file mode 100644 index 5440de6..0000000 --- a/apps/patchwork/settings/base.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Base settings for patchwork project. -""" - -import os - -import django - -ROOT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), - os.pardir, os.pardir, os.pardir) - -# -# Core settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#core-settings -# - -# Models - -INSTALLED_APPS = [ - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.staticfiles', - 'patchwork', -] - -# HTTP - -MIDDLEWARE_CLASSES = [ - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', -] - -if django.VERSION < (1, 7): - MIDDLEWARE_CLASSES.append('django.middleware.doc.XViewMiddleware') -else: - MIDDLEWARE_CLASSES.append( - 'django.contrib.admindocs.middleware.XViewMiddleware') - -# Globalization - -TIME_ZONE = 'Australia/Canberra' - -LANGUAGE_CODE = 'en-au' - -USE_I18N = True - -# URLs - -ROOT_URLCONF = 'patchwork.urls' - -# Templates - -TEMPLATE_DIRS = ( - os.path.join(ROOT_DIR, 'templates'), -) - - -# -# Auth settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#auth -# - -LOGIN_URL = '/user/login/' -LOGIN_REDIRECT_URL = '/user/' - - -# -# Sites settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#sites -# - -SITE_ID = 1 - - -# -# Static files settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#static-files -# - -STATIC_URL = '/static/' - -STATICFILES_DIRS = [ - os.path.join(ROOT_DIR, 'htdocs'), -] - - -# -# Patchwork settings -# - -DEFAULT_PATCHES_PER_PAGE = 100 -DEFAULT_FROM_EMAIL = 'Patchwork <patchwork@patchwork.example.com>' - -CONFIRMATION_VALIDITY_DAYS = 7 - -NOTIFICATION_DELAY_MINUTES = 10 -NOTIFICATION_FROM_EMAIL = DEFAULT_FROM_EMAIL - -# Set to True to enable the Patchwork XML-RPC interface -ENABLE_XMLRPC = False - -# Set to True to enable redirections or URLs from previous versions -# of patchwork -COMPAT_REDIR = True - -# Set to True to always generate https:// links instead of guessing -# the scheme based on current access. This is useful if SSL protocol -# is terminated upstream of the server (e.g. at the load balancer) -FORCE_HTTPS_LINKS = False diff --git a/apps/patchwork/settings/dev.py b/apps/patchwork/settings/dev.py deleted file mode 100644 index 6e373cc..0000000 --- a/apps/patchwork/settings/dev.py +++ /dev/null @@ -1,52 +0,0 @@ -""" -Development settings for patchwork project. - -These are also used in unit tests. - -Design based on: - http://www.revsys.com/blog/2014/nov/21/recommended-django-project-layout/ -""" - -import django - -from base import * - -# -# Core settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#core-settings -# - -# Security - -SECRET_KEY = '00000000000000000000000000000000000000000000000000' - -# Debugging - -DEBUG = True - -# Templates - -TEMPLATE_DEBUG = True - -# Database - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.mysql', - 'HOST': 'localhost', - 'PORT': '', - 'USER': os.environ['PW_TEST_DB_USER'], - 'PASSWORD': os.environ['PW_TEST_DB_PASS'], - 'NAME': 'patchwork', - 'TEST_CHARSET': 'utf8', - }, -} - -if django.VERSION >= (1, 7): - TEST_RUNNER = 'django.test.runner.DiscoverRunner' - -# -# Patchwork settings -# - -ENABLE_XMLRPC = True diff --git a/apps/patchwork/settings/prod.py b/apps/patchwork/settings/prod.py deleted file mode 100644 index d71f3df..0000000 --- a/apps/patchwork/settings/prod.py +++ /dev/null @@ -1,62 +0,0 @@ -""" -Sample production-ready settings for patchwork project. - -Most of these are commented out as they will be installation dependent. - -Design based on: - http://www.revsys.com/blog/2014/nov/21/recommended-django-project-layout/ -""" - -from base import * - -# -# Core settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#core-settings -# - -# Security - -# SECRET_KEY = '00000000000000000000000000000000000000000000000000' - -# Email - -# ADMINS = ( -# ('Jeremy Kerr', 'jk@ozlabs.org'), -# ) - -# Database - -# DATABASES = { -# 'default': { -# 'ENGINE': 'django.db.backends.postgresql_psycopg2', -# 'NAME': 'patchwork', -# }, -# } - -# File Uploads - -# MEDIA_ROOT = os.path.join( -# ROOT_DIR, 'lib', 'python', 'django', 'contrib', 'admin', 'media') - - -# -# Static files settings -# https://docs.djangoproject.com/en/1.6/ref/settings/#static-files -# - -# STATIC_ROOT = '/srv/patchwork/htdocs' - - -# -# Custom user overrides (for legacy) -# - -try: - from local_settings import * -except ImportError, ex: - import sys - sys.stderr.write(\ - ("settings.py: error importing local settings file:\n" + \ - "\t%s\n" + \ - "Do you have a local_settings.py module?\n") % str(ex)) - raise diff --git a/apps/patchwork/templatetags/__init__.py b/apps/patchwork/templatetags/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/apps/patchwork/templatetags/__init__.py +++ /dev/null diff --git a/apps/patchwork/templatetags/filter.py b/apps/patchwork/templatetags/filter.py deleted file mode 100644 index 7a5d9df..0000000 --- a/apps/patchwork/templatetags/filter.py +++ /dev/null @@ -1,36 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -from django.utils.html import escape - -import re - - -register = template.Library() - -@register.filter -def personify(person): - if person.name: - linktext = escape(person.name) - else: - linktext = escape(person.email) - - return '<a href="javascript:personpopup(\'%s\')">%s</a>' % (escape(person.email), linktext) - diff --git a/apps/patchwork/templatetags/listurl.py b/apps/patchwork/templatetags/listurl.py deleted file mode 100644 index 5fe03e4..0000000 --- a/apps/patchwork/templatetags/listurl.py +++ /dev/null @@ -1,136 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -from django.utils.html import escape -from django.utils.safestring import mark_safe -from django.utils.encoding import smart_str -from patchwork.filters import filterclasses -from django.conf import settings -from django.core.urlresolvers import reverse, NoReverseMatch -import re - -register = template.Library() - -# params to preserve across views -list_params = [ c.param for c in filterclasses ] + ['order', 'page'] - -class ListURLNode(template.defaulttags.URLNode): - def __init__(self, kwargs): - super(ListURLNode, self).__init__(None, [], {}, False) - self.params = {} - for (k, v) in kwargs.iteritems(): - if k in list_params: - self.params[k] = v - - def render(self, context): - view_name = template.Variable('list_view.view').resolve(context) - kwargs = template.Variable('list_view.view_params') \ - .resolve(context) - - str = None - try: - str = reverse(view_name, args=[], kwargs=kwargs) - except NoReverseMatch: - try: - project_name = settings.SETTINGS_MODULE.split('.')[0] - str = reverse(project_name + '.' + view_name, - args=[], kwargs=kwargs) - except NoReverseMatch: - raise - - if str is None: - return '' - - params = [] - try: - qs_var = template.Variable('list_view.params') - params = dict(qs_var.resolve(context)) - except Exception: - pass - - for (k, v) in self.params.iteritems(): - params[smart_str(k,'ascii')] = v.resolve(context) - - if not params: - return str - - return str + '?' + '&'.join(['%s=%s' % (k, escape(v)) \ - for (k, v) in params.iteritems()]) - -@register.tag -def listurl(parser, token): - bits = token.contents.split(' ', 1) - if len(bits) < 1: - raise TemplateSyntaxError("'%s' takes at least one argument" - " (path to a view)" % bits[0]) - kwargs = {} - if len(bits) > 1: - for arg in bits[1].split(','): - if '=' in arg: - k, v = arg.split('=', 1) - k = k.strip() - kwargs[k] = parser.compile_filter(v) - else: - raise TemplateSyntaxError("'%s' requires name=value params" \ - % bits[0]) - return ListURLNode(kwargs) - -class ListFieldsNode(template.Node): - def __init__(self, params): - self.params = params - - def render(self, context): - self.view_name = template.Variable('list_view.view').resolve(context) - try: - qs_var = template.Variable('list_view.params') - params = dict(qs_var.resolve(context)) - except Exception: - pass - - params.update(self.params) - - if not params: - return '' - - str = '' - for (k, v) in params.iteritems(): - str += '<input type="hidden" name="%s" value="%s"\>' % \ - (k, escape(v)) - - return mark_safe(str) - -@register.tag -def listfields(parser, token): - bits = token.contents.split(' ', 1) - if len(bits) < 1: - raise TemplateSyntaxError("'%s' takes at least one argument" - " (path to a view)" % bits[0]) - params = {} - if len(bits) > 2: - for arg in bits[2].split(','): - if '=' in arg: - k, v = arg.split('=', 1) - k = k.strip() - params[k] = parser.compile_filter(v) - else: - raise TemplateSyntaxError("'%s' requires name=value params" \ - % bits[0]) - return ListFieldsNode(bits[1], params) - diff --git a/apps/patchwork/templatetags/order.py b/apps/patchwork/templatetags/order.py deleted file mode 100644 index e392f03..0000000 --- a/apps/patchwork/templatetags/order.py +++ /dev/null @@ -1,66 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from django import template -import re - -register = template.Library() - -@register.tag(name = 'ifpatcheditable') -def do_patch_is_editable(parser, token): - try: - tag_name, name, cur_order = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError("%r tag requires two arguments" \ - % token.contents.split()[0]) - - end_tag = 'endifpatcheditable' - nodelist_true = parser.parse([end_tag, 'else']) - - token = parser.next_token() - if token.contents == 'else': - nodelist_false = parser.parse([end_tag]) - parser.delete_first_token() - else: - nodelist_false = template.NodeList() - - return EditablePatchNode(patch_var, nodelist_true, nodelist_false) - -class EditablePatchNode(template.Node): - def __init__(self, patch_var, nodelist_true, nodelist_false): - self.nodelist_true = nodelist_true - self.nodelist_false = nodelist_false - self.patch_var = template.Variable(patch_var) - self.user_var = template.Variable('user') - - def render(self, context): - try: - patch = self.patch_var.resolve(context) - user = self.user_var.resolve(context) - except template.VariableDoesNotExist: - return '' - - if not user.is_authenticated(): - return self.nodelist_false.render(context) - - if not patch.is_editable(user): - return self.nodelist_false.render(context) - - return self.nodelist_true.render(context) diff --git a/apps/patchwork/templatetags/patch.py b/apps/patchwork/templatetags/patch.py deleted file mode 100644 index bec0cab..0000000 --- a/apps/patchwork/templatetags/patch.py +++ /dev/null @@ -1,65 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -import re - -register = template.Library() - -@register.tag(name = 'ifpatcheditable') -def do_patch_is_editable(parser, token): - try: - tag_name, patch_var = token.split_contents() - except ValueError: - raise template.TemplateSyntaxError("%r tag requires one argument" \ - % token.contents.split()[0]) - - end_tag = 'endifpatcheditable' - nodelist_true = parser.parse([end_tag, 'else']) - - token = parser.next_token() - if token.contents == 'else': - nodelist_false = parser.parse([end_tag]) - parser.delete_first_token() - else: - nodelist_false = template.NodeList() - - return EditablePatchNode(patch_var, nodelist_true, nodelist_false) - -class EditablePatchNode(template.Node): - def __init__(self, patch_var, nodelist_true, nodelist_false): - self.nodelist_true = nodelist_true - self.nodelist_false = nodelist_false - self.patch_var = template.Variable(patch_var) - self.user_var = template.Variable('user') - - def render(self, context): - try: - patch = self.patch_var.resolve(context) - user = self.user_var.resolve(context) - except template.VariableDoesNotExist: - return '' - - if not user.is_authenticated(): - return self.nodelist_false.render(context) - - if not patch.is_editable(user): - return self.nodelist_false.render(context) - - return self.nodelist_true.render(context) diff --git a/apps/patchwork/templatetags/person.py b/apps/patchwork/templatetags/person.py deleted file mode 100644 index c337c74..0000000 --- a/apps/patchwork/templatetags/person.py +++ /dev/null @@ -1,43 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -from django.utils.html import escape -from django.utils.safestring import mark_safe -from django.core.urlresolvers import reverse -from patchwork.filters import SubmitterFilter -import re - -register = template.Library() - -@register.filter -def personify(person, project): - - if person.name: - linktext = escape(person.name) - else: - linktext = escape(person.email) - - url = reverse('patchwork.views.patch.list', kwargs = {'project_id' : project.linkname}) - str = '<a href="%s?%s=%s">%s</a>' % \ - (url, SubmitterFilter.param, escape(person.id), linktext) - - return mark_safe(str) - - diff --git a/apps/patchwork/templatetags/pwurl.py b/apps/patchwork/templatetags/pwurl.py deleted file mode 100644 index 98bc1ca..0000000 --- a/apps/patchwork/templatetags/pwurl.py +++ /dev/null @@ -1,76 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -from django.utils.html import escape -from django.utils.safestring import mark_safe -from patchwork.filters import filterclasses -import re - -register = template.Library() - -# params to preserve across views -list_params = [ c.param for c in filterclasses ] + ['order', 'page'] - -class ListURLNode(template.defaulttags.URLNode): - def __init__(self, *args, **kwargs): - super(ListURLNode, self).__init__(*args, **kwargs) - self.params = {} - for (k, v) in kwargs: - if k in list_params: - self.params[k] = v - - def render(self, context): - self.view_name = template.Variable('list_view.view') - str = super(ListURLNode, self).render(context) - if str == '': - return str - params = [] - try: - qs_var = template.Variable('list_view.params') - params = dict(qs_var.resolve(context)) - except Exception: - pass - - params.update(self.params) - - if not params: - return str - - return str + '?' + '&'.join(['%s=%s' % (k, escape(v)) \ - for (k, v) in params.iteritems()]) - -@register.tag -def listurl(parser, token): - bits = token.contents.split(' ', 1) - if len(bits) < 1: - raise TemplateSyntaxError("'%s' takes at least one argument" - " (path to a view)" % bits[0]) - args = [''] - kwargs = {} - if len(bits) > 1: - for arg in bits[2].split(','): - if '=' in arg: - k, v = arg.split('=', 1) - k = k.strip() - kwargs[k] = parser.compile_filter(v) - else: - args.append(parser.compile_filter(arg)) - return PatchworkURLNode(bits[1], args, kwargs) - diff --git a/apps/patchwork/templatetags/syntax.py b/apps/patchwork/templatetags/syntax.py deleted file mode 100644 index abdbb4d..0000000 --- a/apps/patchwork/templatetags/syntax.py +++ /dev/null @@ -1,75 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django import template -from django.utils.html import escape -from django.utils.safestring import mark_safe -import re - -register = template.Library() - -def _compile(t): - (r, str) = t - return (re.compile(r, re.M | re.I), str) - -_patch_span_res = map(_compile, [ - ('^(Index:?|diff|\-\-\-|\+\+\+|\*\*\*) .*$', 'p_header'), - ('^\+.*$', 'p_add'), - ('^-.*$', 'p_del'), - ('^!.*$', 'p_mod'), - ]) - -_patch_chunk_re = \ - re.compile('^(@@ \-\d+(?:,\d+)? \+\d+(?:,\d+)? @@)(.*)$', re.M | re.I) - -_comment_span_res = map(_compile, [ - ('^\s*Signed-off-by: .*$', 'signed-off-by'), - ('^\s*Acked-by: .*$', 'acked-by'), - ('^\s*Nacked-by: .*$', 'nacked-by'), - ('^\s*Tested-by: .*$', 'tested-by'), - ('^\s*Reviewed-by: .*$', 'reviewed-by'), - ('^\s*From: .*$', 'from'), - ('^\s*>.*$', 'quote'), - ]) - -_span = '<span class="%s">%s</span>' - -@register.filter -def patchsyntax(patch): - content = escape(patch.content) - - for (r,cls) in _patch_span_res: - content = r.sub(lambda x: _span % (cls, x.group(0)), content) - - content = _patch_chunk_re.sub( \ - lambda x: \ - _span % ('p_chunk', x.group(1)) + ' ' + \ - _span % ('p_context', x.group(2)), \ - content) - - return mark_safe(content) - -@register.filter -def commentsyntax(comment): - content = escape(comment.content) - - for (r,cls) in _comment_span_res: - content = r.sub(lambda x: _span % (cls, x.group(0)), content) - - return mark_safe(content) diff --git a/apps/patchwork/tests/__init__.py b/apps/patchwork/tests/__init__.py deleted file mode 100644 index 85200bd..0000000 --- a/apps/patchwork/tests/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from patchwork.tests.test_patchparser import * -from patchwork.tests.test_encodings import * -from patchwork.tests.test_bundles import * -from patchwork.tests.test_mboxviews import * -from patchwork.tests.test_updates import * -from patchwork.tests.test_filters import * -from patchwork.tests.test_confirm import * -from patchwork.tests.test_registration import * -from patchwork.tests.test_user import * -from patchwork.tests.test_mail_settings import * -from patchwork.tests.test_notifications import * -from patchwork.tests.test_list import * -from patchwork.tests.test_person import * -from patchwork.tests.test_expiry import * -from patchwork.tests.test_xmlrpc import * diff --git a/apps/patchwork/tests/mail/0001-git-pull-request.mbox b/apps/patchwork/tests/mail/0001-git-pull-request.mbox deleted file mode 100644 index 0dbedbe..0000000 --- a/apps/patchwork/tests/mail/0001-git-pull-request.mbox +++ /dev/null @@ -1,348 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -Hi Linus ! - -Here's powerpc's batch for this merge window. Mostly bits and pieces, -such as Anton doing some performance tuning left and right, and the -usual churn. One hilight is the support for the new Freescale e5500 core -(64-bit BookE). Another one is that we now wire up the whole lot of -socket calls as direct syscalls in addition to the old style indirect -method. - -Cheers, -Ben. - -The following changes since commit e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next - -Andreas Schwab (1): - powerpc: Remove fpscr use from [kvm_]cvt_{fd,df} - -Anton Blanchard (5): - powerpc: Optimise 64bit csum_partial - powerpc: Optimise 64bit csum_partial_copy_generic and add csum_and_copy_from_user - powerpc: Add 64bit csum_and_copy_to_user - powerpc: Feature nop out reservation clear when stcx checks address - powerpc: Check end of stack canary at oops time - -Arnd Bergmann (1): - powerpc/spufs: Use llseek in all file operations - -Benjamin Herrenschmidt (4): - powerpc/dma: Add optional platform override of dma_set_mask() - powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe - Merge remote branch 'kumar/merge' into next - Merge remote branch 'jwb/next' into next - -Denis Kirjanov (1): - powerpc: Use is_32bit_task() helper to test 32-bit binary - -Harninder Rai (1): - powerpc/85xx: add cache-sram support - -Ian Munsie (1): - powerpc: Wire up direct socket system calls - -Ilya Yanok (1): - powerpc/mpc83xx: Support for MPC8308 P1M board - -Joe Perches (2): - powerpc: Use static const char arrays - powerpc: Remove pr_<level> uses of KERN_<level> - -Josh Boyer (1): - powerpc/44x: Update ppc44x_defconfig - -Julia Lawall (7): - powerpc/via-pmu-led.c: Add of_node_put to avoid memory leak - powerpc/maple: Add of_node_put to avoid memory leak - powerpc/powermac/pfunc_core.c: Add of_node_put to avoid memory leak - powerpc/cell: Add of_node_put to avoid memory leak - powerpc/chrp/nvram.c: Add of_node_put to avoid memory leak - powerpc/irq.c: Add of_node_put to avoid memory leak - i2c/i2c-pasemi.c: Fix unsigned return type - -Kumar Gala (11): - powerpc/ppc64e: Fix link problem when building ppc64e_defconfig - powerpc/fsl-pci: Fix MSI support on 83xx platforms - powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers - powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips - powerpc/fsl-booke: Add p3041 DS board support - powerpc: Fix compile error with paca code on ppc64e - powerpc/fsl-booke: Add support for FSL 64-bit e5500 core - powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes - powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips - powerpc/fsl-booke: Add p5020 DS board support - powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig - -Matthew McClintock (7): - powerpc/mm: Assume first cpu is boot_cpuid not 0 - powerpc/kexec: make masking/disabling interrupts generic - powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec - powerpc/85xx: Minor fixups for kexec on 85xx - powerpc/85xx: flush dcache before resetting cores - powerpc/fsl_soc: Search all global-utilities nodes for rstccr - powerpc/fsl_booke: Add support to boot from core other than 0 - -Michael Neuling (1): - powerpc: Move arch_sd_sibling_asym_packing() to smp.c - -Nathan Fontenot (3): - powerpc/pseries: Export device tree updating routines - powerpc/pseries: Export rtas_ibm_suspend_me() - powerpc/pseries: Partition migration in the kernel - -Nishanth Aravamudan (8): - powerpc/pci: Fix return type of BUID_{HI,LO} macros - powerpc/dma: Fix dma_iommu_dma_supported compare - powerpc/dma: Fix check for direct DMA support - powerpc/vio: Use put_device() on device_register failure - powerpc/viobus: Free TCE table on device release - powerpc/pseries: Use kmemdup - powerpc/pci: Cleanup device dma setup code - powerpc/pseries/xics: Use cpu_possible_mask rather than cpu_all_mask - -Paul Gortmaker (1): - powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT - -Paul Mackerras (5): - powerpc: Abstract indexing of lppaca structs - powerpc: Dynamically allocate most lppaca structs - powerpc: Account time using timebase rather than PURR - powerpc/pseries: Re-enable dispatch trace log userspace interface - powerpc/perf: Fix sampling enable for PPC970 - -Scott Wood (1): - oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt. - -Sean MacLennan (2): - powerpc: Fix incorrect .stabs entry for copy_32.S - powerpc: mtmsrd not defined - -Shaohui Xie (1): - fsl_rio: Add comments for sRIO registers. - -Stephen Rothwell (1): - powerpc: define a compat_sys_recv cond_syscall - -Timur Tabi (5): - powerpc: export ppc_proc_freq and ppc_tb_freq as GPL symbols - powerpc/watchdog: Allow the Book-E driver to be compiled as a module - powerpc/p1022: Add probing for individual DMA channels - powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board - powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option - -Tirumala Marri (1): - powerpc/44x: Add support for the AMCC APM821xx SoC - -matt mooney (1): - powerpc/Makefiles: Change to new flag variables - - arch/powerpc/boot/addnote.c | 4 +- - arch/powerpc/boot/dts/bluestone.dts | 254 +++++++++++++ - arch/powerpc/boot/dts/mpc8308_p1m.dts | 332 ++++++++++++++++ - arch/powerpc/boot/dts/p1022ds.dts | 11 + - arch/powerpc/configs/44x/bluestone_defconfig | 68 ++++ - arch/powerpc/configs/e55xx_smp_defconfig | 84 ++++ - arch/powerpc/configs/ppc44x_defconfig | 9 +- - arch/powerpc/configs/ppc64e_defconfig | 4 +- - arch/powerpc/include/asm/checksum.h | 10 + - arch/powerpc/include/asm/compat.h | 4 +- - arch/powerpc/include/asm/cputable.h | 14 +- - arch/powerpc/include/asm/dma-mapping.h | 14 +- - arch/powerpc/include/asm/elf.h | 2 +- - arch/powerpc/include/asm/exception-64s.h | 3 +- - arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++ - arch/powerpc/include/asm/kexec.h | 1 + - arch/powerpc/include/asm/kvm_fpu.h | 4 +- - arch/powerpc/include/asm/lppaca.h | 29 ++ - arch/powerpc/include/asm/machdep.h | 3 + - arch/powerpc/include/asm/mmu-book3e.h | 15 + - arch/powerpc/include/asm/paca.h | 10 +- - arch/powerpc/include/asm/page_64.h | 4 +- - arch/powerpc/include/asm/ppc-pci.h | 4 +- - arch/powerpc/include/asm/ppc_asm.h | 50 ++- - arch/powerpc/include/asm/processor.h | 4 +- - arch/powerpc/include/asm/pte-common.h | 7 + - arch/powerpc/include/asm/rtas.h | 1 + - arch/powerpc/include/asm/systbl.h | 19 + - arch/powerpc/include/asm/system.h | 4 +- - arch/powerpc/include/asm/time.h | 5 - - arch/powerpc/include/asm/unistd.h | 21 +- - arch/powerpc/kernel/Makefile | 4 +- - arch/powerpc/kernel/align.c | 4 +- - arch/powerpc/kernel/asm-offsets.c | 12 +- - arch/powerpc/kernel/cpu_setup_44x.S | 1 + - arch/powerpc/kernel/cpu_setup_fsl_booke.S | 15 + - arch/powerpc/kernel/cputable.c | 43 ++- - arch/powerpc/kernel/crash.c | 13 +- - arch/powerpc/kernel/dma-iommu.c | 21 +- - arch/powerpc/kernel/dma.c | 20 +- - arch/powerpc/kernel/entry_64.S | 40 ++ - arch/powerpc/kernel/fpu.S | 10 - - arch/powerpc/kernel/head_fsl_booke.S | 10 +- - arch/powerpc/kernel/irq.c | 6 +- - arch/powerpc/kernel/lparcfg.c | 14 +- - arch/powerpc/kernel/machine_kexec.c | 24 ++ - arch/powerpc/kernel/machine_kexec_32.c | 4 + - arch/powerpc/kernel/paca.c | 70 ++++- - arch/powerpc/kernel/pci-common.c | 4 +- - arch/powerpc/kernel/ppc970-pmu.c | 2 + - arch/powerpc/kernel/process.c | 12 - - arch/powerpc/kernel/ptrace.c | 2 +- - arch/powerpc/kernel/rtas.c | 4 +- - arch/powerpc/kernel/setup_32.c | 2 +- - arch/powerpc/kernel/smp.c | 14 +- - arch/powerpc/kernel/time.c | 275 +++++++------- - arch/powerpc/kernel/traps.c | 5 + - arch/powerpc/kernel/vdso.c | 6 +- - arch/powerpc/kernel/vdso32/Makefile | 6 +- - arch/powerpc/kernel/vdso64/Makefile | 6 +- - arch/powerpc/kernel/vio.c | 10 +- - arch/powerpc/kvm/Makefile | 2 +- - arch/powerpc/kvm/book3s_paired_singles.c | 44 +-- - arch/powerpc/kvm/emulate.c | 4 +- - arch/powerpc/kvm/fpu.S | 8 - - arch/powerpc/lib/Makefile | 7 +- - arch/powerpc/lib/checksum_64.S | 482 +++++++++++++++++------- - arch/powerpc/lib/checksum_wrappers_64.c | 102 +++++ - arch/powerpc/lib/copy_32.S | 2 +- - arch/powerpc/lib/ldstfp.S | 36 +- - arch/powerpc/lib/locks.c | 4 +- - arch/powerpc/lib/sstep.c | 8 + - arch/powerpc/math-emu/Makefile | 2 +- - arch/powerpc/mm/Makefile | 6 +- - arch/powerpc/mm/fault.c | 6 + - arch/powerpc/mm/fsl_booke_mmu.c | 15 +- - arch/powerpc/mm/mmu_context_nohash.c | 6 +- - arch/powerpc/mm/mmu_decl.h | 5 +- - arch/powerpc/mm/tlb_nohash.c | 56 +++- - arch/powerpc/mm/tlb_nohash_low.S | 2 +- - arch/powerpc/oprofile/Makefile | 4 +- - arch/powerpc/oprofile/backtrace.c | 2 +- - arch/powerpc/oprofile/op_model_fsl_emb.c | 15 +- - arch/powerpc/platforms/44x/Kconfig | 16 + - arch/powerpc/platforms/44x/ppc44x_simple.c | 1 + - arch/powerpc/platforms/83xx/Kconfig | 4 +- - arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +- - arch/powerpc/platforms/85xx/Kconfig | 28 ++- - arch/powerpc/platforms/85xx/Makefile | 2 + - arch/powerpc/platforms/85xx/p1022_ds.c | 2 + - arch/powerpc/platforms/85xx/p3041_ds.c | 64 ++++ - arch/powerpc/platforms/85xx/p5020_ds.c | 69 ++++ - arch/powerpc/platforms/85xx/smp.c | 83 ++++- - arch/powerpc/platforms/Kconfig.cputype | 8 +- - arch/powerpc/platforms/cell/ras.c | 4 +- - arch/powerpc/platforms/cell/spider-pic.c | 4 +- - arch/powerpc/platforms/cell/spufs/file.c | 18 + - arch/powerpc/platforms/chrp/nvram.c | 4 +- - arch/powerpc/platforms/iseries/Makefile | 2 +- - arch/powerpc/platforms/iseries/dt.c | 4 +- - arch/powerpc/platforms/iseries/smp.c | 2 +- - arch/powerpc/platforms/maple/setup.c | 1 + - arch/powerpc/platforms/powermac/pfunc_core.c | 9 +- - arch/powerpc/platforms/pseries/Makefile | 13 +- - arch/powerpc/platforms/pseries/dlpar.c | 7 +- - arch/powerpc/platforms/pseries/dtl.c | 224 +++++++++--- - arch/powerpc/platforms/pseries/lpar.c | 25 ++- - arch/powerpc/platforms/pseries/mobility.c | 362 ++++++++++++++++++ - arch/powerpc/platforms/pseries/pseries.h | 9 + - arch/powerpc/platforms/pseries/setup.c | 52 +++ - arch/powerpc/platforms/pseries/xics.c | 2 +- - arch/powerpc/sysdev/Makefile | 5 +- - arch/powerpc/sysdev/dart_iommu.c | 74 ++++- - arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 +++++ - arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 159 ++++++++ - arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 231 +++++++++++ - arch/powerpc/sysdev/fsl_msi.c | 9 +- - arch/powerpc/sysdev/fsl_pci.c | 60 +++- - arch/powerpc/sysdev/fsl_pci.h | 1 + - arch/powerpc/sysdev/fsl_rio.c | 65 ++-- - arch/powerpc/sysdev/fsl_soc.c | 20 +- - arch/powerpc/sysdev/mpc8xxx_gpio.c | 3 + - arch/powerpc/sysdev/pmi.c | 2 +- - arch/powerpc/xmon/Makefile | 4 +- - drivers/i2c/busses/i2c-pasemi.c | 2 +- - drivers/macintosh/via-pmu-led.c | 4 +- - drivers/watchdog/Kconfig | 22 +- - drivers/watchdog/booke_wdt.c | 47 ++- - include/linux/pci_ids.h | 8 + - kernel/sys_ni.c | 1 + - 130 files changed, 3676 insertions(+), 683 deletions(-) - create mode 100644 arch/powerpc/boot/dts/bluestone.dts - create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts - create mode 100644 arch/powerpc/configs/44x/bluestone_defconfig - create mode 100644 arch/powerpc/configs/e55xx_smp_defconfig - create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h - create mode 100644 arch/powerpc/lib/checksum_wrappers_64.c - create mode 100644 arch/powerpc/platforms/85xx/p3041_ds.c - create mode 100644 arch/powerpc/platforms/85xx/p5020_ds.c - create mode 100644 arch/powerpc/platforms/pseries/mobility.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c - - -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0002-git-pull-request-wrapped.mbox b/apps/patchwork/tests/mail/0002-git-pull-request-wrapped.mbox deleted file mode 100644 index d3ccee1..0000000 --- a/apps/patchwork/tests/mail/0002-git-pull-request-wrapped.mbox +++ /dev/null @@ -1,349 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -Hi Linus ! - -Here's powerpc's batch for this merge window. Mostly bits and pieces, -such as Anton doing some performance tuning left and right, and the -usual churn. One hilight is the support for the new Freescale e5500 core -(64-bit BookE). Another one is that we now wire up the whole lot of -socket calls as direct syscalls in addition to the old style indirect -method. - -Cheers, -Ben. - -The following changes since commit -e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next - -Andreas Schwab (1): - powerpc: Remove fpscr use from [kvm_]cvt_{fd,df} - -Anton Blanchard (5): - powerpc: Optimise 64bit csum_partial - powerpc: Optimise 64bit csum_partial_copy_generic and add csum_and_copy_from_user - powerpc: Add 64bit csum_and_copy_to_user - powerpc: Feature nop out reservation clear when stcx checks address - powerpc: Check end of stack canary at oops time - -Arnd Bergmann (1): - powerpc/spufs: Use llseek in all file operations - -Benjamin Herrenschmidt (4): - powerpc/dma: Add optional platform override of dma_set_mask() - powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe - Merge remote branch 'kumar/merge' into next - Merge remote branch 'jwb/next' into next - -Denis Kirjanov (1): - powerpc: Use is_32bit_task() helper to test 32-bit binary - -Harninder Rai (1): - powerpc/85xx: add cache-sram support - -Ian Munsie (1): - powerpc: Wire up direct socket system calls - -Ilya Yanok (1): - powerpc/mpc83xx: Support for MPC8308 P1M board - -Joe Perches (2): - powerpc: Use static const char arrays - powerpc: Remove pr_<level> uses of KERN_<level> - -Josh Boyer (1): - powerpc/44x: Update ppc44x_defconfig - -Julia Lawall (7): - powerpc/via-pmu-led.c: Add of_node_put to avoid memory leak - powerpc/maple: Add of_node_put to avoid memory leak - powerpc/powermac/pfunc_core.c: Add of_node_put to avoid memory leak - powerpc/cell: Add of_node_put to avoid memory leak - powerpc/chrp/nvram.c: Add of_node_put to avoid memory leak - powerpc/irq.c: Add of_node_put to avoid memory leak - i2c/i2c-pasemi.c: Fix unsigned return type - -Kumar Gala (11): - powerpc/ppc64e: Fix link problem when building ppc64e_defconfig - powerpc/fsl-pci: Fix MSI support on 83xx platforms - powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers - powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips - powerpc/fsl-booke: Add p3041 DS board support - powerpc: Fix compile error with paca code on ppc64e - powerpc/fsl-booke: Add support for FSL 64-bit e5500 core - powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes - powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips - powerpc/fsl-booke: Add p5020 DS board support - powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig - -Matthew McClintock (7): - powerpc/mm: Assume first cpu is boot_cpuid not 0 - powerpc/kexec: make masking/disabling interrupts generic - powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec - powerpc/85xx: Minor fixups for kexec on 85xx - powerpc/85xx: flush dcache before resetting cores - powerpc/fsl_soc: Search all global-utilities nodes for rstccr - powerpc/fsl_booke: Add support to boot from core other than 0 - -Michael Neuling (1): - powerpc: Move arch_sd_sibling_asym_packing() to smp.c - -Nathan Fontenot (3): - powerpc/pseries: Export device tree updating routines - powerpc/pseries: Export rtas_ibm_suspend_me() - powerpc/pseries: Partition migration in the kernel - -Nishanth Aravamudan (8): - powerpc/pci: Fix return type of BUID_{HI,LO} macros - powerpc/dma: Fix dma_iommu_dma_supported compare - powerpc/dma: Fix check for direct DMA support - powerpc/vio: Use put_device() on device_register failure - powerpc/viobus: Free TCE table on device release - powerpc/pseries: Use kmemdup - powerpc/pci: Cleanup device dma setup code - powerpc/pseries/xics: Use cpu_possible_mask rather than cpu_all_mask - -Paul Gortmaker (1): - powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT - -Paul Mackerras (5): - powerpc: Abstract indexing of lppaca structs - powerpc: Dynamically allocate most lppaca structs - powerpc: Account time using timebase rather than PURR - powerpc/pseries: Re-enable dispatch trace log userspace interface - powerpc/perf: Fix sampling enable for PPC970 - -Scott Wood (1): - oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt. - -Sean MacLennan (2): - powerpc: Fix incorrect .stabs entry for copy_32.S - powerpc: mtmsrd not defined - -Shaohui Xie (1): - fsl_rio: Add comments for sRIO registers. - -Stephen Rothwell (1): - powerpc: define a compat_sys_recv cond_syscall - -Timur Tabi (5): - powerpc: export ppc_proc_freq and ppc_tb_freq as GPL symbols - powerpc/watchdog: Allow the Book-E driver to be compiled as a module - powerpc/p1022: Add probing for individual DMA channels - powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board - powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option - -Tirumala Marri (1): - powerpc/44x: Add support for the AMCC APM821xx SoC - -matt mooney (1): - powerpc/Makefiles: Change to new flag variables - - arch/powerpc/boot/addnote.c | 4 +- - arch/powerpc/boot/dts/bluestone.dts | 254 +++++++++++++ - arch/powerpc/boot/dts/mpc8308_p1m.dts | 332 ++++++++++++++++ - arch/powerpc/boot/dts/p1022ds.dts | 11 + - arch/powerpc/configs/44x/bluestone_defconfig | 68 ++++ - arch/powerpc/configs/e55xx_smp_defconfig | 84 ++++ - arch/powerpc/configs/ppc44x_defconfig | 9 +- - arch/powerpc/configs/ppc64e_defconfig | 4 +- - arch/powerpc/include/asm/checksum.h | 10 + - arch/powerpc/include/asm/compat.h | 4 +- - arch/powerpc/include/asm/cputable.h | 14 +- - arch/powerpc/include/asm/dma-mapping.h | 14 +- - arch/powerpc/include/asm/elf.h | 2 +- - arch/powerpc/include/asm/exception-64s.h | 3 +- - arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++ - arch/powerpc/include/asm/kexec.h | 1 + - arch/powerpc/include/asm/kvm_fpu.h | 4 +- - arch/powerpc/include/asm/lppaca.h | 29 ++ - arch/powerpc/include/asm/machdep.h | 3 + - arch/powerpc/include/asm/mmu-book3e.h | 15 + - arch/powerpc/include/asm/paca.h | 10 +- - arch/powerpc/include/asm/page_64.h | 4 +- - arch/powerpc/include/asm/ppc-pci.h | 4 +- - arch/powerpc/include/asm/ppc_asm.h | 50 ++- - arch/powerpc/include/asm/processor.h | 4 +- - arch/powerpc/include/asm/pte-common.h | 7 + - arch/powerpc/include/asm/rtas.h | 1 + - arch/powerpc/include/asm/systbl.h | 19 + - arch/powerpc/include/asm/system.h | 4 +- - arch/powerpc/include/asm/time.h | 5 - - arch/powerpc/include/asm/unistd.h | 21 +- - arch/powerpc/kernel/Makefile | 4 +- - arch/powerpc/kernel/align.c | 4 +- - arch/powerpc/kernel/asm-offsets.c | 12 +- - arch/powerpc/kernel/cpu_setup_44x.S | 1 + - arch/powerpc/kernel/cpu_setup_fsl_booke.S | 15 + - arch/powerpc/kernel/cputable.c | 43 ++- - arch/powerpc/kernel/crash.c | 13 +- - arch/powerpc/kernel/dma-iommu.c | 21 +- - arch/powerpc/kernel/dma.c | 20 +- - arch/powerpc/kernel/entry_64.S | 40 ++ - arch/powerpc/kernel/fpu.S | 10 - - arch/powerpc/kernel/head_fsl_booke.S | 10 +- - arch/powerpc/kernel/irq.c | 6 +- - arch/powerpc/kernel/lparcfg.c | 14 +- - arch/powerpc/kernel/machine_kexec.c | 24 ++ - arch/powerpc/kernel/machine_kexec_32.c | 4 + - arch/powerpc/kernel/paca.c | 70 ++++- - arch/powerpc/kernel/pci-common.c | 4 +- - arch/powerpc/kernel/ppc970-pmu.c | 2 + - arch/powerpc/kernel/process.c | 12 - - arch/powerpc/kernel/ptrace.c | 2 +- - arch/powerpc/kernel/rtas.c | 4 +- - arch/powerpc/kernel/setup_32.c | 2 +- - arch/powerpc/kernel/smp.c | 14 +- - arch/powerpc/kernel/time.c | 275 +++++++------- - arch/powerpc/kernel/traps.c | 5 + - arch/powerpc/kernel/vdso.c | 6 +- - arch/powerpc/kernel/vdso32/Makefile | 6 +- - arch/powerpc/kernel/vdso64/Makefile | 6 +- - arch/powerpc/kernel/vio.c | 10 +- - arch/powerpc/kvm/Makefile | 2 +- - arch/powerpc/kvm/book3s_paired_singles.c | 44 +-- - arch/powerpc/kvm/emulate.c | 4 +- - arch/powerpc/kvm/fpu.S | 8 - - arch/powerpc/lib/Makefile | 7 +- - arch/powerpc/lib/checksum_64.S | 482 +++++++++++++++++------- - arch/powerpc/lib/checksum_wrappers_64.c | 102 +++++ - arch/powerpc/lib/copy_32.S | 2 +- - arch/powerpc/lib/ldstfp.S | 36 +- - arch/powerpc/lib/locks.c | 4 +- - arch/powerpc/lib/sstep.c | 8 + - arch/powerpc/math-emu/Makefile | 2 +- - arch/powerpc/mm/Makefile | 6 +- - arch/powerpc/mm/fault.c | 6 + - arch/powerpc/mm/fsl_booke_mmu.c | 15 +- - arch/powerpc/mm/mmu_context_nohash.c | 6 +- - arch/powerpc/mm/mmu_decl.h | 5 +- - arch/powerpc/mm/tlb_nohash.c | 56 +++- - arch/powerpc/mm/tlb_nohash_low.S | 2 +- - arch/powerpc/oprofile/Makefile | 4 +- - arch/powerpc/oprofile/backtrace.c | 2 +- - arch/powerpc/oprofile/op_model_fsl_emb.c | 15 +- - arch/powerpc/platforms/44x/Kconfig | 16 + - arch/powerpc/platforms/44x/ppc44x_simple.c | 1 + - arch/powerpc/platforms/83xx/Kconfig | 4 +- - arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +- - arch/powerpc/platforms/85xx/Kconfig | 28 ++- - arch/powerpc/platforms/85xx/Makefile | 2 + - arch/powerpc/platforms/85xx/p1022_ds.c | 2 + - arch/powerpc/platforms/85xx/p3041_ds.c | 64 ++++ - arch/powerpc/platforms/85xx/p5020_ds.c | 69 ++++ - arch/powerpc/platforms/85xx/smp.c | 83 ++++- - arch/powerpc/platforms/Kconfig.cputype | 8 +- - arch/powerpc/platforms/cell/ras.c | 4 +- - arch/powerpc/platforms/cell/spider-pic.c | 4 +- - arch/powerpc/platforms/cell/spufs/file.c | 18 + - arch/powerpc/platforms/chrp/nvram.c | 4 +- - arch/powerpc/platforms/iseries/Makefile | 2 +- - arch/powerpc/platforms/iseries/dt.c | 4 +- - arch/powerpc/platforms/iseries/smp.c | 2 +- - arch/powerpc/platforms/maple/setup.c | 1 + - arch/powerpc/platforms/powermac/pfunc_core.c | 9 +- - arch/powerpc/platforms/pseries/Makefile | 13 +- - arch/powerpc/platforms/pseries/dlpar.c | 7 +- - arch/powerpc/platforms/pseries/dtl.c | 224 +++++++++--- - arch/powerpc/platforms/pseries/lpar.c | 25 ++- - arch/powerpc/platforms/pseries/mobility.c | 362 ++++++++++++++++++ - arch/powerpc/platforms/pseries/pseries.h | 9 + - arch/powerpc/platforms/pseries/setup.c | 52 +++ - arch/powerpc/platforms/pseries/xics.c | 2 +- - arch/powerpc/sysdev/Makefile | 5 +- - arch/powerpc/sysdev/dart_iommu.c | 74 ++++- - arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 +++++ - arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 159 ++++++++ - arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 231 +++++++++++ - arch/powerpc/sysdev/fsl_msi.c | 9 +- - arch/powerpc/sysdev/fsl_pci.c | 60 +++- - arch/powerpc/sysdev/fsl_pci.h | 1 + - arch/powerpc/sysdev/fsl_rio.c | 65 ++-- - arch/powerpc/sysdev/fsl_soc.c | 20 +- - arch/powerpc/sysdev/mpc8xxx_gpio.c | 3 + - arch/powerpc/sysdev/pmi.c | 2 +- - arch/powerpc/xmon/Makefile | 4 +- - drivers/i2c/busses/i2c-pasemi.c | 2 +- - drivers/macintosh/via-pmu-led.c | 4 +- - drivers/watchdog/Kconfig | 22 +- - drivers/watchdog/booke_wdt.c | 47 ++- - include/linux/pci_ids.h | 8 + - kernel/sys_ni.c | 1 + - 130 files changed, 3676 insertions(+), 683 deletions(-) - create mode 100644 arch/powerpc/boot/dts/bluestone.dts - create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts - create mode 100644 arch/powerpc/configs/44x/bluestone_defconfig - create mode 100644 arch/powerpc/configs/e55xx_smp_defconfig - create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h - create mode 100644 arch/powerpc/lib/checksum_wrappers_64.c - create mode 100644 arch/powerpc/platforms/85xx/p3041_ds.c - create mode 100644 arch/powerpc/platforms/85xx/p5020_ds.c - create mode 100644 arch/powerpc/platforms/pseries/mobility.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c - - -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0003-git-pull-request-with-diff.mbox b/apps/patchwork/tests/mail/0003-git-pull-request-with-diff.mbox deleted file mode 100644 index b4d578c..0000000 --- a/apps/patchwork/tests/mail/0003-git-pull-request-with-diff.mbox +++ /dev/null @@ -1,141 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -The following changes since commit e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git x86-fixes-for-linus - -------------------> -H. Peter Anvin (1): - x86-32: Make sure the stack is set up before we use it -Matthieu CASTET (1): - x86, nx: Don't force pages RW when setting NX bits - -Suresh Siddha (1): - x86, mtrr: Avoid MTRR reprogramming on BP during boot on UP platforms - - - arch/x86/include/asm/smp.h | 5 +---- - arch/x86/kernel/acpi/sleep.c | 2 +- - arch/x86/kernel/cpu/mtrr/main.c | 10 +++++++++- - arch/x86/kernel/head_32.S | 30 +++++++++++++----------------- - arch/x86/kernel/smpboot.c | 4 ++-- - arch/x86/mm/pageattr.c | 8 -------- - 6 files changed, 26 insertions(+), 33 deletions(-) -diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h -index 4c2f63c..1f46951 100644 ---- a/arch/x86/include/asm/smp.h -+++ b/arch/x86/include/asm/smp.h -@@ -40,10 +40,7 @@ DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); - DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); - - /* Static state in head.S used to set up a CPU */ --extern struct { -- void *sp; -- unsigned short ss; --} stack_start; -+extern unsigned long stack_start; /* Initial stack pointer address */ - - struct smp_ops { - void (*smp_prepare_boot_cpu)(void); -diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c -index 69fd72a..4d9ebba 100644 ---- a/arch/x86/kernel/acpi/sleep.c -+++ b/arch/x86/kernel/acpi/sleep.c -@@ -100,7 +100,7 @@ int acpi_save_state_mem(void) - #else /* CONFIG_64BIT */ - header->trampoline_segment = setup_trampoline() >> 4; - #ifdef CONFIG_SMP -- stack_start.sp = temp_stack + sizeof(temp_stack); -+ stack_start = (unsigned long)temp_stack + sizeof(temp_stack); - early_gdt_descr.address = - (unsigned long)get_cpu_gdt_table(smp_processor_id()); - initial_gs = per_cpu_offset(smp_processor_id()); -diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c -index 01c0f3e..bebabec 100644 ---- a/arch/x86/kernel/cpu/mtrr/main.c -+++ b/arch/x86/kernel/cpu/mtrr/main.c -@@ -793,13 +793,21 @@ void set_mtrr_aps_delayed_init(void) - } - - /* -- * MTRR initialization for all AP's -+ * Delayed MTRR initialization for all AP's - */ - void mtrr_aps_init(void) - { - if (!use_intel()) - return; - -+ /* -+ * Check if someone has requested the delay of AP MTRR initialization, -+ * by doing set_mtrr_aps_delayed_init(), prior to this point. If not, -+ * then we are done. -+ */ -+ if (!mtrr_aps_delayed_init) -+ return; -+ - set_mtrr(~0U, 0, 0, 0); - mtrr_aps_delayed_init = false; - } -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0004-git-pull-request-git+ssh.mbox b/apps/patchwork/tests/mail/0004-git-pull-request-git+ssh.mbox deleted file mode 100644 index da96465..0000000 --- a/apps/patchwork/tests/mail/0004-git-pull-request-git+ssh.mbox +++ /dev/null @@ -1,348 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -Hi Linus ! - -Here's powerpc's batch for this merge window. Mostly bits and pieces, -such as Anton doing some performance tuning left and right, and the -usual churn. One hilight is the support for the new Freescale e5500 core -(64-bit BookE). Another one is that we now wire up the whole lot of -socket calls as direct syscalls in addition to the old style indirect -method. - -Cheers, -Ben. - -The following changes since commit e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - git+ssh://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next - -Andreas Schwab (1): - powerpc: Remove fpscr use from [kvm_]cvt_{fd,df} - -Anton Blanchard (5): - powerpc: Optimise 64bit csum_partial - powerpc: Optimise 64bit csum_partial_copy_generic and add csum_and_copy_from_user - powerpc: Add 64bit csum_and_copy_to_user - powerpc: Feature nop out reservation clear when stcx checks address - powerpc: Check end of stack canary at oops time - -Arnd Bergmann (1): - powerpc/spufs: Use llseek in all file operations - -Benjamin Herrenschmidt (4): - powerpc/dma: Add optional platform override of dma_set_mask() - powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe - Merge remote branch 'kumar/merge' into next - Merge remote branch 'jwb/next' into next - -Denis Kirjanov (1): - powerpc: Use is_32bit_task() helper to test 32-bit binary - -Harninder Rai (1): - powerpc/85xx: add cache-sram support - -Ian Munsie (1): - powerpc: Wire up direct socket system calls - -Ilya Yanok (1): - powerpc/mpc83xx: Support for MPC8308 P1M board - -Joe Perches (2): - powerpc: Use static const char arrays - powerpc: Remove pr_<level> uses of KERN_<level> - -Josh Boyer (1): - powerpc/44x: Update ppc44x_defconfig - -Julia Lawall (7): - powerpc/via-pmu-led.c: Add of_node_put to avoid memory leak - powerpc/maple: Add of_node_put to avoid memory leak - powerpc/powermac/pfunc_core.c: Add of_node_put to avoid memory leak - powerpc/cell: Add of_node_put to avoid memory leak - powerpc/chrp/nvram.c: Add of_node_put to avoid memory leak - powerpc/irq.c: Add of_node_put to avoid memory leak - i2c/i2c-pasemi.c: Fix unsigned return type - -Kumar Gala (11): - powerpc/ppc64e: Fix link problem when building ppc64e_defconfig - powerpc/fsl-pci: Fix MSI support on 83xx platforms - powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers - powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips - powerpc/fsl-booke: Add p3041 DS board support - powerpc: Fix compile error with paca code on ppc64e - powerpc/fsl-booke: Add support for FSL 64-bit e5500 core - powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes - powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips - powerpc/fsl-booke: Add p5020 DS board support - powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig - -Matthew McClintock (7): - powerpc/mm: Assume first cpu is boot_cpuid not 0 - powerpc/kexec: make masking/disabling interrupts generic - powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec - powerpc/85xx: Minor fixups for kexec on 85xx - powerpc/85xx: flush dcache before resetting cores - powerpc/fsl_soc: Search all global-utilities nodes for rstccr - powerpc/fsl_booke: Add support to boot from core other than 0 - -Michael Neuling (1): - powerpc: Move arch_sd_sibling_asym_packing() to smp.c - -Nathan Fontenot (3): - powerpc/pseries: Export device tree updating routines - powerpc/pseries: Export rtas_ibm_suspend_me() - powerpc/pseries: Partition migration in the kernel - -Nishanth Aravamudan (8): - powerpc/pci: Fix return type of BUID_{HI,LO} macros - powerpc/dma: Fix dma_iommu_dma_supported compare - powerpc/dma: Fix check for direct DMA support - powerpc/vio: Use put_device() on device_register failure - powerpc/viobus: Free TCE table on device release - powerpc/pseries: Use kmemdup - powerpc/pci: Cleanup device dma setup code - powerpc/pseries/xics: Use cpu_possible_mask rather than cpu_all_mask - -Paul Gortmaker (1): - powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT - -Paul Mackerras (5): - powerpc: Abstract indexing of lppaca structs - powerpc: Dynamically allocate most lppaca structs - powerpc: Account time using timebase rather than PURR - powerpc/pseries: Re-enable dispatch trace log userspace interface - powerpc/perf: Fix sampling enable for PPC970 - -Scott Wood (1): - oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt. - -Sean MacLennan (2): - powerpc: Fix incorrect .stabs entry for copy_32.S - powerpc: mtmsrd not defined - -Shaohui Xie (1): - fsl_rio: Add comments for sRIO registers. - -Stephen Rothwell (1): - powerpc: define a compat_sys_recv cond_syscall - -Timur Tabi (5): - powerpc: export ppc_proc_freq and ppc_tb_freq as GPL symbols - powerpc/watchdog: Allow the Book-E driver to be compiled as a module - powerpc/p1022: Add probing for individual DMA channels - powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board - powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option - -Tirumala Marri (1): - powerpc/44x: Add support for the AMCC APM821xx SoC - -matt mooney (1): - powerpc/Makefiles: Change to new flag variables - - arch/powerpc/boot/addnote.c | 4 +- - arch/powerpc/boot/dts/bluestone.dts | 254 +++++++++++++ - arch/powerpc/boot/dts/mpc8308_p1m.dts | 332 ++++++++++++++++ - arch/powerpc/boot/dts/p1022ds.dts | 11 + - arch/powerpc/configs/44x/bluestone_defconfig | 68 ++++ - arch/powerpc/configs/e55xx_smp_defconfig | 84 ++++ - arch/powerpc/configs/ppc44x_defconfig | 9 +- - arch/powerpc/configs/ppc64e_defconfig | 4 +- - arch/powerpc/include/asm/checksum.h | 10 + - arch/powerpc/include/asm/compat.h | 4 +- - arch/powerpc/include/asm/cputable.h | 14 +- - arch/powerpc/include/asm/dma-mapping.h | 14 +- - arch/powerpc/include/asm/elf.h | 2 +- - arch/powerpc/include/asm/exception-64s.h | 3 +- - arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++ - arch/powerpc/include/asm/kexec.h | 1 + - arch/powerpc/include/asm/kvm_fpu.h | 4 +- - arch/powerpc/include/asm/lppaca.h | 29 ++ - arch/powerpc/include/asm/machdep.h | 3 + - arch/powerpc/include/asm/mmu-book3e.h | 15 + - arch/powerpc/include/asm/paca.h | 10 +- - arch/powerpc/include/asm/page_64.h | 4 +- - arch/powerpc/include/asm/ppc-pci.h | 4 +- - arch/powerpc/include/asm/ppc_asm.h | 50 ++- - arch/powerpc/include/asm/processor.h | 4 +- - arch/powerpc/include/asm/pte-common.h | 7 + - arch/powerpc/include/asm/rtas.h | 1 + - arch/powerpc/include/asm/systbl.h | 19 + - arch/powerpc/include/asm/system.h | 4 +- - arch/powerpc/include/asm/time.h | 5 - - arch/powerpc/include/asm/unistd.h | 21 +- - arch/powerpc/kernel/Makefile | 4 +- - arch/powerpc/kernel/align.c | 4 +- - arch/powerpc/kernel/asm-offsets.c | 12 +- - arch/powerpc/kernel/cpu_setup_44x.S | 1 + - arch/powerpc/kernel/cpu_setup_fsl_booke.S | 15 + - arch/powerpc/kernel/cputable.c | 43 ++- - arch/powerpc/kernel/crash.c | 13 +- - arch/powerpc/kernel/dma-iommu.c | 21 +- - arch/powerpc/kernel/dma.c | 20 +- - arch/powerpc/kernel/entry_64.S | 40 ++ - arch/powerpc/kernel/fpu.S | 10 - - arch/powerpc/kernel/head_fsl_booke.S | 10 +- - arch/powerpc/kernel/irq.c | 6 +- - arch/powerpc/kernel/lparcfg.c | 14 +- - arch/powerpc/kernel/machine_kexec.c | 24 ++ - arch/powerpc/kernel/machine_kexec_32.c | 4 + - arch/powerpc/kernel/paca.c | 70 ++++- - arch/powerpc/kernel/pci-common.c | 4 +- - arch/powerpc/kernel/ppc970-pmu.c | 2 + - arch/powerpc/kernel/process.c | 12 - - arch/powerpc/kernel/ptrace.c | 2 +- - arch/powerpc/kernel/rtas.c | 4 +- - arch/powerpc/kernel/setup_32.c | 2 +- - arch/powerpc/kernel/smp.c | 14 +- - arch/powerpc/kernel/time.c | 275 +++++++------- - arch/powerpc/kernel/traps.c | 5 + - arch/powerpc/kernel/vdso.c | 6 +- - arch/powerpc/kernel/vdso32/Makefile | 6 +- - arch/powerpc/kernel/vdso64/Makefile | 6 +- - arch/powerpc/kernel/vio.c | 10 +- - arch/powerpc/kvm/Makefile | 2 +- - arch/powerpc/kvm/book3s_paired_singles.c | 44 +-- - arch/powerpc/kvm/emulate.c | 4 +- - arch/powerpc/kvm/fpu.S | 8 - - arch/powerpc/lib/Makefile | 7 +- - arch/powerpc/lib/checksum_64.S | 482 +++++++++++++++++------- - arch/powerpc/lib/checksum_wrappers_64.c | 102 +++++ - arch/powerpc/lib/copy_32.S | 2 +- - arch/powerpc/lib/ldstfp.S | 36 +- - arch/powerpc/lib/locks.c | 4 +- - arch/powerpc/lib/sstep.c | 8 + - arch/powerpc/math-emu/Makefile | 2 +- - arch/powerpc/mm/Makefile | 6 +- - arch/powerpc/mm/fault.c | 6 + - arch/powerpc/mm/fsl_booke_mmu.c | 15 +- - arch/powerpc/mm/mmu_context_nohash.c | 6 +- - arch/powerpc/mm/mmu_decl.h | 5 +- - arch/powerpc/mm/tlb_nohash.c | 56 +++- - arch/powerpc/mm/tlb_nohash_low.S | 2 +- - arch/powerpc/oprofile/Makefile | 4 +- - arch/powerpc/oprofile/backtrace.c | 2 +- - arch/powerpc/oprofile/op_model_fsl_emb.c | 15 +- - arch/powerpc/platforms/44x/Kconfig | 16 + - arch/powerpc/platforms/44x/ppc44x_simple.c | 1 + - arch/powerpc/platforms/83xx/Kconfig | 4 +- - arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +- - arch/powerpc/platforms/85xx/Kconfig | 28 ++- - arch/powerpc/platforms/85xx/Makefile | 2 + - arch/powerpc/platforms/85xx/p1022_ds.c | 2 + - arch/powerpc/platforms/85xx/p3041_ds.c | 64 ++++ - arch/powerpc/platforms/85xx/p5020_ds.c | 69 ++++ - arch/powerpc/platforms/85xx/smp.c | 83 ++++- - arch/powerpc/platforms/Kconfig.cputype | 8 +- - arch/powerpc/platforms/cell/ras.c | 4 +- - arch/powerpc/platforms/cell/spider-pic.c | 4 +- - arch/powerpc/platforms/cell/spufs/file.c | 18 + - arch/powerpc/platforms/chrp/nvram.c | 4 +- - arch/powerpc/platforms/iseries/Makefile | 2 +- - arch/powerpc/platforms/iseries/dt.c | 4 +- - arch/powerpc/platforms/iseries/smp.c | 2 +- - arch/powerpc/platforms/maple/setup.c | 1 + - arch/powerpc/platforms/powermac/pfunc_core.c | 9 +- - arch/powerpc/platforms/pseries/Makefile | 13 +- - arch/powerpc/platforms/pseries/dlpar.c | 7 +- - arch/powerpc/platforms/pseries/dtl.c | 224 +++++++++--- - arch/powerpc/platforms/pseries/lpar.c | 25 ++- - arch/powerpc/platforms/pseries/mobility.c | 362 ++++++++++++++++++ - arch/powerpc/platforms/pseries/pseries.h | 9 + - arch/powerpc/platforms/pseries/setup.c | 52 +++ - arch/powerpc/platforms/pseries/xics.c | 2 +- - arch/powerpc/sysdev/Makefile | 5 +- - arch/powerpc/sysdev/dart_iommu.c | 74 ++++- - arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 +++++ - arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 159 ++++++++ - arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 231 +++++++++++ - arch/powerpc/sysdev/fsl_msi.c | 9 +- - arch/powerpc/sysdev/fsl_pci.c | 60 +++- - arch/powerpc/sysdev/fsl_pci.h | 1 + - arch/powerpc/sysdev/fsl_rio.c | 65 ++-- - arch/powerpc/sysdev/fsl_soc.c | 20 +- - arch/powerpc/sysdev/mpc8xxx_gpio.c | 3 + - arch/powerpc/sysdev/pmi.c | 2 +- - arch/powerpc/xmon/Makefile | 4 +- - drivers/i2c/busses/i2c-pasemi.c | 2 +- - drivers/macintosh/via-pmu-led.c | 4 +- - drivers/watchdog/Kconfig | 22 +- - drivers/watchdog/booke_wdt.c | 47 ++- - include/linux/pci_ids.h | 8 + - kernel/sys_ni.c | 1 + - 130 files changed, 3676 insertions(+), 683 deletions(-) - create mode 100644 arch/powerpc/boot/dts/bluestone.dts - create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts - create mode 100644 arch/powerpc/configs/44x/bluestone_defconfig - create mode 100644 arch/powerpc/configs/e55xx_smp_defconfig - create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h - create mode 100644 arch/powerpc/lib/checksum_wrappers_64.c - create mode 100644 arch/powerpc/platforms/85xx/p3041_ds.c - create mode 100644 arch/powerpc/platforms/85xx/p5020_ds.c - create mode 100644 arch/powerpc/platforms/pseries/mobility.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c - - -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0005-git-pull-request-ssh.mbox b/apps/patchwork/tests/mail/0005-git-pull-request-ssh.mbox deleted file mode 100644 index 7f4c93e..0000000 --- a/apps/patchwork/tests/mail/0005-git-pull-request-ssh.mbox +++ /dev/null @@ -1,348 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -Hi Linus ! - -Here's powerpc's batch for this merge window. Mostly bits and pieces, -such as Anton doing some performance tuning left and right, and the -usual churn. One hilight is the support for the new Freescale e5500 core -(64-bit BookE). Another one is that we now wire up the whole lot of -socket calls as direct syscalls in addition to the old style indirect -method. - -Cheers, -Ben. - -The following changes since commit e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - ssh://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next - -Andreas Schwab (1): - powerpc: Remove fpscr use from [kvm_]cvt_{fd,df} - -Anton Blanchard (5): - powerpc: Optimise 64bit csum_partial - powerpc: Optimise 64bit csum_partial_copy_generic and add csum_and_copy_from_user - powerpc: Add 64bit csum_and_copy_to_user - powerpc: Feature nop out reservation clear when stcx checks address - powerpc: Check end of stack canary at oops time - -Arnd Bergmann (1): - powerpc/spufs: Use llseek in all file operations - -Benjamin Herrenschmidt (4): - powerpc/dma: Add optional platform override of dma_set_mask() - powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe - Merge remote branch 'kumar/merge' into next - Merge remote branch 'jwb/next' into next - -Denis Kirjanov (1): - powerpc: Use is_32bit_task() helper to test 32-bit binary - -Harninder Rai (1): - powerpc/85xx: add cache-sram support - -Ian Munsie (1): - powerpc: Wire up direct socket system calls - -Ilya Yanok (1): - powerpc/mpc83xx: Support for MPC8308 P1M board - -Joe Perches (2): - powerpc: Use static const char arrays - powerpc: Remove pr_<level> uses of KERN_<level> - -Josh Boyer (1): - powerpc/44x: Update ppc44x_defconfig - -Julia Lawall (7): - powerpc/via-pmu-led.c: Add of_node_put to avoid memory leak - powerpc/maple: Add of_node_put to avoid memory leak - powerpc/powermac/pfunc_core.c: Add of_node_put to avoid memory leak - powerpc/cell: Add of_node_put to avoid memory leak - powerpc/chrp/nvram.c: Add of_node_put to avoid memory leak - powerpc/irq.c: Add of_node_put to avoid memory leak - i2c/i2c-pasemi.c: Fix unsigned return type - -Kumar Gala (11): - powerpc/ppc64e: Fix link problem when building ppc64e_defconfig - powerpc/fsl-pci: Fix MSI support on 83xx platforms - powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers - powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips - powerpc/fsl-booke: Add p3041 DS board support - powerpc: Fix compile error with paca code on ppc64e - powerpc/fsl-booke: Add support for FSL 64-bit e5500 core - powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes - powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips - powerpc/fsl-booke: Add p5020 DS board support - powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig - -Matthew McClintock (7): - powerpc/mm: Assume first cpu is boot_cpuid not 0 - powerpc/kexec: make masking/disabling interrupts generic - powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec - powerpc/85xx: Minor fixups for kexec on 85xx - powerpc/85xx: flush dcache before resetting cores - powerpc/fsl_soc: Search all global-utilities nodes for rstccr - powerpc/fsl_booke: Add support to boot from core other than 0 - -Michael Neuling (1): - powerpc: Move arch_sd_sibling_asym_packing() to smp.c - -Nathan Fontenot (3): - powerpc/pseries: Export device tree updating routines - powerpc/pseries: Export rtas_ibm_suspend_me() - powerpc/pseries: Partition migration in the kernel - -Nishanth Aravamudan (8): - powerpc/pci: Fix return type of BUID_{HI,LO} macros - powerpc/dma: Fix dma_iommu_dma_supported compare - powerpc/dma: Fix check for direct DMA support - powerpc/vio: Use put_device() on device_register failure - powerpc/viobus: Free TCE table on device release - powerpc/pseries: Use kmemdup - powerpc/pci: Cleanup device dma setup code - powerpc/pseries/xics: Use cpu_possible_mask rather than cpu_all_mask - -Paul Gortmaker (1): - powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT - -Paul Mackerras (5): - powerpc: Abstract indexing of lppaca structs - powerpc: Dynamically allocate most lppaca structs - powerpc: Account time using timebase rather than PURR - powerpc/pseries: Re-enable dispatch trace log userspace interface - powerpc/perf: Fix sampling enable for PPC970 - -Scott Wood (1): - oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt. - -Sean MacLennan (2): - powerpc: Fix incorrect .stabs entry for copy_32.S - powerpc: mtmsrd not defined - -Shaohui Xie (1): - fsl_rio: Add comments for sRIO registers. - -Stephen Rothwell (1): - powerpc: define a compat_sys_recv cond_syscall - -Timur Tabi (5): - powerpc: export ppc_proc_freq and ppc_tb_freq as GPL symbols - powerpc/watchdog: Allow the Book-E driver to be compiled as a module - powerpc/p1022: Add probing for individual DMA channels - powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board - powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option - -Tirumala Marri (1): - powerpc/44x: Add support for the AMCC APM821xx SoC - -matt mooney (1): - powerpc/Makefiles: Change to new flag variables - - arch/powerpc/boot/addnote.c | 4 +- - arch/powerpc/boot/dts/bluestone.dts | 254 +++++++++++++ - arch/powerpc/boot/dts/mpc8308_p1m.dts | 332 ++++++++++++++++ - arch/powerpc/boot/dts/p1022ds.dts | 11 + - arch/powerpc/configs/44x/bluestone_defconfig | 68 ++++ - arch/powerpc/configs/e55xx_smp_defconfig | 84 ++++ - arch/powerpc/configs/ppc44x_defconfig | 9 +- - arch/powerpc/configs/ppc64e_defconfig | 4 +- - arch/powerpc/include/asm/checksum.h | 10 + - arch/powerpc/include/asm/compat.h | 4 +- - arch/powerpc/include/asm/cputable.h | 14 +- - arch/powerpc/include/asm/dma-mapping.h | 14 +- - arch/powerpc/include/asm/elf.h | 2 +- - arch/powerpc/include/asm/exception-64s.h | 3 +- - arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++ - arch/powerpc/include/asm/kexec.h | 1 + - arch/powerpc/include/asm/kvm_fpu.h | 4 +- - arch/powerpc/include/asm/lppaca.h | 29 ++ - arch/powerpc/include/asm/machdep.h | 3 + - arch/powerpc/include/asm/mmu-book3e.h | 15 + - arch/powerpc/include/asm/paca.h | 10 +- - arch/powerpc/include/asm/page_64.h | 4 +- - arch/powerpc/include/asm/ppc-pci.h | 4 +- - arch/powerpc/include/asm/ppc_asm.h | 50 ++- - arch/powerpc/include/asm/processor.h | 4 +- - arch/powerpc/include/asm/pte-common.h | 7 + - arch/powerpc/include/asm/rtas.h | 1 + - arch/powerpc/include/asm/systbl.h | 19 + - arch/powerpc/include/asm/system.h | 4 +- - arch/powerpc/include/asm/time.h | 5 - - arch/powerpc/include/asm/unistd.h | 21 +- - arch/powerpc/kernel/Makefile | 4 +- - arch/powerpc/kernel/align.c | 4 +- - arch/powerpc/kernel/asm-offsets.c | 12 +- - arch/powerpc/kernel/cpu_setup_44x.S | 1 + - arch/powerpc/kernel/cpu_setup_fsl_booke.S | 15 + - arch/powerpc/kernel/cputable.c | 43 ++- - arch/powerpc/kernel/crash.c | 13 +- - arch/powerpc/kernel/dma-iommu.c | 21 +- - arch/powerpc/kernel/dma.c | 20 +- - arch/powerpc/kernel/entry_64.S | 40 ++ - arch/powerpc/kernel/fpu.S | 10 - - arch/powerpc/kernel/head_fsl_booke.S | 10 +- - arch/powerpc/kernel/irq.c | 6 +- - arch/powerpc/kernel/lparcfg.c | 14 +- - arch/powerpc/kernel/machine_kexec.c | 24 ++ - arch/powerpc/kernel/machine_kexec_32.c | 4 + - arch/powerpc/kernel/paca.c | 70 ++++- - arch/powerpc/kernel/pci-common.c | 4 +- - arch/powerpc/kernel/ppc970-pmu.c | 2 + - arch/powerpc/kernel/process.c | 12 - - arch/powerpc/kernel/ptrace.c | 2 +- - arch/powerpc/kernel/rtas.c | 4 +- - arch/powerpc/kernel/setup_32.c | 2 +- - arch/powerpc/kernel/smp.c | 14 +- - arch/powerpc/kernel/time.c | 275 +++++++------- - arch/powerpc/kernel/traps.c | 5 + - arch/powerpc/kernel/vdso.c | 6 +- - arch/powerpc/kernel/vdso32/Makefile | 6 +- - arch/powerpc/kernel/vdso64/Makefile | 6 +- - arch/powerpc/kernel/vio.c | 10 +- - arch/powerpc/kvm/Makefile | 2 +- - arch/powerpc/kvm/book3s_paired_singles.c | 44 +-- - arch/powerpc/kvm/emulate.c | 4 +- - arch/powerpc/kvm/fpu.S | 8 - - arch/powerpc/lib/Makefile | 7 +- - arch/powerpc/lib/checksum_64.S | 482 +++++++++++++++++------- - arch/powerpc/lib/checksum_wrappers_64.c | 102 +++++ - arch/powerpc/lib/copy_32.S | 2 +- - arch/powerpc/lib/ldstfp.S | 36 +- - arch/powerpc/lib/locks.c | 4 +- - arch/powerpc/lib/sstep.c | 8 + - arch/powerpc/math-emu/Makefile | 2 +- - arch/powerpc/mm/Makefile | 6 +- - arch/powerpc/mm/fault.c | 6 + - arch/powerpc/mm/fsl_booke_mmu.c | 15 +- - arch/powerpc/mm/mmu_context_nohash.c | 6 +- - arch/powerpc/mm/mmu_decl.h | 5 +- - arch/powerpc/mm/tlb_nohash.c | 56 +++- - arch/powerpc/mm/tlb_nohash_low.S | 2 +- - arch/powerpc/oprofile/Makefile | 4 +- - arch/powerpc/oprofile/backtrace.c | 2 +- - arch/powerpc/oprofile/op_model_fsl_emb.c | 15 +- - arch/powerpc/platforms/44x/Kconfig | 16 + - arch/powerpc/platforms/44x/ppc44x_simple.c | 1 + - arch/powerpc/platforms/83xx/Kconfig | 4 +- - arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +- - arch/powerpc/platforms/85xx/Kconfig | 28 ++- - arch/powerpc/platforms/85xx/Makefile | 2 + - arch/powerpc/platforms/85xx/p1022_ds.c | 2 + - arch/powerpc/platforms/85xx/p3041_ds.c | 64 ++++ - arch/powerpc/platforms/85xx/p5020_ds.c | 69 ++++ - arch/powerpc/platforms/85xx/smp.c | 83 ++++- - arch/powerpc/platforms/Kconfig.cputype | 8 +- - arch/powerpc/platforms/cell/ras.c | 4 +- - arch/powerpc/platforms/cell/spider-pic.c | 4 +- - arch/powerpc/platforms/cell/spufs/file.c | 18 + - arch/powerpc/platforms/chrp/nvram.c | 4 +- - arch/powerpc/platforms/iseries/Makefile | 2 +- - arch/powerpc/platforms/iseries/dt.c | 4 +- - arch/powerpc/platforms/iseries/smp.c | 2 +- - arch/powerpc/platforms/maple/setup.c | 1 + - arch/powerpc/platforms/powermac/pfunc_core.c | 9 +- - arch/powerpc/platforms/pseries/Makefile | 13 +- - arch/powerpc/platforms/pseries/dlpar.c | 7 +- - arch/powerpc/platforms/pseries/dtl.c | 224 +++++++++--- - arch/powerpc/platforms/pseries/lpar.c | 25 ++- - arch/powerpc/platforms/pseries/mobility.c | 362 ++++++++++++++++++ - arch/powerpc/platforms/pseries/pseries.h | 9 + - arch/powerpc/platforms/pseries/setup.c | 52 +++ - arch/powerpc/platforms/pseries/xics.c | 2 +- - arch/powerpc/sysdev/Makefile | 5 +- - arch/powerpc/sysdev/dart_iommu.c | 74 ++++- - arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 +++++ - arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 159 ++++++++ - arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 231 +++++++++++ - arch/powerpc/sysdev/fsl_msi.c | 9 +- - arch/powerpc/sysdev/fsl_pci.c | 60 +++- - arch/powerpc/sysdev/fsl_pci.h | 1 + - arch/powerpc/sysdev/fsl_rio.c | 65 ++-- - arch/powerpc/sysdev/fsl_soc.c | 20 +- - arch/powerpc/sysdev/mpc8xxx_gpio.c | 3 + - arch/powerpc/sysdev/pmi.c | 2 +- - arch/powerpc/xmon/Makefile | 4 +- - drivers/i2c/busses/i2c-pasemi.c | 2 +- - drivers/macintosh/via-pmu-led.c | 4 +- - drivers/watchdog/Kconfig | 22 +- - drivers/watchdog/booke_wdt.c | 47 ++- - include/linux/pci_ids.h | 8 + - kernel/sys_ni.c | 1 + - 130 files changed, 3676 insertions(+), 683 deletions(-) - create mode 100644 arch/powerpc/boot/dts/bluestone.dts - create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts - create mode 100644 arch/powerpc/configs/44x/bluestone_defconfig - create mode 100644 arch/powerpc/configs/e55xx_smp_defconfig - create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h - create mode 100644 arch/powerpc/lib/checksum_wrappers_64.c - create mode 100644 arch/powerpc/platforms/85xx/p3041_ds.c - create mode 100644 arch/powerpc/platforms/85xx/p5020_ds.c - create mode 100644 arch/powerpc/platforms/pseries/mobility.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c - - -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0006-git-pull-request-http.mbox b/apps/patchwork/tests/mail/0006-git-pull-request-http.mbox deleted file mode 100644 index e4f9007..0000000 --- a/apps/patchwork/tests/mail/0006-git-pull-request-http.mbox +++ /dev/null @@ -1,348 +0,0 @@ -From benh@kernel.crashing.org Fri Oct 22 11:51:02 2010 -Return-Path: <linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org> -X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bilbo.ozlabs.org -X-Spam-Level: -X-Spam-Status: No, score=0.0 required=3.0 tests=none autolearn=disabled - version=3.3.1 -X-Original-To: jk@ozlabs.org -Delivered-To: jk@ozlabs.org -Received: from bilbo.ozlabs.org (localhost [127.0.0.1]) - by ozlabs.org (Postfix) with ESMTP id ED4B3100937 - for <jk@ozlabs.org>; Fri, 22 Oct 2010 14:51:54 +1100 (EST) -Received: by ozlabs.org (Postfix) - id BF799B70CB; Fri, 22 Oct 2010 14:51:50 +1100 (EST) -Delivered-To: linuxppc-dev@ozlabs.org -Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) - (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) - (Client did not present a certificate) - by ozlabs.org (Postfix) with ESMTPS id 94629B7043 - for <linuxppc-dev@ozlabs.org>; Fri, 22 Oct 2010 14:51:49 +1100 (EST) -Received: from [IPv6:::1] (localhost.localdomain [127.0.0.1]) - by gate.crashing.org (8.14.1/8.13.8) with ESMTP id o9M3p3SP018234; - Thu, 21 Oct 2010 22:51:04 -0500 -Subject: [git pull] Please pull powerpc.git next branch -From: Benjamin Herrenschmidt <benh@kernel.crashing.org> -To: Linus Torvalds <torvalds@linux-foundation.org> -Date: Fri, 22 Oct 2010 14:51:02 +1100 -Message-ID: <1287719462.2198.37.camel@pasglop> -Mime-Version: 1.0 -X-Mailer: Evolution 2.30.3 -Cc: linuxppc-dev list <linuxppc-dev@ozlabs.org>, - Andrew Morton <akpm@linux-foundation.org>, - Linux Kernel list <linux-kernel@vger.kernel.org> -X-BeenThere: linuxppc-dev@lists.ozlabs.org -X-Mailman-Version: 2.1.13 -Precedence: list -List-Id: Linux on PowerPC Developers Mail List <cbe-oss-dev.ozlabs.org> -List-Unsubscribe: <https://lists.ozlabs.org/options/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=unsubscribe> -List-Archive: <http://lists.ozlabs.org/pipermail/linuxppc-dev> -List-Post: <mailto:linuxppc-dev@lists.ozlabs.org> -List-Help: <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=help> -List-Subscribe: <https://lists.ozlabs.org/listinfo/linuxppc-dev>, - <mailto:linuxppc-dev-request@lists.ozlabs.org?subject=subscribe> -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Sender: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -Errors-To: linuxppc-dev-bounces+jk=ozlabs.org@lists.ozlabs.org -X-UID: 11446 -X-Length: 16781 -Status: R -X-Status: N -X-KMail-EncryptionState: -X-KMail-SignatureState: -X-KMail-MDN-Sent: - -Hi Linus ! - -Here's powerpc's batch for this merge window. Mostly bits and pieces, -such as Anton doing some performance tuning left and right, and the -usual churn. One hilight is the support for the new Freescale e5500 core -(64-bit BookE). Another one is that we now wire up the whole lot of -socket calls as direct syscalls in addition to the old style indirect -method. - -Cheers, -Ben. - -The following changes since commit e10117d36ef758da0690c95ecffc09d5dd7da479: - Linus Torvalds (1): - Merge branch 'upstream-linus' of git://git.kernel.org/.../jgarzik/libata-dev - -are available in the git repository at: - - http://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next - -Andreas Schwab (1): - powerpc: Remove fpscr use from [kvm_]cvt_{fd,df} - -Anton Blanchard (5): - powerpc: Optimise 64bit csum_partial - powerpc: Optimise 64bit csum_partial_copy_generic and add csum_and_copy_from_user - powerpc: Add 64bit csum_and_copy_to_user - powerpc: Feature nop out reservation clear when stcx checks address - powerpc: Check end of stack canary at oops time - -Arnd Bergmann (1): - powerpc/spufs: Use llseek in all file operations - -Benjamin Herrenschmidt (4): - powerpc/dma: Add optional platform override of dma_set_mask() - powerpc/dart_iommu: Support for 64-bit iommu bypass window on PCIe - Merge remote branch 'kumar/merge' into next - Merge remote branch 'jwb/next' into next - -Denis Kirjanov (1): - powerpc: Use is_32bit_task() helper to test 32-bit binary - -Harninder Rai (1): - powerpc/85xx: add cache-sram support - -Ian Munsie (1): - powerpc: Wire up direct socket system calls - -Ilya Yanok (1): - powerpc/mpc83xx: Support for MPC8308 P1M board - -Joe Perches (2): - powerpc: Use static const char arrays - powerpc: Remove pr_<level> uses of KERN_<level> - -Josh Boyer (1): - powerpc/44x: Update ppc44x_defconfig - -Julia Lawall (7): - powerpc/via-pmu-led.c: Add of_node_put to avoid memory leak - powerpc/maple: Add of_node_put to avoid memory leak - powerpc/powermac/pfunc_core.c: Add of_node_put to avoid memory leak - powerpc/cell: Add of_node_put to avoid memory leak - powerpc/chrp/nvram.c: Add of_node_put to avoid memory leak - powerpc/irq.c: Add of_node_put to avoid memory leak - i2c/i2c-pasemi.c: Fix unsigned return type - -Kumar Gala (11): - powerpc/ppc64e: Fix link problem when building ppc64e_defconfig - powerpc/fsl-pci: Fix MSI support on 83xx platforms - powerpc/mpc8xxx_gpio: Add support for 'qoriq-gpio' controllers - powerpc/fsl-booke: Add PCI device ids for P2040/P3041/P5010/P5020 QoirQ chips - powerpc/fsl-booke: Add p3041 DS board support - powerpc: Fix compile error with paca code on ppc64e - powerpc/fsl-booke: Add support for FSL 64-bit e5500 core - powerpc/fsl-booke: Add support for FSL Arch v1.0 MMU in setup_page_sizes - powerpc/fsl-booke64: Use TLB CAMs to cover linear mapping on FSL 64-bit chips - powerpc/fsl-booke: Add p5020 DS board support - powerpc/fsl-booke: Add e55xx (64-bit) smp defconfig - -Matthew McClintock (7): - powerpc/mm: Assume first cpu is boot_cpuid not 0 - powerpc/kexec: make masking/disabling interrupts generic - powerpc/85xx: Remove call to mpic_teardown_this_cpu in kexec - powerpc/85xx: Minor fixups for kexec on 85xx - powerpc/85xx: flush dcache before resetting cores - powerpc/fsl_soc: Search all global-utilities nodes for rstccr - powerpc/fsl_booke: Add support to boot from core other than 0 - -Michael Neuling (1): - powerpc: Move arch_sd_sibling_asym_packing() to smp.c - -Nathan Fontenot (3): - powerpc/pseries: Export device tree updating routines - powerpc/pseries: Export rtas_ibm_suspend_me() - powerpc/pseries: Partition migration in the kernel - -Nishanth Aravamudan (8): - powerpc/pci: Fix return type of BUID_{HI,LO} macros - powerpc/dma: Fix dma_iommu_dma_supported compare - powerpc/dma: Fix check for direct DMA support - powerpc/vio: Use put_device() on device_register failure - powerpc/viobus: Free TCE table on device release - powerpc/pseries: Use kmemdup - powerpc/pci: Cleanup device dma setup code - powerpc/pseries/xics: Use cpu_possible_mask rather than cpu_all_mask - -Paul Gortmaker (1): - powerpc: Fix invalid page flags in create TLB CAM path for PTE_64BIT - -Paul Mackerras (5): - powerpc: Abstract indexing of lppaca structs - powerpc: Dynamically allocate most lppaca structs - powerpc: Account time using timebase rather than PURR - powerpc/pseries: Re-enable dispatch trace log userspace interface - powerpc/perf: Fix sampling enable for PPC970 - -Scott Wood (1): - oprofile/fsl emb: Don't set MSR[PMM] until after clearing the interrupt. - -Sean MacLennan (2): - powerpc: Fix incorrect .stabs entry for copy_32.S - powerpc: mtmsrd not defined - -Shaohui Xie (1): - fsl_rio: Add comments for sRIO registers. - -Stephen Rothwell (1): - powerpc: define a compat_sys_recv cond_syscall - -Timur Tabi (5): - powerpc: export ppc_proc_freq and ppc_tb_freq as GPL symbols - powerpc/watchdog: Allow the Book-E driver to be compiled as a module - powerpc/p1022: Add probing for individual DMA channels - powerpc/85xx: add ngPIXIS FPGA device tree node to the P1022DS board - powerpc/watchdog: Make default timeout for Book-E watchdog a Kconfig option - -Tirumala Marri (1): - powerpc/44x: Add support for the AMCC APM821xx SoC - -matt mooney (1): - powerpc/Makefiles: Change to new flag variables - - arch/powerpc/boot/addnote.c | 4 +- - arch/powerpc/boot/dts/bluestone.dts | 254 +++++++++++++ - arch/powerpc/boot/dts/mpc8308_p1m.dts | 332 ++++++++++++++++ - arch/powerpc/boot/dts/p1022ds.dts | 11 + - arch/powerpc/configs/44x/bluestone_defconfig | 68 ++++ - arch/powerpc/configs/e55xx_smp_defconfig | 84 ++++ - arch/powerpc/configs/ppc44x_defconfig | 9 +- - arch/powerpc/configs/ppc64e_defconfig | 4 +- - arch/powerpc/include/asm/checksum.h | 10 + - arch/powerpc/include/asm/compat.h | 4 +- - arch/powerpc/include/asm/cputable.h | 14 +- - arch/powerpc/include/asm/dma-mapping.h | 14 +- - arch/powerpc/include/asm/elf.h | 2 +- - arch/powerpc/include/asm/exception-64s.h | 3 +- - arch/powerpc/include/asm/fsl_85xx_cache_sram.h | 48 +++ - arch/powerpc/include/asm/kexec.h | 1 + - arch/powerpc/include/asm/kvm_fpu.h | 4 +- - arch/powerpc/include/asm/lppaca.h | 29 ++ - arch/powerpc/include/asm/machdep.h | 3 + - arch/powerpc/include/asm/mmu-book3e.h | 15 + - arch/powerpc/include/asm/paca.h | 10 +- - arch/powerpc/include/asm/page_64.h | 4 +- - arch/powerpc/include/asm/ppc-pci.h | 4 +- - arch/powerpc/include/asm/ppc_asm.h | 50 ++- - arch/powerpc/include/asm/processor.h | 4 +- - arch/powerpc/include/asm/pte-common.h | 7 + - arch/powerpc/include/asm/rtas.h | 1 + - arch/powerpc/include/asm/systbl.h | 19 + - arch/powerpc/include/asm/system.h | 4 +- - arch/powerpc/include/asm/time.h | 5 - - arch/powerpc/include/asm/unistd.h | 21 +- - arch/powerpc/kernel/Makefile | 4 +- - arch/powerpc/kernel/align.c | 4 +- - arch/powerpc/kernel/asm-offsets.c | 12 +- - arch/powerpc/kernel/cpu_setup_44x.S | 1 + - arch/powerpc/kernel/cpu_setup_fsl_booke.S | 15 + - arch/powerpc/kernel/cputable.c | 43 ++- - arch/powerpc/kernel/crash.c | 13 +- - arch/powerpc/kernel/dma-iommu.c | 21 +- - arch/powerpc/kernel/dma.c | 20 +- - arch/powerpc/kernel/entry_64.S | 40 ++ - arch/powerpc/kernel/fpu.S | 10 - - arch/powerpc/kernel/head_fsl_booke.S | 10 +- - arch/powerpc/kernel/irq.c | 6 +- - arch/powerpc/kernel/lparcfg.c | 14 +- - arch/powerpc/kernel/machine_kexec.c | 24 ++ - arch/powerpc/kernel/machine_kexec_32.c | 4 + - arch/powerpc/kernel/paca.c | 70 ++++- - arch/powerpc/kernel/pci-common.c | 4 +- - arch/powerpc/kernel/ppc970-pmu.c | 2 + - arch/powerpc/kernel/process.c | 12 - - arch/powerpc/kernel/ptrace.c | 2 +- - arch/powerpc/kernel/rtas.c | 4 +- - arch/powerpc/kernel/setup_32.c | 2 +- - arch/powerpc/kernel/smp.c | 14 +- - arch/powerpc/kernel/time.c | 275 +++++++------- - arch/powerpc/kernel/traps.c | 5 + - arch/powerpc/kernel/vdso.c | 6 +- - arch/powerpc/kernel/vdso32/Makefile | 6 +- - arch/powerpc/kernel/vdso64/Makefile | 6 +- - arch/powerpc/kernel/vio.c | 10 +- - arch/powerpc/kvm/Makefile | 2 +- - arch/powerpc/kvm/book3s_paired_singles.c | 44 +-- - arch/powerpc/kvm/emulate.c | 4 +- - arch/powerpc/kvm/fpu.S | 8 - - arch/powerpc/lib/Makefile | 7 +- - arch/powerpc/lib/checksum_64.S | 482 +++++++++++++++++------- - arch/powerpc/lib/checksum_wrappers_64.c | 102 +++++ - arch/powerpc/lib/copy_32.S | 2 +- - arch/powerpc/lib/ldstfp.S | 36 +- - arch/powerpc/lib/locks.c | 4 +- - arch/powerpc/lib/sstep.c | 8 + - arch/powerpc/math-emu/Makefile | 2 +- - arch/powerpc/mm/Makefile | 6 +- - arch/powerpc/mm/fault.c | 6 + - arch/powerpc/mm/fsl_booke_mmu.c | 15 +- - arch/powerpc/mm/mmu_context_nohash.c | 6 +- - arch/powerpc/mm/mmu_decl.h | 5 +- - arch/powerpc/mm/tlb_nohash.c | 56 +++- - arch/powerpc/mm/tlb_nohash_low.S | 2 +- - arch/powerpc/oprofile/Makefile | 4 +- - arch/powerpc/oprofile/backtrace.c | 2 +- - arch/powerpc/oprofile/op_model_fsl_emb.c | 15 +- - arch/powerpc/platforms/44x/Kconfig | 16 + - arch/powerpc/platforms/44x/ppc44x_simple.c | 1 + - arch/powerpc/platforms/83xx/Kconfig | 4 +- - arch/powerpc/platforms/83xx/mpc830x_rdb.c | 3 +- - arch/powerpc/platforms/85xx/Kconfig | 28 ++- - arch/powerpc/platforms/85xx/Makefile | 2 + - arch/powerpc/platforms/85xx/p1022_ds.c | 2 + - arch/powerpc/platforms/85xx/p3041_ds.c | 64 ++++ - arch/powerpc/platforms/85xx/p5020_ds.c | 69 ++++ - arch/powerpc/platforms/85xx/smp.c | 83 ++++- - arch/powerpc/platforms/Kconfig.cputype | 8 +- - arch/powerpc/platforms/cell/ras.c | 4 +- - arch/powerpc/platforms/cell/spider-pic.c | 4 +- - arch/powerpc/platforms/cell/spufs/file.c | 18 + - arch/powerpc/platforms/chrp/nvram.c | 4 +- - arch/powerpc/platforms/iseries/Makefile | 2 +- - arch/powerpc/platforms/iseries/dt.c | 4 +- - arch/powerpc/platforms/iseries/smp.c | 2 +- - arch/powerpc/platforms/maple/setup.c | 1 + - arch/powerpc/platforms/powermac/pfunc_core.c | 9 +- - arch/powerpc/platforms/pseries/Makefile | 13 +- - arch/powerpc/platforms/pseries/dlpar.c | 7 +- - arch/powerpc/platforms/pseries/dtl.c | 224 +++++++++--- - arch/powerpc/platforms/pseries/lpar.c | 25 ++- - arch/powerpc/platforms/pseries/mobility.c | 362 ++++++++++++++++++ - arch/powerpc/platforms/pseries/pseries.h | 9 + - arch/powerpc/platforms/pseries/setup.c | 52 +++ - arch/powerpc/platforms/pseries/xics.c | 2 +- - arch/powerpc/sysdev/Makefile | 5 +- - arch/powerpc/sysdev/dart_iommu.c | 74 ++++- - arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | 101 +++++ - arch/powerpc/sysdev/fsl_85xx_cache_sram.c | 159 ++++++++ - arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | 231 +++++++++++ - arch/powerpc/sysdev/fsl_msi.c | 9 +- - arch/powerpc/sysdev/fsl_pci.c | 60 +++- - arch/powerpc/sysdev/fsl_pci.h | 1 + - arch/powerpc/sysdev/fsl_rio.c | 65 ++-- - arch/powerpc/sysdev/fsl_soc.c | 20 +- - arch/powerpc/sysdev/mpc8xxx_gpio.c | 3 + - arch/powerpc/sysdev/pmi.c | 2 +- - arch/powerpc/xmon/Makefile | 4 +- - drivers/i2c/busses/i2c-pasemi.c | 2 +- - drivers/macintosh/via-pmu-led.c | 4 +- - drivers/watchdog/Kconfig | 22 +- - drivers/watchdog/booke_wdt.c | 47 ++- - include/linux/pci_ids.h | 8 + - kernel/sys_ni.c | 1 + - 130 files changed, 3676 insertions(+), 683 deletions(-) - create mode 100644 arch/powerpc/boot/dts/bluestone.dts - create mode 100644 arch/powerpc/boot/dts/mpc8308_p1m.dts - create mode 100644 arch/powerpc/configs/44x/bluestone_defconfig - create mode 100644 arch/powerpc/configs/e55xx_smp_defconfig - create mode 100644 arch/powerpc/include/asm/fsl_85xx_cache_sram.h - create mode 100644 arch/powerpc/lib/checksum_wrappers_64.c - create mode 100644 arch/powerpc/platforms/85xx/p3041_ds.c - create mode 100644 arch/powerpc/platforms/85xx/p5020_ds.c - create mode 100644 arch/powerpc/platforms/pseries/mobility.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h - create mode 100644 arch/powerpc/sysdev/fsl_85xx_cache_sram.c - create mode 100644 arch/powerpc/sysdev/fsl_85xx_l2ctlr.c - - -_______________________________________________ -Linuxppc-dev mailing list -Linuxppc-dev@lists.ozlabs.org -https://lists.ozlabs.org/listinfo/linuxppc-dev diff --git a/apps/patchwork/tests/mail/0007-cvs-format-diff.mbox b/apps/patchwork/tests/mail/0007-cvs-format-diff.mbox deleted file mode 100644 index 99735fa..0000000 --- a/apps/patchwork/tests/mail/0007-cvs-format-diff.mbox +++ /dev/null @@ -1,134 +0,0 @@ -Received: with ECARTIS (v1.0.0; list linux-mips); Tue, 06 Dec 2011 01:49:42 +0100 (CET) -Received: from mail3.caviumnetworks.com ([12.108.191.235]:14337 "EHLO - mail3.caviumnetworks.com" rhost-flags-OK-OK-OK-OK) - by eddie.linux-mips.org with ESMTP id S1903632Ab1LFAth (ORCPT - <rfc822;linux-mips@linux-mips.org>); Tue, 6 Dec 2011 01:49:37 +0100 -Received: from caexch01.caveonetworks.com (Not Verified[192.168.16.9]) by mail3.caviumnetworks.com with MailMarshal (v6,7,2,8378) - id <B4edd66f80000>; Mon, 05 Dec 2011 16:51:04 -0800 -Received: from caexch01.caveonetworks.com ([192.168.16.9]) by caexch01.caveonetworks.com with Microsoft SMTPSVC(6.0.3790.4675); - Mon, 5 Dec 2011 16:49:36 -0800 -Received: from dd1.caveonetworks.com ([64.2.3.195]) by caexch01.caveonetworks.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); - Mon, 5 Dec 2011 16:49:35 -0800 -Message-ID: <4EDD669F.30207@cavium.com> -Date: Mon, 05 Dec 2011 16:49:35 -0800 -From: David Daney <david.daney@cavium.com> -User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.15) Gecko/20101027 Fedora/3.0.10-1.fc12 Thunderbird/3.0.10 -MIME-Version: 1.0 -To: binutils <binutils@sourceware.org> -CC: linux-mips <linux-mips@linux-mips.org>, - Manuel Lauss <manuel.lauss@googlemail.com>, - Debian MIPS <debian-mips@lists.debian.org> -Subject: [Patch]: Fix ld pr11138 FAILures on mips*. -Content-Type: multipart/mixed; - boundary="------------080709040708040308010506" -X-OriginalArrivalTime: 06 Dec 2011 00:49:35.0825 (UTC) FILETIME=[ECF8DC10:01CCB3B0] -Return-Path: <David.Daney@caviumnetworks.com> -X-Envelope-To: <"|/home/ecartis/ecartis -s linux-mips"> (uid 0) -X-Orcpt: rfc822;linux-mips@linux-mips.org -Original-Recipient: rfc822;linux-mips@linux-mips.org -X-archive-position: 32041 -X-ecartis-version: Ecartis v1.0.0 -Sender: linux-mips-bounce@linux-mips.org -Errors-to: linux-mips-bounce@linux-mips.org -X-original-sender: david.daney@cavium.com -Precedence: bulk -X-list: linux-mips - -This is a multi-part message in MIME format. ---------------080709040708040308010506 -Content-Type: text/plain; charset=ISO-8859-1; format=flowed -Content-Transfer-Encoding: 7bit - -The pr11138 testcase links an executable with a version script. On -mips64-linux the presence of a version script was causing the -MIPS_RLD_MAP dynamic tag to be populated with a NULL value. When such -an executable was run ld.so would try to dereference this and receive -SIGSEGV, thus killing the process. - -The root cause of this is that the mips linker synthesizes a special -symbol "__RLD_MAP", and then sets MIPS_RLD_MAP to point to it. When a -version script is present, this symbol gets versioned along with all the -rest, and when it is time to take its address, the symbol can no longer -be found as it has had version information appended to its name. - -Since "__RLD_MAP" is really part of the ABI, we want to exclude it from -symbol versioning. To this end, I introduced a new symbol flag -'no_sym_version' to tag this type of symbol. When the "__RLD_MAP" -symbol is created, we set this flag. - -In _bfd_elf_link_assign_sym_version, we then skip all symbols that have -'no_sym_version' set, and everything now works. - -This problem has also been reported in the wild when linking the firefox -executable. - -Tested on mips64-linux-gnu and x86_64-linux-gnu - -Ok to commit? - -2011-12-05 David Daney <david.daney@cavium.com> - - * elf-bfd.h (elf_link_hash_entry): Add no_sym_version field. - * elflink.c (_bfd_elf_link_assign_sym_version): Don't assign a - version if no_sym_version is set. - * elfxx-mips.c (_bfd_mips_elf_create_dynamic_sections): Set - no_sym_version for "__RLD_MAP". - ---------------080709040708040308010506 -Content-Type: text/plain; - name="dd-2.patch" -Content-Transfer-Encoding: 7bit -Content-Disposition: attachment; - filename="dd-2.patch" - -Index: bfd/elf-bfd.h -=================================================================== -RCS file: /cvs/src/src/bfd/elf-bfd.h,v -retrieving revision 1.329 -diff -u -p -r1.329 elf-bfd.h ---- bfd/elf-bfd.h 17 Aug 2011 00:39:38 -0000 1.329 -+++ bfd/elf-bfd.h 5 Dec 2011 20:15:49 -0000 -@@ -198,6 +198,8 @@ struct elf_link_hash_entry - unsigned int pointer_equality_needed : 1; - /* Symbol is a unique global symbol. */ - unsigned int unique_global : 1; -+ /* Symbol should not be versioned. It is part of the ABI */ -+ unsigned int no_sym_version : 1; - - /* String table index in .dynstr if this is a dynamic symbol. */ - unsigned long dynstr_index; -Index: bfd/elflink.c -=================================================================== -RCS file: /cvs/src/src/bfd/elflink.c,v -retrieving revision 1.430 -diff -u -p -r1.430 elflink.c ---- bfd/elflink.c 15 Nov 2011 11:33:57 -0000 1.430 -+++ bfd/elflink.c 5 Dec 2011 20:15:50 -0000 -@@ -1946,6 +1946,9 @@ _bfd_elf_link_assign_sym_version (struct - if (!h->def_regular) - return TRUE; - -+ if (h->no_sym_version) -+ return TRUE; -+ - bed = get_elf_backend_data (info->output_bfd); - p = strchr (h->root.root.string, ELF_VER_CHR); - if (p != NULL && h->verinfo.vertree == NULL) -Index: bfd/elfxx-mips.c -=================================================================== -RCS file: /cvs/src/src/bfd/elfxx-mips.c,v -retrieving revision 1.296 -diff -u -p -r1.296 elfxx-mips.c ---- bfd/elfxx-mips.c 29 Nov 2011 20:28:54 -0000 1.296 -+++ bfd/elfxx-mips.c 5 Dec 2011 20:15:50 -0000 -@@ -7260,6 +7260,7 @@ _bfd_mips_elf_create_dynamic_sections (b - h = (struct elf_link_hash_entry *) bh; - h->non_elf = 0; - h->def_regular = 1; -+ h->no_sym_version = 1; - h->type = STT_OBJECT; - - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - ---------------080709040708040308010506-- - diff --git a/apps/patchwork/tests/mail/0008-git-rename.mbox b/apps/patchwork/tests/mail/0008-git-rename.mbox deleted file mode 100644 index 8277049..0000000 --- a/apps/patchwork/tests/mail/0008-git-rename.mbox +++ /dev/null @@ -1,24 +0,0 @@ -From: "Yann E. MORIN" <yann.morin.1998@free.fr> -Subject: [Buildroot] [PATCH 01/11] package/rpi-userland: rename patches -Date: Tue, 8 Oct 2013 22:09:47 +0000 - -Rename patches to follow standard naming scheme. - -Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> ---- - ...d-pkgconfig-files.patch => rpi-userland-000-add-pkgconfig-files.patch} | 0 - ...erland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch} | 0 - 2 files changed, 0 insertions(+), 0 deletions(-) - rename package/rpi-userland/{rpi-userland-add-pkgconfig-files.patch => rpi-userland-000-add-pkgconfig-files.patch} (100%) - rename package/rpi-userland/{rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch => rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch} (100%) - -diff --git a/package/rpi-userland/rpi-userland-add-pkgconfig-files.patch b/package/rpi-userland/rpi-userland-000-add-pkgconfig-files.patch -similarity index 100% -rename from package/rpi-userland/rpi-userland-add-pkgconfig-files.patch -rename to package/rpi-userland/rpi-userland-000-add-pkgconfig-files.patch -diff --git a/package/rpi-userland/rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch b/package/rpi-userland/rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch -similarity index 100% -rename from package/rpi-userland/rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch -rename to package/rpi-userland/rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch --- -1.8.1.2 diff --git a/apps/patchwork/tests/mail/0009-git-rename-with-diff.mbox b/apps/patchwork/tests/mail/0009-git-rename-with-diff.mbox deleted file mode 100644 index 761cfc1..0000000 --- a/apps/patchwork/tests/mail/0009-git-rename-with-diff.mbox +++ /dev/null @@ -1,32 +0,0 @@ -From: "Yann E. MORIN" <yann.morin.1998@free.fr> -Subject: [Buildroot] [PATCH 01/11] package/rpi-userland: rename patches -Date: Tue, 8 Oct 2013 22:09:47 +0000 - -Rename patches to follow standard naming scheme. - -Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> ---- - ...d-pkgconfig-files.patch => rpi-userland-000-add-pkgconfig-files.patch} | 0 - ...erland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch} | 0 - 2 files changed, 0 insertions(+), 0 deletions(-) - rename package/rpi-userland/{rpi-userland-add-pkgconfig-files.patch => rpi-userland-000-add-pkgconfig-files.patch} (100%) - rename package/rpi-userland/{rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch => rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch} (100%) - -diff --git a/package/rpi-userland/rpi-userland-add-pkgconfig-files.patch b/package/rpi-userland/rpi-userland-000-add-pkgconfig-files.patch -similarity index 100% -rename from package/rpi-userland/rpi-userland-add-pkgconfig-files.patch -rename to package/rpi-userland/rpi-userland-000-add-pkgconfig-files.patch -@@ -100,7 +100,7 @@ - a - a --a -+b - c - c - c -diff --git a/package/rpi-userland/rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch b/package/rpi-userland/rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch -similarity index 100% -rename from package/rpi-userland/rpi-userland-makefiles-0001-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch -rename to package/rpi-userland/rpi-userland-001-makefiles-cmake-vmcs.cmake-allow-to-override-VMCS_IN.patch --- -1.8.1.2 diff --git a/apps/patchwork/tests/mail/0010-invalid-charset.mbox b/apps/patchwork/tests/mail/0010-invalid-charset.mbox deleted file mode 100644 index 10b369d..0000000 --- a/apps/patchwork/tests/mail/0010-invalid-charset.mbox +++ /dev/null @@ -1,90 +0,0 @@ -From libc-alpha-return-50517-siddhesh=redhat.com@sourceware.org Thu Jun 5 10:36:33 2014 -Received: (qmail 11948 invoked by alias); 4 Jun 2014 17:51:01 -0000 -Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm -List-Id: <libc-alpha.sourceware.org> -Sender: libc-alpha-owner@sourceware.org -Date: Wed, 4 Jun 2014 17:50:46 +0000 -From: "Joseph S. Myers" <joseph@codesourcery.com> -To: <libc-alpha@sourceware.org> -Subject: Fix pow overflow in non-default rounding modes (bug 16315) -Message-ID: <Pine.LNX.4.64.1406041749420.3719@digraph.polyomino.org.uk> -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="-1152306461-1522705971-1401904246=:3719" -Content-Length: 24171 - ----1152306461-1522705971-1401904246=:3719 -Content-Type: text/plain; charset="none" -Content-Transfer-Encoding: QUOTED-PRINTABLE - -This patch, relative to a tree with -<https://sourceware.org/ml/libc-alpha/2014-06/msg00076.html> applied, -fixes bug 16315, bad pow handling of overflow/underflow in non-default -rounding modes. Tests of pow are duly converted to ALL_RM_TEST to run -all tests in all rounding modes. - -There are two main issues here. First, various implementations -compute a negative result by negating a positive result, but this -yields inappropriate overflow / underflow values for directed -rounding, so either overflow / underflow results need recomputing in -the correct sign, or the relevant overflowing / underflowing operation -needs to be made to have a result of the correct sign. Second, the -dbl-64 implementation sets FE_TONEAREST internally; in the overflow / -underflow case, the result needs recomputing in the original rounding -mode. - -Tested x86_64 and x86 and ulps updated accordingly. - -(auto-libm-test-out diffs omitted below.) - -2014-06-04 Joseph Myers <joseph@codesourcery.com> - -=09[BZ #16315] -=09* sysdeps/i386/fpu/e_pow.S (__ieee754_pow): Ensure possibly -=09overflowing or underflowing operations take place with sign of -=09result. -=09* sysdeps/i386/fpu/e_powf.S (__ieee754_powf): Likewise. -=09* sysdeps/i386/fpu/e_powl.S (__ieee754_powl): Likewise. -=09* sysdeps/ieee754/dbl-64/e_pow.c: Include <math.h>. -=09(__ieee754_pow): Recompute overflowing and underflowing results in -=09original rounding mode. -=09* sysdeps/x86/fpu/powl_helper.c: Include <stdbool.h>. -=09(__powl_helper): Allow negative argument X and scale negated value -=09as needed. Avoid passing value outside [-1, 1] to f2xm1. -=09* sysdeps/x86_64/fpu/e_powl.S (__ieee754_powl): Ensure possibly -=09overflowing or underflowing operations take place with sign of -=09result. -=09* sysdeps/x86_64/fpu/multiarch/e_pow.c [HAVE_FMA4_SUPPORT]: -=09Include <math.h>. -=09* math/auto-libm-test-in: Add more tests of pow. -=09* math/auto-libm-test-out: Regenerated. -=09* math/libm-test.inc (pow_test): Use ALL_RM_TEST. -=09(pow_tonearest_test_data): Remove. -=09(pow_test_tonearest): Likewise. -=09(pow_towardzero_test_data): Likewise. -=09(pow_test_towardzero): Likewise. -=09(pow_downward_test_data): Likewise. -=09(pow_test_downward): Likewise. -=09(pow_upward_test_data): Likewise. -=09(pow_test_upward): Likewise. -=09(main): Don't call removed functions. -=09* sysdeps/i386/fpu/libm-test-ulps: Update. -=09* sysdeps/x86_64/fpu/libm-test-ulps: Likewise. - -diff --git a/sysdeps/x86_64/fpu/multiarch/e_pow.c b/sysdeps/x86_64/fpu/mult= -iarch/e_pow.c -index a740b6c..433cce0 100644 ---- a/sysdeps/x86_64/fpu/multiarch/e_pow.c -+++ b/sysdeps/x86_64/fpu/multiarch/e_pow.c -@@ -1,5 +1,6 @@ - #ifdef HAVE_FMA4_SUPPORT - # include <init-arch.h> -+# include <math.h> - # include <math_private.h> -=20 - extern double __ieee754_pow_sse2 (double, double); - ---=20 -Joseph S. Myers -joseph@codesourcery.com ----1152306461-1522705971-1401904246=:3719-- diff --git a/apps/patchwork/tests/mail/0011-no-newline-at-end-of-file.mbox b/apps/patchwork/tests/mail/0011-no-newline-at-end-of-file.mbox deleted file mode 100644 index 3ed0597..0000000 --- a/apps/patchwork/tests/mail/0011-no-newline-at-end-of-file.mbox +++ /dev/null @@ -1,45 +0,0 @@ -Subject: [PATCH v3 5/5] selftests, powerpc: Add test for VPHN -From: Greg Kurz <gkurz@linux.vnet.ibm.com> -To: Michael Ellerman <mpe@ellerman.id.au> -Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>, - linuxppc-dev@lists.ozlabs.org -Date: Mon, 23 Feb 2015 16:14:44 +0100 -MIME-Version: 1.0 -Content-Type: text/plain; charset="utf-8" -Content-Transfer-Encoding: 8bit - -The goal is to verify vphn_unpack_associativity() parses VPHN numbers -correctly. We feed it with a variety of input values and compare with -expected results. - -diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile -index 1d5e7ad..476b8dd 100644 ---- a/tools/testing/selftests/powerpc/Makefile -+++ b/tools/testing/selftests/powerpc/Makefile -@@ -13,7 +13,7 @@ CFLAGS := -Wall -O2 -flto -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CUR - - export CC CFLAGS - --TARGETS = pmu copyloops mm tm primitives stringloops -+TARGETS = pmu copyloops mm tm primitives stringloops vphn - - endif - -diff --git a/tools/testing/selftests/powerpc/vphn/vphn.c b/tools/testing/selftests/powerpc/vphn/vphn.c -new file mode 120000 -index 0000000..186b906 ---- /dev/null -+++ b/tools/testing/selftests/powerpc/vphn/vphn.c -@@ -0,0 +1 @@ -+../../../../../arch/powerpc/mm/vphn.c -\ No newline at end of file -diff --git a/tools/testing/selftests/powerpc/vphn/vphn.h b/tools/testing/selftests/powerpc/vphn/vphn.h -new file mode 120000 -index 0000000..7131efe ---- /dev/null -+++ b/tools/testing/selftests/powerpc/vphn/vphn.h -@@ -0,0 +1 @@ -+../../../../../arch/powerpc/mm/vphn.h -\ No newline at end of file - - diff --git a/apps/patchwork/tests/patches/0001-add-line.patch b/apps/patchwork/tests/patches/0001-add-line.patch deleted file mode 100644 index c6cb9f1..0000000 --- a/apps/patchwork/tests/patches/0001-add-line.patch +++ /dev/null @@ -1,7 +0,0 @@ -diff --git a/meep.text b/meep.text -index 3d75d48..a57f4dd 100644 ---- a/meep.text -+++ b/meep.text -@@ -1,1 +1,2 @@ - meep -+meep diff --git a/apps/patchwork/tests/patches/0002-utf-8.patch b/apps/patchwork/tests/patches/0002-utf-8.patch deleted file mode 100644 index 71a2f24..0000000 --- a/apps/patchwork/tests/patches/0002-utf-8.patch +++ /dev/null @@ -1,7 +0,0 @@ -diff --git a/meep.text b/meep.text -index 3d75d48..a57f4dd 100644 ---- a/meep.text -+++ b/meep.text -@@ -1,1 +1,2 @@ - meep -+meëp diff --git a/apps/patchwork/tests/test_bundles.py b/apps/patchwork/tests/test_bundles.py deleted file mode 100644 index 38f3a2c..0000000 --- a/apps/patchwork/tests/test_bundles.py +++ /dev/null @@ -1,646 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2009 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import datetime -from django.test import TestCase -from django.test.client import Client -from django.utils.http import urlencode -from django.conf import settings -from patchwork.models import Patch, Bundle, BundlePatch, Person -from patchwork.tests.utils import defaults, create_user, find_in_context - -def bundle_url(bundle): - return '/bundle/%s/%s/' % (bundle.owner.username, bundle.name) - -class BundleListTest(TestCase): - def setUp(self): - self.user = create_user() - self.client.login(username = self.user.username, - password = self.user.username) - - def testNoBundles(self): - response = self.client.get('/user/bundles/') - self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual( - len(find_in_context(response.context, 'bundles')), 0) - - def testSingleBundle(self): - defaults.project.save() - bundle = Bundle(owner = self.user, project = defaults.project) - bundle.save() - response = self.client.get('/user/bundles/') - self.failUnlessEqual(response.status_code, 200) - self.failUnlessEqual( - len(find_in_context(response.context, 'bundles')), 1) - - def tearDown(self): - self.user.delete() - -class BundleTestBase(TestCase): - def setUp(self, patch_count=3): - patch_names = ['testpatch%d' % (i) for i in range(1, patch_count+1)] - self.user = create_user() - self.client.login(username = self.user.username, - password = self.user.username) - defaults.project.save() - self.bundle = Bundle(owner = self.user, project = defaults.project, - name = 'testbundle') - self.bundle.save() - self.patches = [] - - for patch_name in patch_names: - patch = Patch(project = defaults.project, - msgid = patch_name, name = patch_name, - submitter = Person.objects.get(user = self.user), - content = '') - patch.save() - self.patches.append(patch) - - def tearDown(self): - for patch in self.patches: - patch.delete() - self.bundle.delete() - self.user.delete() - -class BundleViewTest(BundleTestBase): - - def testEmptyBundle(self): - response = self.client.get(bundle_url(self.bundle)) - self.failUnlessEqual(response.status_code, 200) - page = find_in_context(response.context, 'page') - self.failUnlessEqual(len(page.object_list), 0) - - def testNonEmptyBundle(self): - self.bundle.append_patch(self.patches[0]) - - response = self.client.get(bundle_url(self.bundle)) - self.failUnlessEqual(response.status_code, 200) - page = find_in_context(response.context, 'page') - self.failUnlessEqual(len(page.object_list), 1) - - def testBundleOrder(self): - for patch in self.patches: - self.bundle.append_patch(patch) - - response = self.client.get(bundle_url(self.bundle)) - - pos = 0 - for patch in self.patches: - next_pos = response.content.find(patch.name) - # ensure that this patch is after the previous - self.failUnless(next_pos > pos) - pos = next_pos - - # reorder and recheck - i = 0 - for patch in self.patches.__reversed__(): - bundlepatch = BundlePatch.objects.get(bundle = self.bundle, - patch = patch) - bundlepatch.order = i - bundlepatch.save() - i += 1 - - response = self.client.get(bundle_url(self.bundle)) - pos = len(response.content) - for patch in self.patches: - next_pos = response.content.find(patch.name) - # ensure that this patch is now *before* the previous - self.failUnless(next_pos < pos) - pos = next_pos - -class BundleUpdateTest(BundleTestBase): - - def setUp(self): - super(BundleUpdateTest, self).setUp() - self.newname = 'newbundlename' - - def checkPatchformErrors(self, response): - formname = 'patchform' - if not formname in response.context: - return - form = response.context[formname] - if not form: - return - self.assertEquals(form.errors, {}) - - def publicString(self, public): - if public: - return 'on' - return '' - - def testNoAction(self): - data = { - 'form': 'bundle', - 'name': self.newname, - 'public': self.publicString(not self.bundle.public) - } - response = self.client.post(bundle_url(self.bundle), data) - self.assertEqual(response.status_code, 200) - - bundle = Bundle.objects.get(pk = self.bundle.pk) - self.assertEqual(bundle.name, self.bundle.name) - self.assertEqual(bundle.public, self.bundle.public) - - def testUpdateName(self): - newname = 'newbundlename' - data = { - 'form': 'bundle', - 'action': 'update', - 'name': newname, - 'public': self.publicString(self.bundle.public) - } - response = self.client.post(bundle_url(self.bundle), data) - bundle = Bundle.objects.get(pk = self.bundle.pk) - self.assertRedirects(response, bundle_url(bundle)) - self.assertEqual(bundle.name, newname) - self.assertEqual(bundle.public, self.bundle.public) - - def testUpdatePublic(self): - newname = 'newbundlename' - data = { - 'form': 'bundle', - 'action': 'update', - 'name': self.bundle.name, - 'public': self.publicString(not self.bundle.public) - } - response = self.client.post(bundle_url(self.bundle), data) - self.assertEqual(response.status_code, 200) - bundle = Bundle.objects.get(pk = self.bundle.pk) - self.assertEqual(bundle.name, self.bundle.name) - self.assertEqual(bundle.public, not self.bundle.public) - - # check other forms for errors - self.checkPatchformErrors(response) - -class BundleMaintainerUpdateTest(BundleUpdateTest): - - def setUp(self): - super(BundleMaintainerUpdateTest, self).setUp() - profile = self.user.profile - profile.maintainer_projects.add(defaults.project) - profile.save() - -class BundlePublicViewTest(BundleTestBase): - - def setUp(self): - super(BundlePublicViewTest, self).setUp() - self.client.logout() - self.bundle.append_patch(self.patches[0]) - self.url = bundle_url(self.bundle) - - def testPublicBundle(self): - self.bundle.public = True - self.bundle.save() - response = self.client.get(self.url) - self.assertEqual(response.status_code, 200) - self.assertContains(response, self.patches[0].name) - - def testPrivateBundle(self): - self.bundle.public = False - self.bundle.save() - response = self.client.get(self.url) - self.assertEqual(response.status_code, 404) - -class BundlePublicViewMboxTest(BundlePublicViewTest): - def setUp(self): - super(BundlePublicViewMboxTest, self).setUp() - self.url = bundle_url(self.bundle) + "mbox/" - -class BundlePublicModifyTest(BundleTestBase): - """Ensure that non-owners can't modify bundles""" - - def setUp(self): - super(BundlePublicModifyTest, self).setUp() - self.bundle.public = True - self.bundle.save() - self.other_user = create_user() - - def testBundleFormPresence(self): - """Check for presence of the modify form on the bundle""" - self.client.login(username = self.other_user.username, - password = self.other_user.username) - response = self.client.get(bundle_url(self.bundle)) - self.assertNotContains(response, 'name="form" value="bundle"') - self.assertNotContains(response, 'Change order') - - def testBundleFormSubmission(self): - oldname = 'oldbundlename' - newname = 'newbundlename' - data = { - 'form': 'bundle', - 'action': 'update', - 'name': newname, - } - self.bundle.name = oldname - self.bundle.save() - - # first, check that we can modify with the owner - self.client.login(username = self.user.username, - password = self.user.username) - response = self.client.post(bundle_url(self.bundle), data) - self.bundle = Bundle.objects.get(pk = self.bundle.pk) - self.assertEqual(self.bundle.name, newname) - - # reset bundle name - self.bundle.name = oldname - self.bundle.save() - - # log in with a different user, and check that we can no longer modify - self.client.login(username = self.other_user.username, - password = self.other_user.username) - response = self.client.post(bundle_url(self.bundle), data) - self.bundle = Bundle.objects.get(pk = self.bundle.pk) - self.assertNotEqual(self.bundle.name, newname) - -class BundleCreateFromListTest(BundleTestBase): - def testCreateEmptyBundle(self): - newbundlename = 'testbundle-new' - params = {'form': 'patchlistform', - 'bundle_name': newbundlename, - 'action': 'Create', - 'project': defaults.project.id} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'Bundle %s created' % newbundlename) - - def testCreateNonEmptyBundle(self): - newbundlename = 'testbundle-new' - patch = self.patches[0] - - params = {'form': 'patchlistform', - 'bundle_name': newbundlename, - 'action': 'Create', - 'project': defaults.project.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'Bundle %s created' % newbundlename) - self.assertContains(response, 'added to bundle %s' % newbundlename, - count = 1) - - bundle = Bundle.objects.get(name = newbundlename) - self.failUnlessEqual(bundle.patches.count(), 1) - self.failUnlessEqual(bundle.patches.all()[0], patch) - - def testCreateNonEmptyBundleEmptyName(self): - newbundlename = 'testbundle-new' - patch = self.patches[0] - - n_bundles = Bundle.objects.count() - - params = {'form': 'patchlistform', - 'bundle_name': '', - 'action': 'Create', - 'project': defaults.project.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'No bundle name was specified', - status_code = 200) - - # test that no new bundles are present - self.failUnlessEqual(n_bundles, Bundle.objects.count()) - - def testCreateDuplicateName(self): - newbundlename = 'testbundle-dup' - patch = self.patches[0] - - params = {'form': 'patchlistform', - 'bundle_name': newbundlename, - 'action': 'Create', - 'project': defaults.project.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - n_bundles = Bundle.objects.count() - self.assertContains(response, 'Bundle %s created' % newbundlename) - self.assertContains(response, 'added to bundle %s' % newbundlename, - count = 1) - - bundle = Bundle.objects.get(name = newbundlename) - self.failUnlessEqual(bundle.patches.count(), 1) - self.failUnlessEqual(bundle.patches.all()[0], patch) - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertNotContains(response, 'Bundle %s created' % newbundlename) - self.assertContains(response, 'You already have a bundle called') - self.assertEqual(Bundle.objects.count(), n_bundles) - self.assertEqual(bundle.patches.count(), 1) - -class BundleCreateFromPatchTest(BundleTestBase): - def testCreateNonEmptyBundle(self): - newbundlename = 'testbundle-new' - patch = self.patches[0] - - params = {'name': newbundlename, - 'action': 'createbundle'} - - response = self.client.post('/patch/%d/' % patch.id, params) - - self.assertContains(response, - 'Bundle %s created' % newbundlename) - - bundle = Bundle.objects.get(name = newbundlename) - self.failUnlessEqual(bundle.patches.count(), 1) - self.failUnlessEqual(bundle.patches.all()[0], patch) - - def testCreateWithExistingName(self): - newbundlename = self.bundle.name - patch = self.patches[0] - - params = {'name': newbundlename, - 'action': 'createbundle'} - - response = self.client.post('/patch/%d/' % patch.id, params) - - self.assertContains(response, - 'A bundle called %s already exists' % newbundlename) - - count = Bundle.objects.count() - self.failUnlessEqual(Bundle.objects.count(), 1) - -class BundleAddFromListTest(BundleTestBase): - def testAddToEmptyBundle(self): - patch = self.patches[0] - params = {'form': 'patchlistform', - 'action': 'Add', - 'project': defaults.project.id, - 'bundle_id': self.bundle.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'added to bundle %s' % self.bundle.name, - count = 1) - - self.failUnlessEqual(self.bundle.patches.count(), 1) - self.failUnlessEqual(self.bundle.patches.all()[0], patch) - - def testAddToNonEmptyBundle(self): - self.bundle.append_patch(self.patches[0]) - patch = self.patches[1] - params = {'form': 'patchlistform', - 'action': 'Add', - 'project': defaults.project.id, - 'bundle_id': self.bundle.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'added to bundle %s' % self.bundle.name, - count = 1) - - self.failUnlessEqual(self.bundle.patches.count(), 2) - self.failUnless(self.patches[0] in self.bundle.patches.all()) - self.failUnless(self.patches[1] in self.bundle.patches.all()) - - # check order - bps = [ BundlePatch.objects.get(bundle = self.bundle, - patch = self.patches[i]) \ - for i in [0, 1] ] - self.failUnless(bps[0].order < bps[1].order) - - def testAddDuplicate(self): - self.bundle.append_patch(self.patches[0]) - count = self.bundle.patches.count() - patch = self.patches[0] - - params = {'form': 'patchlistform', - 'action': 'Add', - 'project': defaults.project.id, - 'bundle_id': self.bundle.id, - 'patch_id:%d' % patch.id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'Patch '%s' already in bundle' \ - % patch.name, count = 1, status_code = 200) - - self.assertEquals(count, self.bundle.patches.count()) - - def testAddNewAndDuplicate(self): - self.bundle.append_patch(self.patches[0]) - count = self.bundle.patches.count() - patch = self.patches[0] - - params = {'form': 'patchlistform', - 'action': 'Add', - 'project': defaults.project.id, - 'bundle_id': self.bundle.id, - 'patch_id:%d' % patch.id: 'checked', - 'patch_id:%d' % self.patches[1].id: 'checked'} - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - params) - - self.assertContains(response, 'Patch '%s' already in bundle' \ - % patch.name, count = 1, status_code = 200) - self.assertContains(response, 'Patch '%s' added to bundle' \ - % self.patches[1].name, count = 1, - status_code = 200) - self.assertEquals(count + 1, self.bundle.patches.count()) - -class BundleAddFromPatchTest(BundleTestBase): - def testAddToEmptyBundle(self): - patch = self.patches[0] - params = {'action': 'addtobundle', - 'bundle_id': self.bundle.id} - - response = self.client.post('/patch/%d/' % patch.id, params) - - self.assertContains(response, - 'added to bundle "%s"' % self.bundle.name, - count = 1) - - self.failUnlessEqual(self.bundle.patches.count(), 1) - self.failUnlessEqual(self.bundle.patches.all()[0], patch) - - def testAddToNonEmptyBundle(self): - self.bundle.append_patch(self.patches[0]) - patch = self.patches[1] - params = {'action': 'addtobundle', - 'bundle_id': self.bundle.id} - - response = self.client.post('/patch/%d/' % patch.id, params) - - self.assertContains(response, - 'added to bundle "%s"' % self.bundle.name, - count = 1) - - self.failUnlessEqual(self.bundle.patches.count(), 2) - self.failUnless(self.patches[0] in self.bundle.patches.all()) - self.failUnless(self.patches[1] in self.bundle.patches.all()) - - # check order - bps = [ BundlePatch.objects.get(bundle = self.bundle, - patch = self.patches[i]) \ - for i in [0, 1] ] - self.failUnless(bps[0].order < bps[1].order) - -class BundleInitialOrderTest(BundleTestBase): - """When creating bundles from a patch list, ensure that the patches in the - bundle are ordered by date""" - - def setUp(self): - super(BundleInitialOrderTest, self).setUp(5) - - # put patches in an arbitrary order - idxs = [2, 4, 3, 1, 0] - self.patches = [ self.patches[i] for i in idxs ] - - # set dates to be sequential - last_patch = self.patches[0] - for patch in self.patches[1:]: - patch.date = last_patch.date + datetime.timedelta(0, 1) - patch.save() - last_patch = patch - - def _testOrder(self, ids, expected_order): - newbundlename = 'testbundle-new' - - # need to define our querystring explicity to enforce ordering - params = {'form': 'patchlistform', - 'bundle_name': newbundlename, - 'action': 'Create', - 'project': defaults.project.id, - } - - data = urlencode(params) + \ - ''.join([ '&patch_id:%d=checked' % i for i in ids ]) - - response = self.client.post( - '/project/%s/list/' % defaults.project.linkname, - data = data, - content_type = 'application/x-www-form-urlencoded', - ) - - self.assertContains(response, 'Bundle %s created' % newbundlename) - self.assertContains(response, 'added to bundle %s' % newbundlename, - count = 5) - - bundle = Bundle.objects.get(name = newbundlename) - - # BundlePatches should be sorted by .order by default - bps = BundlePatch.objects.filter(bundle = bundle) - - for (bp, p) in zip(bps, expected_order): - self.assertEqual(bp.patch.pk, p.pk) - - bundle.delete() - - def testBundleForwardOrder(self): - ids = map(lambda p: p.id, self.patches) - self._testOrder(ids, self.patches) - - def testBundleReverseOrder(self): - ids = map(lambda p: p.id, self.patches) - ids.reverse() - self._testOrder(ids, self.patches) - -class BundleReorderTest(BundleTestBase): - def setUp(self): - super(BundleReorderTest, self).setUp(5) - for i in range(5): - self.bundle.append_patch(self.patches[i]) - - def checkReordering(self, neworder, start, end): - neworder_ids = [ self.patches[i].id for i in neworder ] - - firstpatch = BundlePatch.objects.get(bundle = self.bundle, - patch = self.patches[start]).patch - - slice_ids = neworder_ids[start:end] - params = {'form': 'reorderform', - 'order_start': firstpatch.id, - 'neworder': slice_ids} - - response = self.client.post(bundle_url(self.bundle), params) - - self.failUnlessEqual(response.status_code, 200) - - bps = BundlePatch.objects.filter(bundle = self.bundle) \ - .order_by('order') - - # check if patch IDs are in the expected order: - bundle_ids = [ bp.patch.id for bp in bps ] - self.failUnlessEqual(neworder_ids, bundle_ids) - - # check if order field is still sequential: - order_numbers = [ bp.order for bp in bps ] - expected_order = range(1, len(neworder)+1) # [1 ... len(neworder)] - self.failUnlessEqual(order_numbers, expected_order) - - def testBundleReorderAll(self): - # reorder all patches: - self.checkReordering([2,1,4,0,3], 0, 5) - - def testBundleReorderEnd(self): - # reorder only the last three patches - self.checkReordering([0,1,3,2,4], 2, 5) - - def testBundleReorderBegin(self): - # reorder only the first three patches - self.checkReordering([2,0,1,3,4], 0, 3) - - def testBundleReorderMiddle(self): - # reorder only 2nd, 3rd, and 4th patches - self.checkReordering([0,2,3,1,4], 1, 4) - -class BundleRedirTest(BundleTestBase): - # old URL: private bundles used to be under /user/bundle/<id> - - def setUp(self): - super(BundleRedirTest, self).setUp() - - @unittest.skipIf(not settings.COMPAT_REDIR, "compat redirections disabled") - def testBundleRedir(self): - url = '/user/bundle/%d/' % self.bundle.id - response = self.client.get(url) - self.assertRedirects(response, bundle_url(self.bundle)) - - @unittest.skipIf(not settings.COMPAT_REDIR, "compat redirections disabled") - def testMboxRedir(self): - url = '/user/bundle/%d/mbox/' % self.bundle.id - response = self.client.get(url) - self.assertRedirects(response,'/bundle/%s/%s/mbox/' % - (self.bundle.owner.username, - self.bundle.name)) diff --git a/apps/patchwork/tests/test_confirm.py b/apps/patchwork/tests/test_confirm.py deleted file mode 100644 index fad5125..0000000 --- a/apps/patchwork/tests/test_confirm.py +++ /dev/null @@ -1,67 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2011 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -from django.test import TestCase -from django.contrib.auth.models import User -from django.core.urlresolvers import reverse -from patchwork.models import EmailConfirmation, Person - -def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs = {'key': conf.key}) - -class TestUser(object): - username = 'testuser' - email = 'test@example.com' - secondary_email = 'test2@example.com' - password = None - - def __init__(self): - self.password = User.objects.make_random_password() - self.user = User.objects.create_user(self.username, - self.email, self.password) - -class InvalidConfirmationTest(TestCase): - def setUp(self): - EmailConfirmation.objects.all().delete() - Person.objects.all().delete() - self.user = TestUser() - self.conf = EmailConfirmation(type = 'userperson', - email = self.user.secondary_email, - user = self.user.user) - self.conf.save() - - def testInactiveConfirmation(self): - self.conf.active = False - self.conf.save() - response = self.client.get(_confirmation_url(self.conf)) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/confirm-error.html') - self.assertEqual(response.context['error'], 'inactive') - self.assertEqual(response.context['conf'], self.conf) - - def testExpiredConfirmation(self): - self.conf.date -= self.conf.validity - self.conf.save() - response = self.client.get(_confirmation_url(self.conf)) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/confirm-error.html') - self.assertEqual(response.context['error'], 'expired') - self.assertEqual(response.context['conf'], self.conf) - diff --git a/apps/patchwork/tests/test_encodings.py b/apps/patchwork/tests/test_encodings.py deleted file mode 100644 index b9032bb..0000000 --- a/apps/patchwork/tests/test_encodings.py +++ /dev/null @@ -1,87 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import os -import time -from patchwork.models import Patch, Person -from patchwork.tests.utils import defaults, read_patch -from django.test import TestCase -from django.test.client import Client - -class UTF8PatchViewTest(TestCase): - patch_filename = '0002-utf-8.patch' - patch_encoding = 'utf-8' - - def setUp(self): - defaults.project.save() - defaults.patch_author_person.save() - self.patch_content = read_patch(self.patch_filename, - encoding = self.patch_encoding) - self.patch = Patch(project = defaults.project, - msgid = 'x', name = defaults.patch_name, - submitter = defaults.patch_author_person, - content = self.patch_content) - self.patch.save() - self.client = Client() - - def testPatchView(self): - response = self.client.get('/patch/%d/' % self.patch.id) - self.assertContains(response, self.patch.name) - - def testMboxView(self): - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertEquals(response.status_code, 200) - self.assertTrue(self.patch.content in \ - response.content.decode(self.patch_encoding)) - - def testRawView(self): - response = self.client.get('/patch/%d/raw/' % self.patch.id) - self.assertEquals(response.status_code, 200) - self.assertEquals(response.content.decode(self.patch_encoding), - self.patch.content) - - def tearDown(self): - self.patch.delete() - defaults.patch_author_person.delete() - defaults.project.delete() - -class UTF8HeaderPatchViewTest(UTF8PatchViewTest): - patch_filename = '0002-utf-8.patch' - patch_encoding = 'utf-8' - patch_author_name = u'P\xe4tch Author' - - def setUp(self): - defaults.project.save() - self.patch_author = Person(name = self.patch_author_name, - email = defaults.patch_author_person.email) - self.patch_author.save() - self.patch_content = read_patch(self.patch_filename, - encoding = self.patch_encoding) - self.patch = Patch(project = defaults.project, - msgid = 'x', name = defaults.patch_name, - submitter = self.patch_author, - content = self.patch_content) - self.patch.save() - self.client = Client() - - def tearDown(self): - self.patch.delete() - self.patch_author.delete() - defaults.project.delete() diff --git a/apps/patchwork/tests/test_expiry.py b/apps/patchwork/tests/test_expiry.py deleted file mode 100644 index 844ed4b..0000000 --- a/apps/patchwork/tests/test_expiry.py +++ /dev/null @@ -1,121 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2014 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import datetime -from django.test import TestCase -from django.contrib.auth.models import User -from patchwork.models import EmailConfirmation, Person, Patch -from patchwork.tests.utils import create_user, defaults -from patchwork.utils import do_expiry - -class TestRegistrationExpiry(TestCase): - - def register(self, date): - user = create_user() - user.is_active = False - user.date_joined = user.last_login = date - user.save() - - conf = EmailConfirmation(type='registration', user=user, - email=user.email) - conf.date = date - conf.save() - - return (user, conf) - - def testOldRegistrationExpiry(self): - date = ((datetime.datetime.now() - EmailConfirmation.validity) - - datetime.timedelta(hours = 1)) - (user, conf) = self.register(date) - - do_expiry() - - self.assertFalse(User.objects.filter(pk = user.pk).exists()) - self.assertFalse(EmailConfirmation.objects.filter(pk = conf.pk) - .exists()) - - - def testRecentRegistrationExpiry(self): - date = ((datetime.datetime.now() - EmailConfirmation.validity) + - datetime.timedelta(hours = 1)) - (user, conf) = self.register(date) - - do_expiry() - - self.assertTrue(User.objects.filter(pk = user.pk).exists()) - self.assertTrue(EmailConfirmation.objects.filter(pk = conf.pk) - .exists()) - - def testInactiveRegistrationExpiry(self): - (user, conf) = self.register(datetime.datetime.now()) - - # confirm registration - conf.user.is_active = True - conf.user.save() - conf.deactivate() - - do_expiry() - - self.assertTrue(User.objects.filter(pk = user.pk).exists()) - self.assertFalse(EmailConfirmation.objects.filter(pk = conf.pk) - .exists()) - - def testPatchSubmitterExpiry(self): - defaults.project.save() - defaults.patch_author_person.save() - - # someone submits a patch... - patch = Patch(project = defaults.project, - msgid = 'test@example.com', name = 'test patch', - submitter = defaults.patch_author_person, - content = defaults.patch) - patch.save() - - # ... then starts registration... - date = ((datetime.datetime.now() - EmailConfirmation.validity) - - datetime.timedelta(hours = 1)) - userid = 'test-user' - user = User.objects.create_user(userid, - defaults.patch_author_person.email, userid) - user.is_active = False - user.date_joined = user.last_login = date - user.save() - - self.assertEqual(user.email, patch.submitter.email) - - conf = EmailConfirmation(type='registration', user=user, - email=user.email) - conf.date = date - conf.save() - - # ... which expires - do_expiry() - - # we should see no matching user - self.assertFalse(User.objects.filter(email = patch.submitter.email) - .exists()) - # but the patch and person should still be present - self.assertTrue(Person.objects.filter( - pk = defaults.patch_author_person.pk).exists()) - self.assertTrue(Patch.objects.filter(pk = patch.pk).exists()) - - # and there should be no user associated with the person - self.assertEqual(Person.objects.get(pk = - defaults.patch_author_person.pk).user, None) diff --git a/apps/patchwork/tests/test_filters.py b/apps/patchwork/tests/test_filters.py deleted file mode 100644 index 2c464e5..0000000 --- a/apps/patchwork/tests/test_filters.py +++ /dev/null @@ -1,45 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2011 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -from django.test import TestCase -from django.test.client import Client -from patchwork.tests.utils import defaults, create_user, find_in_context - -class FilterQueryStringTest(TestCase): - def testFilterQSEscaping(self): - """test that filter fragments in a query string are properly escaped, - and stray ampersands don't get reflected back in the filter - links""" - project = defaults.project - defaults.project.save() - url = '/project/%s/list/?submitter=a%%26b=c' % project.linkname - response = self.client.get(url) - self.failUnlessEqual(response.status_code, 200) - self.failIf('submitter=a&b=c' in response.content) - self.failIf('submitter=a&b=c' in response.content) - - def testUTF8QSHandling(self): - """test that non-ascii characters can be handled by the filter - code""" - project = defaults.project - defaults.project.save() - url = '/project/%s/list/?submitter=%%E2%%98%%83' % project.linkname - response = self.client.get(url) - self.failUnlessEqual(response.status_code, 200) diff --git a/apps/patchwork/tests/test_list.py b/apps/patchwork/tests/test_list.py deleted file mode 100644 index a795a5f..0000000 --- a/apps/patchwork/tests/test_list.py +++ /dev/null @@ -1,116 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2012 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import random -import datetime -import string -import re -from django.test import TestCase -from django.test.client import Client -from patchwork.tests.utils import defaults, create_user, find_in_context -from patchwork.models import Person, Patch -from django.core.urlresolvers import reverse - -class EmptyPatchListTest(TestCase): - - def testEmptyPatchList(self): - """test that we don't output an empty table when there are no - patches present""" - project = defaults.project - defaults.project.save() - url = reverse('patchwork.views.patch.list', - kwargs={'project_id': project.linkname}) - response = self.client.get(url) - self.assertContains(response, 'No patches to display') - self.assertNotContains(response, 'tbody') - -class PatchOrderTest(TestCase): - - d = datetime.datetime - patchmeta = [ - ('AlCMyjOsx', 'AlxMyjOsx@nRbqkQV.wBw', d(2014,3,16,13, 4,50, 155643)), - ('MMZnrcDjT', 'MMmnrcDjT@qGaIfOl.tbk', d(2014,1,25,13, 4,50, 162814)), - ('WGirwRXgK', 'WGSrwRXgK@TriIETY.GhE', d(2014,2,14,13, 4,50, 169305)), - ('isjNIuiAc', 'issNIuiAc@OsEirYx.EJh', d(2014,3,15,13, 4,50, 176264)), - ('XkAQpYGws', 'XkFQpYGws@hzntTcm.JSE', d(2014,1,18,13, 4,50, 182493)), - ('uJuCPWMvi', 'uJACPWMvi@AVRBOBl.ecy', d(2014,3,12,13, 4,50, 189554)), - ('TyQmWtcbg', 'TylmWtcbg@DzrNeNH.JuB', d(2014,2, 3,13, 4,50, 195685)), - ('FpvAhWRdX', 'FpKAhWRdX@agxnCAI.wFO', d(2014,3,15,13, 4,50, 201398)), - ('bmoYvnyWa', 'bmdYvnyWa@aeoPnlX.juy', d(2014,3, 4,13, 4,50, 206800)), - ('CiReUQsAq', 'CiieUQsAq@DnOYRuf.TTI', d(2014,3,28,13, 4,50, 212169)), - ] - - def setUp(self): - defaults.project.save() - - for (name, email, date) in self.patchmeta: - patch_name = 'testpatch' + name - person = Person(name = name, email = email) - person.save() - patch = Patch(project = defaults.project, msgid = patch_name, - submitter = person, content = '', date = date) - patch.save() - - def _extract_patch_ids(self, response): - id_re = re.compile('<tr id="patch_row:(\d+)" ') - ids = [ int(m.group(1)) for m in id_re.finditer(response.content) ] - return ids - - def _test_sequence(self, response, test_fn): - ids = self._extract_patch_ids(response) - self.assertTrue(bool(ids)) - patches = [ Patch.objects.get(id = i) for i in ids ] - pairs = zip(patches, patches[1:]) - [ test_fn(p1, p2) for (p1, p2) in pairs ] - - def testDateOrder(self): - url = reverse('patchwork.views.patch.list', - kwargs={'project_id': defaults.project.linkname}) - response = self.client.get(url + '?order=date') - def test_fn(p1, p2): - self.assertLessEqual(p1.date, p2.date) - self._test_sequence(response, test_fn) - - def testDateReverseOrder(self): - url = reverse('patchwork.views.patch.list', - kwargs={'project_id': defaults.project.linkname}) - response = self.client.get(url + '?order=-date') - def test_fn(p1, p2): - self.assertGreaterEqual(p1.date, p2.date) - self._test_sequence(response, test_fn) - - def testSubmitterOrder(self): - url = reverse('patchwork.views.patch.list', - kwargs={'project_id': defaults.project.linkname}) - response = self.client.get(url + '?order=submitter') - def test_fn(p1, p2): - self.assertLessEqual(p1.submitter.name.lower(), - p2.submitter.name.lower()) - self._test_sequence(response, test_fn) - - def testSubmitterReverseOrder(self): - url = reverse('patchwork.views.patch.list', - kwargs={'project_id': defaults.project.linkname}) - response = self.client.get(url + '?order=-submitter') - def test_fn(p1, p2): - self.assertGreaterEqual(p1.submitter.name.lower(), - p2.submitter.name.lower()) - self._test_sequence(response, test_fn) - diff --git a/apps/patchwork/tests/test_mail_settings.py b/apps/patchwork/tests/test_mail_settings.py deleted file mode 100644 index a193c97..0000000 --- a/apps/patchwork/tests/test_mail_settings.py +++ /dev/null @@ -1,299 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import re -from django.test import TestCase -from django.test.client import Client -from django.core import mail -from django.core.urlresolvers import reverse -from django.contrib.auth.models import User -from patchwork.models import EmailOptout, EmailConfirmation, Person -from patchwork.tests.utils import create_user, error_strings - -class MailSettingsTest(TestCase): - view = 'patchwork.views.mail.settings' - url = reverse(view) - - def testMailSettingsGET(self): - response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) - self.assertTrue(response.context['form']) - - def testMailSettingsPOST(self): - email = u'foo@example.com' - response = self.client.post(self.url, {'email': email}) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/mail-settings.html') - self.assertEquals(response.context['email'], email) - - def testMailSettingsPOSTEmpty(self): - response = self.client.post(self.url, {'email': ''}) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/mail-form.html') - self.assertFormError(response, 'form', 'email', - 'This field is required.') - - def testMailSettingsPOSTInvalid(self): - response = self.client.post(self.url, {'email': 'foo'}) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/mail-form.html') - self.assertFormError(response, 'form', 'email', error_strings['email']) - - def testMailSettingsPOSTOptedIn(self): - email = u'foo@example.com' - response = self.client.post(self.url, {'email': email}) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/mail-settings.html') - self.assertEquals(response.context['is_optout'], False) - self.assertTrue('<strong>may</strong>' in response.content) - optout_url = reverse('patchwork.views.mail.optout') - self.assertTrue(('action="%s"' % optout_url) in response.content) - - def testMailSettingsPOSTOptedOut(self): - email = u'foo@example.com' - EmailOptout(email = email).save() - response = self.client.post(self.url, {'email': email}) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/mail-settings.html') - self.assertEquals(response.context['is_optout'], True) - self.assertTrue('<strong>may not</strong>' in response.content) - optin_url = reverse('patchwork.views.mail.optin') - self.assertTrue(('action="%s"' % optin_url) in response.content) - -class OptoutRequestTest(TestCase): - view = 'patchwork.views.mail.optout' - url = reverse(view) - - def testOptOutRequestGET(self): - response = self.client.get(self.url) - self.assertRedirects(response, reverse('patchwork.views.mail.settings')) - - def testOptoutRequestValidPOST(self): - email = u'foo@example.com' - response = self.client.post(self.url, {'email': email}) - - # check for a confirmation object - self.assertEquals(EmailConfirmation.objects.count(), 1) - conf = EmailConfirmation.objects.get(email = email) - - # check confirmation page - self.assertEquals(response.status_code, 200) - self.assertEquals(response.context['confirmation'], conf) - self.assertTrue(email in response.content) - - # check email - url = reverse('patchwork.views.confirm', kwargs = {'key': conf.key}) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.to, [email]) - self.assertEquals(msg.subject, 'Patchwork opt-out confirmation') - self.assertTrue(url in msg.body) - - def testOptoutRequestInvalidPOSTEmpty(self): - response = self.client.post(self.url, {'email': ''}) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'email', - 'This field is required.') - self.assertTrue(response.context['error']) - self.assertTrue('email_sent' not in response.context) - self.assertEquals(len(mail.outbox), 0) - - def testOptoutRequestInvalidPOSTNonEmail(self): - response = self.client.post(self.url, {'email': 'foo'}) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'email', error_strings['email']) - self.assertTrue(response.context['error']) - self.assertTrue('email_sent' not in response.context) - self.assertEquals(len(mail.outbox), 0) - -class OptoutTest(TestCase): - view = 'patchwork.views.mail.optout' - url = reverse(view) - - def setUp(self): - self.email = u'foo@example.com' - self.conf = EmailConfirmation(type = 'optout', email = self.email) - self.conf.save() - - def testOptoutValidHash(self): - url = reverse('patchwork.views.confirm', - kwargs = {'key': self.conf.key}) - response = self.client.get(url) - - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/optout.html') - self.assertTrue(self.email in response.content) - - # check that we've got an optout in the list - self.assertEquals(EmailOptout.objects.count(), 1) - self.assertEquals(EmailOptout.objects.all()[0].email, self.email) - - # check that the confirmation is now inactive - self.assertFalse(EmailConfirmation.objects.get( - pk = self.conf.pk).active) - - -class OptoutPreexistingTest(OptoutTest): - """Test that a duplicated opt-out behaves the same as the initial one""" - def setUp(self): - super(OptoutPreexistingTest, self).setUp() - EmailOptout(email = self.email).save() - -class OptinRequestTest(TestCase): - view = 'patchwork.views.mail.optin' - url = reverse(view) - - def setUp(self): - self.email = u'foo@example.com' - EmailOptout(email = self.email).save() - - def testOptInRequestGET(self): - response = self.client.get(self.url) - self.assertRedirects(response, reverse('patchwork.views.mail.settings')) - - def testOptInRequestValidPOST(self): - response = self.client.post(self.url, {'email': self.email}) - - # check for a confirmation object - self.assertEquals(EmailConfirmation.objects.count(), 1) - conf = EmailConfirmation.objects.get(email = self.email) - - # check confirmation page - self.assertEquals(response.status_code, 200) - self.assertEquals(response.context['confirmation'], conf) - self.assertTrue(self.email in response.content) - - # check email - url = reverse('patchwork.views.confirm', kwargs = {'key': conf.key}) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.to, [self.email]) - self.assertEquals(msg.subject, 'Patchwork opt-in confirmation') - self.assertTrue(url in msg.body) - - def testOptoutRequestInvalidPOSTEmpty(self): - response = self.client.post(self.url, {'email': ''}) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'email', - 'This field is required.') - self.assertTrue(response.context['error']) - self.assertTrue('email_sent' not in response.context) - self.assertEquals(len(mail.outbox), 0) - - def testOptoutRequestInvalidPOSTNonEmail(self): - response = self.client.post(self.url, {'email': 'foo'}) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'email', error_strings['email']) - self.assertTrue(response.context['error']) - self.assertTrue('email_sent' not in response.context) - self.assertEquals(len(mail.outbox), 0) - -class OptinTest(TestCase): - - def setUp(self): - self.email = u'foo@example.com' - self.optout = EmailOptout(email = self.email) - self.optout.save() - self.conf = EmailConfirmation(type = 'optin', email = self.email) - self.conf.save() - - def testOptinValidHash(self): - url = reverse('patchwork.views.confirm', - kwargs = {'key': self.conf.key}) - response = self.client.get(url) - - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/optin.html') - self.assertTrue(self.email in response.content) - - # check that there's no optout remaining - self.assertEquals(EmailOptout.objects.count(), 0) - - # check that the confirmation is now inactive - self.assertFalse(EmailConfirmation.objects.get( - pk = self.conf.pk).active) - -class OptinWithoutOptoutTest(TestCase): - """Test an opt-in with no existing opt-out""" - view = 'patchwork.views.mail.optin' - url = reverse(view) - - def testOptInWithoutOptout(self): - email = u'foo@example.com' - response = self.client.post(self.url, {'email': email}) - - # check for an error message - self.assertEquals(response.status_code, 200) - self.assertTrue(bool(response.context['error'])) - self.assertTrue('not on the patchwork opt-out list' in response.content) - -class UserProfileOptoutFormTest(TestCase): - """Test that the correct optin/optout forms appear on the user profile - page, for logged-in users""" - - view = 'patchwork.views.user.profile' - url = reverse(view) - optout_url = reverse('patchwork.views.mail.optout') - optin_url = reverse('patchwork.views.mail.optin') - form_re_template = ('<form\s+[^>]*action="%(url)s"[^>]*>' - '.*?<input\s+[^>]*value="%(email)s"[^>]*>.*?' - '</form>') - secondary_email = 'test2@example.com' - - def setUp(self): - self.user = create_user() - self.client.login(username = self.user.username, - password = self.user.username) - - def _form_re(self, url, email): - return re.compile(self.form_re_template % {'url': url, 'email': email}, - re.DOTALL) - - def testMainEmailOptoutForm(self): - form_re = self._form_re(self.optout_url, self.user.email) - response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) - self.assertTrue(form_re.search(response.content) is not None) - - def testMainEmailOptinForm(self): - EmailOptout(email = self.user.email).save() - form_re = self._form_re(self.optin_url, self.user.email) - response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) - self.assertTrue(form_re.search(response.content) is not None) - - def testSecondaryEmailOptoutForm(self): - p = Person(email = self.secondary_email, user = self.user) - p.save() - - form_re = self._form_re(self.optout_url, p.email) - response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) - self.assertTrue(form_re.search(response.content) is not None) - - def testSecondaryEmailOptinForm(self): - p = Person(email = self.secondary_email, user = self.user) - p.save() - EmailOptout(email = p.email).save() - - form_re = self._form_re(self.optin_url, p.email) - response = self.client.get(self.url) - self.assertEquals(response.status_code, 200) - self.assertTrue(form_re.search(response.content) is not None) diff --git a/apps/patchwork/tests/test_mboxviews.py b/apps/patchwork/tests/test_mboxviews.py deleted file mode 100644 index 0e57f42..0000000 --- a/apps/patchwork/tests/test_mboxviews.py +++ /dev/null @@ -1,209 +0,0 @@ -# vim: set fileencoding=utf-8 : -# -# Patchwork - automated patch tracking system -# Copyright (C) 2009 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import email -import datetime -import dateutil.parser, dateutil.tz -from django.test import TestCase -from django.test.client import Client -from patchwork.models import Patch, Comment, Person -from patchwork.tests.utils import defaults, create_user, find_in_context - -class MboxPatchResponseTest(TestCase): - """ Test that the mbox view appends the Acked-by from a patch comment """ - def setUp(self): - defaults.project.save() - - self.person = defaults.patch_author_person - self.person.save() - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - self.patch.save() - comment = Comment(patch = self.patch, msgid = 'p1', - submitter = self.person, - content = 'comment 1 text\nAcked-by: 1\n') - comment.save() - - comment = Comment(patch = self.patch, msgid = 'p2', - submitter = self.person, - content = 'comment 2 text\nAcked-by: 2\n') - comment.save() - - def testPatchResponse(self): - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, - 'Acked-by: 1\nAcked-by: 2\n') - -class MboxPatchSplitResponseTest(TestCase): - """ Test that the mbox view appends the Acked-by from a patch comment, - and places it before an '---' update line. """ - def setUp(self): - defaults.project.save() - - self.person = defaults.patch_author_person - self.person.save() - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - self.patch.save() - comment = Comment(patch = self.patch, msgid = 'p1', - submitter = self.person, - content = 'comment 1 text\nAcked-by: 1\n---\nupdate\n') - comment.save() - - comment = Comment(patch = self.patch, msgid = 'p2', - submitter = self.person, - content = 'comment 2 text\nAcked-by: 2\n') - comment.save() - - def testPatchResponse(self): - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, - 'Acked-by: 1\nAcked-by: 2\n') - -class MboxPassThroughHeaderTest(TestCase): - """ Test that we see 'Cc' and 'To' headers passed through from original - message to mbox view """ - - def setUp(self): - defaults.project.save() - self.person = defaults.patch_author_person - self.person.save() - - self.cc_header = 'Cc: CC Person <cc@example.com>' - self.to_header = 'To: To Person <to@example.com>' - self.date_header = 'Date: Fri, 7 Jun 2013 15:42:54 +1000' - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - - def testCCHeader(self): - self.patch.headers = self.cc_header + '\n' - self.patch.save() - - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, self.cc_header) - - def testToHeader(self): - self.patch.headers = self.to_header + '\n' - self.patch.save() - - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, self.to_header) - - def testDateHeader(self): - self.patch.headers = self.date_header + '\n' - self.patch.save() - - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, self.date_header) - -class MboxBrokenFromHeaderTest(TestCase): - """ Test that a person with characters outside ASCII in his name do - produce correct From header. As RFC 2822 state we must retain the - <user@doamin.tld> format for the mail while the name part may be coded - in some ways. """ - - def setUp(self): - defaults.project.save() - self.person = defaults.patch_author_person - self.person.name = u'©ool guŷ' - self.person.save() - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - - def testFromHeader(self): - self.patch.save() - from_email = '<' + self.person.email + '>' - - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, from_email) - -class MboxDateHeaderTest(TestCase): - """ Test that the date provided in the patch mail view is correct """ - - def setUp(self): - defaults.project.save() - self.person = defaults.patch_author_person - self.person.save() - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - self.patch.save() - - def testDateHeader(self): - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - mail = email.message_from_string(response.content) - mail_date = dateutil.parser.parse(mail['Date']) - # patch dates are all in UTC - patch_date = self.patch.date.replace(tzinfo=dateutil.tz.tzutc(), - microsecond=0) - self.assertEqual(mail_date, patch_date) - - def testSuppliedDateHeader(self): - hour_offset = 3 - tz = dateutil.tz.tzoffset(None, hour_offset * 60 * 60) - date = datetime.datetime.utcnow() - datetime.timedelta(days = 1) - date = date.replace(tzinfo=tz, microsecond=0) - - self.patch.headers = 'Date: %s\n' % date.strftime("%a, %d %b %Y %T %z") - self.patch.save() - - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - mail = email.message_from_string(response.content) - mail_date = dateutil.parser.parse(mail['Date']) - self.assertEqual(mail_date, date) - -class MboxCommentPostcriptUnchangedTest(TestCase): - """ Test that the mbox view doesn't change the postscript part of a mail. - There where always a missing blank right after the postscript - delimiter '---' and an additional newline right before. """ - def setUp(self): - defaults.project.save() - - self.person = defaults.patch_author_person - self.person.save() - - self.patch = Patch(project = defaults.project, - msgid = 'p1', name = 'testpatch', - submitter = self.person, content = '') - self.patch.save() - - self.txt = 'some comment\n---\n some/file | 1 +\n' - - comment = Comment(patch = self.patch, msgid = 'p1', - submitter = self.person, - content = self.txt) - comment.save() - - def testCommentUnchanged(self): - response = self.client.get('/patch/%d/mbox/' % self.patch.id) - self.assertContains(response, self.txt) - self.txt += "\n" - self.assertNotContains(response, self.txt) diff --git a/apps/patchwork/tests/test_notifications.py b/apps/patchwork/tests/test_notifications.py deleted file mode 100644 index ed35140..0000000 --- a/apps/patchwork/tests/test_notifications.py +++ /dev/null @@ -1,255 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2011 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import datetime -from django.test import TestCase -from django.core.urlresolvers import reverse -from django.core import mail -from django.conf import settings -from django.db.utils import IntegrityError -from patchwork.models import Patch, State, PatchChangeNotification, EmailOptout -from patchwork.tests.utils import defaults, create_maintainer -from patchwork.utils import send_notifications - -class PatchNotificationModelTest(TestCase): - """Tests for the creation & update of the PatchChangeNotification model""" - - def setUp(self): - self.project = defaults.project - self.project.send_notifications = True - self.project.save() - self.submitter = defaults.patch_author_person - self.submitter.save() - self.patch = Patch(project = self.project, msgid = 'testpatch', - name = 'testpatch', content = '', - submitter = self.submitter) - - def tearDown(self): - self.patch.delete() - self.submitter.delete() - self.project.delete() - - def testPatchCreation(self): - """Ensure we don't get a notification on create""" - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 0) - - def testPatchUninterestingChange(self): - """Ensure we don't get a notification for "uninteresting" changes""" - self.patch.save() - self.patch.archived = True - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 0) - - def testPatchChange(self): - """Ensure we get a notification for interesting patch changes""" - self.patch.save() - oldstate = self.patch.state - state = State.objects.exclude(pk = oldstate.pk)[0] - - self.patch.state = state - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 1) - notification = PatchChangeNotification.objects.all()[0] - self.assertEqual(notification.patch, self.patch) - self.assertEqual(notification.orig_state, oldstate) - - def testNotificationCancelled(self): - """Ensure we cancel notifications that are no longer valid""" - self.patch.save() - oldstate = self.patch.state - state = State.objects.exclude(pk = oldstate.pk)[0] - - self.patch.state = state - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 1) - - self.patch.state = oldstate - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 0) - - def testNotificationUpdated(self): - """Ensure we update notifications when the patch has a second change, - but keep the original patch details""" - self.patch.save() - oldstate = self.patch.state - newstates = State.objects.exclude(pk = oldstate.pk)[:2] - - self.patch.state = newstates[0] - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 1) - notification = PatchChangeNotification.objects.all()[0] - self.assertEqual(notification.orig_state, oldstate) - orig_timestamp = notification.last_modified - - self.patch.state = newstates[1] - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 1) - notification = PatchChangeNotification.objects.all()[0] - self.assertEqual(notification.orig_state, oldstate) - self.assertTrue(notification.last_modified >= orig_timestamp) - - def testProjectNotificationsDisabled(self): - """Ensure we don't see notifications created when a project is - configured not to send them""" - self.project.send_notifications = False - self.project.save() - - self.patch.save() - oldstate = self.patch.state - state = State.objects.exclude(pk = oldstate.pk)[0] - - self.patch.state = state - self.patch.save() - self.assertEqual(PatchChangeNotification.objects.count(), 0) - -class PatchNotificationEmailTest(TestCase): - - def setUp(self): - self.project = defaults.project - self.project.send_notifications = True - self.project.save() - self.submitter = defaults.patch_author_person - self.submitter.save() - self.patch = Patch(project = self.project, msgid = 'testpatch', - name = 'testpatch', content = '', - submitter = self.submitter) - self.patch.save() - - def tearDown(self): - self.patch.delete() - self.submitter.delete() - self.project.delete() - - def _expireNotifications(self, **kwargs): - timestamp = datetime.datetime.now() - \ - datetime.timedelta(minutes = - settings.NOTIFICATION_DELAY_MINUTES + 1) - - qs = PatchChangeNotification.objects.all() - if kwargs: - qs = qs.filter(**kwargs) - - qs.update(last_modified = timestamp) - - def testNoNotifications(self): - self.assertEquals(send_notifications(), []) - - def testNoReadyNotifications(self): - """ We shouldn't see immediate notifications""" - PatchChangeNotification(patch = self.patch, - orig_state = self.patch.state).save() - - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 0) - - def testNotifications(self): - PatchChangeNotification(patch = self.patch, - orig_state = self.patch.state).save() - self._expireNotifications() - - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.to, [self.submitter.email]) - self.assertTrue(self.patch.get_absolute_url() in msg.body) - - def testNotificationEscaping(self): - self.patch.name = 'Patch name with " character' - self.patch.save() - PatchChangeNotification(patch = self.patch, - orig_state = self.patch.state).save() - self._expireNotifications() - - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.to, [self.submitter.email]) - self.assertFalse('"' in msg.body) - - def testNotificationOptout(self): - """ensure opt-out addresses don't get notifications""" - PatchChangeNotification(patch = self.patch, - orig_state = self.patch.state).save() - self._expireNotifications() - - EmailOptout(email = self.submitter.email).save() - - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 0) - - def testNotificationMerge(self): - patches = [self.patch, - Patch(project = self.project, msgid = 'testpatch-2', - name = 'testpatch 2', content = '', - submitter = self.submitter)] - - for patch in patches: - patch.save() - PatchChangeNotification(patch = patch, - orig_state = patch.state).save() - - self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) - self._expireNotifications() - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertTrue(patches[0].get_absolute_url() in msg.body) - self.assertTrue(patches[1].get_absolute_url() in msg.body) - - def testUnexpiredNotificationMerge(self): - """Test that when there are multiple pending notifications, with - at least one within the notification delay, that other notifications - are held""" - patches = [self.patch, - Patch(project = self.project, msgid = 'testpatch-2', - name = 'testpatch 2', content = '', - submitter = self.submitter)] - - for patch in patches: - patch.save() - PatchChangeNotification(patch = patch, - orig_state = patch.state).save() - - self.assertEquals(PatchChangeNotification.objects.count(), len(patches)) - self._expireNotifications() - - # update one notification, to bring it out of the notification delay - patches[0].state = State.objects.exclude(pk = patches[0].state.pk)[0] - patches[0].save() - - # the updated notification should prevent the other from being sent - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 0) - - # expire the updated notification - self._expireNotifications() - - errors = send_notifications() - self.assertEquals(errors, []) - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertTrue(patches[0].get_absolute_url() in msg.body) - self.assertTrue(patches[1].get_absolute_url() in msg.body) diff --git a/apps/patchwork/tests/test_patchparser.py b/apps/patchwork/tests/test_patchparser.py deleted file mode 100644 index 119936a..0000000 --- a/apps/patchwork/tests/test_patchparser.py +++ /dev/null @@ -1,554 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import os -from email import message_from_string -from django.test import TestCase -from patchwork.models import Project, Person, Patch, Comment, State, \ - get_default_initial_patch_state -from patchwork.tests.utils import read_patch, read_mail, create_email, \ - defaults, create_user - -try: - from email.mime.text import MIMEText -except ImportError: - # Python 2.4 compatibility - from email.MIMEText import MIMEText - -class PatchTest(TestCase): - default_sender = defaults.sender - default_subject = defaults.subject - project = defaults.project - -from patchwork.bin.parsemail import find_content, find_author, find_project, \ - parse_mail - -class InlinePatchTest(PatchTest): - patch_filename = '0001-add-line.patch' - test_comment = 'Test for attached patch' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename) - email = create_email(self.test_comment + '\n' + self.orig_patch) - (self.patch, self.comment) = find_content(self.project, email) - - def testPatchPresence(self): - self.assertTrue(self.patch is not None) - - def testPatchContent(self): - self.assertEquals(self.patch.content, self.orig_patch) - - def testCommentPresence(self): - self.assertTrue(self.comment is not None) - - def testCommentContent(self): - self.assertEquals(self.comment.content, self.test_comment) - - -class AttachmentPatchTest(InlinePatchTest): - patch_filename = '0001-add-line.patch' - test_comment = 'Test for attached patch' - content_subtype = 'x-patch' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename) - email = create_email(self.test_comment, multipart = True) - attachment = MIMEText(self.orig_patch, _subtype = self.content_subtype) - email.attach(attachment) - (self.patch, self.comment) = find_content(self.project, email) - -class AttachmentXDiffPatchTest(AttachmentPatchTest): - content_subtype = 'x-diff' - -class UTF8InlinePatchTest(InlinePatchTest): - patch_filename = '0002-utf-8.patch' - patch_encoding = 'utf-8' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename, self.patch_encoding) - email = create_email(self.test_comment + '\n' + self.orig_patch, - content_encoding = self.patch_encoding) - (self.patch, self.comment) = find_content(self.project, email) - -class NoCharsetInlinePatchTest(InlinePatchTest): - """ Test mails with no content-type or content-encoding header """ - patch_filename = '0001-add-line.patch' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename) - email = create_email(self.test_comment + '\n' + self.orig_patch) - del email['Content-Type'] - del email['Content-Transfer-Encoding'] - (self.patch, self.comment) = find_content(self.project, email) - -class SignatureCommentTest(InlinePatchTest): - patch_filename = '0001-add-line.patch' - test_comment = 'Test comment\nmore comment' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename) - email = create_email( \ - self.test_comment + '\n' + \ - '-- \nsig\n' + self.orig_patch) - (self.patch, self.comment) = find_content(self.project, email) - - -class ListFooterTest(InlinePatchTest): - patch_filename = '0001-add-line.patch' - test_comment = 'Test comment\nmore comment' - - def setUp(self): - self.orig_patch = read_patch(self.patch_filename) - email = create_email( \ - self.test_comment + '\n' + \ - '_______________________________________________\n' + \ - 'Linuxppc-dev mailing list\n' + \ - self.orig_patch) - (self.patch, self.comment) = find_content(self.project, email) - - -class DiffWordInCommentTest(InlinePatchTest): - test_comment = 'Lines can start with words beginning in "diff"\n' + \ - 'difficult\nDifferent' - - -class UpdateCommentTest(InlinePatchTest): - """ Test for '---\nUpdate: v2' style comments to patches. """ - patch_filename = '0001-add-line.patch' - test_comment = 'Test comment\nmore comment\n---\nUpdate: test update' - -class UpdateSigCommentTest(SignatureCommentTest): - """ Test for '---\nUpdate: v2' style comments to patches, with a sig """ - patch_filename = '0001-add-line.patch' - test_comment = 'Test comment\nmore comment\n---\nUpdate: test update' - -class SenderEncodingTest(TestCase): - sender_name = u'example user' - sender_email = 'user@example.com' - from_header = 'example user <user@example.com>' - - def setUp(self): - mail = 'From: %s\n' % self.from_header + \ - 'Subject: test\n\n' + \ - 'test' - self.email = message_from_string(mail) - (self.person, new) = find_author(self.email) - self.person.save() - - def tearDown(self): - self.person.delete() - - def testName(self): - self.assertEquals(self.person.name, self.sender_name) - - def testEmail(self): - self.assertEquals(self.person.email, self.sender_email) - - def testDBQueryName(self): - db_person = Person.objects.get(name = self.sender_name) - self.assertEquals(self.person, db_person) - - def testDBQueryEmail(self): - db_person = Person.objects.get(email = self.sender_email) - self.assertEquals(self.person, db_person) - - -class SenderUTF8QPEncodingTest(SenderEncodingTest): - sender_name = u'\xe9xample user' - from_header = '=?utf-8?q?=C3=A9xample=20user?= <user@example.com>' - -class SenderUTF8QPSplitEncodingTest(SenderEncodingTest): - sender_name = u'\xe9xample user' - from_header = '=?utf-8?q?=C3=A9xample?= user <user@example.com>' - -class SenderUTF8B64EncodingTest(SenderUTF8QPEncodingTest): - from_header = '=?utf-8?B?w6l4YW1wbGUgdXNlcg==?= <user@example.com>' - -class SubjectEncodingTest(PatchTest): - sender = 'example user <user@example.com>' - subject = 'test subject' - subject_header = 'test subject' - - def setUp(self): - mail = 'From: %s\n' % self.sender + \ - 'Subject: %s\n\n' % self.subject_header + \ - 'test\n\n' + defaults.patch - self.projects = defaults.project - self.email = message_from_string(mail) - - def testSubjectEncoding(self): - (patch, comment) = find_content(self.project, self.email) - self.assertEquals(patch.name, self.subject) - -class SubjectUTF8QPEncodingTest(SubjectEncodingTest): - subject = u'test s\xfcbject' - subject_header = '=?utf-8?q?test=20s=c3=bcbject?=' - -class SubjectUTF8QPMultipleEncodingTest(SubjectEncodingTest): - subject = u'test s\xfcbject' - subject_header = 'test =?utf-8?q?s=c3=bcbject?=' - -class SenderCorrelationTest(TestCase): - existing_sender = 'Existing Sender <existing@example.com>' - non_existing_sender = 'Non-existing Sender <nonexisting@example.com>' - - def mail(self, sender): - return message_from_string('From: %s\nSubject: Test\n\ntest\n' % sender) - - def setUp(self): - self.existing_sender_mail = self.mail(self.existing_sender) - self.non_existing_sender_mail = self.mail(self.non_existing_sender) - (self.person, new) = find_author(self.existing_sender_mail) - self.person.save() - - def testExisingSender(self): - (person, new) = find_author(self.existing_sender_mail) - self.assertEqual(new, False) - self.assertEqual(person.id, self.person.id) - - def testNonExisingSender(self): - (person, new) = find_author(self.non_existing_sender_mail) - self.assertEqual(new, True) - self.assertEqual(person.id, None) - - def testExistingDifferentFormat(self): - mail = self.mail('existing@example.com') - (person, new) = find_author(mail) - self.assertEqual(new, False) - self.assertEqual(person.id, self.person.id) - - def testExistingDifferentCase(self): - mail = self.mail(self.existing_sender.upper()) - (person, new) = find_author(mail) - self.assertEqual(new, False) - self.assertEqual(person.id, self.person.id) - - def tearDown(self): - self.person.delete() - -class MultipleProjectPatchTest(TestCase): - """ Test that patches sent to multiple patchwork projects are - handled correctly """ - - test_comment = 'Test Comment' - patch_filename = '0001-add-line.patch' - msgid = '<1@example.com>' - - def setUp(self): - self.p1 = Project(linkname = 'test-project-1', name = 'Project 1', - listid = '1.example.com', listemail='1@example.com') - self.p2 = Project(linkname = 'test-project-2', name = 'Project 2', - listid = '2.example.com', listemail='2@example.com') - - self.p1.save() - self.p2.save() - - patch = read_patch(self.patch_filename) - email = create_email(self.test_comment + '\n' + patch) - email['Message-Id'] = self.msgid - - del email['List-ID'] - email['List-ID'] = '<' + self.p1.listid + '>' - parse_mail(email) - - del email['List-ID'] - email['List-ID'] = '<' + self.p2.listid + '>' - parse_mail(email) - - def testParsedProjects(self): - self.assertEquals(Patch.objects.filter(project = self.p1).count(), 1) - self.assertEquals(Patch.objects.filter(project = self.p2).count(), 1) - - def tearDown(self): - self.p1.delete() - self.p2.delete() - - -class MultipleProjectPatchCommentTest(MultipleProjectPatchTest): - """ Test that followups to multiple-project patches end up on the - correct patch """ - - comment_msgid = '<2@example.com>' - comment_content = 'test comment' - - def setUp(self): - super(MultipleProjectPatchCommentTest, self).setUp() - - for project in [self.p1, self.p2]: - email = MIMEText(self.comment_content) - email['From'] = defaults.sender - email['Subject'] = defaults.subject - email['Message-Id'] = self.comment_msgid - email['List-ID'] = '<' + project.listid + '>' - email['In-Reply-To'] = self.msgid - parse_mail(email) - - def testParsedComment(self): - for project in [self.p1, self.p2]: - patch = Patch.objects.filter(project = project)[0] - # we should see two comments now - the original mail with the patch, - # and the one we parsed in setUp() - self.assertEquals(Comment.objects.filter(patch = patch).count(), 2) - -class ListIdHeaderTest(TestCase): - """ Test that we parse List-Id headers from mails correctly """ - def setUp(self): - self.project = Project(linkname = 'test-project-1', name = 'Project 1', - listid = '1.example.com', listemail='1@example.com') - self.project.save() - - def testNoListId(self): - email = MIMEText('') - project = find_project(email) - self.assertEquals(project, None) - - def testBlankListId(self): - email = MIMEText('') - email['List-Id'] = '' - project = find_project(email) - self.assertEquals(project, None) - - def testWhitespaceListId(self): - email = MIMEText('') - email['List-Id'] = ' ' - project = find_project(email) - self.assertEquals(project, None) - - def testSubstringListId(self): - email = MIMEText('') - email['List-Id'] = 'example.com' - project = find_project(email) - self.assertEquals(project, None) - - def testShortListId(self): - """ Some mailing lists have List-Id headers in short formats, where it - is only the list ID itself (without enclosing angle-brackets). """ - email = MIMEText('') - email['List-Id'] = self.project.listid - project = find_project(email) - self.assertEquals(project, self.project) - - def testLongListId(self): - email = MIMEText('') - email['List-Id'] = 'Test text <%s>' % self.project.listid - project = find_project(email) - self.assertEquals(project, self.project) - - def tearDown(self): - self.project.delete() - -class MBoxPatchTest(PatchTest): - def setUp(self): - self.mail = read_mail(self.mail_file, project = self.project) - -class GitPullTest(MBoxPatchTest): - mail_file = '0001-git-pull-request.mbox' - - def testGitPullRequest(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(patch.pull_url is not None) - self.assertTrue(patch.content is None) - self.assertTrue(comment is not None) - -class GitPullWrappedTest(GitPullTest): - mail_file = '0002-git-pull-request-wrapped.mbox' - -class GitPullWithDiffTest(MBoxPatchTest): - mail_file = '0003-git-pull-request-with-diff.mbox' - - def testGitPullWithDiff(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertEqual('git://git.kernel.org/pub/scm/linux/kernel/git/tip/' + - 'linux-2.6-tip.git x86-fixes-for-linus', patch.pull_url) - self.assertTrue( - patch.content.startswith('diff --git a/arch/x86/include/asm/smp.h'), - patch.content) - self.assertTrue(comment is not None) - -class GitPullGitSSHUrlTest(GitPullTest): - mail_file = '0004-git-pull-request-git+ssh.mbox' - -class GitPullSSHUrlTest(GitPullTest): - mail_file = '0005-git-pull-request-ssh.mbox' - -class GitPullHTTPUrlTest(GitPullTest): - mail_file = '0006-git-pull-request-http.mbox' - -class GitRenameOnlyTest(MBoxPatchTest): - mail_file = '0008-git-rename.mbox' - - def testGitRename(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(comment is not None) - self.assertEqual(patch.content.count("\nrename from "), 2) - self.assertEqual(patch.content.count("\nrename to "), 2) - -class GitRenameWithDiffTest(MBoxPatchTest): - mail_file = '0009-git-rename-with-diff.mbox' - - def testGitRename(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(comment is not None) - self.assertEqual(patch.content.count("\nrename from "), 2) - self.assertEqual(patch.content.count("\nrename to "), 2) - self.assertEqual(patch.content.count('\n-a\n+b'), 1) - -class CVSFormatPatchTest(MBoxPatchTest): - mail_file = '0007-cvs-format-diff.mbox' - - def testPatch(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(comment is not None) - self.assertTrue(patch.content.startswith('Index')) - -class CharsetFallbackPatchTest(MBoxPatchTest): - """ Test mail with and invalid charset name, and check that we can parse - with one of the fallback encodings""" - - mail_file = '0010-invalid-charset.mbox' - - def testPatch(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(comment is not None) - -class NoNewlineAtEndOfFilePatchTest(MBoxPatchTest): - mail_file = '0011-no-newline-at-end-of-file.mbox' - - def testPatch(self): - (patch, comment) = find_content(self.project, self.mail) - self.assertTrue(patch is not None) - self.assertTrue(comment is not None) - self.assertTrue(patch.content.startswith('diff --git a/tools/testing/selftests/powerpc/Makefile')) - # Confirm the trailing no newline marker doesn't end up in the comment - self.assertFalse(comment.content.rstrip().endswith('\ No newline at end of file')) - # Confirm it's instead at the bottom of the patch - self.assertTrue(patch.content.rstrip().endswith('\ No newline at end of file')) - # Confirm we got both markers - self.assertEqual(2, patch.content.count('\ No newline at end of file')) - -class DelegateRequestTest(TestCase): - patch_filename = '0001-add-line.patch' - msgid = '<1@example.com>' - invalid_delegate_email = "nobody" - - def setUp(self): - self.patch = read_patch(self.patch_filename) - self.user = create_user() - self.p1 = Project(linkname = 'test-project-1', name = 'Project 1', - listid = '1.example.com', listemail='1@example.com') - self.p1.save() - - def get_email(self): - email = create_email(self.patch) - del email['List-ID'] - email['List-ID'] = '<' + self.p1.listid + '>' - email['Message-Id'] = self.msgid - return email - - def _assertDelegate(self, delegate): - query = Patch.objects.filter(project=self.p1) - self.assertEquals(query.count(), 1) - self.assertEquals(query[0].delegate, delegate) - - def testDelegate(self): - email = self.get_email() - email['X-Patchwork-Delegate'] = self.user.email - parse_mail(email) - self._assertDelegate(self.user) - - def testNoDelegate(self): - email = self.get_email() - parse_mail(email) - self._assertDelegate(None) - - def testInvalidDelegateFallsBackToNoDelegate(self): - email = self.get_email() - email['X-Patchwork-Delegate'] = self.invalid_delegate_email - parse_mail(email) - self._assertDelegate(None) - - def tearDown(self): - self.p1.delete() - self.user.delete() - -class InitialPatchStateTest(TestCase): - patch_filename = '0001-add-line.patch' - msgid = '<1@example.com>' - invalid_state_name = "Nonexistent Test State" - - def setUp(self): - self.patch = read_patch(self.patch_filename) - self.user = create_user() - self.p1 = Project(linkname = 'test-project-1', name = 'Project 1', - listid = '1.example.com', listemail='1@example.com') - self.p1.save() - self.default_state = get_default_initial_patch_state() - self.nondefault_state = State.objects.get(name="Accepted") - - def get_email(self): - email = create_email(self.patch) - del email['List-ID'] - email['List-ID'] = '<' + self.p1.listid + '>' - email['Message-Id'] = self.msgid - return email - - def _assertState(self, state): - query = Patch.objects.filter(project=self.p1) - self.assertEquals(query.count(), 1) - self.assertEquals(query[0].state, state) - - def testNonDefaultStateIsActuallyNotTheDefaultState(self): - self.assertNotEqual(self.default_state, self.nondefault_state) - - def testExplicitNonDefaultStateRequest(self): - email = self.get_email() - email['X-Patchwork-State'] = self.nondefault_state.name - parse_mail(email) - self._assertState(self.nondefault_state) - - def testExplicitDefaultStateRequest(self): - email = self.get_email() - email['X-Patchwork-State'] = self.default_state.name - parse_mail(email) - self._assertState(self.default_state) - - def testImplicitDefaultStateRequest(self): - email = self.get_email() - parse_mail(email) - self._assertState(self.default_state) - - def testInvalidTestStateDoesNotExist(self): - with self.assertRaises(State.DoesNotExist): - State.objects.get(name=self.invalid_state_name) - - def testInvalidStateRequestFallsBackToDefaultState(self): - email = self.get_email() - email['X-Patchwork-State'] = self.invalid_state_name - parse_mail(email) - self._assertState(self.default_state) - - def tearDown(self): - self.p1.delete() - self.user.delete() diff --git a/apps/patchwork/tests/test_person.py b/apps/patchwork/tests/test_person.py deleted file mode 100644 index d948096..0000000 --- a/apps/patchwork/tests/test_person.py +++ /dev/null @@ -1,55 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2013 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -from django.test import TestCase -from django.test.client import Client -from patchwork.models import EmailConfirmation, Person, Bundle -import json - -class SubmitterCompletionTest(TestCase): - def setUp(self): - self.people = [ - Person(name = "Test Name", email = "test1@example.com"), - Person(email = "test2@example.com"), - ] - map(lambda p: p.save(), self.people) - - def testNameComplete(self): - response = self.client.get('/submitter/', {'q': 'name'}) - self.assertEquals(response.status_code, 200) - data = json.loads(response.content) - self.assertEquals(len(data), 1) - self.assertEquals(data[0]['fields']['name'], 'Test Name') - - def testEmailComplete(self): - response = self.client.get('/submitter/', {'q': 'test2'}) - self.assertEquals(response.status_code, 200) - data = json.loads(response.content) - self.assertEquals(len(data), 1) - self.assertEquals(data[0]['fields']['email'], 'test2@example.com') - - def testCompleteLimit(self): - for i in range(3,10): - person = Person(email = 'test%d@example.com' % i) - person.save() - response = self.client.get('/submitter/', {'q': 'test', 'l': 5}) - self.assertEquals(response.status_code, 200) - data = json.loads(response.content) - self.assertEquals(len(data), 5) diff --git a/apps/patchwork/tests/test_registration.py b/apps/patchwork/tests/test_registration.py deleted file mode 100644 index 845b60b..0000000 --- a/apps/patchwork/tests/test_registration.py +++ /dev/null @@ -1,210 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -from django.test import TestCase -from django.test.client import Client -from django.core import mail -from django.core.urlresolvers import reverse -from django.contrib.auth.models import User -from patchwork.models import EmailConfirmation, Person -from patchwork.tests.utils import create_user - -def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs = {'key': conf.key}) - -class TestUser(object): - firstname = 'Test' - lastname = 'User' - username = 'testuser' - email = 'test@example.com' - password = 'foobar' - -class RegistrationTest(TestCase): - def setUp(self): - self.user = TestUser() - self.client = Client() - self.default_data = {'username': self.user.username, - 'first_name': self.user.firstname, - 'last_name': self.user.lastname, - 'email': self.user.email, - 'password': self.user.password} - self.required_error = 'This field is required.' - self.invalid_error = 'Enter a valid value.' - - def testRegistrationForm(self): - response = self.client.get('/register/') - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/registration_form.html') - - def testBlankFields(self): - for field in ['username', 'email', 'password']: - data = self.default_data.copy() - del data[field] - response = self.client.post('/register/', data) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', field, self.required_error) - - def testInvalidUsername(self): - data = self.default_data.copy() - data['username'] = 'invalid user' - response = self.client.post('/register/', data) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'username', self.invalid_error) - - def testExistingUsername(self): - user = create_user() - data = self.default_data.copy() - data['username'] = user.username - response = self.client.post('/register/', data) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'username', - 'This username is already taken. Please choose another.') - - def testExistingEmail(self): - user = create_user() - data = self.default_data.copy() - data['email'] = user.email - response = self.client.post('/register/', data) - self.assertEquals(response.status_code, 200) - self.assertFormError(response, 'form', 'email', - 'This email address is already in use ' + \ - 'for the account "%s".\n' % user.username) - - def testValidRegistration(self): - response = self.client.post('/register/', self.default_data) - self.assertEquals(response.status_code, 200) - self.assertContains(response, 'confirmation email has been sent') - - # check for presence of an inactive user object - users = User.objects.filter(username = self.user.username) - self.assertEquals(users.count(), 1) - user = users[0] - self.assertEquals(user.username, self.user.username) - self.assertEquals(user.email, self.user.email) - self.assertEquals(user.is_active, False) - - # check for confirmation object - confs = EmailConfirmation.objects.filter(user = user, - type = 'registration') - self.assertEquals(len(confs), 1) - conf = confs[0] - self.assertEquals(conf.email, self.user.email) - - # check for a sent mail - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.subject, 'Patchwork account confirmation') - self.assertTrue(self.user.email in msg.to) - self.assertTrue(_confirmation_url(conf) in msg.body) - - # ...and that the URL is valid - response = self.client.get(_confirmation_url(conf)) - self.assertEquals(response.status_code, 200) - -class RegistrationConfirmationTest(TestCase): - - def setUp(self): - self.user = TestUser() - self.default_data = {'username': self.user.username, - 'first_name': self.user.firstname, - 'last_name': self.user.lastname, - 'email': self.user.email, - 'password': self.user.password} - - def testRegistrationConfirmation(self): - self.assertEqual(EmailConfirmation.objects.count(), 0) - response = self.client.post('/register/', self.default_data) - self.assertEquals(response.status_code, 200) - self.assertContains(response, 'confirmation email has been sent') - - self.assertEqual(EmailConfirmation.objects.count(), 1) - conf = EmailConfirmation.objects.filter()[0] - self.assertFalse(conf.user.is_active) - self.assertTrue(conf.active) - - response = self.client.get(_confirmation_url(conf)) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/registration-confirm.html') - - conf = EmailConfirmation.objects.get(pk = conf.pk) - self.assertTrue(conf.user.is_active) - self.assertFalse(conf.active) - - def testRegistrationNewPersonSetup(self): - """ Check that the person object created after registration has the - correct details """ - - # register - self.assertEqual(EmailConfirmation.objects.count(), 0) - response = self.client.post('/register/', self.default_data) - self.assertEquals(response.status_code, 200) - self.assertFalse(Person.objects.exists()) - - # confirm - conf = EmailConfirmation.objects.filter()[0] - response = self.client.get(_confirmation_url(conf)) - self.assertEquals(response.status_code, 200) - - qs = Person.objects.filter(email = self.user.email) - self.assertTrue(qs.exists()) - person = Person.objects.get(email = self.user.email) - - self.assertEquals(person.name, - self.user.firstname + ' ' + self.user.lastname) - - def testRegistrationExistingPersonSetup(self): - """ Check that the person object created after registration has the - correct details """ - - fullname = self.user.firstname + ' ' + self.user.lastname - person = Person(name = fullname, email = self.user.email) - person.save() - - # register - self.assertEqual(EmailConfirmation.objects.count(), 0) - response = self.client.post('/register/', self.default_data) - self.assertEquals(response.status_code, 200) - - # confirm - conf = EmailConfirmation.objects.filter()[0] - response = self.client.get(_confirmation_url(conf)) - self.assertEquals(response.status_code, 200) - - person = Person.objects.get(email = self.user.email) - - self.assertEquals(person.name, fullname) - - def testRegistrationExistingPersonUnmodified(self): - """ Check that an unconfirmed registration can't modify an existing - Person object""" - - fullname = self.user.firstname + ' ' + self.user.lastname - person = Person(name = fullname, email = self.user.email) - person.save() - - # register - data = self.default_data.copy() - data['first_name'] = 'invalid' - data['last_name'] = 'invalid' - self.assertEquals(data['email'], person.email) - response = self.client.post('/register/', data) - self.assertEquals(response.status_code, 200) - - self.assertEquals(Person.objects.get(pk = person.pk).name, fullname) diff --git a/apps/patchwork/tests/test_updates.py b/apps/patchwork/tests/test_updates.py deleted file mode 100644 index 177ee78..0000000 --- a/apps/patchwork/tests/test_updates.py +++ /dev/null @@ -1,118 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django.test import TestCase -from django.core.urlresolvers import reverse -from patchwork.models import Patch, Person, State -from patchwork.tests.utils import defaults, create_maintainer - -class MultipleUpdateTest(TestCase): - def setUp(self): - defaults.project.save() - self.user = create_maintainer(defaults.project) - self.client.login(username = self.user.username, - password = self.user.username) - self.properties_form_id = 'patchform-properties' - self.url = reverse( - 'patchwork.views.patch.list', args = [defaults.project.linkname]) - self.base_data = { - 'action': 'Update', 'project': str(defaults.project.id), - 'form': 'patchlistform', 'archived': '*', 'delegate': '*', - 'state': '*'} - self.patches = [] - for name in ['patch one', 'patch two', 'patch three']: - patch = Patch(project = defaults.project, msgid = name, - name = name, content = '', - submitter = Person.objects.get(user = self.user)) - patch.save() - self.patches.append(patch) - - def _selectAllPatches(self, data): - for patch in self.patches: - data['patch_id:%d' % patch.id] = 'checked' - - def testArchivingPatches(self): - data = self.base_data.copy() - data.update({'archived': 'True'}) - self._selectAllPatches(data) - response = self.client.post(self.url, data) - self.assertContains(response, 'No patches to display', - status_code = 200) - for patch in [Patch.objects.get(pk = p.pk) for p in self.patches]: - self.assertTrue(patch.archived) - - def testUnArchivingPatches(self): - # Start with one patch archived and the remaining ones unarchived. - self.patches[0].archived = True - self.patches[0].save() - data = self.base_data.copy() - data.update({'archived': 'False'}) - self._selectAllPatches(data) - response = self.client.post(self.url, data) - self.assertContains(response, self.properties_form_id, - status_code = 200) - for patch in [Patch.objects.get(pk = p.pk) for p in self.patches]: - self.assertFalse(patch.archived) - - def _testStateChange(self, state): - data = self.base_data.copy() - data.update({'state': str(state)}) - self._selectAllPatches(data) - response = self.client.post(self.url, data) - self.assertContains(response, self.properties_form_id, - status_code = 200) - return response - - def testStateChangeValid(self): - states = [patch.state.pk for patch in self.patches] - state = State.objects.exclude(pk__in = states)[0] - self._testStateChange(state.pk) - for p in self.patches: - self.assertEquals(Patch.objects.get(pk = p.pk).state, state) - - def testStateChangeInvalid(self): - state = max(State.objects.all().values_list('id', flat = True)) + 1 - orig_states = [patch.state for patch in self.patches] - response = self._testStateChange(state) - self.assertEquals( \ - [Patch.objects.get(pk = p.pk).state for p in self.patches], - orig_states) - self.assertFormError(response, 'patchform', 'state', - 'Select a valid choice. That choice is not one ' + \ - 'of the available choices.') - - def _testDelegateChange(self, delegate_str): - data = self.base_data.copy() - data.update({'delegate': delegate_str}) - self._selectAllPatches(data) - response = self.client.post(self.url, data) - self.assertContains(response, self.properties_form_id, - status_code=200) - return response - - def testDelegateChangeValid(self): - delegate = create_maintainer(defaults.project) - response = self._testDelegateChange(str(delegate.pk)) - for p in self.patches: - self.assertEquals(Patch.objects.get(pk = p.pk).delegate, delegate) - - def testDelegateClear(self): - response = self._testDelegateChange('') - for p in self.patches: - self.assertEquals(Patch.objects.get(pk = p.pk).delegate, None) diff --git a/apps/patchwork/tests/test_user.py b/apps/patchwork/tests/test_user.py deleted file mode 100644 index 0faa970..0000000 --- a/apps/patchwork/tests/test_user.py +++ /dev/null @@ -1,195 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -from django.test import TestCase -from django.test.client import Client -from django.core import mail -from django.core.urlresolvers import reverse -from django.conf import settings -from django.contrib.auth.models import User -from patchwork.models import EmailConfirmation, Person, Bundle -from patchwork.tests.utils import defaults, error_strings - -def _confirmation_url(conf): - return reverse('patchwork.views.confirm', kwargs = {'key': conf.key}) - -class TestUser(object): - username = 'testuser' - email = 'test@example.com' - secondary_email = 'test2@example.com' - password = None - - def __init__(self): - self.password = User.objects.make_random_password() - self.user = User.objects.create_user(self.username, - self.email, self.password) - -class UserPersonRequestTest(TestCase): - def setUp(self): - self.user = TestUser() - self.client.login(username = self.user.username, - password = self.user.password) - EmailConfirmation.objects.all().delete() - - def testUserPersonRequestForm(self): - response = self.client.get('/user/link/') - self.assertEquals(response.status_code, 200) - self.assertTrue(response.context['linkform']) - - def testUserPersonRequestEmpty(self): - response = self.client.post('/user/link/', {'email': ''}) - self.assertEquals(response.status_code, 200) - self.assertTrue(response.context['linkform']) - self.assertFormError(response, 'linkform', 'email', - 'This field is required.') - - def testUserPersonRequestInvalid(self): - response = self.client.post('/user/link/', {'email': 'foo'}) - self.assertEquals(response.status_code, 200) - self.assertTrue(response.context['linkform']) - self.assertFormError(response, 'linkform', 'email', - error_strings['email']) - - def testUserPersonRequestValid(self): - response = self.client.post('/user/link/', - {'email': self.user.secondary_email}) - self.assertEquals(response.status_code, 200) - self.assertTrue(response.context['confirmation']) - - # check that we have a confirmation saved - self.assertEquals(EmailConfirmation.objects.count(), 1) - conf = EmailConfirmation.objects.all()[0] - self.assertEquals(conf.user, self.user.user) - self.assertEquals(conf.email, self.user.secondary_email) - self.assertEquals(conf.type, 'userperson') - - # check that an email has gone out... - self.assertEquals(len(mail.outbox), 1) - msg = mail.outbox[0] - self.assertEquals(msg.subject, 'Patchwork email address confirmation') - self.assertTrue(self.user.secondary_email in msg.to) - self.assertTrue(_confirmation_url(conf) in msg.body) - - # ...and that the URL is valid - response = self.client.get(_confirmation_url(conf)) - self.assertEquals(response.status_code, 200) - self.assertTemplateUsed(response, 'patchwork/user-link-confirm.html') - -class UserPersonConfirmTest(TestCase): - def setUp(self): - EmailConfirmation.objects.all().delete() - Person.objects.all().delete() - self.user = TestUser() - self.client.login(username = self.user.username, - password = self.user.password) - self.conf = EmailConfirmation(type = 'userperson', - email = self.user.secondary_email, - user = self.user.user) - self.conf.save() - - def testUserPersonConfirm(self): - self.assertEquals(Person.objects.count(), 0) - response = self.client.get(_confirmation_url(self.conf)) - self.assertEquals(response.status_code, 200) - - # check that the Person object has been created and linked - self.assertEquals(Person.objects.count(), 1) - person = Person.objects.get(email = self.user.secondary_email) - self.assertEquals(person.email, self.user.secondary_email) - self.assertEquals(person.user, self.user.user) - - # check that the confirmation has been marked as inactive. We - # need to reload the confirmation to check this. - conf = EmailConfirmation.objects.get(pk = self.conf.pk) - self.assertEquals(conf.active, False) - -class UserLoginRedirectTest(TestCase): - - def testUserLoginRedirect(self): - url = '/user/' - response = self.client.get(url) - self.assertRedirects(response, settings.LOGIN_URL + '?next=' + url) - -class UserProfileTest(TestCase): - - def setUp(self): - self.user = TestUser() - self.client.login(username = self.user.username, - password = self.user.password) - - def testUserProfile(self): - response = self.client.get('/user/') - self.assertContains(response, 'User Profile: %s' % self.user.username) - self.assertContains(response, 'User Profile: %s' % self.user.username) - - def testUserProfileNoBundles(self): - response = self.client.get('/user/') - self.assertContains(response, 'You have no bundles') - - def testUserProfileBundles(self): - project = defaults.project - project.save() - - bundle = Bundle(project = project, name = 'test-1', - owner = self.user.user) - bundle.save() - - response = self.client.get('/user/') - - self.assertContains(response, 'You have the following bundle') - self.assertContains(response, bundle.get_absolute_url()) - -class UserPasswordChangeTest(TestCase): - form_url = reverse('django.contrib.auth.views.password_change') - done_url = reverse('django.contrib.auth.views.password_change_done') - - def testPasswordChangeForm(self): - self.user = TestUser() - self.client.login(username = self.user.username, - password = self.user.password) - - response = self.client.get(self.form_url) - self.assertContains(response, 'Change my password') - - def testPasswordChange(self): - self.user = TestUser() - self.client.login(username = self.user.username, - password = self.user.password) - - old_password = self.user.password - new_password = User.objects.make_random_password() - - data = { - 'old_password': old_password, - 'new_password1': new_password, - 'new_password2': new_password, - } - - response = self.client.post(self.form_url, data) - self.assertRedirects(response, self.done_url) - - user = User.objects.get(id = self.user.user.id) - - self.assertFalse(user.check_password(old_password)) - self.assertTrue(user.check_password(new_password)) - - response = self.client.get(self.done_url) - self.assertContains(response, - "Your password has been changed sucessfully") diff --git a/apps/patchwork/tests/test_xmlrpc.py b/apps/patchwork/tests/test_xmlrpc.py deleted file mode 100644 index 2b459b2..0000000 --- a/apps/patchwork/tests/test_xmlrpc.py +++ /dev/null @@ -1,55 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2014 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import unittest -import xmlrpclib -from django.test import LiveServerTestCase -from django.core.urlresolvers import reverse -from django.conf import settings -from patchwork.models import Person, Patch -from patchwork.tests.utils import defaults - -@unittest.skipUnless(settings.ENABLE_XMLRPC, - "requires xmlrpc interface (use the ENABLE_XMLRPC setting)") -class XMLRPCTest(LiveServerTestCase): - - def setUp(self): - settings.STATIC_URL = '/' - self.url = (self.live_server_url + - reverse('patchwork.views.xmlrpc.xmlrpc')) - self.rpc = xmlrpclib.Server(self.url) - - def testGetRedirect(self): - response = self.client.get(self.url) - self.assertRedirects(response, - reverse('patchwork.views.help', - kwargs = {'path': 'pwclient/'})) - - def testList(self): - defaults.project.save() - defaults.patch_author_person.save() - patch = Patch(project = defaults.project, - submitter = defaults.patch_author_person, - msgid = defaults.patch_name, - content = defaults.patch) - patch.save() - - patches = self.rpc.patch_list() - self.assertEqual(len(patches), 1) - self.assertEqual(patches[0]['id'], patch.id) diff --git a/apps/patchwork/tests/utils.py b/apps/patchwork/tests/utils.py deleted file mode 100644 index 782ed36..0000000 --- a/apps/patchwork/tests/utils.py +++ /dev/null @@ -1,138 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -import os -import codecs -from patchwork.models import Project, Person -from django.contrib.auth.models import User -from django.forms.fields import EmailField - -from email import message_from_file -try: - from email.mime.text import MIMEText - from email.mime.multipart import MIMEMultipart -except ImportError: - # Python 2.4 compatibility - from email.MIMEText import MIMEText - from email.MIMEMultipart import MIMEMultipart - -# helper functions for tests -_test_mail_dir = os.path.join(os.path.dirname(__file__), 'mail') -_test_patch_dir = os.path.join(os.path.dirname(__file__), 'patches') - -class defaults(object): - project = Project(linkname = 'test-project', name = 'Test Project', - listid = 'test.example.com') - - patch_author = 'Patch Author <patch-author@example.com>' - patch_author_person = Person(name = 'Patch Author', - email = 'patch-author@example.com') - - comment_author = 'Comment Author <comment-author@example.com>' - - sender = 'Test Author <test-author@example.com>' - - subject = 'Test Subject' - - patch_name = 'Test Patch' - - patch = """--- /dev/null 2011-01-01 00:00:00.000000000 +0800 -+++ a 2011-01-01 00:00:00.000000000 +0800 -@@ -0,0 +1 @@ -+a -""" - -error_strings = { - 'email': 'Enter a valid email address.', -} - -_user_idx = 1 -def create_user(): - global _user_idx - userid = 'test%d' % _user_idx - email = '%s@example.com' % userid - _user_idx += 1 - - user = User.objects.create_user(userid, email, userid) - user.save() - - person = Person(email = email, name = userid, user = user) - person.save() - - return user - -def create_maintainer(project): - user = create_user() - profile = user.profile - profile.maintainer_projects.add(project) - profile.save() - return user - -def find_in_context(context, key): - if isinstance(context, list): - for c in context: - v = find_in_context(c, key) - if v is not None: - return v - else: - if key in context: - return context[key] - return None - -def read_patch(filename, encoding = None): - file_path = os.path.join(_test_patch_dir, filename) - if encoding is not None: - f = codecs.open(file_path, encoding = encoding) - else: - f = file(file_path) - - return f.read() - -def read_mail(filename, project = None): - file_path = os.path.join(_test_mail_dir, filename) - mail = message_from_file(open(file_path)) - if project is not None: - mail['List-Id'] = project.listid - return mail - -def create_email(content, subject = None, sender = None, multipart = False, - project = None, content_encoding = None): - if subject is None: - subject = defaults.subject - if sender is None: - sender = defaults.sender - if project is None: - project = defaults.project - if content_encoding is None: - content_encoding = 'us-ascii' - - if multipart: - msg = MIMEMultipart() - body = MIMEText(content, _subtype = 'plain', - _charset = content_encoding) - msg.attach(body) - else: - msg = MIMEText(content, _charset = content_encoding) - - msg['Subject'] = subject - msg['From'] = sender - msg['List-Id'] = project.listid - - - return msg diff --git a/apps/patchwork/urls.py b/apps/patchwork/urls.py deleted file mode 100644 index b28eb90..0000000 --- a/apps/patchwork/urls.py +++ /dev/null @@ -1,103 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django.conf.urls import patterns, url, include -from django.conf import settings -from django.contrib import admin -from django.contrib.auth import views as auth_views - -admin.autodiscover() - -urlpatterns = patterns('', - url(r'^admin/', include(admin.site.urls)), - - (r'^$', 'patchwork.views.projects'), - (r'^project/(?P<project_id>[^/]+)/list/$', 'patchwork.views.patch.list'), - (r'^project/(?P<project_id>[^/]+)/$', 'patchwork.views.project.project'), - - # patch views - (r'^patch/(?P<patch_id>\d+)/$', 'patchwork.views.patch.patch'), - (r'^patch/(?P<patch_id>\d+)/raw/$', 'patchwork.views.patch.content'), - (r'^patch/(?P<patch_id>\d+)/mbox/$', 'patchwork.views.patch.mbox'), - - # logged-in user stuff - (r'^user/$', 'patchwork.views.user.profile'), - (r'^user/todo/$', 'patchwork.views.user.todo_lists'), - (r'^user/todo/(?P<project_id>[^/]+)/$', 'patchwork.views.user.todo_list'), - - (r'^user/bundles/$', - 'patchwork.views.bundle.bundles'), - - (r'^user/link/$', 'patchwork.views.user.link'), - (r'^user/unlink/(?P<person_id>[^/]+)/$', 'patchwork.views.user.unlink'), - - # password change - url(r'^user/password-change/$', auth_views.password_change, - name='password_change'), - url(r'^user/password-change/done/$', auth_views.password_change_done, - name='password_change_done'), - - # login/logout - url(r'^user/login/$', auth_views.login, - {'template_name': 'patchwork/login.html'}, - name = 'auth_login'), - url(r'^user/logout/$', auth_views.logout, - {'template_name': 'patchwork/logout.html'}, - name = 'auth_logout'), - - # registration - (r'^register/', 'patchwork.views.user.register'), - - # public view for bundles - (r'^bundle/(?P<username>[^/]*)/(?P<bundlename>[^/]*)/$', - 'patchwork.views.bundle.bundle'), - (r'^bundle/(?P<username>[^/]*)/(?P<bundlename>[^/]*)/mbox/$', - 'patchwork.views.bundle.mbox'), - - (r'^confirm/(?P<key>[0-9a-f]+)/$', 'patchwork.views.confirm'), - - # submitter autocomplete - (r'^submitter/$', 'patchwork.views.submitter_complete'), - - # email setup - (r'^mail/$', 'patchwork.views.mail.settings'), - (r'^mail/optout/$', 'patchwork.views.mail.optout'), - (r'^mail/optin/$', 'patchwork.views.mail.optin'), - - # help! - (r'^help/(?P<path>.*)$', 'patchwork.views.help'), -) - -if settings.ENABLE_XMLRPC: - urlpatterns += patterns('', - (r'xmlrpc/$', 'patchwork.views.xmlrpc.xmlrpc'), - (r'^pwclient/$', 'patchwork.views.pwclient'), - (r'^project/(?P<project_id>[^/]+)/pwclientrc/$', - 'patchwork.views.pwclientrc'), - ) - -# redirect from old urls -if settings.COMPAT_REDIR: - urlpatterns += patterns('', - (r'^user/bundle/(?P<bundle_id>[^/]+)/$', - 'patchwork.views.bundle.bundle_redir'), - (r'^user/bundle/(?P<bundle_id>[^/]+)/mbox/$', - 'patchwork.views.bundle.mbox_redir'), - ) - diff --git a/apps/patchwork/utils.py b/apps/patchwork/utils.py deleted file mode 100644 index 9ed9e41..0000000 --- a/apps/patchwork/utils.py +++ /dev/null @@ -1,248 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -import itertools -import datetime -from django.shortcuts import get_object_or_404 -from django.template.loader import render_to_string -from django.contrib.auth.models import User -from django.contrib.sites.models import Site -from django.conf import settings -from django.core.mail import EmailMessage -from django.db.models import Max, Q, F -from django.db.utils import IntegrityError -from patchwork.forms import MultiplePatchForm -from patchwork.models import Bundle, Project, BundlePatch, UserProfile, \ - PatchChangeNotification, EmailOptout, EmailConfirmation - -def get_patch_ids(d, prefix = 'patch_id'): - ids = [] - - for (k, v) in d.items(): - a = k.split(':') - if len(a) != 2: - continue - if a[0] != prefix: - continue - if not v: - continue - ids.append(a[1]) - - return ids - -class Order(object): - order_map = { - 'date': 'date', - 'name': 'name', - 'state': 'state__ordering', - 'submitter': 'submitter__name', - 'delegate': 'delegate__username', - } - default_order = ('date', True) - - def __init__(self, str = None, editable = False): - self.reversed = False - self.editable = editable - (self.order, self.reversed) = self.default_order - - if self.editable: - return - - if str is None or str == '': - return - - reversed = False - if str[0] == '-': - str = str[1:] - reversed = True - - if str not in self.order_map.keys(): - return - - self.order = str - self.reversed = reversed - - def __str__(self): - str = self.order - if self.reversed: - str = '-' + str - return str - - def name(self): - return self.order - - def reversed_name(self): - if self.reversed: - return self.order - else: - return '-' + self.order - - def apply(self, qs): - q = self.order_map[self.order] - if self.reversed: - q = '-' + q - - orders = [q] - - # if we're using a non-default order, add the default as a secondary - # ordering. We reverse the default if the primary is reversed. - (default_name, default_reverse) = self.default_order - if self.order != default_name: - q = self.order_map[default_name] - if self.reversed ^ default_reverse: - q = '-' + q - orders.append(q) - - return qs.order_by(*orders) - -bundle_actions = ['create', 'add', 'remove'] -def set_bundle(user, project, action, data, patches, context): - # set up the bundle - bundle = None - if action == 'create': - bundle_name = data['bundle_name'].strip() - if '/' in bundle_name: - return ['Bundle names can\'t contain slashes'] - - if not bundle_name: - return ['No bundle name was specified'] - - if Bundle.objects.filter(owner = user, name = bundle_name).count() > 0: - return ['You already have a bundle called "%s"' % bundle_name] - - bundle = Bundle(owner = user, project = project, - name = bundle_name) - bundle.save() - context.add_message("Bundle %s created" % bundle.name) - - elif action =='add': - bundle = get_object_or_404(Bundle, id = data['bundle_id']) - - elif action =='remove': - bundle = get_object_or_404(Bundle, id = data['removed_bundle_id']) - - if not bundle: - return ['no such bundle'] - - for patch in patches: - if action == 'create' or action == 'add': - bundlepatch_count = BundlePatch.objects.filter(bundle = bundle, - patch = patch).count() - if bundlepatch_count == 0: - bundle.append_patch(patch) - context.add_message("Patch '%s' added to bundle %s" % \ - (patch.name, bundle.name)) - else: - context.add_message("Patch '%s' already in bundle %s" % \ - (patch.name, bundle.name)) - - elif action == 'remove': - try: - bp = BundlePatch.objects.get(bundle = bundle, patch = patch) - bp.delete() - context.add_message("Patch '%s' removed from bundle %s\n" % \ - (patch.name, bundle.name)) - except Exception: - pass - - bundle.save() - - return [] - -def send_notifications(): - date_limit = datetime.datetime.now() - \ - datetime.timedelta(minutes = - settings.NOTIFICATION_DELAY_MINUTES) - - # This gets funky: we want to filter out any notifications that should - # be grouped with other notifications that aren't ready to go out yet. To - # do that, we join back onto PatchChangeNotification (PCN -> Patch -> - # Person -> Patch -> max(PCN.last_modified)), filtering out any maxima - # that are with the date_limit. - qs = PatchChangeNotification.objects \ - .annotate(m = Max('patch__submitter__patch__patchchangenotification' - '__last_modified')) \ - .filter(m__lt = date_limit) - - groups = itertools.groupby(qs.order_by('patch__submitter'), - lambda n: n.patch.submitter) - - errors = [] - - for (recipient, notifications) in groups: - notifications = list(notifications) - projects = set([ n.patch.project.linkname for n in notifications ]) - - def delete_notifications(): - pks = [ n.pk for n in notifications ] - PatchChangeNotification.objects.filter(pk__in = pks).delete() - - if EmailOptout.is_optout(recipient.email): - delete_notifications() - continue - - context = { - 'site': Site.objects.get_current(), - 'person': recipient, - 'notifications': notifications, - 'projects': projects, - } - - subject = render_to_string( - 'patchwork/patch-change-notification-subject.text', - context).strip() - content = render_to_string('patchwork/patch-change-notification.mail', - context) - - message = EmailMessage(subject = subject, body = content, - from_email = settings.NOTIFICATION_FROM_EMAIL, - to = [recipient.email], - headers = {'Precedence': 'bulk'}) - - try: - message.send() - except ex: - errors.append((recipient, ex)) - continue - - delete_notifications() - - return errors - -def do_expiry(): - # expire any pending confirmations - q = (Q(date__lt = datetime.datetime.now() - EmailConfirmation.validity) | - Q(active = False)) - EmailConfirmation.objects.filter(q).delete() - - # expire inactive users with no pending confirmation - pending_confs = EmailConfirmation.objects.values('user') - users = User.objects.filter( - is_active = False, - last_login = F('date_joined') - ).exclude( - id__in = pending_confs - ) - - # delete users - users.delete() - - - diff --git a/apps/patchwork/views/__init__.py b/apps/patchwork/views/__init__.py deleted file mode 100644 index dfca56d..0000000 --- a/apps/patchwork/views/__init__.py +++ /dev/null @@ -1,220 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from base import * -from patchwork.utils import Order, get_patch_ids, bundle_actions, set_bundle -from patchwork.paginator import Paginator -from patchwork.forms import MultiplePatchForm -from patchwork.models import Comment -import re -import datetime - -try: - from email.mime.nonmultipart import MIMENonMultipart - from email.encoders import encode_7or8bit - from email.parser import HeaderParser - from email.header import Header - import email.utils -except ImportError: - # Python 2.4 compatibility - from email.MIMENonMultipart import MIMENonMultipart - from email.Encoders import encode_7or8bit - from email.Parser import HeaderParser - from email.Header import Header - import email.Utils - email.utils = email.Utils - -def generic_list(request, project, view, - view_args = {}, filter_settings = [], patches = None, - editable_order = False): - - context = PatchworkRequestContext(request, - list_view = view, - list_view_params = view_args) - - context.project = project - order = Order(request.REQUEST.get('order'), editable = editable_order) - - # Explicitly set data to None because request.POST will be an empty dict - # when the form is not submitted, but passing a non-None data argument to - # a forms.Form will make it bound and we don't want that to happen unless - # there's been a form submission. - data = None - if request.method == 'POST': - data = request.POST - user = request.user - properties_form = None - if project.is_editable(user): - - # we only pass the post data to the MultiplePatchForm if that was - # the actual form submitted - data_tmp = None - if data and data.get('form', '') == 'patchlistform': - data_tmp = data - - properties_form = MultiplePatchForm(project, data = data_tmp) - - if request.method == 'POST' and data.get('form') == 'patchlistform': - action = data.get('action', '').lower() - - # special case: the user may have hit enter in the 'create bundle' - # text field, so if non-empty, assume the create action: - if data.get('bundle_name', False): - action = 'create' - - ps = Patch.objects.filter(id__in = get_patch_ids(data)) - - if action in bundle_actions: - errors = set_bundle(user, project, action, data, ps, context) - - elif properties_form and action == properties_form.action: - errors = process_multiplepatch_form(properties_form, user, - action, ps, context) - else: - errors = [] - - if errors: - context['errors'] = errors - - for (filterclass, setting) in filter_settings: - if isinstance(setting, dict): - context.filters.set_status(filterclass, **setting) - elif isinstance(setting, list): - context.filters.set_status(filterclass, *setting) - else: - context.filters.set_status(filterclass, setting) - - if patches is None: - patches = Patch.objects.filter(project=project) - - patches = context.filters.apply(patches) - if not editable_order: - patches = order.apply(patches) - - # we don't need the content or headers for a list; they're text fields - # that can potentially contain a lot of data - patches = patches.defer('content', 'headers') - - # but we will need to follow the state and submitter relations for - # rendering the list template - patches = patches.select_related('state', 'submitter') - - paginator = Paginator(request, patches) - - context.update({ - 'page': paginator.current_page, - 'patchform': properties_form, - 'project': project, - 'order': order, - }) - - return context - - -def process_multiplepatch_form(form, user, action, patches, context): - errors = [] - if not form.is_valid() or action != form.action: - return ['The submitted form data was invalid'] - - if len(patches) == 0: - context.add_message("No patches selected; nothing updated") - return errors - - changed_patches = 0 - for patch in patches: - if not patch.is_editable(user): - errors.append("You don't have permissions to edit patch '%s'" - % patch.name) - continue - - changed_patches += 1 - form.save(patch) - - if changed_patches == 1: - context.add_message("1 patch updated") - elif changed_patches > 1: - context.add_message("%d patches updated" % changed_patches) - else: - context.add_message("No patches updated") - - return errors - -class PatchMbox(MIMENonMultipart): - patch_charset = 'utf-8' - def __init__(self, _text): - MIMENonMultipart.__init__(self, 'text', 'plain', - **{'charset': self.patch_charset}) - self.set_payload(_text.encode(self.patch_charset)) - encode_7or8bit(self) - -def patch_to_mbox(patch): - postscript_re = re.compile('\n-{2,3} ?\n') - - comment = None - try: - comment = Comment.objects.get(patch = patch, msgid = patch.msgid) - except Exception: - pass - - body = '' - if comment: - body = comment.content.strip() + "\n" - - parts = postscript_re.split(body, 1) - if len(parts) == 2: - (body, postscript) = parts - body = body.strip() + "\n" - postscript = postscript.rstrip() - else: - postscript = '' - - for comment in Comment.objects.filter(patch = patch) \ - .exclude(msgid = patch.msgid): - body += comment.patch_responses() - - if postscript: - body += '---\n' + postscript + '\n' - - if patch.content: - body += '\n' + patch.content - - delta = patch.date - datetime.datetime.utcfromtimestamp(0) - utc_timestamp = delta.seconds + delta.days*24*3600 - - mail = PatchMbox(body) - mail['Subject'] = patch.name - mail['From'] = email.utils.formataddr(( - str(Header(patch.submitter.name, mail.patch_charset)), - patch.submitter.email)) - mail['X-Patchwork-Id'] = str(patch.id) - mail['Message-Id'] = patch.msgid - mail.set_unixfrom('From patchwork ' + patch.date.ctime()) - - - copied_headers = ['To', 'Cc', 'Date'] - orig_headers = HeaderParser().parsestr(str(patch.headers)) - for header in copied_headers: - if header in orig_headers: - mail[header] = orig_headers[header] - - if 'Date' not in mail: - mail['Date'] = email.utils.formatdate(utc_timestamp) - - return mail diff --git a/apps/patchwork/views/base.py b/apps/patchwork/views/base.py deleted file mode 100644 index 6d7dd13..0000000 --- a/apps/patchwork/views/base.py +++ /dev/null @@ -1,122 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from patchwork.models import Patch, Project, Person, EmailConfirmation -from django.shortcuts import render_to_response, get_object_or_404 -from django.http import HttpResponse, HttpResponseRedirect, Http404 -from patchwork.requestcontext import PatchworkRequestContext -from django.core import serializers, urlresolvers -from django.template.loader import render_to_string -from django.conf import settings -from django.db.models import Q - -def projects(request): - context = PatchworkRequestContext(request) - projects = Project.objects.all() - - if projects.count() == 1: - return HttpResponseRedirect( - urlresolvers.reverse('patchwork.views.patch.list', - kwargs = {'project_id': projects[0].linkname})) - - context['projects'] = projects - return render_to_response('patchwork/projects.html', context) - -def pwclientrc(request, project_id): - project = get_object_or_404(Project, linkname = project_id) - context = PatchworkRequestContext(request) - context.project = project - if settings.FORCE_HTTPS_LINKS or request.is_secure(): - context['scheme'] = 'https' - else: - context['scheme'] = 'http' - response = HttpResponse(content_type = "text/plain") - response['Content-Disposition'] = 'attachment; filename=.pwclientrc' - response.write(render_to_string('patchwork/pwclientrc', context)) - return response - -def pwclient(request): - context = PatchworkRequestContext(request) - response = HttpResponse(content_type = "text/x-python") - response['Content-Disposition'] = 'attachment; filename=pwclient' - response.write(render_to_string('patchwork/pwclient', context)) - return response - -def confirm(request, key): - import patchwork.views.user, patchwork.views.mail - views = { - 'userperson': patchwork.views.user.link_confirm, - 'registration': patchwork.views.user.register_confirm, - 'optout': patchwork.views.mail.optout_confirm, - 'optin': patchwork.views.mail.optin_confirm, - } - - conf = get_object_or_404(EmailConfirmation, key = key) - if conf.type not in views: - raise Http404 - - if conf.active and conf.is_valid(): - return views[conf.type](request, conf) - - context = PatchworkRequestContext(request) - context['conf'] = conf - if not conf.active: - context['error'] = 'inactive' - elif not conf.is_valid(): - context['error'] = 'expired' - - return render_to_response('patchwork/confirm-error.html', context) - -def submitter_complete(request): - search = request.GET.get('q', '') - limit = request.GET.get('l', None) - response = HttpResponse(content_type = "text/plain") - - if len(search) <= 3: - return response - - queryset = Person.objects.filter(Q(name__icontains = search) | - Q(email__icontains = search)) - if limit is not None: - try: - limit = int(limit) - except ValueError: - limit = None - - if limit is not None and limit > 0: - queryset = queryset[:limit] - - json_serializer = serializers.get_serializer("json")() - json_serializer.serialize(queryset, ensure_ascii=False, stream=response) - return response - -help_pages = {'': 'index.html', - 'about/': 'about.html', - } - -if settings.ENABLE_XMLRPC: - help_pages['pwclient/'] = 'pwclient.html' - -def help(request, path): - context = PatchworkRequestContext(request) - if path in help_pages: - return render_to_response('patchwork/help/' + help_pages[path], context) - raise Http404 - diff --git a/apps/patchwork/views/bundle.py b/apps/patchwork/views/bundle.py deleted file mode 100644 index 3fb47e2..0000000 --- a/apps/patchwork/views/bundle.py +++ /dev/null @@ -1,221 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from django.contrib.auth.decorators import login_required -from django.contrib.auth.models import User -from django.shortcuts import render_to_response, get_object_or_404 -from patchwork.requestcontext import PatchworkRequestContext -from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound -import django.core.urlresolvers -from patchwork.models import Patch, Bundle, BundlePatch, Project -from patchwork.utils import get_patch_ids -from patchwork.forms import BundleForm, DeleteBundleForm -from patchwork.views import generic_list, patch_to_mbox -from patchwork.filters import DelegateFilter - -@login_required -def setbundle(request): - context = PatchworkRequestContext(request) - - bundle = None - - if request.method == 'POST': - action = request.POST.get('action', None) - if action is None: - pass - elif action == 'create': - project = get_object_or_404(Project, - id = request.POST.get('project')) - bundle = Bundle(owner = request.user, project = project, - name = request.POST['name']) - bundle.save() - patch_id = request.POST.get('patch_id', None) - if patch_id: - patch = get_object_or_404(Patch, id = patch_id) - try: - bundle.append_patch(patch) - except Exception: - pass - bundle.save() - elif action == 'add': - bundle = get_object_or_404(Bundle, - owner = request.user, id = request.POST['id']) - bundle.save() - - patch_id = request.get('patch_id', None) - if patch_id: - patch_ids = patch_id - else: - patch_ids = get_patch_ids(request.POST) - - for id in patch_ids: - try: - patch = Patch.objects.get(id = id) - bundle.append_patch(patch) - except: - pass - - bundle.save() - elif action == 'delete': - try: - bundle = Bundle.objects.get(owner = request.user, - id = request.POST['id']) - bundle.delete() - except Exception: - pass - - bundle = None - - else: - bundle = get_object_or_404(Bundle, owner = request.user, - id = request.POST['bundle_id']) - - if 'error' in context: - pass - - if bundle: - return HttpResponseRedirect( - django.core.urlresolvers.reverse( - 'patchwork.views.bundle.bundle', - kwargs = {'bundle_id': bundle.id} - ) - ) - else: - return HttpResponseRedirect( - django.core.urlresolvers.reverse( - 'patchwork.views.bundle.list') - ) - -@login_required -def bundles(request): - context = PatchworkRequestContext(request) - - if request.method == 'POST': - form_name = request.POST.get('form_name', '') - - if form_name == DeleteBundleForm.name: - form = DeleteBundleForm(request.POST) - if form.is_valid(): - bundle = get_object_or_404(Bundle, - id = form.cleaned_data['bundle_id']) - bundle.delete() - - bundles = Bundle.objects.filter(owner = request.user) - for bundle in bundles: - bundle.delete_form = DeleteBundleForm(auto_id = False, - initial = {'bundle_id': bundle.id}) - - context['bundles'] = bundles - - return render_to_response('patchwork/bundles.html', context) - -def bundle(request, username, bundlename): - bundle = get_object_or_404(Bundle, owner__username = username, - name = bundlename) - filter_settings = [(DelegateFilter, DelegateFilter.AnyDelegate)] - - is_owner = request.user == bundle.owner - - if not (is_owner or bundle.public): - return HttpResponseNotFound() - - if is_owner: - if request.method == 'POST' and request.POST.get('form') == 'bundle': - action = request.POST.get('action', '').lower() - if action == 'delete': - bundle.delete() - return HttpResponseRedirect( - django.core.urlresolvers.reverse( - 'patchwork.views.user.profile') - ) - elif action == 'update': - form = BundleForm(request.POST, instance = bundle) - if form.is_valid(): - form.save() - - # if we've changed the bundle name, redirect to new URL - bundle = Bundle.objects.get(pk = bundle.pk) - if bundle.name != bundlename: - return HttpResponseRedirect(bundle.get_absolute_url()) - - else: - form = BundleForm(instance = bundle) - else: - form = BundleForm(instance = bundle) - - if request.method == 'POST' and \ - request.POST.get('form') == 'reorderform': - order = get_object_or_404(BundlePatch, bundle = bundle, - patch__id = request.POST.get('order_start')).order - - for patch_id in request.POST.getlist('neworder'): - bundlepatch = get_object_or_404(BundlePatch, - bundle = bundle, patch__id = patch_id) - bundlepatch.order = order - bundlepatch.save() - order += 1 - else: - form = None - - context = generic_list(request, bundle.project, - 'patchwork.views.bundle.bundle', - view_args = {'username': bundle.owner.username, - 'bundlename': bundle.name}, - filter_settings = filter_settings, - patches = bundle.ordered_patches(), - editable_order = is_owner) - - context['bundle'] = bundle - context['bundleform'] = form - - return render_to_response('patchwork/bundle.html', context) - -def mbox(request, username, bundlename): - bundle = get_object_or_404(Bundle, owner__username = username, - name = bundlename) - - if not (request.user == bundle.owner or bundle.public): - return HttpResponseNotFound() - - mbox = '\n'.join([patch_to_mbox(p).as_string(True) - for p in bundle.ordered_patches()]) - - response = HttpResponse(content_type='text/plain') - response['Content-Disposition'] = \ - 'attachment; filename=bundle-%d-%s.mbox' % (bundle.id, bundle.name) - - response.write(mbox) - return response - -@login_required -def bundle_redir(request, bundle_id): - bundle = get_object_or_404(Bundle, id = bundle_id, owner = request.user) - return HttpResponseRedirect(bundle.get_absolute_url()) - -@login_required -def mbox_redir(request, bundle_id): - bundle = get_object_or_404(Bundle, id = bundle_id, owner = request.user) - return HttpResponseRedirect(django.core.urlresolvers.reverse( - 'patchwork.views.bundle.mbox', kwargs = { - 'username': request.user.username, - 'bundlename': bundle.name, - })) - - - diff --git a/apps/patchwork/views/mail.py b/apps/patchwork/views/mail.py deleted file mode 100644 index aebba34..0000000 --- a/apps/patchwork/views/mail.py +++ /dev/null @@ -1,119 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2010 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from patchwork.requestcontext import PatchworkRequestContext -from patchwork.models import EmailOptout, EmailConfirmation -from patchwork.forms import OptinoutRequestForm, EmailForm -from django.shortcuts import render_to_response -from django.template.loader import render_to_string -from django.conf import settings as conf_settings -from django.core.mail import send_mail -from django.core.urlresolvers import reverse -from django.http import HttpResponseRedirect - -def settings(request): - context = PatchworkRequestContext(request) - if request.method == 'POST': - form = EmailForm(data = request.POST) - if form.is_valid(): - email = form.cleaned_data['email'] - is_optout = EmailOptout.objects.filter(email = email).count() > 0 - context.update({ - 'email': email, - 'is_optout': is_optout, - }) - return render_to_response('patchwork/mail-settings.html', context) - - else: - form = EmailForm() - context['form'] = form - return render_to_response('patchwork/mail-form.html', context) - -def optout_confirm(request, conf): - context = PatchworkRequestContext(request) - - email = conf.email.strip().lower() - # silently ignore duplicated optouts - if EmailOptout.objects.filter(email = email).count() == 0: - optout = EmailOptout(email = email) - optout.save() - - conf.deactivate() - context['email'] = conf.email - - return render_to_response('patchwork/optout.html', context) - -def optin_confirm(request, conf): - context = PatchworkRequestContext(request) - - email = conf.email.strip().lower() - EmailOptout.objects.filter(email = email).delete() - - conf.deactivate() - context['email'] = conf.email - - return render_to_response('patchwork/optin.html', context) - -def optinout(request, action, description): - context = PatchworkRequestContext(request) - - mail_template = 'patchwork/%s-request.mail' % action - html_template = 'patchwork/%s-request.html' % action - - if request.method != 'POST': - return HttpResponseRedirect(reverse(settings)) - - form = OptinoutRequestForm(data = request.POST) - if not form.is_valid(): - context['error'] = ('There was an error in the %s form. ' + - 'Please review the form and re-submit.') % \ - description - context['form'] = form - return render_to_response(html_template, context) - - email = form.cleaned_data['email'] - if action == 'optin' and \ - EmailOptout.objects.filter(email = email).count() == 0: - context['error'] = ('The email address %s is not on the ' + - 'patchwork opt-out list, so you don\'t ' + - 'need to opt back in') % email - context['form'] = form - return render_to_response(html_template, context) - - conf = EmailConfirmation(type = action, email = email) - conf.save() - context['confirmation'] = conf - mail = render_to_string(mail_template, context) - try: - send_mail('Patchwork %s confirmation' % description, mail, - conf_settings.DEFAULT_FROM_EMAIL, [email]) - context['email'] = mail - context['email_sent'] = True - except Exception, ex: - context['error'] = 'An error occurred during confirmation . ' + \ - 'Please try again later.' - context['admins'] = conf_settings.ADMINS - - return render_to_response(html_template, context) - -def optout(request): - return optinout(request, 'optout', 'opt-out') - -def optin(request): - return optinout(request, 'optin', 'opt-in') diff --git a/apps/patchwork/views/patch.py b/apps/patchwork/views/patch.py deleted file mode 100644 index 62ff853..0000000 --- a/apps/patchwork/views/patch.py +++ /dev/null @@ -1,107 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from patchwork.models import Patch, Project, Bundle -from patchwork.forms import PatchForm, CreateBundleForm -from patchwork.requestcontext import PatchworkRequestContext -from django.shortcuts import render_to_response, get_object_or_404 -from django.http import HttpResponse, HttpResponseForbidden -from patchwork.views import generic_list, patch_to_mbox - -def patch(request, patch_id): - context = PatchworkRequestContext(request) - patch = get_object_or_404(Patch, id=patch_id) - context.project = patch.project - editable = patch.is_editable(request.user) - - form = None - createbundleform = None - - if editable: - form = PatchForm(instance = patch) - if request.user.is_authenticated(): - createbundleform = CreateBundleForm() - - if request.method == 'POST': - action = request.POST.get('action', None) - if action: - action = action.lower() - - if action == 'createbundle': - bundle = Bundle(owner = request.user, project = patch.project) - createbundleform = CreateBundleForm(instance = bundle, - data = request.POST) - if createbundleform.is_valid(): - createbundleform.save() - bundle.append_patch(patch) - bundle.save() - createbundleform = CreateBundleForm() - context.add_message('Bundle %s created' % bundle.name) - - elif action == 'addtobundle': - bundle = get_object_or_404(Bundle, id = \ - request.POST.get('bundle_id')) - try: - bundle.append_patch(patch) - bundle.save() - context.add_message('Patch added to bundle "%s"' % bundle.name) - except Exception, ex: - context.add_message("Couldn't add patch '%s' to bundle %s: %s" \ - % (patch.name, bundle.name, ex.message)) - - # all other actions require edit privs - elif not editable: - return HttpResponseForbidden() - - elif action is None: - form = PatchForm(data = request.POST, instance = patch) - if form.is_valid(): - form.save() - context.add_message('Patch updated') - - context['patch'] = patch - context['patchform'] = form - context['createbundleform'] = createbundleform - context['project'] = patch.project - - return render_to_response('patchwork/patch.html', context) - -def content(request, patch_id): - patch = get_object_or_404(Patch, id=patch_id) - response = HttpResponse(content_type="text/x-patch") - response.write(patch.content) - response['Content-Disposition'] = 'attachment; filename=' + \ - patch.filename().replace(';', '').replace('\n', '') - return response - -def mbox(request, patch_id): - patch = get_object_or_404(Patch, id=patch_id) - response = HttpResponse(content_type="text/plain") - response.write(patch_to_mbox(patch).as_string(True)) - response['Content-Disposition'] = 'attachment; filename=' + \ - patch.filename().replace(';', '').replace('\n', '') - return response - - -def list(request, project_id): - project = get_object_or_404(Project, linkname=project_id) - context = generic_list(request, project, 'patchwork.views.patch.list', - view_args = {'project_id': project.linkname}) - return render_to_response('patchwork/list.html', context) diff --git a/apps/patchwork/views/project.py b/apps/patchwork/views/project.py deleted file mode 100644 index 114dbe0..0000000 --- a/apps/patchwork/views/project.py +++ /dev/null @@ -1,38 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2009 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from patchwork.models import Patch, Project -from django.shortcuts import render_to_response, get_object_or_404 -from django.contrib.auth.models import User -from patchwork.requestcontext import PatchworkRequestContext - -def project(request, project_id): - context = PatchworkRequestContext(request) - project = get_object_or_404(Project, linkname = project_id) - context.project = project - - context['maintainers'] = User.objects.filter( \ - profile__maintainer_projects = project) - context['n_patches'] = Patch.objects.filter(project = project, - archived = False).count() - context['n_archived_patches'] = Patch.objects.filter(project = project, - archived = True).count() - - return render_to_response('patchwork/project.html', context) diff --git a/apps/patchwork/views/user.py b/apps/patchwork/views/user.py deleted file mode 100644 index 126ecc9..0000000 --- a/apps/patchwork/views/user.py +++ /dev/null @@ -1,216 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -from django.contrib.auth.decorators import login_required -from patchwork.requestcontext import PatchworkRequestContext -from django.shortcuts import render_to_response, get_object_or_404 -from django.contrib import auth -from django.contrib.sites.models import Site -from django.http import HttpResponseRedirect -from patchwork.models import Project, Bundle, Person, EmailConfirmation, \ - State, EmailOptout -from patchwork.forms import UserProfileForm, UserPersonLinkForm, \ - RegistrationForm -from patchwork.filters import DelegateFilter -from patchwork.views import generic_list -from django.template.loader import render_to_string -from django.conf import settings -from django.core.mail import send_mail -import django.core.urlresolvers - -def register(request): - context = PatchworkRequestContext(request) - if request.method == 'POST': - form = RegistrationForm(request.POST) - if form.is_valid(): - data = form.cleaned_data - # create inactive user - user = auth.models.User.objects.create_user(data['username'], - data['email'], - data['password']) - user.is_active = False; - user.first_name = data.get('first_name', '') - user.last_name = data.get('last_name', '') - user.save() - - # create confirmation - conf = EmailConfirmation(type = 'registration', user = user, - email = user.email) - conf.save() - - # send email - mail_ctx = {'site': Site.objects.get_current(), - 'confirmation': conf} - - subject = render_to_string('patchwork/activation_email_subject.txt', - mail_ctx).replace('\n', ' ').strip() - - message = render_to_string('patchwork/activation_email.txt', - mail_ctx) - - send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, - [conf.email]) - - # setting 'confirmation' in the template indicates success - context['confirmation'] = conf - - else: - form = RegistrationForm() - - return render_to_response('patchwork/registration_form.html', - { 'form': form }, - context_instance=context) - -def register_confirm(request, conf): - conf.user.is_active = True - conf.user.save() - conf.deactivate() - try: - person = Person.objects.get(email__iexact = conf.user.email) - except Person.DoesNotExist: - person = Person(email = conf.user.email, - name = conf.user.profile.name()) - person.user = conf.user - person.save() - - return render_to_response('patchwork/registration-confirm.html') - -@login_required -def profile(request): - context = PatchworkRequestContext(request) - - if request.method == 'POST': - form = UserProfileForm(instance = request.user.profile, - data = request.POST) - if form.is_valid(): - form.save() - else: - form = UserProfileForm(instance = request.user.profile) - - context.project = request.user.profile.primary_project - context['bundles'] = Bundle.objects.filter(owner = request.user) - context['profileform'] = form - - optout_query = '%s.%s IN (SELECT %s FROM %s)' % ( - Person._meta.db_table, - Person._meta.get_field('email').column, - EmailOptout._meta.get_field('email').column, - EmailOptout._meta.db_table) - people = Person.objects.filter(user = request.user) \ - .extra(select = {'is_optout': optout_query}) - context['linked_emails'] = people - context['linkform'] = UserPersonLinkForm() - - return render_to_response('patchwork/profile.html', context) - -@login_required -def link(request): - context = PatchworkRequestContext(request) - - if request.method == 'POST': - form = UserPersonLinkForm(request.POST) - if form.is_valid(): - conf = EmailConfirmation(type = 'userperson', - user = request.user, - email = form.cleaned_data['email']) - conf.save() - context['confirmation'] = conf - - try: - send_mail('Patchwork email address confirmation', - render_to_string('patchwork/user-link.mail', - context), - settings.DEFAULT_FROM_EMAIL, - [form.cleaned_data['email']]) - except Exception: - context['confirmation'] = None - context['error'] = 'An error occurred during confirmation. ' + \ - 'Please try again later' - else: - form = UserPersonLinkForm() - context['linkform'] = form - - return render_to_response('patchwork/user-link.html', context) - -@login_required -def link_confirm(request, conf): - context = PatchworkRequestContext(request) - - try: - person = Person.objects.get(email__iexact = conf.email) - except Person.DoesNotExist: - person = Person(email = conf.email) - - person.link_to_user(conf.user) - person.save() - conf.deactivate() - - context['person'] = person - - return render_to_response('patchwork/user-link-confirm.html', context) - -@login_required -def unlink(request, person_id): - person = get_object_or_404(Person, id = person_id) - - if request.method == 'POST': - if person.email != request.user.email: - person.user = None - person.save() - - url = django.core.urlresolvers.reverse('patchwork.views.user.profile') - return HttpResponseRedirect(url) - - -@login_required -def todo_lists(request): - todo_lists = [] - - for project in Project.objects.all(): - patches = request.user.profile.todo_patches(project = project) - if not patches.count(): - continue - - todo_lists.append({'project': project, 'n_patches': patches.count()}) - - if len(todo_lists) == 1: - return todo_list(request, todo_lists[0]['project'].linkname) - - context = PatchworkRequestContext(request) - context['todo_lists'] = todo_lists - context.project = request.user.profile.primary_project - return render_to_response('patchwork/todo-lists.html', context) - -@login_required -def todo_list(request, project_id): - project = get_object_or_404(Project, linkname = project_id) - patches = request.user.profile.todo_patches(project = project) - filter_settings = [(DelegateFilter, - {'delegate': request.user})] - - context = generic_list(request, project, - 'patchwork.views.user.todo_list', - view_args = {'project_id': project.linkname}, - filter_settings = filter_settings, - patches = patches) - - context['action_required_states'] = \ - State.objects.filter(action_required = True).all() - return render_to_response('patchwork/todo-list.html', context) diff --git a/apps/patchwork/views/xmlrpc.py b/apps/patchwork/views/xmlrpc.py deleted file mode 100644 index 84ed408..0000000 --- a/apps/patchwork/views/xmlrpc.py +++ /dev/null @@ -1,450 +0,0 @@ -# Patchwork - automated patch tracking system -# Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org> -# -# This file is part of the Patchwork package. -# -# Patchwork is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Patchwork is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Patchwork; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Patchwork XMLRPC interface -# - -from SimpleXMLRPCServer import SimpleXMLRPCDispatcher -from django.http import HttpResponse, HttpResponseRedirect, \ - HttpResponseServerError -from django.core import urlresolvers -from django.contrib.auth import authenticate -from patchwork.models import Patch, Project, Person, State -from patchwork.views import patch_to_mbox -from django.views.decorators.csrf import csrf_exempt - -import sys -import base64 -import xmlrpclib - -class PatchworkXMLRPCDispatcher(SimpleXMLRPCDispatcher): - def __init__(self): - if sys.version_info[:3] >= (2,5,): - SimpleXMLRPCDispatcher.__init__(self, allow_none=False, - encoding=None) - def _dumps(obj, *args, **kwargs): - kwargs['allow_none'] = self.allow_none - kwargs['encoding'] = self.encoding - return xmlrpclib.dumps(obj, *args, **kwargs) - else: - def _dumps(obj, *args, **kwargs): - return xmlrpclib.dumps(obj, *args, **kwargs) - SimpleXMLRPCDispatcher.__init__(self) - - self.dumps = _dumps - - # map of name => (auth, func) - self.func_map = {} - - def register_function(self, fn, auth_required): - self.func_map[fn.__name__] = (auth_required, fn) - - - def _user_for_request(self, request): - auth_header = None - - if 'HTTP_AUTHORIZATION' in request.META: - auth_header = request.META.get('HTTP_AUTHORIZATION') - elif 'Authorization' in request.META: - auth_header = request.META.get('Authorization') - - if auth_header is None or auth_header == '': - raise Exception("No authentication credentials given") - - str = auth_header.strip() - - if not str.startswith('Basic '): - raise Exception("Authentication scheme not supported") - - str = str[len('Basic '):].strip() - - try: - decoded = base64.decodestring(str) - username, password = decoded.split(':', 1) - except: - raise Exception("Invalid authentication credentials") - - return authenticate(username = username, password = password) - - - def _dispatch(self, request, method, params): - if method not in self.func_map.keys(): - raise Exception('method "%s" is not supported' % method) - - auth_required, fn = self.func_map[method] - - if auth_required: - user = self._user_for_request(request) - if not user: - raise Exception("Invalid username/password") - - params = (user,) + params - - return fn(*params) - - def _marshaled_dispatch(self, request): - try: - params, method = xmlrpclib.loads(request.body) - - response = self._dispatch(request, method, params) - # wrap response in a singleton tuple - response = (response,) - response = self.dumps(response, methodresponse=1) - except xmlrpclib.Fault, fault: - response = self.dumps(fault) - except: - # report exception back to server - response = self.dumps( - xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), - ) - - return response - -dispatcher = PatchworkXMLRPCDispatcher() - -# XMLRPC view function -@csrf_exempt -def xmlrpc(request): - if request.method != 'POST': - return HttpResponseRedirect( - urlresolvers.reverse('patchwork.views.help', - kwargs = {'path': 'pwclient/'})) - - response = HttpResponse() - try: - ret = dispatcher._marshaled_dispatch(request) - response.write(ret) - except Exception: - return HttpResponseServerError() - - return response - -# decorator for XMLRPC methods. Setting login_required to true will call -# the decorated function with a non-optional user as the first argument. -def xmlrpc_method(login_required = False): - def wrap(f): - dispatcher.register_function(f, login_required) - return f - - return wrap - - - -# We allow most of the Django field lookup types for remote queries -LOOKUP_TYPES = ["iexact", "contains", "icontains", "gt", "gte", "lt", - "in", "startswith", "istartswith", "endswith", - "iendswith", "range", "year", "month", "day", "isnull" ] - -####################################################################### -# Helper functions -####################################################################### - -def project_to_dict(obj): - """Return a trimmed down dictionary representation of a Project - object which is OK to send to the client.""" - return \ - { - 'id' : obj.id, - 'linkname' : obj.linkname, - 'name' : obj.name, - } - -def person_to_dict(obj): - """Return a trimmed down dictionary representation of a Person - object which is OK to send to the client.""" - - # Make sure we don't return None even if the user submitted a patch - # with no real name. XMLRPC can't marshall None. - if obj.name is not None: - name = obj.name - else: - name = obj.email - - return \ - { - 'id' : obj.id, - 'email' : obj.email, - 'name' : name, - 'user' : unicode(obj.user).encode("utf-8"), - } - -def patch_to_dict(obj): - """Return a trimmed down dictionary representation of a Patch - object which is OK to send to the client.""" - return \ - { - 'id' : obj.id, - 'date' : unicode(obj.date).encode("utf-8"), - 'filename' : obj.filename(), - 'msgid' : obj.msgid, - 'name' : obj.name, - 'project' : unicode(obj.project).encode("utf-8"), - 'project_id' : obj.project_id, - 'state' : unicode(obj.state).encode("utf-8"), - 'state_id' : obj.state_id, - 'archived' : obj.archived, - 'submitter' : unicode(obj.submitter).encode("utf-8"), - 'submitter_id' : obj.submitter_id, - 'delegate' : unicode(obj.delegate).encode("utf-8"), - 'delegate_id' : max(obj.delegate_id, 0), - 'commit_ref' : max(obj.commit_ref, ''), - } - -def bundle_to_dict(obj): - """Return a trimmed down dictionary representation of a Bundle - object which is OK to send to the client.""" - return \ - { - 'id' : obj.id, - 'name' : obj.name, - 'n_patches' : obj.n_patches(), - 'public_url' : obj.public_url(), - } - -def state_to_dict(obj): - """Return a trimmed down dictionary representation of a State - object which is OK to send to the client.""" - return \ - { - 'id' : obj.id, - 'name' : obj.name, - } - -####################################################################### -# Public XML-RPC methods -####################################################################### - -@xmlrpc_method(False) -def pw_rpc_version(): - """Return Patchwork XML-RPC interface version.""" - return 1 - -@xmlrpc_method(False) -def project_list(search_str="", max_count=0): - """Get a list of projects matching the given filters.""" - try: - if len(search_str) > 0: - projects = Project.objects.filter(linkname__icontains = search_str) - else: - projects = Project.objects.all() - - if max_count > 0: - return map(project_to_dict, projects)[:max_count] - else: - return map(project_to_dict, projects) - except: - return [] - -@xmlrpc_method(False) -def project_get(project_id): - """Return structure for the given project ID.""" - try: - project = Project.objects.filter(id = project_id)[0] - return project_to_dict(project) - except: - return {} - -@xmlrpc_method(False) -def person_list(search_str="", max_count=0): - """Get a list of Person objects matching the given filters.""" - try: - if len(search_str) > 0: - people = (Person.objects.filter(name__icontains = search_str) | - Person.objects.filter(email__icontains = search_str)) - else: - people = Person.objects.all() - - if max_count > 0: - return map(person_to_dict, people)[:max_count] - else: - return map(person_to_dict, people) - - except: - return [] - -@xmlrpc_method(False) -def person_get(person_id): - """Return structure for the given person ID.""" - try: - person = Person.objects.filter(id = person_id)[0] - return person_to_dict(person) - except: - return {} - -@xmlrpc_method(False) -def patch_list(filter={}): - """Get a list of patches matching the given filters.""" - try: - # We allow access to many of the fields. But, some fields are - # filtered by raw object so we must lookup by ID instead over - # XML-RPC. - ok_fields = [ - "id", - "name", - "project_id", - "submitter_id", - "delegate_id", - "archived", - "state_id", - "date", - "commit_ref", - "hash", - "msgid", - "max_count", - ] - - dfilter = {} - max_count = 0 - - for key in filter: - parts = key.split("__") - if parts[0] not in ok_fields: - # Invalid field given - return [] - if len(parts) > 1: - if LOOKUP_TYPES.count(parts[1]) == 0: - # Invalid lookup type given - return [] - - if parts[0] == 'project_id': - dfilter['project'] = Project.objects.filter(id = - filter[key])[0] - elif parts[0] == 'submitter_id': - dfilter['submitter'] = Person.objects.filter(id = - filter[key])[0] - elif parts[0] == 'delegate_id': - dfilter['delegate'] = Person.objects.filter(id = - filter[key])[0] - elif parts[0] == 'state_id': - dfilter['state'] = State.objects.filter(id = - filter[key])[0] - elif parts[0] == 'max_count': - max_count = filter[key] - else: - dfilter[key] = filter[key] - - patches = Patch.objects.filter(**dfilter) - - if max_count > 0: - return map(patch_to_dict, patches[:max_count]) - else: - return map(patch_to_dict, patches) - - except: - return [] - -@xmlrpc_method(False) -def patch_get(patch_id): - """Return structure for the given patch ID.""" - try: - patch = Patch.objects.filter(id = patch_id)[0] - return patch_to_dict(patch) - except: - return {} - -@xmlrpc_method(False) -def patch_get_by_hash(hash): - """Return structure for the given patch hash.""" - try: - patch = Patch.objects.filter(hash = hash)[0] - return patch_to_dict(patch) - except: - return {} - -@xmlrpc_method(False) -def patch_get_by_project_hash(project, hash): - """Return structure for the given patch hash.""" - try: - patch = Patch.objects.filter(project__linkname = project, - hash = hash)[0] - return patch_to_dict(patch) - except: - return {} - -@xmlrpc_method(False) -def patch_get_mbox(patch_id): - """Return mbox string for the given patch ID.""" - try: - patch = Patch.objects.filter(id = patch_id)[0] - return patch_to_mbox(patch).as_string(True) - except: - return "" - -@xmlrpc_method(False) -def patch_get_diff(patch_id): - """Return diff for the given patch ID.""" - try: - patch = Patch.objects.filter(id = patch_id)[0] - return patch.content - except: - return "" - -@xmlrpc_method(True) -def patch_set(user, patch_id, params): - """Update a patch with the key,value pairs in params. Only some parameters - can be set""" - try: - ok_params = ['state', 'commit_ref', 'archived'] - - patch = Patch.objects.get(id = patch_id) - - if not patch.is_editable(user): - raise Exception('No permissions to edit this patch') - - for (k, v) in params.iteritems(): - if k not in ok_params: - continue - - if k == 'state': - patch.state = State.objects.get(id = v) - - else: - setattr(patch, k, v) - - patch.save() - - return True - - except: - raise - -@xmlrpc_method(False) -def state_list(search_str="", max_count=0): - """Get a list of state structures matching the given search string.""" - try: - if len(search_str) > 0: - states = State.objects.filter(name__icontains = search_str) - else: - states = State.objects.all() - - if max_count > 0: - return map(state_to_dict, states)[:max_count] - else: - return map(state_to_dict, states) - except: - return [] - -@xmlrpc_method(False) -def state_get(state_id): - """Return structure for the given state ID.""" - try: - state = State.objects.filter(id = state_id)[0] - return state_to_dict(state) - except: - return {} |