~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: 2009-02-25 23:04:11 UTC
  • Revision ID: grantw@unimelb.edu.au-20090225230411-lbdyl32ir0m3d59b
Make all of the services executable.

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