Move GetTipOfTrunkSvnRevision to gclient.py and cleanup tests.

I'm planning on reusing GetTipOfTrunkSvnRevision outside of
cros_mark_chrome_as_stable, so I'm moving the function to gclient.py
so it can be reusable.

Besides this, I've updated the script to consistently use
cros_build_lib.RunCommand so that we don't need to switch between
mocking out this and cros_mark_chrome_as_stable.RunCommand in the
test. This keeps the test simpler and easier to understand.

BUG=chromium-os:36324
TEST=Run all unit tests. Chrome trybots.

Change-Id: I12741c66874aff8cfd870bac166cceb9c7ef7e82
Reviewed-on: https://gerrit.chromium.org/gerrit/43135
Reviewed-by: Ryan Cui <rcui@chromium.org>
Commit-Queue: David James <davidjames@chromium.org>
Tested-by: David James <davidjames@chromium.org>
diff --git a/lib/gclient.py b/lib/gclient.py
index ddb6551..db939e5 100644
--- a/lib/gclient.py
+++ b/lib/gclient.py
@@ -6,6 +6,7 @@
 
 import os
 import pprint
+import re
 
 from chromite.lib import cros_build_lib
 from chromite.lib import osutils
@@ -58,6 +59,22 @@
   return external_url, internal_url, pdf_url
 
 
+def GetTipOfTrunkSvnRevision(svn_url):
+  """Returns the current svn revision for the chrome tree."""
+  cmd = ['svn', 'info', svn_url]
+  svn_info = cros_build_lib.RunCommand(cmd, redirect_stdout=True).output
+
+  revision_re = re.compile('^Revision:\s+(\d+)')
+  for line in svn_info.splitlines():
+    match = revision_re.match(line)
+    if match:
+      svn_revision = match.group(1)
+      cros_build_lib.Info('Found SVN Revision %s' % svn_revision)
+      return svn_revision
+
+  raise Exception('Could not find revision information from %s' % svn_url)
+
+
 def _GetGclientURLs(internal, use_pdf, rev):
   """Get the URLs to use in gclient file.
 
diff --git a/scripts/cros_mark_chrome_as_stable.py b/scripts/cros_mark_chrome_as_stable.py
index 5698462..41aef8d 100644
--- a/scripts/cros_mark_chrome_as_stable.py
+++ b/scripts/cros_mark_chrome_as_stable.py
@@ -28,7 +28,6 @@
 from chromite.lib import cros_build_lib
 from chromite.lib import gclient
 from chromite.lib import git
-from chromite.lib.cros_build_lib import RunCommand
 from chromite.scripts import cros_mark_as_stable
 
 # Helper regex's for finding ebuilds.
@@ -52,27 +51,12 @@
 
 _CHROME_SVN_TAG = 'CROS_SVN_COMMIT'
 
+
 def _GetSvnUrl(base_url):
   """Returns the path to the svn url for the given chrome branch."""
   return os.path.join(base_url, 'trunk')
 
 
-def  _GetTipOfTrunkSvnRevision(base_url):
-  """Returns the current svn revision for the chrome tree."""
-  svn_url = _GetSvnUrl(base_url)
-  svn_info = RunCommand(['svn', 'info', svn_url], redirect_stdout=True).output
-
-  revision_re = re.compile('^Revision:\s+(\d+).*')
-  for line in svn_info.splitlines():
-    match = revision_re.search(line)
-    if match:
-      svn_revision = match.group(1)
-      cros_build_lib.Info('Found SVN Revision %s' % svn_revision)
-      return svn_revision
-
-  raise Exception('Could not find revision information from %s' % svn_url)
-
-
 def _GetVersionContents(chrome_version_info):
   """Returns the current Chromium version, from the contents of a VERSION file.
 
@@ -102,7 +86,7 @@
   # Use the fact we are SVN, hence ordered.
   # Dodge the fact it will silently ignore the revision if it is not
   # yet known.  (i.e. too high)
-  repo_version = _GetTipOfTrunkSvnRevision(base_url)
+  repo_version = gclient.GetTipOfTrunkSvnRevision(base_url)
   while revision > repo_version:
     if time.time() - start > time_to_wait:
       raise Exception('Timeout Exceeeded')
@@ -110,9 +94,9 @@
     msg = 'Repository only has version %s, looking for %s.  Sleeping...'
     cros_build_lib.Info(msg, repo_version, revision)
     time.sleep(30)
-    repo_version = _GetTipOfTrunkSvnRevision(base_url)
+    repo_version = gclient.GetTipOfTrunkSvnRevision(base_url)
 
