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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: William Grant
  • Date: 2009-01-13 01:36:15 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1123
Merge setup-refactor branch. This completely breaks existing installations;
every path (both filesystem and Python) has changed. Do not upgrade without
knowing what you are doing.

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