OLD | NEW |
1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 # | 4 # |
5 # Adapted from portage/getbinpkg.py -- Portage binary-package helper functions | 5 # Adapted from portage/getbinpkg.py -- Portage binary-package helper functions |
6 # Copyright 2003-2004 Gentoo Foundation | 6 # Copyright 2003-2004 Gentoo Foundation |
7 # Distributed under the terms of the GNU General Public License v2 | 7 # Distributed under the terms of the GNU General Public License v2 |
8 | 8 |
9 import operator | 9 import operator |
10 import os | 10 import os |
11 import tempfile | 11 import tempfile |
12 import time | 12 import time |
13 import urllib2 | 13 import urllib2 |
14 import urlparse | |
15 | 14 |
16 class PackageIndex(object): | 15 class PackageIndex(object): |
17 """A parser for the Portage Packages index file. | 16 """A parser for the Portage Packages index file. |
18 | 17 |
19 The Portage Packages index file serves to keep track of what packages are | 18 The Portage Packages index file serves to keep track of what packages are |
20 included in a tree. It contains the following sections: | 19 included in a tree. It contains the following sections: |
21 1) The header. The header tracks general key/value pairs that don't apply | 20 1) The header. The header tracks general key/value pairs that don't apply |
22 to any specific package. E.g., it tracks the base URL of the packages | 21 to any specific package. E.g., it tracks the base URL of the packages |
23 file, and the number of packages included in the file. The header is | 22 file, and the number of packages included in the file. The header is |
24 terminated by a blank line. | 23 terminated by a blank line. |
(...skipping 22 matching lines...) Expand all Loading... |
47 | 46 |
48 Args: | 47 Args: |
49 db: Dictionary to populate with SHA1 -> URL mapping for packages. | 48 db: Dictionary to populate with SHA1 -> URL mapping for packages. |
50 """ | 49 """ |
51 | 50 |
52 uri = self.header['URI'] | 51 uri = self.header['URI'] |
53 for pkg in self.packages: | 52 for pkg in self.packages: |
54 cpv, sha1 = pkg['CPV'], pkg.get('SHA1') | 53 cpv, sha1 = pkg['CPV'], pkg.get('SHA1') |
55 if sha1: | 54 if sha1: |
56 path = pkg.get('PATH', cpv + '.tbz2') | 55 path = pkg.get('PATH', cpv + '.tbz2') |
57 db[sha1] = urlparse.urljoin(uri, path) | 56 db[sha1] = '%s/%s' % (uri.rstrip('/'), path) |
58 | 57 |
59 def _ReadPkgIndex(self, pkgfile): | 58 def _ReadPkgIndex(self, pkgfile): |
60 """Read a list of key/value pairs from the Packages file into a dictionary. | 59 """Read a list of key/value pairs from the Packages file into a dictionary. |
61 | 60 |
62 Both header entries and package entries are lists of key/value pairs, so | 61 Both header entries and package entries are lists of key/value pairs, so |
63 they can both be read by this function. Entries can be terminated by empty | 62 they can both be read by this function. Entries can be terminated by empty |
64 lines or by the end of the file. | 63 lines or by the end of the file. |
65 | 64 |
66 This function will read lines from the specified file until it encounters | 65 This function will read lines from the specified file until it encounters |
67 the a blank line or the end of the file. | 66 the a blank line or the end of the file. |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 | 193 |
195 Args: | 194 Args: |
196 base_uri: Base URI for all packages in the file. We set | 195 base_uri: Base URI for all packages in the file. We set |
197 self.header['URI'] to this value, so all packages must live under | 196 self.header['URI'] to this value, so all packages must live under |
198 this directory. | 197 this directory. |
199 path_prefix: Path prefix to use for all current packages in the file. | 198 path_prefix: Path prefix to use for all current packages in the file. |
200 This will be added to the beginning of the path for every package. | 199 This will be added to the beginning of the path for every package. |
201 """ | 200 """ |
202 self.header['URI'] = base_uri | 201 self.header['URI'] = base_uri |
203 for pkg in self.packages: | 202 for pkg in self.packages: |
204 pkg['PATH'] = urlparse.urljoin(path_prefix, pkg['CPV'] + '.tbz2') | 203 pkg['PATH'] = '%s/%s' % (path_prefix.rstrip('/'), pkg['CPV'] + '.tbz2') |
205 | 204 |
206 def Write(self, pkgfile): | 205 def Write(self, pkgfile): |
207 """Write a packages file to disk. | 206 """Write a packages file to disk. |
208 | 207 |
209 If 'modified' flag is set, the TIMESTAMP and PACKAGES fields in the header | 208 If 'modified' flag is set, the TIMESTAMP and PACKAGES fields in the header |
210 will be updated before writing to disk. | 209 will be updated before writing to disk. |
211 | 210 |
212 Args: | 211 Args: |
213 pkgfile: A python file object. | 212 pkgfile: A python file object. |
214 """ | 213 """ |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 """Grab the latest binary package database from the specified URL. | 269 """Grab the latest binary package database from the specified URL. |
271 | 270 |
272 Args: | 271 Args: |
273 binhost_url: Base URL of remote packages (PORTAGE_BINHOST). | 272 binhost_url: Base URL of remote packages (PORTAGE_BINHOST). |
274 | 273 |
275 Returns: | 274 Returns: |
276 A PackageIndex object, if the Packages file can be retrieved. If the | 275 A PackageIndex object, if the Packages file can be retrieved. If the |
277 server returns status code 404, None is returned. | 276 server returns status code 404, None is returned. |
278 """ | 277 """ |
279 | 278 |
280 url = urlparse.urljoin(binhost_url, 'Packages') | 279 url = '%s/Packages' % binhost_url.rstrip('/') |
281 try: | 280 try: |
282 f = _RetryUrlOpen(url) | 281 f = _RetryUrlOpen(url) |
283 except urllib2.HTTPError as e: | 282 except urllib2.HTTPError as e: |
284 if e.code == 404: | 283 if e.code == 404: |
285 return None | 284 return None |
286 raise | 285 raise |
287 | 286 |
288 pkgindex = PackageIndex() | 287 pkgindex = PackageIndex() |
289 pkgindex.Read(f) | 288 pkgindex.Read(f) |
290 pkgindex.header.setdefault('URI', binhost_url) | 289 pkgindex.header.setdefault('URI', binhost_url) |
291 f.close() | 290 f.close() |
292 return pkgindex | 291 return pkgindex |
293 | 292 |
294 | 293 |
295 def GrabLocalPackageIndex(package_path): | 294 def GrabLocalPackageIndex(package_path): |
296 """Read a local packages file from disk into a PackageIndex() object. | 295 """Read a local packages file from disk into a PackageIndex() object. |
297 | 296 |
298 Args: | 297 Args: |
299 package_path: Directory containing Packages file. | 298 package_path: Directory containing Packages file. |
300 | 299 |
301 Returns: | 300 Returns: |
302 A PackageIndex object. | 301 A PackageIndex object. |
303 """ | 302 """ |
304 packages_file = file(os.path.join(package_path, 'Packages')) | 303 packages_file = file(os.path.join(package_path, 'Packages')) |
305 pkgindex = PackageIndex() | 304 pkgindex = PackageIndex() |
306 pkgindex.Read(packages_file) | 305 pkgindex.Read(packages_file) |
307 packages_file.close() | 306 packages_file.close() |
308 return pkgindex | 307 return pkgindex |
OLD | NEW |