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

« back to all changes in this revision

Viewing changes to ivle/fileservice_lib/action.py

  • Committer: David Coles
  • Date: 2010-07-27 04:52:14 UTC
  • Revision ID: coles.david@gmail.com-20100727045214-p32h1kc0gcv48dpr
Worksheets: Strip off whitespace from the end of exercise attempts.

This solves an issue where accidental whitespace in an attempt will cause 
"IndentationError" syntax error (which don't occur when run in console).

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?).
138
136
from ivle import (util, studpath, zip)
139
137
from ivle.fileservice_lib.exceptions import WillNotOverwrite
140
138
import ivle.conf
141
 
 
142
 
 
143
 
def get_login(_realm, existing_login, _may_save):
144
 
    """Callback function used by pysvn for authentication.
145
 
    realm, existing_login, _may_save: The 3 arguments passed by pysvn to
146
 
        callback_get_login.
147
 
        The following has been determined empirically, not from docs:
148
 
        existing_login will be the name of the user who owns the process on
149
 
        the first attempt, "" on subsequent attempts. We use this fact.
150
 
    """
151
 
    # Only provide credentials on the _first_ attempt.
152
 
    # If we're being asked again, then it means the credentials failed for
153
 
    # some reason and we should just fail. (This is not desirable, but it's
154
 
    # better than being asked an infinite number of times).
155
 
    return (existing_login != "", str(ivle.conf.login),
156
 
                                  str(ivle.conf.svn_pass), True)
157
 
 
158
 
# Make a Subversion client object
159
 
svnclient = pysvn.Client()
160
 
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)
161
145
svnclient.exception_style = 0               # Simple (string) exceptions
162
146
 
163
147
DEFAULT_LOGMESSAGE = "No log message supplied."
229
213
 
230
214
    Does not mutate req.
231
215
    """
232
 
    (_, _, r) = studpath.url_to_jailpaths(actionpath_to_urlpath(req, path))
 
216
    r = studpath.to_home_path(actionpath_to_urlpath(req, path))
233
217
    if r is None:
234
218
        raise ActionError("Invalid path")
235
219
    return r
333
317
    """
334
318
    frompath = fields.getfirst('from')
335
319
    topath = fields.getfirst('to')
336
 
    movefile(req, frompath, topath)
 
320
    svn = fields.getfirst('svn')
 
321
    if svn:
 
322
        svn_movefile(req, frompath, topath)
 
323
    else:
 
324
        movefile(req, frompath, topath)
337
325
 
338
326
def action_mkdir(req, fields):
339
327
    """Creates a directory with the given path.
421
409
    for datum in data:
422
410
        # Each of the uploaded files
423
411
        filepath = os.path.join(path, datum.filename)
424
 
        (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
412
        filepath_local = studpath.to_home_path(filepath)
425
413
        if os.path.isdir(filepath_local):
426
414
            raise ActionError("A directory already exists "
427
415
                    + "with that name")
437
425
            # filename)
438
426
            try:
439
427
                # First get the entire path (within jail)
440
 
                _, _, abspath = studpath.url_to_jailpaths(path)
 
428
                abspath = studpath.to_home_path(path)
441
429
                abspath = os.path.join(os.sep, abspath)
442
430
                zip.unzip(abspath, filedata)
443
431
            except (OSError, IOError):
446
434
                raise ActionError("File '" + e.filename + "' already exists.")
447
435
        else:
448
436
            # Not a zip file
449
 
            (_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
 
437
            filepath_local = studpath.to_home_path(filepath)
450
438
            if filepath_local is None:
451
439
                raise ActionError("Invalid path")
452
440
 
533
521
    Reads fields: 'path'
534
522
    """
535
523
    paths = fields.getlist('path')
536
 
    user = studpath.url_to_local(req.path)[0]
 
524
    user = util.split_path(req.path)[0]
537
525
    homedir = "/home/%s" % user
538
526
    if len(paths):
539
527
        paths = map(lambda path: actionpath_to_local(req, path), paths)
540
528
    else:
541
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
529
        paths = [studpath.to_home_path(req.path)]
542
530
 
543
531
    # Set all the dirs in home dir world browsable (o+r,o+x)
544
532
    #FIXME: Should really only do those in the direct path not all of the 
568
556
    if len(paths):
569
557
        paths = map(lambda path: actionpath_to_local(req, path), paths)
