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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: wagrant
  • Date: 2008-09-18 08:49:50 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:1049
setup.setuputil: Print the fake cp -r before the copy, not the removal.

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