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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: dcoles
  • Date: 2008-08-13 07:26:44 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1017
Console: Refactored a lot of the console stuff into a class to make calls to 
the console from Python a lot nicer. Eventually it should even be able to be 
used by consoleservice but needs a little more work (at the moment it's only 
used for starting the console).
Also added in a few Tutorial specific functions to console such as 'inspect' 
which gives a summary of the the evaluated code block and flush to clear and 
optionally set globals.

Listmake will need to be rerun after this revision due to the new 
lib/common/console.py

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
# UID of the Webserver
 
47
wwwuid = 33
 
48
 
 
49
def copy_file_to_jail(src, dry):
 
50
    """Copies a single file from an absolute location into the same location
 
51
    within the jail. src must begin with a '/'. The jail will be located
 
52
    in a 'jail' subdirectory of the current path."""
 
53
    action_copyfile(src, 'jail' + src, dry)
 
54
 
 
55
# The actions call Python os functions but print actions and handle dryness.
 
56
# May still throw os exceptions if errors occur.
 
57
 
 
58
class RunError:
 
59
    """Represents an error when running a program (nonzero return)."""
 
60
    def __init__(self, prog, retcode):
 
61
        self.prog = prog
 
62
        self.retcode = retcode
 
63
    def __str__(self):
 
64
        return str(self.prog) + " returned " + repr(self.retcode)
 
65
 
 
66
def action_runprog(prog, args, dry):
 
67
    """Runs a unix program. Searches in $PATH. Synchronous (waits for the
 
68
    program to return). Runs in the current environment. First prints the
 
69
    action as a "bash" line.
 
70
 
 
71
    Throws a RunError with a retcode of the return value of the program,
 
72
    if the program did not return 0.
 
73
 
 
74
    prog: String. Name of the program. (No path required, if in $PATH).
 
75
    args: [String]. Arguments to the program. (Note, this does not allow you to
 
76
        set argv[0]; it will always be prog.)
 
77
    dry: Bool. If True, prints but does not execute.
 
78
    """
 
79
    print prog, string.join(args, ' ')
 
80
    if dry: return
 
81
    ret = os.spawnvp(os.P_WAIT, prog, [prog] + args)
 
82
    if ret != 0:
 
83
        raise RunError(prog, ret)
 
84
 
 
85
def action_remove(path, dry):
 
86
    """Calls rmtree, deleting the target file if it exists."""
 
87
    try:
 
88
        print "rm -r", path
 
89
        if not dry:
 
90
            shutil.rmtree(path, True)
 
91
    except OSError, (err, msg):
 
92
        if err != errno.EEXIST:
 
93
            raise
 
94
        # Otherwise, didn't exist, so we don't care
 
95
 
 
96
def action_rename(src, dst, dry):
 
97
    """Calls rename. Deletes the target if it already exists."""
 
98
    action_remove(dst, dry)
 
99
    print "mv ", src, dst
 
100
    if dry: return
 
101
    try:
 
102
        os.rename(src, dst)
 
103
    except OSError, (err, msg):
 
104
        if err != errno.EEXIST:
 
105
            raise
 
106
 
 
107
def action_mkdir(path, dry):
 
108
    """Calls mkdir. Silently ignored if the directory already exists.
 
109
    Creates all parent directories as necessary."""
 
110
    print "mkdir -p", path
 
111
    if dry: return
 
112
    try:
 
113
        os.makedirs(path)
 
114
    except OSError, (err, msg):
 
115
        if err != errno.EEXIST:
 
116
            raise
 
117
 
 
118
def action_copytree(src, dst, dry):
 
119
    """Copies an entire directory tree. Symlinks are seen as normal files and
 
120
    copies of the entire file (not the link) are made. Creates all parent
 
121
    directories as necessary.
 
122
 
 
123
    See shutil.copytree."""
 
124
    # Allow copying over itself
 
125
    if (os.path.normpath(os.path.join(os.getcwd(),src)) ==
 
126
        os.path.normpath(os.path.join(os.getcwd(),dst))):
 
127
        return
 
128
    
 
129
    # Try to do the copy with rsync, if that fails just copy
 
130
    try:
 
131
        action_runprog(RSYNC, ['-a','--delete',src + '/',dst], dry)
 
132
    except RunError:
 
133
        print "cp -r", src, dst
 
134
        if dry: return
 
135
        action_remove(dst, dry)
 
136
        shutil.copytree(src, dst, True)
 
137
 
 
138
def action_linktree(src, dst, dry):
 
139
    """Hard-links an entire directory tree. Same as copytree but the created
 
140
    files are hard-links not actual copies. Removes the existing destination.
 
141
    """
 
142
    action_remove(dst, dry)
 
143
    print "<cp with hardlinks> -r", src, dst
 
144
    if dry: return
 
145
    common.makeuser.linktree(src, dst)
 
146
 
 
147
def action_copylist(srclist, dst, dry, srcdir="."):
 
148
    """Copies all files in a list to a new location. The files in the list
 
149
    are read relative to the current directory, and their destinations are the
 
150
    same paths relative to dst. Creates all parent directories as necessary.
 
151
    srcdir is "." by default, can be overridden.
 
152
    """
 
