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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: mattgiuca
  • Date: 2008-07-21 05:25:48 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:920
userdb: Added to table "offering" fields max_students_per_group and
    max_groups_per_student.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# IVLE - Informatics Virtual Learning Environment
 
2
# Copyright (C) 2007-2008 The University of Melbourne
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 
 
18
# Module: setup/setuputil
 
19
# Author: Matt Giuca, Refactored by David Coles
 
20
# Date:   02/07/2008
 
21
 
 
22
# setup/setuputil.py
 
23
# Contains a set of functions useful for the setup program.
 
24
 
 
25
import os
 
26
import shutil
 
27
import errno
 
28
import sys
 
29
import pysvn
 
30
import string
 
31
import stat
 
32
 
 
33
# Import modules from the website is tricky since they're in the www
 
34
# directory.
 
35
sys.path.append('lib')
 
36
import common.makeuser
 
37
 
 
38
# Determine which Python version (2.4 or 2.5, for example) we are running,
 
39
# and use that as the filename to the Python directory.
 
40
# Just get the first 3 characters of sys.version.
 
41
PYTHON_VERSION = sys.version[0:3]
 
42
 
 
43
# Location of standard programs
 
44
RSYNC = '/usr/bin/rsync'
 
45
 
 
46
def copy_file_to_jail(src, dry):
 
47
    """Copies a single file from an absolute location into the same location
 
48
    within the jail. src must begin with a '/'. The jail will be located
 
49
    in a 'jail' subdirectory of the current path."""
 
50
    action_copyfile(src, 'jail' + src, dry)
 
51
 
 
52
# The actions call Python os functions but print actions and handle dryness.
 
53
# May still throw os exceptions if errors occur.
 
54
 
 
55
class RunError:
 
56
    """Represents an error when running a program (nonzero return)."""
 
57
    def __init__(self, prog, retcode):
 
58
        self.prog = prog
 
59
        self.retcode = retcode
 
60
    def __str__(self):
 
61
        return str(self.prog) + " returned " + repr(self.retcode)
 
62
 
 
63
def action_runprog(prog, args, dry):
 
64
    """Runs a unix program. Searches in $PATH. Synchronous (waits for the
 
65
    program to return). Runs in the current environment. First prints the
 
66
    action as a "bash" line.
 
67
 
 
68
    Throws a RunError with a retcode of the return value of the program,
 
69
    if the program did not return 0.
 
70
 
 
71
    prog: String. Name of the program. (No path required, if in $PATH).
 
72
    args: [String]. Arguments to the program. (Note, this does not allow you to
 
73
        set argv[0]; it will always be prog.)
 
74
    dry: Bool. If True, prints but does not execute.
 
75
    """
 
76
    print prog, string.join(args, ' ')
 
77
    if dry: return
 
78
    ret = os.spawnvp(os.P_WAIT, prog, [prog] + args)
 
79
    if ret != 0:
 
80
        raise RunError(prog, ret)
 
81
 
 
82
def action_remove(path, dry):
 
83
    """Calls rmtree, deleting the target file if it exists."""
 
84
    try:
 
85
        print "rm -r", path
 
86
        if not dry:
 
87
            shutil.rmtree(path, True)
 
88
    except OSError, (err, msg):
 
89
        if err != errno.EEXIST:
 
90
            raise
 
91
        # Otherwise, didn't exist, so we don't care
 
92
 
 
93
def action_rename(src, dst, dry):
 
94
    """Calls rename. Deletes the target if it already exists."""
 
95
    action_remove(dst, dry)
 
96
    print "mv ", src, dst
 
97
    if dry: return
 
98
    try:
 
99
        os.rename(src, dst)
 
100
    except OSError, (err, msg):
 
101
        if err != errno.EEXIST:
 
102
            raise
 
103
 
 
104
def action_mkdir(path, dry):
 
105
    """Calls mkdir. Silently ignored if the directory already exists.
 
106
    Creates all parent directories as necessary."""
 
107
    print "mkdir -p", path
 
108
    if dry: return
 
109
    try:
 
110
        os.makedirs(path)
 
111
    except OSError, (err, msg):
 
112
        if err != errno.EEXIST:
 
113
            raise
 
114
 
 
115
def action_copytree(src, dst, dry):
 
116
    """Copies an entire directory tree. Symlinks are seen as normal files and
 
117
    copies of the entire file (not the link) are made. Creates all parent
 
118
    directories as necessary.
 
119
 
 
120
    See shutil.copytree."""
 
121
    # Allow copying over itself
 
122
    if (os.path.normpath(os.path.join(os.getcwd(),src)) ==
 
123
        os.path.normpath(os.path.join(os.getcwd(),dst))):
 
124
        return
 
125
    
 
126
    # Try to do the copy with rsync, if that fails just copy
 
127
    try:
 
128
        action_runprog(RSYNC, ['-a','--delete',src + '/',dst], dry)
 
129
    except RunError:
 
130
        print "cp -r", src, dst
 
131
        if dry: return
 
132
        action_remove(dst, dry)
 
133
        shutil.copytree(src, dst, True)
 
134
 
 
135
def action_linktree(src, dst, dry):
 
