~ubuntu-branches/ubuntu/precise/enigmail/precise-security

« back to all changes in this revision

Viewing changes to mozilla/testing/mozbase/setup_development.py

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2014-01-30 11:42:56 UTC
  • mfrom: (0.12.17)
  • Revision ID: package-import@ubuntu.com-20140130114256-6yvx7ylu1cwrhwp2
Tags: 2:1.7-0ubuntu0.12.04.1
* New upstream release v1.7 to support Thunderbird 31

* No longer requires a Mozilla build system, so we use the upstream
  tarball directly now
  - update debian/rules
  - drop libgtk2.0-dev, libidl-dev, libdbus-glib-1-dev, libnotify-dev,
    libasound2-dev, libxt-dev, autoconf2.13 and mesa-common-dev
    build-depends, as these were only there because we were using a hacked
    Mozilla build system
* Update to source format 3.0
* Drop thunderbird-dev build-depend - the only binary code in enigmail now
  uses ctypes, so we don't need the SDK
* Drop debian/patches/no_libxpcom.patch - it doesn't build a binary component
  now
* Drop debian/patches/use_sdk.patch - there's no dependency on the
  Thunderbird SDK now

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
 
3
 
# This Source Code Form is subject to the terms of the Mozilla Public
4
 
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
5
 
# You can obtain one at http://mozilla.org/MPL/2.0/.
6
 
 
7
 
"""
8
 
Setup mozbase packages for development.
9
 
 
10
 
Packages may be specified as command line arguments.
11
 
If no arguments are given, install all packages.
12
 
 
13
 
See https://wiki.mozilla.org/Auto-tools/Projects/MozBase
14
 
"""
15
 
 
16
 
import pkg_resources
17
 
import os
18
 
import sys
19
 
from optparse import OptionParser
20
 
 
21
 
from subprocess import PIPE
22
 
try:
23
 
    from subprocess import check_call as call
24
 
except ImportError:
25
 
    from subprocess import call
26
 
 
27
 
 
28
 
# directory containing this file
29
 
here = os.path.dirname(os.path.abspath(__file__))
30
 
 
31
 
# all python packages
32
 
all_packages = [i for i in os.listdir(here)
33
 
                if os.path.exists(os.path.join(here, i, 'setup.py'))]
34
 
 
35
 
def cycle_check(order, dependencies):
36
 
    """ensure no cyclic dependencies"""
37
 
    order_dict = dict([(j, i) for i, j in enumerate(order)])
38
 
    for package, deps in dependencies.items():
39
 
        index = order_dict[package]
40
 
        for d in deps:
41
 
            assert index > order_dict[d], "Cyclic dependencies detected"
42
 
 
43
 
def info(directory):
44
 
    "get the package setup.py information"
45
 
 
46
 
    assert os.path.exists(os.path.join(directory, 'setup.py'))
47
 
 
48
 
    # setup the egg info
49
 
    call([sys.executable, 'setup.py', 'egg_info'], cwd=directory, stdout=PIPE)
50
 
 
51
 
    # get the .egg-info directory
52
 
    egg_info = [entry for entry in os.listdir(directory)
53
 
                if entry.endswith('.egg-info')]
54
 
    assert len(egg_info) == 1, 'Expected one .egg-info directory in %s, got: %s' % (directory, egg_info)
55
 
    egg_info = os.path.join(directory, egg_info[0])
56
 
    assert os.path.isdir(egg_info), "%s is not a directory" % egg_info
57
 
 
58
 
    # read the package information
59
 
    pkg_info = os.path.join(egg_info, 'PKG-INFO')
60
 
    info_dict = {}
61
 
    for line in file(pkg_info).readlines():
62
 
        if not line or line[0].isspace():
63
 
            continue # XXX neglects description
64
 
        assert ':' in line
65
 
        key, value = [i.strip() for i in line.split(':', 1)]
66
 
        info_dict[key] = value
67
 
 
68
 
    return info_dict
69
 
 
70
 
def get_dependencies(directory):
71
 
    "returns the package name and dependencies given a package directory"
72
 
 
73
 
    # get the package metadata
74
 
    info_dict = info(directory)
75
 
 
76
 
    # get the .egg-info directory
77
 
    egg_info = [entry for entry in os.listdir(directory)
78
 
                if entry.endswith('.egg-info')][0]
79
 
 
80
 
    # read the dependencies
81
 
    requires = os.path.join(directory, egg_info, 'requires.txt')
82
 
    if os.path.exists(requires):
83
 
        dependencies = [line.strip()
84
 
                        for line in file(requires).readlines()
85
 
                        if line.strip()]
86
 
    else:
87
 
        dependencies = []
88
 
 
89
 
    # return the information
90
 
    return info_dict['Name'], dependencies
91
 
 
92
 
def dependency_info(dep):
93
 
    "return dictionary of dependency information from a dependency string"
94
 
    retval = dict(Name=None, Type=None, Version=None)
95
 
    for joiner in ('==', '<=', '>='):
96
 
        if joiner in dep:
97
 
            retval['Type'] = joiner
98
 
            name, version = [i.strip() for i in dep.split(joiner, 1)]
99
 
            retval['Name'] = name
100
 
            retval['Version'] = version
101
 
            break
102
 
    else:
103
 
        retval['name'] = dep.strip()
104
 
    return retval
105
 
 
106
 
