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

« back to all changes in this revision

Viewing changes to ivle/fileservice_lib/action.py

  • Committer: William Grant
  • Date: 2010-02-11 05:09:56 UTC
  • Revision ID: grantw@unimelb.edu.au-20100211050956-t5i2z6b8iulxteza
Unbreak existing tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
91
91
# action=svnupdate: Bring a file up to date with the head revision.
92
92
#       path:   The path to the file to be updated. Only one file may be
93
93
#               specified.
 
94
#       revision: The revision number to update to. If not provided this
 
95
#               defaults to HEAD.
94
96
#
95
97
# action=svnpublish: Set the "published" flag on a file to True.
96
98
#       path:   The path to the file to be published. Can be specified
119
121
#       path:   The path to the directory to be checked (under the IVLE
120
122
#               repository base).
121
123
#
 
124
# action=svncleanup: Recursively clean up the working copy, removing locks,
 
125
#   resuming unfinished operations, etc.
 
126
#       path:   The path to the directory to be cleaned
 
127
#
122
128
# TODO: Implement the following actions:
123
129
#   svnupdate (done?)
124
130
# TODO: Implement ZIP unpacking in putfiles (done?).
131
137
import os
132
138
import cStringIO
133
139
import shutil
 
140
import urllib
134
141
 
135
142
import pysvn
136
143
 
137
144
from ivle import (util, studpath, zip)
138
145
from ivle.fileservice_lib.exceptions import WillNotOverwrite
139
146
import ivle.conf
140
 
 
141
 
 
142
 
def get_login(_realm, existing_login, _may_save):
143
 
    """Callback function used by pysvn for authentication.
144
 
    realm, existing_login, _may_save: The 3 arguments passed by pysvn to
145
 
        callback_get_login.
146
 
        The following has been determined empirically, not from docs:
147
 
        existing_login will be the name of the user who owns the process on
148
 
        the first attempt, "" on subsequent attempts. We use this fact.
149
 
    """
150
 
    # Only provide credentials on the _first_ attempt.
151
 
    # If we're being asked again, then it means the credentials failed for
152
 
    # some reason and we should just fail. (This is not desirable, but it's
153
 
    # better than being asked an infinite number of times).
154
 
    return (existing_login != "", str(ivle.conf.login),
155
 
                                  str(ivle.conf.svn_pass), True)
156
 
 
157
 
# Make a Subversion client object
158
 
svnclient = pysvn.Client()
159
 
svnclient.callback_get_login = get_login
 
147
import ivle.svn
 
148
 
 
149
# Make a Subversion client object (which will log in with this user's
 
150
# credentials, upon request)
 
151
svnclient = ivle.svn.create_auth_svn_client(username=ivle.conf.login,
 
152
                                            password=ivle.conf.svn_pass)
160
153
svnclient.exception_style = 0               # Simple (string) exceptions
161
154
 
162
155
DEFAULT_LOGMESSAGE = "No log message supplied."
197
190
    except KeyError:
198
191
        # Default, just send an error but then continue
199
192
        raise ActionError("Unknown action")
200
 
    action(req, fields)
 
193
    return action(req, fields)
201
194
 
202
195
def actionpath_to_urlpath(req, path):
203
196
    """Determines the URL path (relative to the student home) upon which the
228
221
 
229
222
    Does not mutate req.
230
223
    """
231
 
    (_, _, r) = studpath.url_to_jailpaths(actionpath_to_urlpath(req, path))
 
224
    r = studpath.to_home_path(actionpath_to_urlpath(req, path))
232
225
    if r is None:
233
226
        raise ActionError("Invalid path")
234
227
    return r
420
413
    for datum in data:
421
414
        # Each of the uploaded files
422
415
        filepath = os.path.join(path, datum.filename)
