~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/webapp/filesystem/diff/__init__.py

  • Committer: William Grant
  • Date: 2009-02-23 23:47:02 UTC
  • mfrom: (1099.1.211 new-dispatch)
  • Revision ID: grantw@unimelb.edu.au-20090223234702-db4b1llly46ignwo
Merge from lp:~ivle-dev/ivle/new-dispatch.

Pretty much everything changes. Reread the setup docs. Backup your databases.
Every file is now in a different installed location, the configuration system
is rewritten, the dispatch system is rewritten, URLs are different, the
database is different, worksheets and exercises are no longer on the
filesystem, we use a templating engine, jail service protocols are rewritten,
we don't repeat ourselves, we have authorization rewritten, phpBB is gone,
and probably lots of other things that I cannot remember.

This is certainly the biggest commit I have ever made, and hopefully
the largest I ever will.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# IVLE
2
 
# Copyright (C) 2007-2008 The University of Melbourne
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2009 The University of Melbourne
3
3
#
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 
18
 
# App: Diff Service
19
 
# Author: David Coles
20
 
# Date: 21/2/2008
21
 
 
22
 
# This app is a wrapper around the diff script run through the trampoline
23
 
 
24
 
import os.path
 
18
# Author: David Coles, Will Grant
 
19
 
 
20
'''Components of the webapp for diffing user files.'''
 
21
 
 
22
import os
 
23
import re
 
24
import cgi
 
25
 
 
26
import cjson
 
27
import genshi
25
28
 
26
29
import ivle.conf
27
30
import ivle.interpret
28
 
 
29
 
 
30
 
# handle_with_trampoline controls the way in which fileservice_lib is invoked.
31
 
# If False, it will simply be called directly by this handler.
32
 
# If True, the request will get marshalled into a CGI environment and the
33
 
# trampoline will invoke services/fileservices within the user's jail (SetUID'd
34
 
# to them). This script will then wrap the CGI environment in a replica of the
35
 
# original environment and handle it that way.
36
 
# This is a lot of overhead but it's the only way to properly ensure we are
37
 
# acting "as" that user and therefore we don't run into permissions problems.
38
 
# If set to True, it will be a lot more efficient, but there will be
39
 
# permissions issues unless all user's files are owned by the web server user.
40
 
HANDLE_WITH_TRAMPOLINE = True
41
 
 
42
 
diffservice_path = os.path.join(ivle.conf.share_path, 'services/diffservice')
43
 
 
44
 
def handle(req):
45
 
    """Handler for the File Services application."""
46
 
    req.styles = ["media/diff/diff.css"] # CSS styles
47
 
    req.write_html_head_foot = True     # Have dispatch print head and foot
48
 
 
49
 
    # Handle
50
 
    if not HANDLE_WITH_TRAMPOLINE:
51
 
        pass
52
 
    else:
53
 
        if req.path == "":
54
 
            req.throw_redirect(os.path.join(req.uri,req.user.login));
55
 
        interp_object = ivle.interpret.interpreter_objects["cgi-python"]
56
 
        user_jail_dir = os.path.join(ivle.conf.jail_base, req.user.login)
57
 
        ivle.interpret.interpret_file(req, req.user, user_jail_dir,
58
 
            diffservice_path, interp_object)
59
 
 
 
31
from ivle.webapp.base.xhtml import XHTMLView
 
32
from ivle.webapp.base.plugins import ViewPlugin, MediaPlugin
 
33
from ivle.webapp.errors import NotFound, BadRequest
 
34
 
 
35
class DiffView(XHTMLView):
 
36
    '''A view to present a nice XHTML Subversion diff from a user's jail.'''
 
37
    template = 'template.html'
 
38
 
 
39
    def __init__(self, req, path):
 
40
        self.path = path
 
41
 
 
42
    def authorize(self, req):
 
43
        return req.user is not None
 
44
 
 
45
    def populate(self, req, ctx):
 
46
        self.plugin_styles[Plugin] = ['diff.css']
 
47
 
 
48
        revfields = req.get_fieldstorage().getlist("r")
 
49
        if len(revfields) > 2:
 
50
            raise BadRequest('A maximum of two revisions can be given.')
 
51
 
 
52
        revs = [revfield.value for revfield in revfields]
 
53
 
 
54
        jail_dir = os.path.join(ivle.conf.jail_base, req.user.login)
 
55
        (out, err) = ivle.interpret.execute_raw(req.user, jail_dir, '/home',
 
56
                    os.path.join(ivle.conf.share_path, 'services/diffservice'),
 
57
                    [self.path] + revs)
 
58
        assert not err
 
59
 
 
60
        response = cjson.decode(out)
 
61
        if 'error' in response:
 
62
            if response['error'] == 'notfound':
 
63
                raise NotFound()
 
64
            else:
 
65
                raise AssertionError('Unknown error from diffservice: %s' %
 
66
                                     response['error'])
 
67
 
 
68
        # No error. We must be safe.
 
69
        diff = response['diff']
 
70
 
 
71
        # Split up the udiff into individual files
 
72
        diff_matcher = re.compile(
 
73
            r'^Index: (.*)\n\=+\n((?:[^I].*\n)*)',re.MULTILINE
 
74
        )
 
75
 
 
76
        # Create a dict with (name, HTMLdiff) pairs for each non-empty diff.
 
77
        ctx['files'] = dict([(fd[0], genshi.XML(htmlfy_diff(fd[1])))
 
78
                             for fd in diff_matcher.findall(diff)
 
79
                             if fd[1]])
 
80
 
 
81
 
 
82
def htmlfy_diff(difftext):
 
83
    """Adds HTML markup to a udiff string"""
 
84
    output = cgi.escape(difftext)
 
85
    subs = {
 
86
     r'^([\+\-]{3})\s(\S+)\s\((.+)\)$':
 
87
         r'<span class="diff-files">\1 \2 <em>(\3)</em></span>',
 
88
     r'^\@\@ (.*) \@\@$':
 
89
         r'<span class="diff-range">@@ \1 @@</span>',
 
90
     r'^\+(.*)$':
 
91
         r'<span class="diff-add">+\1</span>',
 
92
     r'^\-(.*)$':
 
93
         r'<span class="diff-sub">-\1</span>',
 
94
     r'^\\(.*)$':
 
95
         r'<span class="diff-special">\\\1</span>'
 
96
    }
 
97
 
 
98
    for match in subs:
 
99
        output = re.compile(match, re.MULTILINE).sub(subs[match], output)
 
100
 
 
101
    return '<pre class="diff">%s</pre>' % output
 
102
 
 
103
class Plugin(ViewPlugin, MediaPlugin):
 
104
    '''Registration class for diff components.'''
 
105
    urls = [
 
106
        ('diff/', DiffView, {'path': ''}),
 
107
        ('diff/*(path)', DiffView),
 
108
    ]
 
109
 
 
110
    media = 'media'