cbuildbot: Add patch support for manifest projects that map to multiple paths

For cases when we have a project appear more than once in the manifest but
pinned to different branches or SHA1 revisions, we need to ensure that
the patch application logic correctly determines the right project path.

This CL adds the following heuristic:
1) For an unversioned manifest, unless the revision= for the project path
   specifies a branch, consider it an invalid destination for applying a patch.
2) For versioned manifests, ignore projects that have no named upstream=
   field. This should currently only be true for projects that matched 1) in
   the unversioned case.

BUG=chromium:330736
TEST=trybot, unit test

Change-Id: I712784970aa078779b3cf7cd9149de18a0db3aca
Reviewed-on: https://chromium-review.googlesource.com/181162
Reviewed-by: David James <davidjames@chromium.org>
Tested-by: Gaurav Shah <gauravsh@chromium.org>
Commit-Queue: Gaurav Shah <gauravsh@chromium.org>
diff --git a/scripts/cros_merge_to_branch.py b/scripts/cros_merge_to_branch.py
index 9041c12..a2f61a5 100644
--- a/scripts/cros_merge_to_branch.py
+++ b/scripts/cros_merge_to_branch.py
@@ -156,7 +156,7 @@
     # Get the path to the first checkout associated with this change. Since
     # all of the checkouts share git objects, it doesn't matter which checkout
     # we pick.
-    path = manifest.FindCheckouts(patch.project)[0]['path']
+    path = manifest.FindCheckouts(patch.project, only_patchable=True)[0]['path']
 
     reference = os.path.join(constants.SOURCE_ROOT, path)
     if not os.path.isdir(reference):
@@ -192,8 +192,8 @@
   """Returns true if the given manifest contains all the patches.
 
   Args:
-    manifest - an instance of git.Manifest
-    patches - a collection GerritPatch objects.
+    manifest: an instance of git.Manifest
+    patches: a collection of GerritPatch objects.
   """
   for patch in patches:
     if not manifest.FindCheckouts(patch.project):