~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-25 07:34:50 UTC
  • Revision ID: grantw@unimelb.edu.au-20100225073450-zcl8ev5hlyhbszeu
Activate the Storm C extensions if possible. Moar speed.

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
 
#
95
 
# action=svnpublish: Set the "published" flag on a file to True.
96
 
#       path:   The path to the file to be published. Can be specified
97
 
#               multiple times.
98
 
#
99
 
# action=svnunpublish: Set the "published" flag on a file to False.
100
 
#       path:   The path to the file to be unpublished. Can be specified
101
 
#               multiple times.
 
94
#       revision: The revision number to update to. If not provided this
 
95
#               defaults to HEAD.
102
96
#
103
97
# action=svncommit: Commit a file(s) or directory(s) to the repository.
104
98
#       path:   The path to the file or directory to be committed. Can be
119
113
#       path:   The path to the directory to be checked (under the IVLE
120
114
#               repository base).
121
115
#
 
116
# action=svncleanup: Recursively clean up the working copy, removing locks,
 
117
#   resuming unfinished operations, etc.
 
118
#       path:   The path to the directory to be cleaned
 
119
#
122
120
# TODO: Implement the following actions:
123
121
#   svnupdate (done?)
124
122
# TODO: Implement ZIP unpacking in putfiles (done?).
131
129
import os
132
130
import cStringIO
133
131
import shutil
 
132
import urllib
134
133
 
135
134
import pysvn
136
135
 
137
136
from ivle import (util, studpath, zip)
138
137
from ivle.fileservice_lib.exceptions import WillNotOverwrite
139
138
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
 
139
import ivle.svn
 
140
 
 
141
# Make a Subversion client object (which will log in with this user's
 
142
# credentials, upon request)
 
143
svnclient = ivle.svn.create_auth_svn_client(username=ivle.conf.login,
 
144
                                            password=ivle.conf.svn_pass)
160
145
svnclient.exception_style = 0               # Simple (string) exceptions
161
146
 
162
147
DEFAULT_LOGMESSAGE = "No log message supplied."
197
182
    except KeyError:
198
183
        # Default, just send an error but then continue
199
184
        raise ActionError("Unknown action")
200
 
    action(req, fields)
 
185
    return action(req, fields)
201
186
 
202
187
def actionpath_to_urlpath(req, path):
203
188
    """Determines the URL path (relative to the student home) upon which the
228
213
 
229
214
    Does not mutate req.
230
215
    """
231
 
    (_, _, r) = studpath.url_to_jailpaths(actionpath_to_urlpath(req, path))
 
216
    r = studpath.to_home_path(actionpath_to_urlpath(req, path))
232
217
    if r is None:
233
218
        raise ActionError("Invalid path")
234
219
    return r
420
405
    for datum in data:
421
406
        # Each of the uploaded files
422
407
        filepath = os.path.join(path, datum.filename)