570
558
    else:
571
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
 
559
        paths = [studpath.to_home_path(req.path)]
572
560
 
573
561
    try:
574
562
        for path in paths:
588
576
    Reads fields: 'path' (multiple)
589
577
    """
590
578
    paths = fields.getlist('path')
591
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
579
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
580
                paths)
592
581
 
593
582
    try:
594
583
        svnclient.add(paths, recurse=True, force=True)
601
590
    Reads fields: 'path' (multiple)
602
591
    """
603
592
    paths = fields.getlist('path')
604
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
593
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
594
                paths)
605
595
 
606
596
    try:
607
597
        svnclient.remove(paths, force=True)
611
601
def action_svnupdate(req, fields):
612
602
    """Performs a "svn update" to each file specified.
613
603
 
614
 
    Reads fields: 'path'
 
604
    Reads fields: 'path' and 'revision'
615
605
    """
616
606
    path = fields.getfirst('path')
 
607
    revision = fields.getfirst('revision')
617
608
    if path is None:
618
609
        raise ActionError("Required field missing")
619
 
    path = actionpath_to_local(req, path)
 
610
    if revision is None:
 
611
        revision = pysvn.Revision( pysvn.opt_revision_kind.head )
 
612
    else:
 
613
        try:
 
614
            revision = pysvn.Revision(pysvn.opt_revision_kind.number,
 
615
                    int(revision))
 
616
        except ValueError, e:
 
617
            raise ActionError("Bad revision number: '%s'"%revision,)
 
618
    path = actionpath_to_local(req, path).decode('utf-8')
620
619
 
621
620
    try:
622
 
        svnclient.update(path, recurse=True)
 
621
        svnclient.update(path, recurse=True, revision=revision)
623
622
    except pysvn.ClientError, e:
624
623
        raise ActionError(str(e))
625
624
 
631
630
    path = fields.getfirst('path')
632
631
    if path is None:
633
632
        raise ActionError("Required field missing")
634
 
    path = actionpath_to_local(req, path)
 
633
    path = actionpath_to_local(req, path).decode('utf-8')
635
634
 
636
635
    try:
637
636
        svnclient.resolved(path, recurse=True)
644
643
    Reads fields: 'path' (multiple)
645
644
    """
646
645
    paths = fields.getlist('path')
647
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
 
646
    paths = map(lambda path: actionpath_to_local(req, path).decode('utf-8'),
 
647
                paths)
648
648
 
649
649
    try:
650
650
        svnclient.revert(paths, recurse=True)
651
651
    except pysvn.ClientError, e:
652
652
        raise ActionError(str(e))
653
653
 
654
 
def action_svnpublish(req, fields):
655
 
    """Sets svn property "ivle:published" on each file specified.
656
 
    Should only be called on directories (only effective on directories
657
 
    anyway).
658
 
 
659
 
    Reads fields: 'path'
660
 
 
661
 
    XXX Currently unused by the client (calls action_publish instead, which
662
 
    has a completely different publishing model).
663
 
    """
664
 
    paths = fields.getlist('path')
665
 
    if len(paths):
666
 
        paths = map(lambda path: actionpath_to_local(req, path), paths)
667
 
    else:
668
 
        paths = [studpath.url_to_jailpaths(req.path)[2]]
669
 
 
670
 
    try:
671
 
        for path in paths:
672
 
            # Note: Property value doesn't matter
673
 
            svnclient.propset("ivle:published", "", path, recurse=False)
674
 
    except pysvn.ClientError, e:
675
 
        raise ActionError("Directory could not be published")
676
 
 
677
 
def action_svnunpublish(req, fields):
678
 
    """Deletes svn property "ivle:published" on each file specified.
679
 
 
680
 
    Reads fields: 'path'
681
 
 
682
 
    XXX Currently unused by the client (calls action_unpublish instead, which
683
 
    has a completely different publishing model).
684
 
    """
685
 
    paths = fields.getlist('path')
686
 
    paths = map(lambda path: actionpath_to_local(req, path), paths)
687
 
 
688
 
    try:
689
 
        for path in paths:
690
 
            svnclient.propdel("ivle:published", path, recurse=False)
691
 
    except pysvn.ClientError, e:
692
 
        raise ActionError("Directory could not be unpublished")
693
 
 
694
654
def action_svncommit(req, fields):
695
655
    """Performs a "svn commit" to each file specified.
