cros_extract_deps: Add flag to disable solver backtracking

Portage will fall back to lower versions of packages if it cannot solve
the depgraph for the highest available version of that package. We'd
prefer that be an error so that breaking a depgraph fails in the CQ
instead of silently falling back to using other versions of packages.

BUG=chromium:1094099, chromium:1067729
TEST=None

Change-Id: I5e93d21619679f62fd54aff6feb445579ac01337
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2246714
Tested-by: Chris McDonald <cjmcdonald@chromium.org>
Commit-Queue: Chris McDonald <cjmcdonald@chromium.org>
Reviewed-by: Alex Klein <saklein@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/scripts/cros_extract_deps.py b/scripts/cros_extract_deps.py
index cfc5bd4..f3b6baa 100644
--- a/scripts/cros_extract_deps.py
+++ b/scripts/cros_extract_deps.py
@@ -270,7 +270,8 @@
 def ExtractDeps(sysroot,
                 package_list,
                 formatting='deps',
-                include_bdepend=True):
+                include_bdepend=True,
+                backtrack=True):
   """Returns the set of dependencies for the packages in package_list.
 
   For calculating dependencies graph, this should only consider packages
@@ -289,6 +290,10 @@
       docstring of GenerateCPEList.
     include_bdepend: Controls whether BDEPEND packages that would be installed
       to BROOT (usually "/" instead of ROOT) are included in the output.
+    backtrack: Setting to False disables backtracking in Portage's dependency
+      solver. If the highest available version of dependencies doesn't produce
+      a solvable graph Portage will give up and return an error instead of
+      trying other candidates.
 
   Returns:
     A JSON-izable object that either follows 'deps' or 'cpe' format.
@@ -296,6 +301,8 @@
   lib_argv = ['--quiet', '--pretend', '--emptytree']
   if include_bdepend:
     lib_argv += ['--include-bdepend']
+  if not backtrack:
+    lib_argv += ['--backtrack=0']
   lib_argv += ['--sysroot=%s' % sysroot]
   lib_argv.extend(package_list)
 
diff --git a/service/dependency.py b/service/dependency.py
index b2fd544..642ac2e 100644
--- a/service/dependency.py
+++ b/service/dependency.py
@@ -324,7 +324,8 @@
     board_deps, board_bdeps = cros_extract_deps.ExtractDeps(
         sysroot=sysroot_path,
         package_list=board_packages,
-        include_bdepend=False)
+        include_bdepend=False,
+        backtrack=False)
 
     results['package_deps'].update(board_deps)
     results['package_deps'].update(board_bdeps)