423
 
        (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
408
        filepath_local = studpath.to_home_path(filepath)
424
409
        if os.path.isdir(filepath_local):
425
410
            raise ActionError("A directory already exists "
426
411
                    + "with that name")
436
421
            # filename)
437
422
            try:
438
423
                # First get the entire path (within jail)
439
 
                _, _, abspath = studpath.url_to_jailpaths(path)
 
424
                abspath = studpath.to_home_path(path)
440
425
                abspath = os.path.join(os.sep, abspath)
441
426
                zip.unzip(abspath, filedata)
442
427
            except (OSError, IOError):
445
430
                raise ActionError("File '" + e.filename + "' already exists.")
446
431
        else:
447
432
            # Not a zip file
448
 
            (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
433
            filepath_local = studpath.to_home_path(filepath)
449
434
            if filepath_local is None:
450
435
                raise ActionError("Invalid path")
451
436
 
532
517
    Reads fields: 'path'
533
518
    """
534
519
    paths = fields.getlist('path')
535
 
    user = studpath.url_to_local(req.path)[0]
 
520
    user = util.split_path(req.path)[0]
536
521
    homedir = "/home/%s" % user
537
522
    if len(paths):
538
523
        paths = map(lambda path: actionpath_to_local(req, path), paths)
539
524
    else:
540
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
525
        paths = [studpath.to_home_path(req.path)]
541
526
 
542
527
    # Set all the dirs in home dir world browsable (o+r,o+x)
543
528
    #FIXME: Should really only do those in the direct path not all of the 
567
552
    if len(paths):
568
553
        paths = map(lambda path: actionpath_to_local(req, path), paths)
569
554
    else:
570
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
555
        paths = [studpath.to_home_path(req.path)]
571
556
 
572
557
    try:
573
558
        for path in paths:
587
572
    Reads fields: 'path' (multiple)
588
573
    """
589
574
    paths = fields.getlist('path')
590
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
575
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
576
                paths)
591
577
 
592
578
    try:
593
579
        svnclient.add(paths, recurse=True, force=True)
600
586
    Reads fields: 'path' (multiple)
601
587
    """
602
588
    paths = fields.getlist('path')
603
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
589
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
590
                paths)
604
591
 
605
592
    try:
606
593
        svnclient.remove(paths, force=True)
610
597
def action_svnupdate(req, fields):
611
598
    """Performs a "svn update" to each file specified.
612
599
 
613
 
    Reads fields: 'path'
 
600
    Reads fields: 'path' and 'revision'
614
601
    """
615
602
    path = fields.getfirst('path')
 
603
    revision = fields.getfirst('revision')
616
604
    if path is None:
617
605
        raise ActionError("Required field missing")
618
 
    path = actionpath_to_local(req, path)
 
606
    if revision is None:
 
607
        revision = pysvn.Revision( pysvn.opt_revision_kind.head )
 
608
    else:
 
609
        try:
 
610
            revision = pysvn.Revision(pysvn.opt_revision_kind.number,
 
611
                    int(revision))
 
612
        except ValueError, e:
 
613
            raise ActionError("Bad revision number: '%s'"%revision,)
 
614
    path = actionpath_to_local(req, path).decode('utf-8')
619
615
 
620
616
    try:
621
 
        svnclient.update(path, recurse=True)
 
617
        svnclient.update(path, recurse=True, revision=revision)
622
618
    except pysvn.ClientError, e:
623
619
        raise ActionError(str(e))
624
620
 
630
626
    path = fields.getfirst('path')
631
627
    if path is None:
632
628
        raise ActionError("Required field missing")
633
 
    path = actionpath_to_local(req, path)
 
629
    path = actionpath_to_local(req, path).decode('utf-8')
634
630
 
635
631
    try:
636
632
        svnclient.resolved(path, recurse=True)
643
639
    Reads fields: 'path' (multiple)
644
640
    """
645
641
    paths = fields.getlist('path')
646
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
642
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
643
                paths)
647
644
 
648
645
    try:
649
646
        svnclient.revert(paths, recurse=True)
650
647
    except pysvn.ClientError, e:
651
648
        raise ActionError(str(e))
652
649
 
653
 
def action_svnpublish(req, fields):
654
 
    """Sets svn property "ivle:published" on each file specified.
655
 
    Should only be called on directories (only effective on directories
656
 
    anyway).
657
 
 
658
 
    Reads fields: 'path'
659
 
 
660
 
    XXX Currently unused by the client (calls action_publish instead, which
661
 
    has a completely different publishing model).
662
 
    """
663
 
    paths = fields.getlist('path')
664
 
    if len(paths):
665
 
        paths = map(lambda path: actionpath_to_local(req, path), paths)
666
 
    else:
667
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
668
 
 
669
 
    try:
670
 
        for path in paths:
671
 
            # Note: Property value doesn't matter
672
 
            svnclient.propset("ivle:published", "", path, recurse=False)
673
 
    except pysvn.ClientError, e:
674
 
        raise ActionError("Directory could not be published")
675
 
 
676
 
def action_svnunpublish(req, fields):
677
 
    """Deletes svn property "ivle:published" on each file specified.
678
 
 
679
 
    Reads fields: 'path'
680
 
 
681
 
    XXX Currently unused by the client (calls action_unpublish instead, which
682
 
    has a completely different publishing model).
683
 
    """
684
 
    paths = fields.getlist('path')
685
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
686
 
 
687
 
    try:
688
 
        for path in paths:
689
 
            svnclient.propdel("ivle:published", path, recurse=False)
690
 
    except pysvn.ClientError, e:
691
 
        raise ActionError("Directory could not be unpublished")
692
 
 
693
650
def action_svncommit(req, fields):
694
651
    """Performs a "svn commit" to each file specified.
695
652
 
696
653
    Reads fields: 'path' (multiple), 'logmsg' (optional)
697
654
    """
698
655
    paths = fields.getlist('path')
699
 
    paths = map(lambda path: actionpath_to_local(req, str(path)), paths)
700
 
    logmsg = str(fields.getfirst('logmsg', DEFAULT_LOGMESSAGE))
 
