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

« back to all changes in this revision

Viewing changes to setup/setuputil.py

  • Committer: mattgiuca
  • Date: 2008-01-11 00:49:06 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:172
util: Added buildurl function.

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