def unroll_dependencies(dependencies):
107
 
    """
108
 
    unroll a set of dependencies to a flat list
109
 
 
110
 
    dependencies = {'packageA': set(['packageB', 'packageC', 'packageF']),
111
 
                    'packageB': set(['packageC', 'packageD', 'packageE', 'packageG']),
112
 
                    'packageC': set(['packageE']),
113
 
                    'packageE': set(['packageF', 'packageG']),
114
 
                    'packageF': set(['packageG']),
115
 
                    'packageX': set(['packageA', 'packageG'])}
116
 
    """
117
 
 
118
 
    order = []
119
 
 
120
 
    # flatten all
121
 
    packages = set(dependencies.keys())
122
 
    for deps in dependencies.values():
123
 
        packages.update(deps)
124
 
 
125
 
    while len(order) != len(packages):
126
 
 
127
 
        for package in packages.difference(order):
128
 
            if set(dependencies.get(package, set())).issubset(order):
129
 
                order.append(package)
130
 
                break
131
 
        else:
132
 
            raise AssertionError("Cyclic dependencies detected")
133
 
 
134
 
    cycle_check(order, dependencies) # sanity check
135
 
 
136
 
    return order
137
 
 
138
 
 
139
 
def main(args=sys.argv[1:]):
140
 
 
141
 
    # parse command line options
142
 
    usage = '%prog [options] [package] [package] [...]'
143
 
    parser = OptionParser(usage=usage, description=__doc__)
144
 
    parser.add_option('-d', '--dependencies', dest='list_dependencies',
145
 
                      action='store_true', default=False,
146
 
                      help="list dependencies for the packages")
147
 
    parser.add_option('--list', action='store_true', default=False,
148
 
                      help="list what will be installed")
149
 
    options, packages = parser.parse_args(args)
150
 
 
151
 
    if not packages:
152
 
        # install all packages
153
 
        packages = sorted(all_packages)
154
 
 
155
 
    # ensure specified packages are in the list
156
 
    assert set(packages).issubset(all_packages), "Packages should be in %s (You gave: %s)" % (all_packages, packages)
157
 
 
158
 
    if options.list_dependencies:
159
 
        # list the package dependencies
160
 
        for package in packages:
161
 
            print '%s: %s' % get_dependencies(os.path.join(here, package))
162
 
        parser.exit()
163
 
 
164
 
    # gather dependencies
165
 
    # TODO: version conflict checking
166
 
    deps = {}
167
 
    alldeps = {}
168
 
    mapping = {} # mapping from subdir name to package name
169
 
    # core dependencies
170
 
    for package in packages:
171
 
        key, value = get_dependencies(os.path.join(here, package))
172
 
        deps[key] = [dependency_info(dep)['Name'] for dep in value]
173
 
        mapping[package] = key
174
 
 
175
 
        # keep track of all dependencies for non-mozbase packages
176
 
        for dep in value:
177
 
            alldeps[dependency_info(dep)['Name']] = ''.join(dep.split())
178
 
 
179
 
    # indirect dependencies
180
 
    flag = True
181
 
    while flag:
182
 
        flag = False
183
 
        for value in deps.values():
184
 
            for dep in value:
185
 
                if dep in all_packages and dep not in deps:
186
 
                    key, value = get_dependencies(os.path.join(here, dep))
187
 
                    deps[key] = [sanitize_dependency(dep) for dep in value]
188
 
 
189
 
                    for dep in value:
190
 
                        alldeps[sanitize_dependency(dep)] = ''.join(dep.split())
191
 
                    mapping[package] = key
192
 
                    flag = True
193
 
                    break
194
 
            if flag:
195
 
                break
196
 
 
197
 
    # get the remaining names for the mapping
198
 
    for package in all_packages:
199
 
        if package in mapping:
200
 
            continue
201
 
        key, value = get_dependencies(os.path.join(here, package))
202
 
        mapping[package] = key
203
 
 
204
 
    # unroll dependencies
205
 
    unrolled = unroll_dependencies(deps)
206
 
 
207
 
    # make a reverse mapping: package name -> subdirectory
208
 
    reverse_mapping = dict([(j,i) for i, j in mapping.items()])
209
 
 
210
 
    # we only care about dependencies in mozbase
211
 
    unrolled = [package for package in unrolled if package in reverse_mapping]
212
 
 
213
 
    if options.list:
214
 
        # list what will be installed
215
 
        for package in unrolled:
216
 
            print package
217
 
        parser.exit()
218
 
 
219
 
    # install non-mozbase dependencies
220
 
    # (currently none on modern python)
221
 
    # these need to be installed separately and the --no-deps flag
222
 
    # subsequently used due to a bug in setuptools; see
223
 
    # https://bugzilla.mozilla.org/show_bug.cgi?id=759836
224
 
    pypi_deps = dict([(i, j) for i,j in alldeps.items()
225
 
                      if i not in unrolled])
226
 
    for package, version in pypi_deps.items():
227
 
        # easy_install should be available since we rely on setuptools
228
 
        call(['easy_install', version])
229
 
 
230
 
    # set up the packages for development
231
 
    for package in unrolled:
232
 
        call([sys.executable, 'setup.py', 'develop', '--no-deps'],
233
 
             cwd=os.path.join(here, reverse_mapping[package]))
234
 
 
235
 
if __name__ == '__main__':
236
 
    main()