423
 
        (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
416
        filepath_local = studpath.to_home_path(filepath)
424
417
        if os.path.isdir(filepath_local):
425
418
            raise ActionError("A directory already exists "
426
419
                    + "with that name")
436
429
            # filename)
437
430
            try:
438
431
                # First get the entire path (within jail)
439
 
                _, _, abspath = studpath.url_to_jailpaths(path)
 
432
                abspath = studpath.to_home_path(path)
440
433
                abspath = os.path.join(os.sep, abspath)
441
434
                zip.unzip(abspath, filedata)
442
435
            except (OSError, IOError):
445
438
                raise ActionError("File '" + e.filename + "' already exists.")
446
439
        else:
447
440
            # Not a zip file
448
 
            (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
441
            filepath_local = studpath.to_home_path(filepath)
449
442
            if filepath_local is None:
450
443
                raise ActionError("Invalid path")
451
444
 
532
525
    Reads fields: 'path'
533
526
    """
534
527
    paths = fields.getlist('path')
535
 
    user = studpath.url_to_local(req.path)[0]
 
528
    user = util.split_path(req.path)[0]
536
529
    homedir = "/home/%s" % user
537
530
    if len(paths):
538
531
        paths = map(lambda path: actionpath_to_local(req, path), paths)
539
532
    else:
540
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
533
        paths = [studpath.to_home_path(req.path)]
541
534
 
542
535
    # Set all the dirs in home dir world browsable (o+r,o+x)
543
536
    #FIXME: Should really only do those in the direct path not all of the 
567
560
    if len(paths):
568
561
        paths = map(lambda path: actionpath_to_local(req, path), paths)
569
562
    else:
570
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
563
        paths = [studpath.to_home_path(req.path)]
571
564
 
572
565
    try:
573
566
        for path in paths:
610
603
def action_svnupdate(req, fields):
611
604
    """Performs a "svn update" to each file specified.
612
605
 
613
 
    Reads fields: 'path'
 
606
    Reads fields: 'path' and 'revision'
614
607
    """
615
608
    path = fields.getfirst('path')
 
609
    revision = fields.getfirst('revision')
616
610
    if path is None:
617
611
        raise ActionError("Required field missing")
 
612
    if revision is None:
 
613
        revision = pysvn.Revision( pysvn.opt_revision_kind.head )
 
614
    else:
 
615
        try:
 
616
            revision = pysvn.Revision(pysvn.opt_revision_kind.number,
 
617
                    int(revision))
 
618
        except ValueError, e:
 
619
            raise ActionError("Bad revision number: '%s'"%revision,)
618
620
    path = actionpath_to_local(req, path)
619
621
 
620
622
    try:
621
 
        svnclient.update(path, recurse=True)
 
623
        svnclient.update(path, recurse=True, revision=revision)
622
624
    except pysvn.ClientError, e:
623
625
        raise ActionError(str(e))
624
626
 
664
666
    if len(paths):
665
667
        paths = map(lambda path: actionpath_to_local(req, path), paths)
666
668
    else:
667
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
669
        paths = [studpath.to_home_path(req.path)]
668
670
 
669
671
    try:
670
672
        for path in paths:
713
715
    paths = fields.getlist('path')
714
716
    if len(paths) != 2:
715
717
        raise ActionError("usage: svncheckout url local-path")
716
 
    url = ivle.conf.svn_addr + "/" + paths[0]
 
718
    url = ivle.conf.svn_addr + "/" + urllib.quote(paths[0])
717
719
    local_path = actionpath_to_local(req, str(paths[1]))
718
720
    try:
719
 
        svnclient.callback_get_login = get_login
720
721
        svnclient.checkout(url, local_path, recurse=True)
721
722
    except pysvn.ClientError, e:
722
723
        raise ActionError(str(e))
728
729
    """
729
730
    path = fields.getfirst('path')
730
731
    logmsg = fields.getfirst('logmsg')
731
 
    url = ivle.conf.svn_addr + "/" + path
 
732
    url = ivle.conf.svn_addr + "/" + urllib.quote(path)
732
733
    try:
733
 
        svnclient.callback_get_login = get_login
734
734
        svnclient.mkdir(url, log_message=logmsg)
735
735
    except pysvn.ClientError, e:
736
736
        raise ActionError(str(e))
738
738
def action_svnrepostat(req, fields):
739
739
    """Discovers whether a path exists in a repo under the IVLE SVN root.
740
740
 
 
741
    If it does exist, returns a dict containing its metadata.
 
742
 
741
743
    Reads fields: 'path'
742
744
    """
743
745
    path = fields.getfirst('path')
744
 
    url = ivle.conf.svn_addr + "/" + path
745
 
    svnclient.exception_style = 1 
 
746
    url = ivle.conf.svn_addr + "/" + urllib.quote(path)
 
747
    svnclient.exception_style = 1
746
748
 
747
749
    try:
748
 
        svnclient.callback_get_login = get_login
749
 
        svnclient.info2(url)
 
750
        info = svnclient.info2(url,
 
751
            revision=pysvn.Revision(pysvn.opt_revision_kind.head))[0][1]
 
752
        return {'svnrevision': info['rev'].number
 
753
                  if info['rev'] and
 
754
                     info['rev'].kind == pysvn.opt_revision_kind.number
 
755
                  else None}
750
756
    except pysvn.ClientError, e:
751
757
        # Error code 170000 means ENOENT in this revision.
752
758
        if e[1][0][1] == 170000:
753
759
            raise util.IVLEError(404, 'The specified repository path does not exist')
754
760
        else:
755
761
            raise ActionError(str(e[0]))
756
 
            
 
762
 
 
763
 
 
764
def action_svncleanup(req, fields):
 
765
    """Recursively clean up the working copy, removing locks, resuming 
 
766
    unfinished operations, etc.
 
767
        path:   The path to be cleaned"""
 
768
 
 
769
    path = fields.getfirst('path')
 
770
    if path is None:
 
771
        raise ActionError("Required field missing")
 
772
    path = actionpath_to_local(req, path)
 
773
 
 
774
    try:
 
775
        svnclient.cleanup(path)
 
776
    except pysvn.ClientError, e:
 
777
        raise ActionError(str(e))
 
778
 
757
779
 
758
780
# Table of all action functions #
759
781
# Each function has the interface f(req, fields).
779
801
    "svncheckout" : action_svncheckout,
780
802
    "svnrepomkdir" : action_svnrepomkdir,
781
803
    "svnrepostat" : action_svnrepostat,
 
804
    "svncleanup" : action_svncleanup,
782
805
}