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

« back to all changes in this revision

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

ivle.webapp.filesystem.diff: Port www/apps/diff to new framework. This moves
    all of the presentation logic into the app, with the service returning
    just a raw diff. This now runs the service using ivle.interpret#execute_raw

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
import os
 
21
import re
 
22
import cgi
 
23
 
 
24
import cjson
 
25
import genshi
25
26
 
26
27
import ivle.conf
27
28
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
 
29
from ivle.webapp.base.xhtml import XHTMLView
 
30
from ivle.webapp.base.plugins import BasePlugin
 
31
from ivle.webapp.errors import NotFound
41
32
 
42
33
diffservice_path = os.path.join(ivle.conf.share_path, 'services/diffservice')
43
34
 
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"]
 
35
class DiffView(XHTMLView):
 
36
    template = 'template.html'
 
37
 
 
38
    def populate(self, req, ctx):
 
39
        req.styles = ["/media/diff/diff.css"] # CSS styles
 
40
 
 
41
        revfields = req.get_fieldstorage().getlist("r")
 
42
        if len(revfields) > 2:
 
43
            raise BadRequest('A maximum of two revisions can be given.')
 
44
 
 
45
        revs = [revfield.value for revfield in revfields]
 
46
 
56
47
        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
 
 
 
48
        (out, err) = ivle.interpret.execute_raw(req.user, user_jail_dir,
 
49
                                 '/home', diffservice_path, [self.path] + revs)
 
50
        assert not err
 
51
 
 
52
        response = cjson.decode(out)
 
53
        if 'error' in response:
 
54
            if response['error'] == 'notfound':
 
55
                raise NotFound()
 
56
            else:
 
57
                raise AssertionError('Unknown error from diffservice: %s' %
 
58
                                     response['error'])
 
59
 
 
60
        # No error. We must be safe.
 
61
        diff = response['diff']
 
62
 
 
63
        # Split up the udiff into individual files
 
64
        diff_matcher = re.compile(
 
65
            r'^Index: (.*)\n\=+\n((?:[^I].*\n)*)',re.MULTILINE
 
66
        )
 
67
 
 
68
        # Create a dict with (name, HTMLdiff) pairs for each non-empty diff.
 
69
        ctx['files'] = dict([(fd[0], genshi.XML(htmlfy_diff(fd[1])))
 
70
                             for fd in diff_matcher.findall(diff)
 
71
                             if fd[1]])
 
72
 
 
73
 
 
74
def htmlfy_diff(difftext):
 
75
    """Adds HTML markup to a udiff string"""
 
76
    output = cgi.escape(difftext)
 
77
    subs = {
 
78
     r'^([\+\-]{3})\s(\S+)\s\((.+)\)$':
 
79
         r'<span class="diff-files">\1 \2 <em>(\3)</em></span>',
 
80
     r'^\@\@ (.*) \@\@$':
 
81
         r'<span class="diff-range">@@ \1 @@</span>',
 
82
     r'^\+(.*)$':
 
83
         r'<span class="diff-add">+\1</span>',
 
84
     r'^\-(.*)$':
 
85
         r'<span class="diff-sub">-\1</span>',
 
86
     r'^\\(.*)$':
 
87
         r'<span class="diff-special">\\\1</span>'
 
88
    }
 
89
 
 
90
    for match in subs:
 
91
        output = re.compile(match, re.MULTILINE).sub(subs[match], output)
 
92
 
 
93
    return '<pre class="diff">%s</pre>' % output
 
94
 
 
95
class Plugin(BasePlugin):
 
96
    urls = [
 
97
        ('diff/', DiffView, {'path': ''}),
 
98
        ('diff/*(path)', DiffView),
 
99
    ]