696
656
 
697
657
    Reads fields: 'path' (multiple), 'logmsg' (optional)
698
658
    """
699
659
    paths = fields.getlist('path')
700
 
    paths = map(lambda path: actionpath_to_local(req, str(path)), paths)
701
 
    logmsg = str(fields.getfirst('logmsg', DEFAULT_LOGMESSAGE))
 
660
    if len(paths):
 
661
        paths = map(lambda path:actionpath_to_local(req,path).decode('utf-8'),
 
662
                    paths)
 
663
    else:
 
664
        paths = [studpath.to_home_path(req.path).decode('utf-8')]
 
665
    logmsg = str(fields.getfirst('logmsg',
 
666
                 DEFAULT_LOGMESSAGE)).decode('utf-8')
702
667
    if logmsg == '': logmsg = DEFAULT_LOGMESSAGE
703
668
 
704
669
    try:
716
681
        raise ActionError("usage: svncheckout url local-path")
717
682
    url = ivle.conf.svn_addr + "/" + urllib.quote(paths[0])
718
683
    local_path = actionpath_to_local(req, str(paths[1]))
 
684
    url = url.decode('utf-8')
 
685
    local_path = local_path.decode('utf-8')
719
686
    try:
720
 
        svnclient.callback_get_login = get_login
721
687
        svnclient.checkout(url, local_path, recurse=True)
722
688
    except pysvn.ClientError, e:
723
689
        raise ActionError(str(e))
729
695
    """
730
696
    path = fields.getfirst('path')
731
697
    logmsg = fields.getfirst('logmsg')
732
 
    url = ivle.conf.svn_addr + "/" + path
 
698
    url = (ivle.conf.svn_addr + "/" + urllib.quote(path)).decode('utf-8')
733
699
    try:
734
 
        svnclient.callback_get_login = get_login
735
700
        svnclient.mkdir(url, log_message=logmsg)
736
701
    except pysvn.ClientError, e:
737
702
        raise ActionError(str(e))
744
709
    Reads fields: 'path'
745
710
    """
746
711
    path = fields.getfirst('path')
747
 
    url = ivle.conf.svn_addr + "/" + path
 
712
    url = (ivle.conf.svn_addr + "/" + urllib.quote(path)).decode('utf-8')
748
713
    svnclient.exception_style = 1
749
714
 
750
715
    try:
751
 
        svnclient.callback_get_login = get_login
752
716
        info = svnclient.info2(url,
753
717
            revision=pysvn.Revision(pysvn.opt_revision_kind.head))[0][1]
754
718
        return {'svnrevision': info['rev'].number
758
722
    except pysvn.ClientError, e:
759
723
        # Error code 170000 means ENOENT in this revision.
760
724
        if e[1][0][1] == 170000:
761
 
            raise util.IVLEError(404, 'The specified repository path does not exist')
 
725
            req.status = 404
 
726
            raise ActionError('The specified repository path does not exist')
762
727
        else:
763
728
            raise ActionError(str(e[0]))
764
 
            
 
729
 
 
730
 
 
731
def action_svncleanup(req, fields):
 
732
    """Recursively clean up the working copy, removing locks, resuming 
 
733
    unfinished operations, etc.
 
734
        path:   The path to be cleaned"""
 
735
 
 
736
    path = fields.getfirst('path')
 
737
    if path is None:
 
738
        raise ActionError("Required field missing")
 
739
    path = actionpath_to_local(req, path).decode('utf-8')
 
740
 
 
741
    try:
 
742
        svnclient.cleanup(path)
 
743
    except pysvn.ClientError, e:
 
744
        raise ActionError(str(e))
 
745
 
765
746
 
766
747
# Table of all action functions #
767
748
# Each function has the interface f(req, fields).
781
762
    "svnupdate" : action_svnupdate,
782
763
    "svnresolved" : action_svnresolved,
783
764
    "svnrevert" : action_svnrevert,
784
 
    "svnpublish" : action_svnpublish,
785
 
    "svnunpublish" : action_svnunpublish,
786
765
    "svncommit" : action_svncommit,
787
766
    "svncheckout" : action_svncheckout,
788
767
    "svnrepomkdir" : action_svnrepomkdir,
789
768
    "svnrepostat" : action_svnrepostat,
 
769
    "svncleanup" : action_svncleanup,
790
770
}