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
94
# revision: The revision number to update to. If not provided this
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).
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
122
128
# TODO: Implement the following actions:
123
129
# svnupdate (done?)
124
130
# TODO: Implement ZIP unpacking in putfiles (done?).
198
205
# Default, just send an error but then continue
199
206
raise ActionError("Unknown action")
207
return action(req, fields)
202
209
def actionpath_to_urlpath(req, path):
203
210
"""Determines the URL path (relative to the student home) upon which the
229
236
Does not mutate req.
231
(_, _, r) = studpath.url_to_jailpaths(actionpath_to_urlpath(req, path))
238
r = studpath.to_home_path(actionpath_to_urlpath(req, path))
233
240
raise ActionError("Invalid path")
420
427
for datum in data:
421
428
# Each of the uploaded files
422
429
filepath = os.path.join(path, datum.filename)
423
(_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
430
filepath_local = studpath.to_home_path(filepath)
424
431
if os.path.isdir(filepath_local):
425
432
raise ActionError("A directory already exists "
426
433
+ "with that name")
438
445
# First get the entire path (within jail)
439
_, _, abspath = studpath.url_to_jailpaths(path)
446
abspath = studpath.to_home_path(path)
440
447
abspath = os.path.join(os.sep, abspath)
441
448
zip.unzip(abspath, filedata)
442
449
except (OSError, IOError):
445
452
raise ActionError("File '" + e.filename + "' already exists.")
448
(_, _, filepath_local) = studpath.url_to_jailpaths(filepath)
455
filepath_local = studpath.to_home_path(filepath)
449
456
if filepath_local is None:
450
457
raise ActionError("Invalid path")
532
539
Reads fields: 'path'
534
541
paths = fields.getlist('path')
535
user = studpath.url_to_local(req.path)[0]
542
user = util.split_path(req.path)[0]
536
543
homedir = "/home/%s" % user
538
545
paths = map(lambda path: actionpath_to_local(req, path), paths)
540
paths = [studpath.url_to_jailpaths(req.path)[2]]
547
paths = [studpath.to_home_path(req.path)]
542
549
# Set all the dirs in home dir world browsable (o+r,o+x)
543
550
#FIXME: Should really only do those in the direct path not all of the
610
617
def action_svnupdate(req, fields):
611
618
"""Performs a "svn update" to each file specified.
620
Reads fields: 'path' and 'revision'
615
622
path = fields.getfirst('path')
623
revision = fields.getfirst('revision')
617
625
raise ActionError("Required field missing")
627
revision = pysvn.Revision( pysvn.opt_revision_kind.head )
630
revision = pysvn.Revision(pysvn.opt_revision_kind.number,
632
except ValueError, e:
633
raise ActionError("Bad revision number: '%s'"%revision,)
618
634
path = actionpath_to_local(req, path)
621
svnclient.update(path, recurse=True)
637
svnclient.update(path, recurse=True, revision=revision)
622
638
except pysvn.ClientError, e:
623
639
raise ActionError(str(e))
713
729
paths = fields.getlist('path')
714
730
if len(paths) != 2:
715
731
raise ActionError("usage: svncheckout url local-path")
716
url = ivle.conf.svn_addr + "/" + paths[0]
732
url = ivle.conf.svn_addr + "/" + urllib.quote(paths[0])
717
733
local_path = actionpath_to_local(req, str(paths[1]))
719
735
svnclient.callback_get_login = get_login
738
754
def action_svnrepostat(req, fields):
739
755
"""Discovers whether a path exists in a repo under the IVLE SVN root.
757
If it does exist, returns a dict containing its metadata.
741
759
Reads fields: 'path'
743
761
path = fields.getfirst('path')
744
762
url = ivle.conf.svn_addr + "/" + path
745
svnclient.exception_style = 1
763
svnclient.exception_style = 1
748
766
svnclient.callback_get_login = get_login
767
info = svnclient.info2(url,
768
revision=pysvn.Revision(pysvn.opt_revision_kind.head))[0][1]
769
return {'svnrevision': info['rev'].number
771
info['rev'].kind == pysvn.opt_revision_kind.number
750
773
except pysvn.ClientError, e:
751
774
# Error code 170000 means ENOENT in this revision.
752
775
if e[1][0][1] == 170000:
753
776
raise util.IVLEError(404, 'The specified repository path does not exist')
755
778
raise ActionError(str(e[0]))
781
def action_svncleanup(req, fields):
782
"""Recursively clean up the working copy, removing locks, resuming
783
unfinished operations, etc.
784
path: The path to be cleaned"""
786
path = fields.getfirst('path')
788
raise ActionError("Required field missing")
789
path = actionpath_to_local(req, path)
792
svnclient.cleanup(path)
793
except pysvn.ClientError, e:
794
raise ActionError(str(e))
758
797
# Table of all action functions #
759
798
# Each function has the interface f(req, fields).
779
818
"svncheckout" : action_svncheckout,
780
819
"svnrepomkdir" : action_svnrepomkdir,
781
820
"svnrepostat" : action_svnrepostat,
821
"svncleanup" : action_svncleanup,