656
    if len(paths):
 
657
        paths = map(lambda path:actionpath_to_local(req,path).decode('utf-8'),
 
658
                    paths)
 
659
    else:
 
660
        paths = [studpath.to_home_path(req.path).decode('utf-8')]
 
661
    logmsg = str(fields.getfirst('logmsg',
 
662
                 DEFAULT_LOGMESSAGE)).decode('utf-8')
701
663
    if logmsg == '': logmsg = DEFAULT_LOGMESSAGE
702
664
 
703
665
    try:
713
675
    paths = fields.getlist('path')
714
676
    if len(paths) != 2:
715
677
        raise ActionError("usage: svncheckout url local-path")
716
 
    url = ivle.conf.svn_addr + "/" + paths[0]
 
678
    url = ivle.conf.svn_addr + "/" + urllib.quote(paths[0])
717
679
    local_path = actionpath_to_local(req, str(paths[1]))
 
680
    url = url.decode('utf-8')
 
681
    local_path = local_path.decode('utf-8')
718
682
    try:
719
 
        svnclient.callback_get_login = get_login
720
683
        svnclient.checkout(url, local_path, recurse=True)
721
684
    except pysvn.ClientError, e:
722
685
        raise ActionError(str(e))
728
691
    """
729
692
    path = fields.getfirst('path')
730
693
    logmsg = fields.getfirst('logmsg')
731
 
    url = ivle.conf.svn_addr + "/" + path
 
694
    url = (ivle.conf.svn_addr + "/" + urllib.quote(path)).decode('utf-8')
732
695
    try:
733
 
        svnclient.callback_get_login = get_login
734
696
        svnclient.mkdir(url, log_message=logmsg)
735
697
    except pysvn.ClientError, e:
736
698
        raise ActionError(str(e))
738
700
def action_svnrepostat(req, fields):
739
701
    """Discovers whether a path exists in a repo under the IVLE SVN root.
740
702
 
 
703
    If it does exist, returns a dict containing its metadata.
 
704
 
741
705
    Reads fields: 'path'
742
706
    """
743
707
    path = fields.getfirst('path')
744
 
    url = ivle.conf.svn_addr + "/" + path
745
 
    svnclient.exception_style = 1 
 
708
    url = (ivle.conf.svn_addr + "/" + urllib.quote(path)).decode('utf-8')
 
709
    svnclient.exception_style = 1
746
710
 
747
711
    try:
748
 
        svnclient.callback_get_login = get_login
749
 
        svnclient.info2(url)
 
712
        info = svnclient.info2(url,
 
713
            revision=pysvn.Revision(pysvn.opt_revision_kind.head))[0][1]
 
714
        return {'svnrevision': info['rev'].number
 
715
                  if info['rev'] and
 
716
                     info['rev'].kind == pysvn.opt_revision_kind.number
 
717
                  else None}
750
718
    except pysvn.ClientError, e:
751
719
        # Error code 170000 means ENOENT in this revision.
752
720
        if e[1][0][1] == 170000:
753
721
            raise util.IVLEError(404, 'The specified repository path does not exist')
754
722
        else:
755
723
            raise ActionError(str(e[0]))
756
 
            
 
724
 
 
725
 
 
726
def action_svncleanup(req, fields):
 
727
    """Recursively clean up the working copy, removing locks, resuming 
 
728
    unfinished operations, etc.
 
729
        path:   The path to be cleaned"""
 
730
 
 
731
    path = fields.getfirst('path')
 
732
    if path is None:
 
733
        raise ActionError("Required field missing")
 
734
    path = actionpath_to_local(req, path).decode('utf-8')
 
735
 
 
736
    try:
 
737
        svnclient.cleanup(path)
 
738
    except pysvn.ClientError, e:
 
739
        raise ActionError(str(e))
 
740
 
757
741
 
758
742
# Table of all action functions #
759
743
# Each function has the interface f(req, fields).
773
757
    "svnupdate" : action_svnupdate,
774
758
    "svnresolved" : action_svnresolved,
775
759
    "svnrevert" : action_svnrevert,
776
 
    "svnpublish" : action_svnpublish,
777
 
    "svnunpublish" : action_svnunpublish,
778
760
    "svncommit" : action_svncommit,
779
761
    "svncheckout" : action_svncheckout,
780
762
    "svnrepomkdir" : action_svnrepomkdir,
781
763
    "svnrepostat" : action_svnrepostat,
 
764
    "svncleanup" : action_svncleanup,
782
765
}