136
    """Hard-links an entire directory tree. Same as copytree but the created
 
137
    files are hard-links not actual copies. Removes the existing destination.
 
138
    """
 
139
    action_remove(dst, dry)
 
140
    print "<cp with hardlinks> -r", src, dst
 
141
    if dry: return
 
142
    common.makeuser.linktree(src, dst)
 
143
 
 
144
def action_copylist(srclist, dst, dry, srcdir="."):
 
145
    """Copies all files in a list to a new location. The files in the list
 
146
    are read relative to the current directory, and their destinations are the
 
147
    same paths relative to dst. Creates all parent directories as necessary.
 
148
    srcdir is "." by default, can be overridden.
 
149
    """
 
150
    for srcfile in srclist:
 
151
        dstfile = os.path.join(dst, srcfile)
 
152
        srcfile = os.path.join(srcdir, srcfile)
 
153
        dstdir = os.path.split(dstfile)[0]
 
154
        if not os.path.isdir(dstdir):
 
155
            action_mkdir(dstdir, dry)
 
156
        print "cp -f", srcfile, dstfile
 
157
        if not dry:
 
158
            try:
 
159
                shutil.copyfile(srcfile, dstfile)
 
160
                shutil.copymode(srcfile, dstfile)
 
161
            except shutil.Error:
 
162
                pass
 
163
 
 
164
def action_copyfile(src, dst, dry):
 
165
    """Copies one file to a new location. Creates all parent directories
 
166
    as necessary.
 
167
    Warn if file not found.
 
168
    """
 
169
    dstdir = os.path.split(dst)[0]
 
170
    if not os.path.isdir(dstdir):
 
171
        action_mkdir(dstdir, dry)
 
172
    print "cp -f", src, dst
 
173
    if not dry:
 
174
        try:
 
175
            shutil.copyfile(src, dst)
 
176
            shutil.copymode(src, dst)
 
177
        except (shutil.Error, IOError), e:
 
178
            print "Warning: " + str(e)
 
179
 
 
180
def action_symlink(src, dst, dry):
 
181
    """Creates a symlink in a given location. Creates all parent directories
 
182
    as necessary.
 
183
    """
 
184
    dstdir = os.path.split(dst)[0]
 
185
    if not os.path.isdir(dstdir):
 
186
        action_mkdir(dstdir, dry)
 
187
    # Delete existing file
 
188
    if os.path.exists(dst):
 
189
        os.remove(dst)
 
190
    print "ln -fs", src, dst
 
191
    if not dry:
 
192
        os.symlink(src, dst)
 
193
 
 
194
def action_append(ivle_pth, ivle_www):
 
195
    file = open(ivle_pth, 'a+')
 
196
    file.write(ivle_www + '\n')
 
197
    file.close()
 
198
 
 
199
def action_chown_setuid(file, dry):
 
200
    """Chowns a file to root, and sets the setuid bit on the file.
 
201
    Calling this function requires the euid to be root.
 
202
    The actual mode of path is set to: rws--s--s
 
203
    """
 
204
    print "chown root:root", file
 
205
    if not dry:
 
206
        os.chown(file, 0, 0)
 
207
    print "chmod a+xs", file
 
208
    print "chmod u+rw", file
 
209
    if not dry:
 
210
        os.chmod(file, stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
 
211
            | stat.S_ISUID | stat.S_IRUSR | stat.S_IWUSR)
 
212
 
 
213
def action_chmod_x(file, dry):
 
214
    """Chmod 755 a file (sets permissions to rwxr-xr-x)."""
 
215
    print "chmod 755", file
 
216
    if not dry:
 
217
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
 
218
            | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH)
 
219
 
 
220
def query_user(default, prompt):
 
221
    """Prompts the user for a string, which is read from a line of stdin.
 
222
    Exits silently if EOF is encountered. Returns the string, with spaces
 
223
    removed from the beginning and end.
 
224
 
 
225
    Returns default if a 0-length line (after spaces removed) was read.
 
226
    """
 
227
    sys.stdout.write('%s\n    (default: "%s")\n>' % (prompt, default))
 
228
    try:
 
229
        val = sys.stdin.readline()
 
230
    except KeyboardInterrupt:
 
231
        # Ctrl+C
 
232
        sys.stdout.write("\n")
 
233
        sys.exit(1)
 
234
    sys.stdout.write("\n")
 
235
    # If EOF, exit
 
236
    if val == '': sys.exit(1)
 
237
    # If empty line, return default
 
238
    val = val.strip()
 
239
    if val == '': return default
 
240
    return val
 
241
 
 
242
def filter_mutate(function, list):
 
243
    """Like built-in filter, but mutates the given list instead of returning a
 
244
    new one. Returns None."""
 
245
    i = len(list)-1
 
246
    while i >= 0:
 
247
        # Delete elements which do not match
 
248
        if not function(list[i]):
 
249
            del list[i]
 
250
        i -= 1
 
251
 
 
252
def get_svn_revision():
 
253
    """Returns either the current SVN revision of this build, or None"""
 
254
    try:
 
255
        svn = pysvn.Client()
 
256
        entry = svn.info('.')
 
257
        revnum = entry.revision.number
 
258
    except pysvn.ClientError, e:
 
259
        revnum = None
 
260
    return revnum
 
261