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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: matt.giuca
  • Date: 2009-01-12 00:36:24 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1074
Removed "prototypes" directory (very old and clearly no longer used).

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