Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 202 lines (160 sloc) 6.618 kb
e816caa @wlach Update licensing headers for new MPL 2.0 boilerplate
wlach authored
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 # You can obtain one at http://mozilla.org/MPL/2.0/.
32e90d9 @k0s add a script to setup for development
k0s authored
4
5 """
6 Setup mozbase packages for development.
7
8 Packages may be specified as command line arguments.
9 If no arguments are given, install all packages.
10
11 See https://wiki.mozilla.org/Auto-tools/Projects/MozBase
12 """
13
14 # XXX note that currently directory names must equal package names
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 dependencies(directory):
44 """
45 get the dependencies of a package directory containing a setup.py
46 returns the package name and the list of dependencies
47 """
48 assert os.path.exists(os.path.join(directory, 'setup.py'))
49
50 # setup the egg info
51 call([sys.executable, 'setup.py', 'egg_info'], cwd=directory, stdout=PIPE)
52
53 # get the .egg-info directory
54 egg_info = [i for i in os.listdir(directory)
55 if i.endswith('.egg-info')]
56 assert len(egg_info) == 1, 'Expected one .egg-info directory in %s, got: %s' % (directory, egg_info)
57 egg_info = os.path.join(directory, egg_info[0])
58 assert os.path.isdir(egg_info), "%s is not a directory" % egg_info
59
60 # read the dependencies
61 requires = os.path.join(egg_info, 'requires.txt')
62 if os.path.exists(requires):
63 dependencies = [i.strip() for i in file(requires).readlines() if i.strip()]
64 else:
65 dependencies = []
66
67 # read the package information
68 pkg_info = os.path.join(egg_info, 'PKG-INFO')
69 info_dict = {}
70 for line in file(pkg_info).readlines():
71 if not line or line[0].isspace():
72 continue # XXX neglects description
73 assert ':' in line
74 key, value = [i.strip() for i in line.split(':', 1)]
75 info_dict[key] = value
76
77
78 # return the information
79 return info_dict['Name'], dependencies
80
81 def sanitize_dependency(dep):
82 """
83 remove version numbers from deps
84 """
85 for joiner in ('==', '<=', '>='):
86 if joiner in dep:
87 dep = dep.split(joiner, 1)[0].strip()
88 return dep # XXX only one joiner allowed right now
89 return dep
fef85bb @ahal Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
90
32e90d9 @k0s add a script to setup for development
k0s authored
91
92 def unroll_dependencies(dependencies):
93 """
94 unroll a set of dependencies to a flat list
95
96 dependencies = {'packageA': set(['packageB', 'packageC', 'packageF']),
97 'packageB': set(['packageC', 'packageD', 'packageE', 'packageG']),
98 'packageC': set(['packageE']),
99 'packageE': set(['packageF', 'packageG']),
100 'packageF': set(['packageG']),
101 'packageX': set(['packageA', 'packageG'])}
102 """
103
104 order = []
105
106 # flatten all
107 packages = set(dependencies.keys())
108 for deps in dependencies.values():
109 packages.update(deps)
110
111 while len(order) != len(packages):
112
113 for package in packages.difference(order):
114 if set(dependencies.get(package, set())).issubset(order):
115 order.append(package)
116 break
117 else:
118 raise AssertionError("Cyclic dependencies detected")
119
120 cycle_check(order, dependencies) # sanity check
fef85bb @ahal Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
121
32e90d9 @k0s add a script to setup for development
k0s authored
122 return order
fef85bb @ahal Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
123
32e90d9 @k0s add a script to setup for development
k0s authored
124
125 def main(args=sys.argv[1:]):
126
127 # parse command line options
128 usage = '%prog [options] [package] [package] [...]'
129 parser = OptionParser(usage=usage, description=__doc__)
130 parser.add_option('-d', '--dependencies', dest='list_dependencies',
131 action='store_true', default=False,
132 help="list dependencies for the packages")
133 parser.add_option('--list', action='store_true', default=False,
134 help="list what will be installed")
135 options, packages = parser.parse_args(args)
136
137 if not packages:
138 # install all packages
139 packages = sorted(all_packages)
140
141 # ensure specified packages are in the list
1cf1471 @k0s improve error message
k0s authored
142 assert set(packages).issubset(all_packages), "Packages should be in %s (You gave: %s)" % (all_packages, packages)
32e90d9 @k0s add a script to setup for development
k0s authored
143
144 if options.list_dependencies:
145 # list the package dependencies
146 for package in packages:
147 print '%s: %s' % dependencies(os.path.join(here, package))
148 parser.exit()
149
150 # gather dependencies
151 deps = {}
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
152 mapping = {} # mapping from subdir name to package name
32e90d9 @k0s add a script to setup for development
k0s authored
153 # core dependencies
154 for package in packages:
155 key, value = dependencies(os.path.join(here, package))
156 deps[key] = [sanitize_dependency(dep) for dep in value]
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
157 mapping[package] = key
32e90d9 @k0s add a script to setup for development
k0s authored
158 # indirect dependencies
159 flag = True
160 while flag:
161 flag = False
162 for value in deps.values():
163 for dep in value:
164 if dep in all_packages and dep not in deps:
165 key, value = dependencies(os.path.join(here, dep))
166 deps[key] = [sanitize_dependency(dep) for dep in value]
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
167 mapping[package] = key
32e90d9 @k0s add a script to setup for development
k0s authored
168 flag = True
169 break
170 if flag:
171 break
172
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
173 # get the remaining names for the mapping
174 for package in all_packages:
175 if package in mapping:
176 continue
177 key, value = dependencies(os.path.join(here, package))
178 mapping[package] = key
179
32e90d9 @k0s add a script to setup for development
k0s authored
180 # unroll dependencies
181 unrolled = unroll_dependencies(deps)
182
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
183 # make a reverse mapping: package name -> subdirectory
184 reverse_mapping = dict([(j,i) for i, j in mapping.items()])
32e90d9 @k0s add a script to setup for development
k0s authored
185
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
186 # we only care about dependencies in mozbase
187 unrolled = [package for package in unrolled if package in reverse_mapping]
fef85bb @ahal Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
188
32e90d9 @k0s add a script to setup for development
k0s authored
189 if options.list:
190 # list what will be installed
191 for package in unrolled:
192 print package
193 parser.exit()
194
195 # set up the packages for development
196 for package in unrolled:
fef85bb @ahal Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
197 call([sys.executable, 'setup.py', 'develop'],
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
198 cwd=os.path.join(here, reverse_mapping[package]))
32e90d9 @k0s add a script to setup for development
k0s authored
199
200 if __name__ == '__main__':
201 main()
Something went wrong with that request. Please try again.