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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: dcoles
  • Date: 2008-07-03 04:20:54 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:803
Setup: Modularised setup.py so it is now no longer over 1000 lines. This should 
allow us to get in there and tidy up each module much easier. Also removed 
updatejails since this functionality seems to be duplicated with remakeuser.py 
and remakealluser.py scripts.

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
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.
 
70
    dry: Bool. If True, prints but does not execute.
 
71
    """
 
72
    print prog, string.join(args, ' ')
 
73
    if dry: return
 
74
    ret = os.spawnvp(os.P_WAIT, prog, args)
 
75
    if ret != 0:
 
76
        raise RunError(prog, ret)
 
77
 
 
78
def action_remove(path, dry):
 
79
    """Calls rmtree, deleting the target file if it exists."""
 
80
    try:
 
81
        print "rm -r", path
 
82
        if not dry:
 
83
            shutil.rmtree(path, True)
 
84
    except OSError, (err, msg):
 
85
        if err != errno.EEXIST:
 
86
            raise
 
87
        # Otherwise, didn't exist, so we don't care
 
88
 
 
89
def action_rename(src, dst, dry):
 
90
    """Calls rename. Deletes the target if it already exists."""
 
91
    action_remove(dst, dry)
 
92
    print "mv ", src, dst
 
93
    if dry: return
 
94
    try:
 
95
        os.rename(src, dst)
 
96
    except OSError, (err, msg):
 
97
        if err != errno.EEXIST:
 
98
            raise
 
99
 
 
100
def action_mkdir(path, dry):
 
101
    """Calls mkdir. Silently ignored if the directory already exists.
 
102
    Creates all parent directories as necessary."""
 
103
    print "mkdir -p", path
 
104
    if dry: return
 
105
    try:
 
106
        os.makedirs(path)
 
107
    except OSError, (err, msg):
 
108
        if err != errno.EEXIST:
 
109
            raise
 
110
 
 
111
def action_copytree(src, dst, dry):
 
112
    """Copies an entire directory tree. Symlinks are seen as normal files and
 
113
    copies of the entire file (not the link) are made. Creates all parent
 
114
    directories as necessary.
 
115
 
 
116
    See shutil.copytree."""
 
117
    # Allow copying over itself
 
118
    if (os.path.normpath(os.path.join(os.getcwd(),src)) ==
 
119
        os.path.normpath(os.path.join(os.getcwd(),dst))):
 
120
        return
 
121
    action_remove(dst, dry)
 
122
    print "cp -r", src, dst
 
123
    if dry: return
 
124
    shutil.copytree(src, dst, True)
 
125
 
 
126
def action_linktree(src, dst, dry):
 
127
    """Hard-links an entire directory tree. Same as copytree but the created
 
128
    files are hard-links not actual copies. Removes the existing destination.
 
129
    """
 
130
    action_remove(dst, dry)
 
131
    print "<cp with hardlinks> -r", src, dst
 
132
    if dry: return
 
133
    common.makeuser.linktree(src, dst)
 
134
 
 
135
def action_copylist(srclist, dst, dry, srcdir="."):
 
136
    """Copies all files in a list to a new location. The files in the list
 
137
    are read relative to the current directory, and their destinations are the
 
138
    same paths relative to dst. Creates all parent directories as necessary.
 
139
    srcdir is "." by default, can be overridden.
 
140
    """
 
141
    for srcfile in srclist:
 
142
        dstfile = os.path.join(dst, srcfile)
 
143
        srcfile = os.path.join(srcdir, srcfile)
 
144
        dstdir = os.path.split(dstfile)[0]
 
145
        if not os.path.isdir(dstdir):
 
146
            action_mkdir(dstdir, dry)
 
147
        print "cp -f", srcfile, dstfile
 
148
        if not dry:
 
149
            try:
 
150
                shutil.copyfile(srcfile, dstfile)
 
151
                shutil.copymode(srcfile, dstfile)
 
152
            except shutil.Error:
 
153
                pass
 
154
 
 
155
def action_copyfile(src, dst, dry):
 
156
    """Copies one file to a new location. Creates all parent directories
 
