| Index: cros_extract_deps
|
| diff --git a/cros_extract_deps b/cros_extract_deps
|
| deleted file mode 100755
|
| index 03ba92cafa2175241d1cb6ae5566464ff7be430a..0000000000000000000000000000000000000000
|
| --- a/cros_extract_deps
|
| +++ /dev/null
|
| @@ -1,200 +0,0 @@
|
| -#!/usr/bin/python
|
| -# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
| -# Use of this source code is governed by a BSD-style license that can be
|
| -# found in the LICENSE file.
|
| -
|
| -"""Extract dependency tree out of emerge and make it accessible and useful."""
|
| -
|
| -import json
|
| -import optparse
|
| -import re
|
| -import shutil
|
| -import subprocess
|
| -import sys
|
| -import tempfile
|
| -import time
|
| -
|
| -class ParseException(Exception):
|
| - def __init__(self, reason):
|
| - Exception.__init__(self)
|
| - self.reason = reason
|
| -
|
| - def __str__(self):
|
| - return self.reason
|
| -
|
| -
|
| -class SetEncoder(json.JSONEncoder):
|
| - """Custom json encoder class, doesn't hate set types."""
|
| - def default(self, o):
|
| - if isinstance(o, set):
|
| - return list(o)
|
| - return json.JSONEncoder.default(self, o)
|
| -
|
| -
|
| -def GetDepLinesFromPortage(options, packages):
|
| - """Get dependency lines out of emerge.
|
| -
|
| - This calls emerge -p --debug and extracts the 'digraph' lines which detail
|
| - the dependencies."
|
| - """
|
| - # Use a temporary directory for $ROOT, so that emerge will consider all
|
| - # packages regardless of current build status.
|
| - temp_dir = tempfile.mkdtemp()
|
| -
|
| - emerge = 'emerge'
|
| - if options.board:
|
| - emerge += '-' + options.board
|
| - cmdline = [emerge, '-p', '--debug', '--root=' + temp_dir]
|
| - if not options.build_time:
|
| - cmdline.append('--root-deps=rdeps')
|
| - cmdline += packages
|
| -
|
| - # Store output in a temp file as it is too big for a unix pipe.
|
| - stderr_buffer = tempfile.TemporaryFile()
|
| -
|
| - depsproc = subprocess.Popen(cmdline, stderr=stderr_buffer,
|
| - stdout=open('/dev/null', 'w'), bufsize=64*1024)
|
| - depsproc.wait()
|
| -
|
| - subprocess.check_call(['sudo', 'rm', '-rf', temp_dir])
|
| -
|
| - assert(depsproc.returncode==0)
|
| -
|
| - stderr_buffer.seek(0)
|
| - lines = []
|
| - output = False
|
| - for line in stderr_buffer:
|
| - stripped = line.rstrip()
|
| - if output:
|
| - lines.append(stripped)
|
| - if stripped == 'digraph:':
|
| - output = True
|
| -
|
| - if not output:
|
| - raise ParseException('Could not find digraph in output from emerge.')
|
| -
|
| - return lines
|
| -
|
| -
|
| -def ParseDepLines(lines):
|
| - """Parse the dependency lines into a dependency tree.
|
| -
|
| - This parses the digraph lines, extract the information and builds the
|
| - dependency tree (doubly-linked)."
|
| - """
|
| - # The digraph output looks like this:
|
| -
|
| - # hard-host-depends depends on
|
| - # ('ebuild', '/tmp/root', 'dev-lang/swig-1.3.36', 'merge') depends on
|
| - # ('ebuild', '/tmp/root', 'dev-lang/perl-5.8.8-r8', 'merge') (buildtime)
|
| - # ('binary', '/tmp/root', 'sys-auth/policykit-0.9-r1', 'merge') depends on
|
| - # ('binary', '/tmp/root', 'x11-misc/xbitmaps-1.1.0', 'merge') (no children)
|
| -
|
| - re_deps = re.compile(r'(?P<indent>\W*)\(\'(?P<package_type>\w+)\','
|
| - r' \'(?P<destination>[\w/\.-]+)\','
|
| - r' \'(?P<category>[\w\+-]+)/(?P<package_name>[\w\+-]+)-'
|
| - r'(?P<version>\d+[\w\.-]*)\', \'(?P<action>\w+)\'\)'
|
| - r' (?P<dep_type>(depends on|\(.*\)))')
|
| - re_seed_deps = re.compile(r'(?P<package_name>[\w\+/-]+) depends on')
|
| - # Packages that fail the previous regex should match this one and be noted as
|
| - # failure.
|
| - re_failed = re.compile(r'.*depends on.*')
|
| -
|
| - deps_map = {}
|
| -
|
| - current_package = None
|
| - for line in lines:
|
| - deps_match = re_deps.match(line)
|
| - if deps_match:
|
| - package_name = deps_match.group('package_name')
|
| - category = deps_match.group('category')
|
| - indent = deps_match.group('indent')
|
| - action = deps_match.group('action')
|
| - dep_type = deps_match.group('dep_type')
|
| - version = deps_match.group('version')
|
| -
|
| - # Pretty print what we've captured.
|
| - full_package_name = '%s/%s-%s' % (category, package_name, version)
|
| -
|
| - try:
|
| - package_info = deps_map[full_package_name]
|
| - except KeyError:
|
| - package_info = {
|
| - 'deps': set(),
|
| - 'rev_deps': set(),
|
| - 'name': package_name,
|
| - 'category': category,
|
| - 'version': version,
|
| - 'full_name': full_package_name,
|
| - 'action': action,
|
| - }
|
| - deps_map[full_package_name] = package_info
|
| -
|
| - if not indent:
|
| - if dep_type == 'depends on':
|
| - current_package = package_info
|
| - else:
|
| - current_package = None
|
| - else:
|
| - if not current_package:
|
| - raise ParseException('Found a dependency without parent:\n' + line)
|
| - if dep_type == 'depend on':
|
| - raise ParseException('Found extra levels of dependencies:\n' + line)
|
| - current_package['deps'].add(full_package_name)
|
| - package_info['rev_deps'].add(current_package['full_name'])
|
| -
|
| - else:
|
| - seed_match = re_seed_deps.match(line)
|
| - if seed_match:
|
| - package_name = seed_match.group('package_name')
|
| -
|
| - try:
|
| - current_package = deps_map[package_name]
|
| - except KeyError:
|
| - current_package = {
|
| - 'deps': set(),
|
| - 'rev_deps': set(),
|
| - 'name': package_name,
|
| - 'category': '',
|
| - 'version': '',
|
| - 'full_name': package_name,
|
| - 'action': 'seed',
|
| - }
|
| - deps_map[package_name] = current_package
|
| -
|
| - else:
|
| - # Is this a package that failed to match our huge regex?
|
| - failed_match = re_failed.match(line)
|
| - if failed_match:
|
| - raise ParseException('Couldn\'t understand line:\n' + line)
|
| -
|
| - return deps_map
|
| -
|
| -
|
| -def main():
|
| - parser = optparse.OptionParser(usage='usage: %prog [options] package1 ...')
|
| - parser.add_option('-b', '--board',
|
| - help='The board to extract dependencies from.')
|
| - parser.add_option('-B', '--build-time', action='store_true',
|
| - dest='build_time',
|
| - help='Also extract build-time dependencies.')
|
| - parser.add_option('-o', '--output', default=None,
|
| - help='Output file.')
|
| - (options, packages) = parser.parse_args()
|
| - if not packages:
|
| - parser.print_usage()
|
| - sys.exit(1)
|
| -
|
| - lines = GetDepLinesFromPortage(options, packages)
|
| - deps_map = ParseDepLines(lines)
|
| - output = json.dumps(deps_map, sort_keys=True, indent=2, cls=SetEncoder)
|
| - if options.output:
|
| - output_file = open(options.output, 'w')
|
| - output_file.write(output)
|
| - output_file.close()
|
| - else:
|
| - print output
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - main()
|
|
|