]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blob - naoki/backend.py
Merge branch 'master' of ssh://git.ipfire.org/pub/git/ipfire-3.x into clean
[people/ms/ipfire-3.x.git] / naoki / backend.py
1 #!/usr/bin/python
2
3 import os
4
5 import chroot
6 import util
7
8 from constants import *
9
10 __cache = {
11 "package_names" : None,
12 "group_names" : None,
13 }
14
15 def get_package_names(toolchain=False):
16 if not __cache["package_names"]:
17 names = []
18 for repo in get_repositories(toolchain):
19 names.extend(repo.package_names)
20
21 __cache["package_names"] = sorted(names)
22
23 return __cache["package_names"]
24
25 def get_group_names():
26 if not __cache["group_names"]:
27 groups = []
28 for package in get_package_names():
29 package = PackageInfo(package)
30 if not package.group in groups:
31 groups.append(package.group)
32
33 __cache["group_names"] = sorted(groups)
34
35 return __cache["group_names"]
36
37 def find_package_name(name, toolchain=False):
38 if name in get_package_names(toolchain):
39 return name
40
41 for package in get_package_names(toolchain):
42 if os.path.basename(package) == name:
43 return package
44
45 def depsolve(packages, recursive=False):
46 deps = []
47 for package in packages:
48 if not package in deps:
49 deps.append(package)
50
51 if not recursive or not deps:
52 return deps
53
54 while True:
55 length = len(deps)
56 for dep in deps[:]:
57 deps.extend(dep.dependencies)
58
59 new_deps = []
60 for dep in deps:
61 if not dep in new_deps:
62 new_deps.append(dep)
63
64 deps = new_deps
65
66 if length == len(deps):
67 break
68
69 deps.sort()
70 return deps
71
72 def deptree(packages):
73 ret = [packages]
74
75 while True:
76 next = []
77 stage = ret[-1][:]
78 for package in stage[:]:
79 for dep in package.info.dependencies_all:
80 if dep in ret[-1]:
81 stage.remove(package)
82 next.append(package)
83 break
84
85 ret[-1] = stage
86 if next:
87 ret.append(next)
88 continue
89
90 break
91
92 return ret
93
94 def depsort(packages):
95 ret = []
96 for l1 in deptree(packages):
97 ret.extend(l1)
98 return ret
99
100 class PackageInfo(object):
101 __data = {}
102
103 def __init__(self, name):
104 self._name = name
105
106 def __repr__(self):
107 return "<PackageInfo %s>" % self.name
108
109 def get_data(self):
110 if not self.__data.has_key(self.name):
111 self.__data[self.name] = self.fetch()
112
113 return self.__data[self.name]
114
115 def set_data(self, data):
116 self.__data[self.name] = data
117
118 _data = property(get_data, set_data)
119
120 def fetch(self):
121 env = os.environ.copy()
122 env.update(config.environment)
123 env["PKGROOT"] = PKGSDIR
124 output = util.do("make -f %s" % self.filename, shell=True,
125 cwd=os.path.join(PKGSDIR, self.name), returnOutput=1, env=env)
126
127 ret = {}
128 for line in output.splitlines():
129 a = line.split("=", 1)
130 if not len(a) == 2: continue
131 key, val = a
132 ret[key] = val.strip("\"")
133
134 ret["FINGERPRINT"] = self.fingerprint
135
136 return ret
137
138 def fmtstr(self, s):
139 return s % self.all
140
141 def getPackage(self, naoki):
142 return Package(self.name, naoki)
143
144 @property
145 def all(self):
146 return {
147 "description" : self.description,
148 "filename" : self.filename,
149 "fingerprint" : self.fingerprint,
150 "group" : self.group,
151 "license" : self.license,
152 "maintainer" : self.maintainer,
153 "name" : self.name,
154 "objects" : self.objects,
155 "patches" : self.patches,
156 "release" : self.release,
157 "summary" : self.summary,
158 "version" : self.version,
159 }
160
161 def _dependencies(self, s, recursive=False):
162 c = s + "_CACHE"
163 if not self._data.has_key(c):
164 deps = []
165 for name in self._data.get(s).split(" "):
166 name = find_package_name(name)
167 if name:
168 deps.append(Dependency(name))
169
170 self._data.update({c : depsolve(deps, recursive)})
171
172 return self._data.get(c)
173
174 @property
175 def dependencies(self):
176 return self._dependencies("PKG_DEPENDENCIES")
177
178 @property
179 def dependencies_build(self):
180 return self._dependencies("PKG_BUILD_DEPENDENCIES")
181
182 @property
183 def dependencies_all(self):
184 return depsolve(self.dependencies + self.dependencies_build, recursive=True)
185
186 @property
187 def description(self):
188 return self._data.get("PKG_DESCRIPTION")
189
190 @property
191 def filename(self):
192 return os.path.join(PKGSDIR, self.name, os.path.basename(self.name)) + ".nm"
193
194 @property
195 def fingerprint(self):
196 return "%d" % os.stat(self.filename).st_mtime
197
198 @property
199 def group(self):
200 return self._data.get("PKG_GROUP")
201
202 @property
203 def id(self):
204 return "%s-%s-%s" % (self.name, self.version, self.release)
205
206 @property
207 def license(self):
208 return self._data.get("PKG_LICENSE")
209
210 @property
211 def maintainer(self):
212 return self._data.get("PKG_MAINTAINER")
213
214 @property
215 def name(self):
216 return self._name
217
218 @property
219 def objects(self):
220 return self._data.get("PKG_OBJECTS").split(" ")
221
222 @property
223 def package_files(self):
224 return self._data.get("PKG_PACKAGES_FILES").split(" ")
225
226 @property
227 def patches(self):
228 return self._data.get("PKG_PATCHES").split(" ")
229
230 @property
231 def release(self):
232 return self._data.get("PKG_REL")
233
234 @property
235 def summary(self):
236 return self._data.get("PKG_SUMMARY")
237
238 @property
239 def version(self):
240 return self._data.get("PKG_VER")
241
242
243 class Dependency(PackageInfo):
244 def __repr__(self):
245 return "<Dependency %s>" % self.name
246
247
248 class Package(object):
249 def __init__(self, name, naoki):
250 self.info = PackageInfo(name)
251 self.naoki = naoki
252
253 #self.log.debug("Initialized package object %s" % name)
254
255 def build(self):
256 environment = chroot.Environment(self)
257 environment.build()
258
259 def download(self):
260 return "TODO"
261 files = self.info.objects
262 #self.log.info("Downloading %s..." % files)
263 download(self.info.objects)
264
265 def extract(self, dest):
266 files = [os.path.join(PACKAGESDIR, file) for file in self.info.package_files]
267 if not files:
268 return
269
270 self.log.debug("Extracting %s..." % files)
271 util.do("%s --root=%s %s" % (os.path.join(TOOLSDIR, "decompressor"),
272 dest, " ".join(files)), shell=True)
273
274 @property
275 def log(self):
276 return self.naoki.logging.getBuildLogger(self.info.id)
277
278
279 def get_repositories(toolchain=False):
280 if toolchain:
281 return Repository("toolchain")
282
283 repos = []
284 for repo in os.listdir(PKGSDIR):
285 if os.path.isdir(os.path.join(PKGSDIR, repo)):
286 repos.append(repo)
287
288 repos.remove("toolchain")
289
290 return [Repository(repo) for repo in repos]
291
292 class Repository(object):
293 def __init__(self, name):
294 self.name = name
295
296 def __repr__(self):
297 return "<Repository %s>" % self.name
298
299 @property
300 def packages(self):
301 packages = []
302 for package in os.listdir(self.path):
303 package = PackageInfo(os.path.join(self.name, package))
304 packages.append(package)
305
306 return packages
307
308 @property
309 def package_names(self):
310 return [package.name for package in self.packages]
311
312 @property
313 def path(self):
314 return os.path.join(PKGSDIR, self.name)
315
316 if __name__ == "__main__":
317 pi = PackageInfo("core/grub")
318
319 print pi.dependencies