39
41
from ivle.database import Project, ProjectSet, Offering, Subject
41
def fetch_submission(submission, target, svnclient, config):
43
def fetch_submission(submission, target, svnclient, config, zip=False):
42
44
"""Fetch a submission from a user's repository, and dump it in a given
44
46
@param submission: Submission object, detailing the submission.
45
47
@param target: Target directory for the project (will create a
46
48
subdirectory for each submission).
49
@param svnclient: pysvn.Client object.
47
50
@param config: Config object.
51
@param zip: If True, zips up the submission.
49
53
# submission_name is the name of the user or group who owns the repo
50
54
submission_name = submission.assessed.principal.name
58
62
svnclient.export(url, target_final, force=True,
59
63
revision=revision, recurse=True)
65
# If required, zip up the directory
67
make_zip(target_final, target_final + ".zip")
68
# Remove the target tree
69
shutil.rmtree(target_final)
61
71
def get_repo_url(submission, config):
62
72
"""Gets a local (file:) URL to the repository for a given submission.
63
73
This will consult submission.path to find the path within the repository
90
100
# Attach "file://" to the front of the absolute path, to make it a URL
91
101
return "file://" + os.path.join(os.path.abspath(repo_path), path_in_repo)
103
def make_zip(source, dest):
104
"""Zip up a directory tree or file. The ZIP file will always contain just
105
a single directory or file at the top level (it will not be a ZIP bomb).
106
@param source: Path to a directory or file to zip up.
107
@param dest: Path to a zip file to create.
109
# NOTE: This code is mostly copied from ivle.zip (but very different)
110
zip = zipfile.ZipFile(dest, 'w')
112
# Write the source file/directory itself
113
# (If this is a directory it will NOT recurse)
114
zip.write(source, os.path.basename(source))
116
if os.path.isdir(source):
117
# All paths within the zip file are relative to relativeto
118
relativeto = os.path.dirname(source)
119
# Write the top-level directory
120
# Walk the directory tree
122
raise OSError("Could not access a file (zipping)")
123
for (dirpath, dirnames, filenames) in \
124
os.walk(source, onerror=error):
125
arc_dirpath = os.path.relpath(dirpath, relativeto)
126
for filename in dirnames + filenames:
127
zip.write(os.path.join(dirpath, filename),
128
os.path.join(arc_dirpath, filename))
93
132
def main(argv=None):
121
160
help="Destination directory (default to '.', creates a subdirectory, "
122
161
"so will not pollute PATH).",
124
# XXX -z has no effect
125
163
parser.add_option("-z", "--zip",
126
164
action="store_true", dest="zip",
127
165
help="Store each submission in a Zip file.",
211
249
for submission in project.latest_submissions:
213
fetch_submission(submission, target_dir, svnclient, config)
251
fetch_submission(submission, target_dir, svnclient, config,
214
253
except Exception, e:
215
254
# Catch all exceptions (to ensure if one student has a problem, it
216
255
# is reported, and we can continue)