gclient_scm: Add option to specify the branch the patch is based on.

Also add shortcuts, so we don't have to look through all the branches
if the patch is based on a common branch (i.e. master, infra/config, lkgr)


Bug: 870279
Change-Id: I625a8481dccac9a475b096b926e6fab7efe676b0
Reviewed-on: https://chromium-review.googlesource.com/1161094
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
diff --git a/tests/gclient_scm_test.py b/tests/gclient_scm_test.py
index cb85612..123167a 100755
--- a/tests/gclient_scm_test.py
+++ b/tests/gclient_scm_test.py
@@ -1088,12 +1088,12 @@
     """
     for i in commits:
       name = os.path.join(self.root_dir, 'commit ' + str(i))
-      self.assertTrue(os.path.exists(name))
+      self.assertTrue(os.path.exists(name), 'Commit not found: %s' % name)
 
     all_commits = set(range(1, len(self.FAKE_REPOS.git_hashes['repo_1'])))
     for i in all_commits - set(commits):
       name = os.path.join(self.root_dir, 'commit ' + str(i))
-      self.assertFalse(os.path.exists(name))
+      self.assertFalse(os.path.exists(name), 'Unexpected commit: %s' % name)
 
   def testCanCloneGerritChange(self):
     scm = gclient_scm.GitWrapper(self.url, self.root_dir, '.')
@@ -1133,7 +1133,7 @@
     scm.update(self.options, None, file_list)
     self.assertEqual(self.githash('repo_1', 4), self.gitrevparse(self.root_dir))
 
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 2, 3, 4, 5, 6])
@@ -1155,7 +1155,7 @@
     self.assertEqual(self.githash('repo_1', 1), self.gitrevparse(self.root_dir))
 
     # Apply the change on top of that.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 5, 6])
@@ -1172,7 +1172,7 @@
     self.assertEqual(self.githash('repo_1', 9), self.gitrevparse(self.root_dir))
 
     # Apply the change on top of that.
-    scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 2, 7, 8, 9, 10])
@@ -1190,7 +1190,7 @@
     self.assertEqual(self.githash('repo_1', 7), self.gitrevparse(self.root_dir))
 
     # Apply the change on top of that.
-    scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', None, self.options,
                         file_list)
 
     # We shouldn't have rebased on top of 2 (which is the merge base between
@@ -1199,6 +1199,24 @@
     self.assertCommits([1, 2, 7, 10])
     self.assertEqual(self.githash('repo_1', 7), self.gitrevparse(self.root_dir))
 
+  def testCheckoutOriginFeaturePatchBranch(self):
+    scm = gclient_scm.GitWrapper(self.url, self.root_dir, '.')
+    file_list = []
+
+    # Sync to the hash instead of 'origin/feature'
+    self.options.revision = self.githash('repo_1', 9)
+    scm.update(self.options, None, file_list)
+    self.assertEqual(self.githash('repo_1', 9), self.gitrevparse(self.root_dir))
+
+    # Apply refs/changes/34/1234/1, created for branch 'origin/master' on top of
+    # 'origin/feature'.
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', 'origin/master',
+                        self.options, file_list)
+
+    # Commits 5 and 6 are part of the patch, and commits 1, 2, 7, 8 and 9 are
+    # part of 'origin/feature'.
+    self.assertCommits([1, 2, 5, 6, 7, 8, 9])
+    self.assertEqual(self.githash('repo_1', 9), self.gitrevparse(self.root_dir))
 
   def testDoesntRebasePatchMaster(self):
     """Tests that we can apply a patch without rebasing it.
@@ -1211,7 +1229,7 @@
     self.assertEqual(self.githash('repo_1', 4), self.gitrevparse(self.root_dir))
 
     # Apply the change on top of that.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 2, 3, 5, 6])
@@ -1230,7 +1248,7 @@
     self.assertEqual(self.githash('repo_1', 1), self.gitrevparse(self.root_dir))
 
     # Apply the change on top of that.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 2, 3, 5, 6])
@@ -1245,7 +1263,7 @@
     scm.update(self.options, None, file_list)
     self.assertEqual(self.githash('repo_1', 4), self.gitrevparse(self.root_dir))
 
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
 
     self.assertCommits([1, 2, 3, 4, 5, 6])
@@ -1265,14 +1283,14 @@
     # Checkout 'refs/changes/34/1234/1' modifies the 'change' file, so trying to
     # patch 'refs/changes/36/1236/1' creates a patch failure.
     with self.assertRaises(subprocess2.CalledProcessError) as cm:
-      scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', self.options,
-                          file_list)
+      scm.apply_patch_ref(self.url, 'refs/changes/36/1236/1', None,
+                          self.options, file_list)
     self.assertEqual(cm.exception.cmd[:2], ['git', 'cherry-pick'])
     self.assertIn('error: could not apply', cm.exception.stderr)
 
     # Try to apply 'refs/changes/35/1235/1', which doesn't have a merge
     # conflict.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
     self.assertCommits([1, 2, 3, 5, 6])
     self.assertEqual(self.githash('repo_1', 5), self.gitrevparse(self.root_dir))
@@ -1290,7 +1308,7 @@
     # 'refs/changes/34/1234/1' will be an empty commit, since the changes were
     # already present in the tree as commit 11.
     # Make sure we deal with this gracefully.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
     self.assertCommits([1, 2, 3, 5, 6, 12])
     self.assertEqual(self.githash('repo_1', 12),
@@ -1313,7 +1331,7 @@
 
     # Try to apply 'refs/changes/35/1235/1', which doesn't have a merge
     # conflict.
-    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', self.options,
+    scm.apply_patch_ref(self.url, 'refs/changes/35/1235/1', None, self.options,
                         file_list)
     self.assertCommits([1, 2, 3, 5, 6])
     self.assertEqual(self.githash('repo_1', 5), self.gitrevparse(self.root_dir))