157
    as necessary.
 
158
    Warn if file not found.
 
159
    """
 
160
    dstdir = os.path.split(dst)[0]
 
161
    if not os.path.isdir(dstdir):
 
162
        action_mkdir(dstdir, dry)
 
163
    print "cp -f", src, dst
 
164
    if not dry:
 
165
        try:
 
166
            shutil.copyfile(src, dst)
 
167
            shutil.copymode(src, dst)
 
168
        except (shutil.Error, IOError), e:
 
169
            print "Warning: " + str(e)
 
170
 
 
171
def action_symlink(src, dst, dry):
 
172
    """Creates a symlink in a given location. Creates all parent directories
 
173
    as necessary.
 
174
    """
 
175
    dstdir = os.path.split(dst)[0]
 
176
    if not os.path.isdir(dstdir):
 
177
        action_mkdir(dstdir, dry)
 
178
    # Delete existing file
 
179
    if os.path.exists(dst):
 
180
        os.remove(dst)
 
181
    print "ln -fs", src, dst
 
182
    if not dry:
 
183
        os.symlink(src, dst)
 
184
 
 
185
def action_append(ivle_pth, ivle_www):
 
186
    file = open(ivle_pth, 'a+')
 
187
    file.write(ivle_www + '\n')
 
188
    file.close()
 
189
 
 
190
def action_chown_setuid(file, dry):
 
191
    """Chowns a file to root, and sets the setuid bit on the file.
 
192
    Calling this function requires the euid to be root.
 
193
    The actual mode of path is set to: rws--s--s
 
194
    """
 
195
    print "chown root:root", file
 
196
    if not dry:
 
197
        os.chown(file, 0, 0)
 
198
    print "chmod a+xs", file
 
199
    print "chmod u+rw", file
 
200
    if not dry:
 
201
        os.chmod(file, stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
 
202
            | stat.S_ISUID | stat.S_IRUSR | stat.S_IWUSR)
 
203
 
 
204
def action_chmod_x(file, dry):
 
205
    """Chmod 755 a file (sets permissions to rwxr-xr-x)."""
 
206
    print "chmod 755", file
 
207
    if not dry:
 
208
        os.chmod(file, stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR
 
209
            | stat.S_IXGRP | stat.S_IRGRP | stat.S_IXOTH | stat.S_IROTH)
 
210
 
 
211
def query_user(default, prompt):
 
212
    """Prompts the user for a string, which is read from a line of stdin.
 
213
    Exits silently if EOF is encountered. Returns the string, with spaces
 
214
    removed from the beginning and end.
 
215
 
 
216
    Returns default if a 0-length line (after spaces removed) was read.
 
217
    """
 
218
    sys.stdout.write('%s\n    (default: "%s")\n>' % (prompt, default))
 
219
    try:
 
220
        val = sys.stdin.readline()
 
221
    except KeyboardInterrupt:
 
222
        # Ctrl+C
 
223
        sys.stdout.write("\n")
 
224
        sys.exit(1)
 
225
    sys.stdout.write("\n")
 
226
    # If EOF, exit
 
227
    if val == '': sys.exit(1)
 
228
    # If empty line, return default
 
229
    val = val.strip()
 
230
    if val == '': return default
 
231
    return val
 
232
 
 
233
def filter_mutate(function, list):
 
234
    """Like built-in filter, but mutates the given list instead of returning a
 
235
    new one. Returns None."""
 
236
    i = len(list)-1
 
237
    while i >= 0:
 
238
        # Delete elements which do not match
 
239
        if not function(list[i]):
 
240
            del list[i]
 
241
        i -= 1
 
242
 
 
243
def get_svn_revision():
 
244
    """Returns either the current SVN revision of this build, or None"""
 
245
    try:
 
246
        svn = pysvn.Client()
 
247
        entry = svn.info('.')
 
248
        revnum = entry.revision.number
 
249
    except pysvn.ClientError, e:
 
250
        revnum = None
 
251
    return revnum
 
252