Edgewall Software

TracOnWindows: trac-0.10.3-win32-install.py

File trac-0.10.3-win32-install.py, 11.7 kB (added by cboos, 22 months ago)

All-in-one installer (not a graphical installer)

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