Edgewall Software

TracOnWindows/Rewrite: trac-0.10-win32-install.py

File trac-0.10-win32-install.py, 11.6 kB (added by cboos, 23 months ago)

Script updated for the 0.10 release

Line 
1#!/bin/env python
2"""Trac installer"""
3
4
5
6#!python
7"""Bootstrap setuptools installation
8
9If you want to use setuptools in your package's setup.py, just include this
10file in the same directory with it, and add this to the top of your setup.py::
11
12    from ez_setup import use_setuptools
13    use_setuptools()
14
15If you want to require a specific version of setuptools, set a download
16mirror, or use an alternate download directory, you can do so by supplying
17the appropriate options to ``use_setuptools()``.
18
19This file can also be run as a script to install or upgrade setuptools.
20"""
21import sys
22DEFAULT_VERSION = "0.6c2"
23DEFAULT_URL     = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
24
25md5_data = {
26    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
27    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
28    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
29    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
30    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
31    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
32    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
33    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
34    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
35    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
36    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
37    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
38}
39
40import sys, os
41
42# TRACBEGIN
43
44def get_python():
45    """Displays information about where to download Python for your system.
46    Currently, this will always return False. The idea is that eventually
47    it may actually download Python if you want it to (in which case, it
48    would return True)."""
49    print """
50The recommended Python for Trac is Python 2.4.3. You can download
51it here:
52
53http://www.python.org/ftp/python/2.4.3/python-2.4.3.msi
54"""
55    return False
56
57def get_yesno(default="y"):
58    """Gets a valid 'y' or 'n' answer from the user."""
59    while True:
60        fromuser = raw_input("(y|n, default %s)" % default)
61        if fromuser:
62            val = fromuser[0].lower()
63            if val == "y" or val == "n":
64                break
65        else:
66            return default
67    return val
68
69def check_python():
70    if sys.version_info[:2] != (2,4):
71        print """
72This installer requires Python 2.4
73"""
74        if not get_python():
75            sys.exit(1)
76
77def check_directory():
78    """Ensures that the current directory does not contain a Trac
79    directory that setuptools will attempt to install from."""
80    if os.path.exists("trac") or os.path.exists("Trac"):
81        print """There is a 'trac' directory in the current directory.
82        EasyInstall will normally try to install from this directory rather
83        than picking up the installation package from the net."""
84        if os.access("..", os.W_OK) and not \
85            os.path.exists(os.path.join("..", "trac")) and not \
86            os.path.exists(os.path.join("..", "Trac")):
87            print """
88This installer needs a place to store the setuptools installation
89package to do its work. The parent directory of this one is writeable.
90Should the installation proceed from there ('n' to exit)?"""
91            upone = get_yesno()
92            if upone == "n":
93                sys.exit(1)
94            os.chdir("..")
95        else:
96            print """
97This installer needs to run in a directory that does not contain a
98'trac' directory and it also needs to run in a directory that
99you have write access to. Please change directories and rerun this
100installer.
101"""
102            sys.exit(1)
103
104def check_subversion(args):
105    try:
106        from svn import fs
107    except ImportError:
108        pass
109    else:
110        return
111    print """
112Would you like to use Trac with a Subversion repository
113"""
114    usesvn = get_yesno()
115    if usesvn:
116        args.insert(0, '-Z')
117        args.append('http://subversion.tigris.org/downloads/'
118                    'svn-python-1.4.0-py2.4.exe')
119
120def update_args():
121    """Sets up the command line arguments for ez_setup.py"""
122    if len(sys.argv) > 1:
123        args = sys.argv[1:]
124    else:
125        args = []
126    args.append("-f")
127    args.append("http://clearsilver.net/downloads")
128    args.append("-U")
129    args.append("clearsilver==0.9.14")
130    args.append("pysqlite")
131    args.append("http://ftp.edgewall.com/pub/trac/trac-0.10.tar.gz")
132    return args
133
134def fix_siteconfig():
135    import pkg_resources
136    del sys.modules['trac']
137    pkg_resources.require('trac')
138    siteconfig = pkg_resources.resource_filename('trac', 'siteconfig.py')
139    open(siteconfig, 'w').write("""# PLEASE DO NOT EDIT THIS FILE!
140# This file was autogenerated when installing Trac 0.10.
141#
142import os
143import pkg_resources
144_sharedir = os.path.normpath(pkg_resources.resource_filename('trac', '../share/trac'))
145
146__default_conf_dir__ = os.path.join(_sharedir, 'conf')
147__default_templates_dir__ = os.path.join(_sharedir, 'templates')
148__default_htdocs_dir__ = os.path.join(_sharedir, 'htdocs')
149__default_wiki_dir__ = os.path.join(_sharedir, 'wiki-default')
150__default_macros_dir__ = os.path.join(_sharedir, 'wiki-macros')
151__default_plugins_dir__ = os.path.join(_sharedir, 'plugins')
152""")
153
154def trac_main():
155    print "Trac Windows Installer"
156    check_python()
157    check_directory()
158    args = update_args()
159    check_subversion(args)
160    print "Beginning setuptools/EasyInstall installation and Trac" \
161          "download"
162    main(args)
163    fix_siteconfig()
164   
165# TRACEND
166
167def _validate_md5(egg_name, data):
168    if egg_name in md5_data:
169        from md5 import md5
170        digest = md5(data).hexdigest()
171        if digest != md5_data[egg_name]:
172            print >>sys.stderr, (
173                "md5 validation of %s failed!  (Possible download problem?)"
174                % egg_name
175            )
176            sys.exit(2)
177    return data
178
179
180def use_setuptools(
181    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
182    download_delay=15
183):
184    """Automatically find/download setuptools and make it available on sys.path
185
186    `version` should be a valid setuptools version number that is available
187    as an egg for download under the `download_base` URL (which should end with
188    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
189    it is not already available.  If `download_delay` is specified, it should
190    be the number of seconds that will be paused before initiating a download,
191    should one be required.  If an older version of setuptools is installed,
192    this routine will print a message to ``sys.stderr`` and raise SystemExit in
193    an attempt to abort the calling script.
194    """
195    try:
196        import setuptools
197        if setuptools.__version__ == '0.0.1':
198            print >>sys.stderr, (
199            "You have an obsolete version of setuptools installed.  Please\n"
200            "remove it from your system entirely before rerunning this script."
201            )
202            sys.exit(2)
203    except ImportError:
204        egg = download_setuptools(version, download_base, to_dir, download_delay)
205        sys.path.insert(0, egg)
206        import setuptools; setuptools.bootstrap_install_from = egg
207
208    import pkg_resources
209    try:
210        pkg_resources.require("setuptools>="+version)
211
212    except pkg_resources.VersionConflict, e:
213        # XXX could we install in a subprocess here?
214        print >>sys.stderr, (
215            "The required version of setuptools (>=%s) is not available, and\n"
216            "can't be installed while this script is running. Please install\n"
217            " a more recent version first.\n\n(Currently using %r)"
218        ) % (version, e.args[0])
219        sys.exit(2)
220
221def download_setuptools(
222    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
223    delay = 15
224):
225    """Download setuptools from a specified location and return its filename
226
227    `version` should be a valid setuptools version number that is available
228    as an egg for download under the `download_base` URL (which should end
229    with a '/'). `to_dir` is the directory where the egg will be downloaded.
230    `delay` is the number of seconds to pause before an actual download attempt.
231    """
232    import urllib2, shutil
233    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
234    url = download_base + egg_name
235    saveto = os.path.join(to_dir, egg_name)
236    src = dst = None
237    if not os.path.exists(saveto):  # Avoid repeated downloads
238        try:
239            from distutils import log
240            if delay:
241                log.warn("""
242---------------------------------------------------------------------------
243This script requires setuptools version %s to run (even to display
244help).  I will attempt to download it for you (from
245%s), but
246you may need to enable firewall access for this script first.
247I will start the download in %d seconds.
248
249(Note: if this machine does not have network access, please obtain the file
250
251   %s
252
253and place it in this directory before rerunning this script.)
254---------------------------------------------------------------------------""",
255                    version, download_base, delay, url
256                ); from time import sleep; sleep(delay)
257            log.warn("Downloading %s", url)
258            src = urllib2.urlopen(url)
259            # Read/write all in one block, so we don't create a corrupt file
260            # if the download is interrupted.
261            data = _validate_md5(egg_name, src.read())
262            dst = open(saveto,"wb"); dst.write(data)
263        finally:
264            if src: src.close()
265            if dst: dst.close()
266    return os.path.realpath(saveto)
267
268def main(argv, version=DEFAULT_VERSION):
269    """Install or upgrade setuptools and EasyInstall"""
270
271    try:
272        import setuptools
273    except ImportError:
274        egg = None
275        try:
276            egg = download_setuptools(version, delay=0)
277            sys.path.insert(0,egg)
278            from setuptools.command.easy_install import main
279            return main(list(argv)+[egg])   # we're done here
280        finally:
281            if egg and os.path.exists(egg):
282                os.unlink(egg)
283    else:
284        if setuptools.__version__ == '0.0.1':
285            # tell the user to uninstall obsolete version
286            use_setuptools(version)
287
288    req = "setuptools>="+version
289    import pkg_resources
290    try:
291        pkg_resources.require(req)
292    except pkg_resources.VersionConflict:
293        try:
294            from setuptools.command.easy_install import main
295        except ImportError:
296            from easy_install import main
297        main(list(argv)+[download_setuptools(delay=0)])
298        sys.exit(0) # try to force an exit
299    else:
300        if argv:
301            from setuptools.command.easy_install import main
302            main(argv)
303        else:
304            print "Setuptools version",version,"or greater has been installed."
305            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
306
307
308
309def update_md5(filenames):
310    """Update our built-in md5 registry"""
311
312    import re
313    from md5 import md5
314
315    for name in filenames:
316        base = os.path.basename(name)
317        f = open(name,'rb')
318        md5_data[base] = md5(f.read()).hexdigest()
319        f.close()
320
321    data = ["    %r: %r,\n" % it for it in md5_data.items()]
322    data.sort()
323    repl = "".join(data)
324
325    import inspect
326    srcfile = inspect.getsourcefile(sys.modules[__name__])
327    f = open(srcfile, 'rb'); src = f.read(); f.close()
328
329    match = re.search("\nmd5_data = {\n([^}]+)}", src)
330    if not match:
331        print >>sys.stderr, "Internal error!"
332        sys.exit(2)
333
334    src = src[:match.start(1)] + repl + src[match.end(1):]
335    f = open(srcfile,'w')
336    f.write(src)
337    f.close()
338
339
340if __name__=='__main__':
341    trac_main()