Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(408)

Side by Side Diff: parallel_emerge

Issue 6094001: Update parallel_emerge to experimentally support Portage 2.1.9. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: Rebase Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python2.6 1 #!/usr/bin/python2.6
2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Program to run emerge in parallel, for significant speedup. 6 """Program to run emerge in parallel, for significant speedup.
7 7
8 Usage: 8 Usage:
9 ./parallel_emerge [--board=BOARD] [--workon=PKGS] [--no-workon-deps] 9 ./parallel_emerge [--board=BOARD] [--workon=PKGS] [--no-workon-deps]
10 [--force-remote-binary=PKGS] [emerge args] package 10 [--force-remote-binary=PKGS] [emerge args] package
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 # TODO(davidjames): Update Portage to expose public APIs for these features. 75 # TODO(davidjames): Update Portage to expose public APIs for these features.
76 from _emerge.actions import adjust_configs 76 from _emerge.actions import adjust_configs
77 from _emerge.actions import load_emerge_config 77 from _emerge.actions import load_emerge_config
78 from _emerge.create_depgraph_params import create_depgraph_params 78 from _emerge.create_depgraph_params import create_depgraph_params
79 from _emerge.depgraph import depgraph as emerge_depgraph 79 from _emerge.depgraph import depgraph as emerge_depgraph
80 from _emerge.depgraph import _frozen_depgraph_config 80 from _emerge.depgraph import _frozen_depgraph_config
81 from _emerge.main import emerge_main 81 from _emerge.main import emerge_main
82 from _emerge.main import parse_opts 82 from _emerge.main import parse_opts
83 from _emerge.Package import Package 83 from _emerge.Package import Package
84 from _emerge.Scheduler import Scheduler 84 from _emerge.Scheduler import Scheduler
85 from _emerge.SetArg import SetArg
85 from _emerge.stdout_spinner import stdout_spinner 86 from _emerge.stdout_spinner import stdout_spinner
86 import portage 87 import portage
87 import portage.debug 88 import portage.debug
88 import portage.versions 89 import portage.versions
89 90
91 new_portage = not portage.VERSION.startswith("2.1.7.")
92 if new_portage:
93 from portage._global_updates import _global_updates
94 else:
95 from portage import _global_updates
90 96
91 def Usage(): 97 def Usage():
92 """Print usage.""" 98 """Print usage."""
93 print "Usage:" 99 print "Usage:"
94 print " ./parallel_emerge [--board=BOARD] [--workon=PKGS] [--no-workon-deps]" 100 print " ./parallel_emerge [--board=BOARD] [--workon=PKGS] [--no-workon-deps]"
95 print " [--rebuild] [emerge args] package" 101 print " [--rebuild] [emerge args] package"
96 print 102 print
97 print "Packages specified as workon packages are always built from source." 103 print "Packages specified as workon packages are always built from source."
98 print "Unless --no-workon-deps is specified, packages that depend on these" 104 print "Unless --no-workon-deps is specified, packages that depend on these"
99 print "packages are also built from source." 105 print "packages are also built from source."
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 settings, trees, mtimedb = load_emerge_config() 389 settings, trees, mtimedb = load_emerge_config()
384 390
385 # Check whether our portage tree is out of date. Typically, this happens 391 # Check whether our portage tree is out of date. Typically, this happens
386 # when you're setting up a new portage tree, such as in setup_board and 392 # when you're setting up a new portage tree, such as in setup_board and
387 # make_chroot. In that case, portage applies a bunch of global updates 393 # make_chroot. In that case, portage applies a bunch of global updates
388 # here. Once the updates are finished, we need to commit any changes 394 # here. Once the updates are finished, we need to commit any changes
389 # that the global update made to our mtimedb, and reload the config. 395 # that the global update made to our mtimedb, and reload the config.
390 # 396 #
391 # Portage normally handles this logic in emerge_main, but again, we can't 397 # Portage normally handles this logic in emerge_main, but again, we can't
392 # use that function here. 398 # use that function here.
393 if portage._global_updates(trees, mtimedb["updates"]): 399 if _global_updates(trees, mtimedb["updates"]):
394 mtimedb.commit() 400 mtimedb.commit()
395 settings, trees, mtimedb = load_emerge_config(trees=trees) 401 settings, trees, mtimedb = load_emerge_config(trees=trees)
396 402
397 # Setup implied options. Portage normally handles this logic in 403 # Setup implied options. Portage normally handles this logic in
398 # emerge_main. 404 # emerge_main.
399 if "--buildpkgonly" in opts or "buildpkg" in settings.features: 405 if "--buildpkgonly" in opts or "buildpkg" in settings.features:
400 opts.setdefault("--buildpkg", True) 406 opts.setdefault("--buildpkg", True)
401 if "--getbinpkgonly" in opts: 407 if "--getbinpkgonly" in opts:
402 opts.setdefault("--usepkgonly", True) 408 opts.setdefault("--usepkgonly", True)
403 opts.setdefault("--getbinpkg", True) 409 opts.setdefault("--getbinpkg", True)
(...skipping 27 matching lines...) Expand all
431 adjust_configs(opts, trees) 437 adjust_configs(opts, trees)
432 438
433 # Save our configuration so far in the emerge object 439 # Save our configuration so far in the emerge object
434 emerge = self.emerge 440 emerge = self.emerge
435 emerge.action, emerge.opts = action, opts 441 emerge.action, emerge.opts = action, opts
436 emerge.settings, emerge.trees, emerge.mtimedb = settings, trees, mtimedb 442 emerge.settings, emerge.trees, emerge.mtimedb = settings, trees, mtimedb
437 emerge.cmdline_packages = cmdline_packages 443 emerge.cmdline_packages = cmdline_packages
438 root = settings["ROOT"] 444 root = settings["ROOT"]
439 emerge.root_config = trees[root]["root_config"] 445 emerge.root_config = trees[root]["root_config"]
440 446
447 if new_portage and "--usepkg" in opts:
448 emerge.trees[root]["bintree"].populate("--getbinpkg" in opts)
449
441 def CheckUseFlags(self, pkgsettings, cur_pkg, new_pkg): 450 def CheckUseFlags(self, pkgsettings, cur_pkg, new_pkg):
442 """Are the use flags in cur_pkg up to date? 451 """Are the use flags in cur_pkg up to date?
443 452
444 Return True if use flags are up to date; return false otherwise.""" 453 Return True if use flags are up to date; return false otherwise."""
445 454
446 # cur_use: The set of flags that were enabled when the package was 455 # cur_use: The set of flags that were enabled when the package was
447 # first installed. 456 # first installed.
448 # cur_iuse: The set of flags that affected the specified package 457 # cur_iuse: The set of flags that affected the specified package
449 # when it was first installed. 458 # when it was first installed.
450 # 459 #
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 # specifying --tree as well, we tell emerge that it's not safe to remove 500 # specifying --tree as well, we tell emerge that it's not safe to remove
492 # uninstall instructions because we're planning on analyzing the output. 501 # uninstall instructions because we're planning on analyzing the output.
493 emerge_opts["--tree"] = True 502 emerge_opts["--tree"] = True
494 emerge_opts["--emptytree"] = True 503 emerge_opts["--emptytree"] = True
495 504
496 # Set up parameters. 505 # Set up parameters.
497 params = create_depgraph_params(emerge_opts, emerge.action) 506 params = create_depgraph_params(emerge_opts, emerge.action)
498 frozen_config = _frozen_depgraph_config(emerge.settings, emerge.trees, 507 frozen_config = _frozen_depgraph_config(emerge.settings, emerge.trees,
499 emerge_opts, emerge.spinner) 508 emerge_opts, emerge.spinner)
500 backtrack_max = emerge_opts.get('--backtrack', 5) 509 backtrack_max = emerge_opts.get('--backtrack', 5)
501 runtime_pkg_mask = None 510 backtrack_parameters = {}
502 allow_backtracking = backtrack_max > 0 511 allow_backtracking = backtrack_max > 0
503 512
504 # Try up to backtrack_max times to create a working depgraph. Each time we 513 # Try up to backtrack_max times to create a working depgraph. Each time we
505 # run into a conflict, mask the offending package and try again. 514 # run into a conflict, mask the offending package and try again.
506 # TODO(davidjames): When Portage supports --force-remote-binary directly, 515 # TODO(davidjames): When Portage supports --force-remote-binary directly,
507 # switch back to using the backtrack_depgraph function. 516 # switch back to using the backtrack_depgraph function.
508 for i in range(backtrack_max + 1): 517 for i in range(backtrack_max + 2):
509 if i == backtrack_max:
510 # Looks like we hit the backtracking limit. Run the dependency
511 # calculation one more time (from scratch) to show the original error
512 # message.
513 runtime_pkg_mask = None
514 allow_backtracking = False
515
516 # Create a depgraph object. 518 # Create a depgraph object.
517 depgraph = emerge_depgraph(emerge.settings, emerge.trees, emerge_opts, 519 depgraph = emerge_depgraph(emerge.settings, emerge.trees, emerge_opts,
518 params, emerge.spinner, frozen_config=frozen_config, 520 params, emerge.spinner, frozen_config=frozen_config,
519 allow_backtracking=allow_backtracking, 521 allow_backtracking=allow_backtracking,
520 runtime_pkg_mask=runtime_pkg_mask) 522 **backtrack_parameters)
521 523
522 if i == 0: 524 if i == 0:
523 for cpv in self.forced_remote_binary_packages: 525 for cpv in self.forced_remote_binary_packages:
524 # If --force-remote-binary was specified, we want to use this package 526 # If --force-remote-binary was specified, we want to use this package
525 # regardless of its use flags. Unfortunately, Portage doesn't support 527 # regardless of its use flags. Unfortunately, Portage doesn't support
526 # ignoring use flags for just one package. To convince Portage to 528 # ignoring use flags for just one package. To convince Portage to
527 # install the package, we trick Portage into thinking the package has 529 # install the package, we trick Portage into thinking the package has
528 # the right use flags. 530 # the right use flags.
529 # TODO(davidjames): Update Portage to support --force-remote-binary 531 # TODO(davidjames): Update Portage to support --force-remote-binary
530 # directly, so that this hack isn't necessary. 532 # directly, so that this hack isn't necessary.
531 pkg = depgraph._pkg(cpv, "binary", emerge.root_config) 533 pkg = depgraph._pkg(cpv, "binary", emerge.root_config)
532 pkgsettings = frozen_config.pkgsettings[pkg.root] 534 pkgsettings = frozen_config.pkgsettings[pkg.root]
533 pkgsettings.setcpv(pkg) 535 pkgsettings.setcpv(pkg)
534 pkg.use.enabled = pkgsettings["PORTAGE_USE"].split() 536 pkg.use.enabled = pkgsettings["PORTAGE_USE"].split()
535 537
536 # Select the packages we want. 538 # Select the packages we want.
537 success, favorites = depgraph.select_files(packages) 539 success, favorites = depgraph.select_files(packages)
538 if success: 540 if success:
539 break 541 break
540 elif depgraph.need_restart(): 542 elif depgraph.need_restart() and i < backtrack_max:
541 # Looks like we found some packages that can't be installed due to 543 # Looks like we found some packages that can't be installed due to
542 # conflicts. Try again, masking out the conflicting packages. 544 # conflicts. Try again, masking out the conflicting packages.
543 runtime_pkg_mask = depgraph.get_runtime_pkg_mask() 545 if new_portage:
546 backtrack_parameters = depgraph.get_backtrack_parameters()
547 else:
548 backtrack_parameters = {
549 'runtime_pkg_mask': depgraph.get_runtime_pkg_mask()
550 }
544 elif allow_backtracking and i > 0: 551 elif allow_backtracking and i > 0:
545 # Looks like we tried all the possible combinations, and we still can't 552 # Looks like we can't solve the graph. Stop backtracking and report an
546 # solve the graph. Stop backtracking, so that we can report an error 553 # error message.
547 # message. 554 backtrack_parameters.pop('runtime_pkg_mask', None)
548 runtime_pkg_mask = None
549 allow_backtracking = False 555 allow_backtracking = False
550 else: 556 else:
551 break 557 break
552 558
553 # Delete the --tree option, because we don't really want to display a 559 # Delete the --tree option, because we don't really want to display a
554 # tree. We just wanted to get emerge to leave uninstall instructions on 560 # tree. We just wanted to get emerge to leave uninstall instructions on
555 # the graph. Later, when we display the graph, we'll want standard-looking 561 # the graph. Later, when we display the graph, we'll want standard-looking
556 # output, so removing the --tree option is important. 562 # output, so removing the --tree option is important.
557 frozen_config.myopts.pop("--tree", None) 563 frozen_config.myopts.pop("--tree", None)
558 564
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 # 640 #
635 # Here's an example CPV: chromeos-base/power_manager-0.0.1-r1 641 # Here's an example CPV: chromeos-base/power_manager-0.0.1-r1
636 # Split up, this CPV would be: 642 # Split up, this CPV would be:
637 # C -- Component: chromeos-base 643 # C -- Component: chromeos-base
638 # P -- Path: power_manager 644 # P -- Path: power_manager
639 # V -- Version: 0.0.1-r1 645 # V -- Version: 0.0.1-r1
640 # 646 #
641 # We just refer to CPVs as packages here because it's easier. 647 # We just refer to CPVs as packages here because it's easier.
642 deps = {} 648 deps = {}
643 for child, priorities in node_deps[0].items(): 649 for child, priorities in node_deps[0].items():
650 if isinstance(child, SetArg): continue
644 deps[str(child.cpv)] = dict(action=str(child.operation), 651 deps[str(child.cpv)] = dict(action=str(child.operation),
645 deptype=str(priorities[-1]), 652 deptype=str(priorities[-1]),
646 deps={}) 653 deps={})
647 654
648 # We've built our list of deps, so we can add our package to the tree. 655 # We've built our list of deps, so we can add our package to the tree.
649 if isinstance(node, Package): 656 if isinstance(node, Package):
650 deps_tree[str(node.cpv)] = dict(action=str(node.operation), 657 deps_tree[str(node.cpv)] = dict(action=str(node.operation),
651 deps=deps) 658 deps=deps)
652 659
653 emptytree = "--emptytree" in emerge.opts 660 emptytree = "--emptytree" in emerge.opts
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 remote_ready = PrebuiltsReady(pkg, remote_pkgs, remote_ready_cache) 1192 remote_ready = PrebuiltsReady(pkg, remote_pkgs, remote_ready_cache)
1186 if remote_ready and (local_mtime <= remote_mtime or pkg in cycles): 1193 if remote_ready and (local_mtime <= remote_mtime or pkg in cycles):
1187 MergeChildren(pkg, "mandatory") 1194 MergeChildren(pkg, "mandatory")
1188 else: 1195 else:
1189 MergeChildren(pkg, "mandatory_source") 1196 MergeChildren(pkg, "mandatory_source")
1190 1197
1191 def UsePrebuiltPackages(remote_pkgs): 1198 def UsePrebuiltPackages(remote_pkgs):
1192 """Update packages that can use prebuilts to do so.""" 1199 """Update packages that can use prebuilts to do so."""
1193 start = time.time() 1200 start = time.time()
1194 1201
1195 # Build list of prebuilt packages 1202 # Build list of prebuilt packages.
1196 prebuilt_pkgs = {} 1203 prebuilt_pkgs = {}
1197 for pkg, info in deps_map.iteritems(): 1204 for pkg, info in deps_map.iteritems():
1198 if info and info["action"] == "merge": 1205 if info and info["action"] == "merge":
1199 if (not info["force_remote_binary"] and info["mandatory_source"] or 1206 if (not info["force_remote_binary"] and info["mandatory_source"] or
1200 "--usepkgonly" not in emerge.opts and pkg not in remote_pkgs): 1207 "--usepkgonly" not in emerge.opts and pkg not in remote_pkgs):
1201 continue 1208 continue
1202 1209
1203 db_pkg = emerge.depgraph._pkg(pkg, "binary", emerge.root_config) 1210 db_pkg = emerge.depgraph._pkg(pkg, "binary", emerge.root_config)
1204 if info["force_remote_binary"]: 1211 if info["force_remote_binary"]:
1205 # Undo our earlier hacks to the use flags so that the use flags 1212 # Undo our earlier hacks to the use flags so that the use flags
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1387 It expects package identifiers to be passed to it via task_queue. When 1394 It expects package identifiers to be passed to it via task_queue. When
1388 a task is started, it pushes the (target, filename) to the started_queue. 1395 a task is started, it pushes the (target, filename) to the started_queue.
1389 The output is stored in filename. When a merge starts or finishes, we push 1396 The output is stored in filename. When a merge starts or finishes, we push
1390 EmergeJobState objects to the job_queue. 1397 EmergeJobState objects to the job_queue.
1391 """ 1398 """
1392 1399
1393 SetupWorkerSignals() 1400 SetupWorkerSignals()
1394 settings, trees, mtimedb = emerge.settings, emerge.trees, emerge.mtimedb 1401 settings, trees, mtimedb = emerge.settings, emerge.trees, emerge.mtimedb
1395 opts, spinner = emerge.opts, emerge.spinner 1402 opts, spinner = emerge.opts, emerge.spinner
1396 opts["--nodeps"] = True 1403 opts["--nodeps"] = True
1404 if new_portage:
1405 # When Portage launches new processes, it goes on a rampage and closes all
1406 # open file descriptors. Ask Portage not to do that, as it breaks us.
1407 portage.process.get_open_fds = lambda: []
1397 while True: 1408 while True:
1398 # Wait for a new item to show up on the queue. This is a blocking wait, 1409 # Wait for a new item to show up on the queue. This is a blocking wait,
1399 # so if there's nothing to do, we just sit here. 1410 # so if there's nothing to do, we just sit here.
1400 target = task_queue.get() 1411 target = task_queue.get()
1401 if not target: 1412 if not target:
1402 # If target is None, this means that the main thread wants us to quit. 1413 # If target is None, this means that the main thread wants us to quit.
1403 # The other workers need to exit too, so we'll push the message back on 1414 # The other workers need to exit too, so we'll push the message back on
1404 # to the queue so they'll get it too. 1415 # to the queue so they'll get it too.
1405 task_queue.put(target) 1416 task_queue.put(target)
1406 return 1417 return
1407 db_pkg = package_db[target] 1418 db_pkg = package_db[target]
1408 db_pkg.root_config = emerge.root_config 1419 db_pkg.root_config = emerge.root_config
1409 install_list = [db_pkg] 1420 install_list = [db_pkg]
1410 pkgname = db_pkg.pf 1421 pkgname = db_pkg.pf
1411 output = tempfile.NamedTemporaryFile(prefix=pkgname + "-", delete=False) 1422 output = tempfile.NamedTemporaryFile(prefix=pkgname + "-", delete=False)
1412 start_timestamp = time.time() 1423 start_timestamp = time.time()
1413 job = EmergeJobState(target, pkgname, False, output.name, start_timestamp) 1424 job = EmergeJobState(target, pkgname, False, output.name, start_timestamp)
1414 job_queue.put(job) 1425 job_queue.put(job)
1415 if "--pretend" in opts: 1426 if "--pretend" in opts:
1416 retcode = 0 1427 retcode = 0
1417 else: 1428 else:
1418 save_stdout = sys.stdout 1429 save_stdout = sys.stdout
1419 save_stderr = sys.stderr 1430 save_stderr = sys.stderr
1420 try: 1431 try:
1421 sys.stdout = output 1432 sys.stdout = output
1422 sys.stderr = output 1433 sys.stderr = output
1423 scheduler = Scheduler(settings, trees, mtimedb, opts, spinner, 1434 if new_portage:
1424 install_list, [], emerge.scheduler_graph) 1435 emerge.scheduler_graph.mergelist = install_list
1436 scheduler = Scheduler(settings, trees, mtimedb, opts, spinner,
1437 favorites=[], graph_config=emerge.scheduler_graph)
1438 else:
1439 scheduler = Scheduler(settings, trees, mtimedb, opts, spinner,
1440 install_list, [], emerge.scheduler_graph)
1425 retcode = scheduler.merge() 1441 retcode = scheduler.merge()
1426 except Exception: 1442 except Exception:
1427 traceback.print_exc(file=output) 1443 traceback.print_exc(file=output)
1428 retcode = 1 1444 retcode = 1
1429 finally: 1445 finally:
1430 sys.stdout = save_stdout 1446 sys.stdout = save_stdout
1431 sys.stderr = save_stderr 1447 sys.stderr = save_stderr
1432 output.close() 1448 output.close()
1433 if retcode is None: 1449 if retcode is None:
1434 retcode = 0 1450 retcode = 0
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1876 # need to upgrade the rest of the packages. So we'll go ahead and do that. 1892 # need to upgrade the rest of the packages. So we'll go ahead and do that.
1877 if portage_upgrade: 1893 if portage_upgrade:
1878 args = sys.argv[1:] + ["--nomerge=sys-apps/portage"] 1894 args = sys.argv[1:] + ["--nomerge=sys-apps/portage"]
1879 os.execvp(os.path.realpath(sys.argv[0]), args) 1895 os.execvp(os.path.realpath(sys.argv[0]), args)
1880 1896
1881 print "Done" 1897 print "Done"
1882 sys.exit(0) 1898 sys.exit(0)
1883 1899
1884 if __name__ == "__main__": 1900 if __name__ == "__main__":
1885 main() 1901 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698