-  chrome_version_info = RunCommand(
+  chrome_version_info = cros_build_lib.RunCommand(
       ['svn', 'cat', '-r', revision, svn_url],
       redirect_stdout=True,
       error_message='Could not read version file at %s revision %s.' %
@@ -128,13 +112,14 @@
      root: path to the root of the chromium checkout.
   """
   version_file = os.path.join(root, 'src', 'chrome', 'VERSION')
-  chrome_version_info = RunCommand(
+  chrome_version_info = cros_build_lib.RunCommand(
       ['cat', version_file],
       redirect_stdout=True,
       error_message='Could not read version file at %s.' % version_file).output
 
   return _GetVersionContents(chrome_version_info)
 
+
 def _GetLatestRelease(base_url, branch=None):
   """Gets the latest release version from the buildspec_url for the branch.
 
@@ -145,10 +130,11 @@
     Latest version string.
   """
   buildspec_url = os.path.join(base_url, 'releases')
-  svn_ls = RunCommand(['svn', 'ls', buildspec_url],
-                      redirect_stdout=True).output
-  sorted_ls = RunCommand(['sort', '--version-sort', '-r'], input=svn_ls,
-                         redirect_stdout=True).output
+  svn_ls = cros_build_lib.RunCommand(['svn', 'ls', buildspec_url],
+                                     redirect_stdout=True).output
+  sorted_ls = cros_build_lib.RunCommand(['sort', '--version-sort', '-r'],
+                                        input=svn_ls,
+                                        redirect_stdout=True).output
   if branch:
     chrome_version_re = re.compile('^%s\.\d+.*' % branch)
   else:
@@ -157,9 +143,9 @@
   for chrome_version in sorted_ls.splitlines():
     if chrome_version_re.match(chrome_version):
       deps_url = os.path.join(buildspec_url, chrome_version, 'DEPS')
-      deps_check = RunCommand(['svn', 'ls', deps_url],
-                              error_code_ok=True,
-                              redirect_stdout=True).output
+      deps_check = cros_build_lib.RunCommand(['svn', 'ls', deps_url],
+                                             error_code_ok=True,
+                                             redirect_stdout=True).output
       if deps_check == 'DEPS\n':
         return chrome_version.rstrip('/')
 
@@ -396,9 +382,10 @@
                                                 new_ebuild,
                                                 chrome_rev))
 
-  RunCommand(['git', 'add', new_ebuild_path], cwd=overlay_dir)
+  cros_build_lib.RunCommand(['git', 'add', new_ebuild_path], cwd=overlay_dir)
   if stable_candidate and not stable_candidate.IsSticky():
-    RunCommand(['git', 'rm', stable_candidate.ebuild_path], cwd=overlay_dir)
+    cros_build_lib.RunCommand(['git', 'rm', stable_candidate.ebuild_path],
+                              cwd=overlay_dir)
 
   portage_utilities.EBuild.CommitChange(
       _GIT_COMMIT_MESSAGE % {'chrome_rev': chrome_rev,
@@ -461,7 +448,7 @@
     version_to_uprev = _GetSpecificVersionUrl(options.chrome_url,
                                               commit_to_use)
   elif chrome_rev == constants.CHROME_REV_TOT:
-    commit_to_use = _GetTipOfTrunkSvnRevision(options.chrome_url)
+    commit_to_use = gclient.GetTipOfTrunkSvnRevision(options.chrome_url)
     version_to_uprev = _GetSpecificVersionUrl(options.chrome_url,
                                               commit_to_use)
   elif chrome_rev == constants.CHROME_REV_LATEST:
@@ -489,7 +476,8 @@
   # In the case of uprevving overlays that have patches applied to them,
   # include the patched changes in the stabilizing branch.
   if existing_branch:
-    RunCommand(['git', 'rebase', existing_branch], cwd=overlay_dir)
+    cros_build_lib.RunCommand(['git', 'rebase', existing_branch],
+                              cwd=overlay_dir)
 
   chrome_version_atom = MarkChromeEBuildAsStable(
       stable_candidate, unstable_ebuild, chrome_rev, version_to_uprev,
diff --git a/scripts/cros_mark_chrome_as_stable_unittest.py b/scripts/cros_mark_chrome_as_stable_unittest.py
index 0dfaa81..91a8b1d 100755
--- a/scripts/cros_mark_chrome_as_stable_unittest.py
+++ b/scripts/cros_mark_chrome_as_stable_unittest.py
@@ -17,7 +17,9 @@
                                 '..', '..'))
 from chromite.buildbot import constants
 from chromite.buildbot import portage_utilities
+from chromite.lib import cros_build_lib
 from chromite.lib import cros_test_lib
+from chromite.lib import gclient
 from chromite.scripts import cros_mark_chrome_as_stable
 
 # pylint: disable=W0212,R0904
@@ -133,15 +135,15 @@
   def testGetTipOfTrunkSvnRevision(self):
     """Tests if we can get the latest svn revision from TOT."""
     A_URL = 'dorf://mink/delaane/forkat/sertiunu.ortg./desk'
-    self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
-    cros_mark_chrome_as_stable.RunCommand(
-        ['svn', 'info', cros_mark_chrome_as_stable._GetSvnUrl(A_URL)],
+    self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+    cros_build_lib.RunCommand(
+        ['svn', 'info', A_URL],
         redirect_stdout=True).AndReturn(
           _StubCommandResult(
             'Some Junk 2134\nRevision: %s\nOtherInfo: test_data' %
             fake_svn_rev))
     self.mox.ReplayAll()
-    revision = cros_mark_chrome_as_stable._GetTipOfTrunkSvnRevision(A_URL)
+    revision = gclient.GetTipOfTrunkSvnRevision(A_URL)
     self.mox.VerifyAll()
     self.assertEquals(revision, fake_svn_rev)
 
@@ -150,14 +152,14 @@
     ARBITRARY_URL = 'Pratooey'
     path = os.path.join(cros_mark_chrome_as_stable._GetSvnUrl(ARBITRARY_URL),
                         'src', 'chrome', 'VERSION')
-    self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
-    cros_mark_chrome_as_stable.RunCommand(
-        ['svn', 'info', cros_mark_chrome_as_stable._GetSvnUrl(ARBITRARY_URL)],
+    self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+    cros_build_lib.RunCommand(
+        ['svn', 'info', ARBITRARY_URL],
         redirect_stdout=True).AndReturn(
           _StubCommandResult(
             'Some Junk 2134\nRevision: %s\nOtherInfo: test_data' %
             fake_svn_rev))
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['svn', 'cat', '-r', fake_svn_rev, path], redirect_stdout=True,
         error_message=mox.IsA(str)).AndReturn(
           _StubCommandResult('A=8\nB=0\nC=256\nD=0'))
@@ -174,19 +176,19 @@
     input_data = ['7.0.224.1/', '7.0.224.2/', '8.0.365.5/', 'LATEST.txt']
     test_data = '\n'.join(input_data)
     sorted_data = '\n'.join(reversed(input_data))
-    self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
-    cros_mark_chrome_as_stable.RunCommand(
+    self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+    cros_build_lib.RunCommand(
         ['svn', 'ls', ARBITRARY_URL + '/releases'],
         redirect_stdout=True).AndReturn(_StubCommandResult(test_data))
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['sort', '--version-sort', '-r'], input=test_data,
         redirect_stdout=True).AndReturn(_StubCommandResult(sorted_data))
     # pretend this one is missing to test the skipping logic.
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['svn', 'ls', ARBITRARY_URL + '/releases/8.0.365.5/DEPS'],
         error_code_ok=True, redirect_stdout=True).AndReturn(
           _StubCommandResult('BAH BAH BAH'))
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['svn', 'ls', ARBITRARY_URL + '/releases/7.0.224.2/DEPS'],
         error_code_ok=True, redirect_stdout=True).AndReturn(
           _StubCommandResult('DEPS\n'))
@@ -202,14 +204,14 @@
                            '8.0.224.2/',
                            '8.0.365.5/',
                            'LATEST.txt'])
-    self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
-    cros_mark_chrome_as_stable.RunCommand(
+    self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
+    cros_build_lib.RunCommand(
         ['svn', 'ls', ARBITRARY_URL + '/releases'],
         redirect_stdout=True).AndReturn(_StubCommandResult('some_data'))
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['sort', '--version-sort', '-r'], input='some_data',
         redirect_stdout=True).AndReturn(_StubCommandResult(test_data))
-    cros_mark_chrome_as_stable.RunCommand(
+    cros_build_lib.RunCommand(
         ['svn', 'ls', ARBITRARY_URL + '/releases/8.0.224.2/DEPS'],
         error_code_ok=True, redirect_stdout=True).AndReturn(
           _StubCommandResult('DEPS\n'))
@@ -257,7 +259,7 @@
       new_ebuild_path: path to the to be created path
       commit_string_indicator: a string that the commit message must contain
     """
-    self.mox.StubOutWithMock(cros_mark_chrome_as_stable, 'RunCommand')
+    self.mox.StubOutWithMock(cros_build_lib, 'RunCommand')
     self.mox.StubOutWithMock(portage_utilities.EBuild, 'CommitChange')
     stable_candidate = cros_mark_chrome_as_stable.ChromeEBuild(old_ebuild_path)
     unstable_ebuild = cros_mark_chrome_as_stable.ChromeEBuild(self.unstable)
@@ -265,10 +267,8 @@
     commit = None
     overlay_dir = self.mock_chrome_dir
 
-    cros_mark_chrome_as_stable.RunCommand(['git', 'add', new_ebuild_path],
-                                          cwd=overlay_dir)
-    cros_mark_chrome_as_stable.RunCommand(['git', 'rm', old_ebuild_path],
-                                          cwd=overlay_dir)
+    cros_build_lib.RunCommand(['git', 'add', new_ebuild_path], cwd=overlay_dir)
+    cros_build_lib.RunCommand(['git', 'rm', old_ebuild_path], cwd=overlay_dir)
     portage_utilities.EBuild.CommitChange(
         mox.StrContains(commit_string_indicator), overlay_dir)