153
    for srcfile in srclist:
 
154
        dstfile = os.path.join(dst, srcfile)
 
155
        srcfile = os.path.join(srcdir, srcfile)
 
156
        dstdir = os.path.split(dstfile)[0]
 
157
        if not os.path.isdir(dstdir):
 
158
            action_mkdir(dstdir, dry)
 
159
        print "cp -f", srcfile, dstfile
 
160
        if not dry:
 
161
            try:
 
162
                shutil.copyfile(srcfile, dstfile)
 
163
                shutil.copymode(srcfile, dstfile)
 
164
            except shutil.Error:
 
165
                pass
 
166
 
 
167
def action_copyfile(src, dst, dry):
 
168
    """Copies one file to a new location. Creates all parent directories
 
169
    as necessary.
 
170
    Warn if file not found.
 
171
    """
 
172
    dstdir = os.path.split(dst)[0]
 
173
    if not os.path.isdir(dstdir):
 
174
        action_mkdir(dstdir, dry)
 
175
    print "cp -f", src, dst
 
176
    if not dry:
 
177
        try:
 
178
            shutil.copyfile(src, dst)
 
179
            shutil.copymode(src, dst)
 
180
        except (shutil.Error, IOError), e:
 
181
            print "Warning: " + str(e)
 
182
 
 
183
def action_symlink(src, dst, dry):
 
184
    """Creates a symlink in a given location. Creates all parent directories
 
185
    as necessary.
 
186
    """
 
187
    dstdir = os.path.split(dst)[0]
 
188
    if not os.path.isdir(dstdir):
 
189
        action_mkdir(dstdir, dry)
 
190
    # Delete existing file
 
191
    if os.path.exists(dst):
 
192
        os.remove(dst)
 
193
    print "ln -fs", src, dst
 
194
    if not dry:
 
195
        os.symlink(src, dst)
 
196
 
 
197
def action_append(ivle_pth, ivle_www):
 
198
    file = open(ivle_pth, 'a+')
 
199
    file.write(ivle_www + '\n')
 
200
    file.close()
 
201
 
 
202
def action_chown_setuid(file, dry):
 
203
    """Chowns a file to root, and sets the setuid bit on the file.
 
204
    Calling this function requires the euid to be root.
 
205
    The actual mode of path is set to: rws--s--s
 
206
    """
 
207
    print "chown root:root", file
 
208
    if not dry:
 
209
        os.chown(file, 0, 0)
 
210
    print "chmod a+xs", file
 
211
    print "chmod u+rw", file
 
212
    if not dry:
 
213
        os.chmod(file, stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
 
214
            | stat.S_ISUID | stat.S_IRUSR | stat.S_IWUSR)
 
215
 
 
216
def action_chmod_x(file, dry):
 
217
    """Chmod 755 a file (sets permissions to rwxr-xr-x)."""
 
218
    print "chmod 755", file
 
219
    if not dry:
 
220
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
 
221
            | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH)
 
222
 
 
223
def action_make_private(file, dry):
 
224
    """Ensures that a file is private to IVLE (chowns to www-data and chmod to 
 
225
    600)"""
 
226
    print "chown %s:%s %s"%(wwwuid, wwwuid, file)
 
227
    if not dry:
 
228
        os.chown(file, wwwuid, wwwuid)
 
229
    print "chmod 600", file
 
230
    if not dry:
 
231
        os.chmod(file, stat.S_IRUSR | stat.S_IWUSR)
 
232
 
 
233
def query_user(default, prompt):
 
234
    """Prompts the user for a string, which is read from a line of stdin.
 
235
    Exits silently if EOF is encountered. Returns the string, with spaces
 
236
    removed from the beginning and end.
 
237
 
 
238
    Returns default if a 0-length line (after spaces removed) was read.
 
239
    """
 
240
    sys.stdout.write('%s\n    (default: "%s")\n>' % (prompt, default))
 
241
    try:
 
242
        val = sys.stdin.readline()
 
243
    except KeyboardInterrupt:
 
244
        # Ctrl+C
 
245
        sys.stdout.write("\n")
 
246
        sys.exit(1)
 
247
    sys.stdout.write("\n")
 
248
    # If EOF, exit
 
249
    if val == '': sys.exit(1)
 
250
    # If empty line, return default
 
251
    val = val.strip()
 
252
    if val == '': return default
 
253
    return val
 
254
 
 
255
def filter_mutate(function, list):
 
256
    """Like built-in filter, but mutates the given list instead of returning a
 
257
    new one. Returns None."""
 
258
    i = len(list)-1
 
259
    while i >= 0:
 
260
        # Delete elements which do not match
 
261
        if not function(list[i]):
 
262
            del list[i]
 
263
        i -= 1
 
264
 
 
265
def get_svn_revision():
 
266
    """Returns either the current SVN revision of this build, or None"""
 
267
    try:
 
268
        svn = pysvn.Client()
 
269
        entry = svn.info('.')
 
270
        revnum = entry.revision.number
 
271
    except pysvn.ClientError, e:
 
272
        revnum = None
 
273
    return revnum
 
274