Add infrastructure to download golang and build AppRTC collider.

This is required to support https://codereview.chromium.org/751333004/.

BUG=438217
R=kjellander@chromium.org

Review URL: https://codereview.chromium.org/759163003

git-svn-id: http://src.chromium.org/svn/trunk/deps/third_party/webrtc/webrtc.DEPS@293294 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
diff --git a/DEPS b/DEPS
index c09d481..518b220 100644
--- a/DEPS
+++ b/DEPS
@@ -40,7 +40,13 @@
   {
     "pattern": ".",
     "action" : ["python",
-                "webrtc.DEPS/download_appengine_sdk.py",
+                "webrtc.DEPS/download_appengine_and_mercurial.py",
+                "webrtc.DEPS"],
+  },
+  {
+    "pattern": ".",
+    "action" : ["python",
+                "webrtc.DEPS/download_golang.py",
                 "webrtc.DEPS"],
   },
   {
@@ -51,6 +57,18 @@
                 "webrtc.DEPS/copy_apprtc.py"],
   },
   {
+    # Build Mercurial which is needed by the golang toolchain.
+    "pattern": ".",
+    "action" : ["python",
+                "webrtc.DEPS/build_mercurial_local.py"],
+  },
+  {
+    # Build AppRTC Collider using the golang toolchain.
+    "pattern": ".",
+    "action" : ["python",
+                "webrtc.DEPS/build_apprtc_collider.py"],
+  },
+  {
     # Download test resources, i.e. video and audio files from Google Storage.
     # These resources are used by the Android bots.
     "pattern": "\\.sha1",
diff --git a/build_apprtc_collider.py b/build_apprtc_collider.py
new file mode 100755
index 0000000..4b0f86b
--- /dev/null
+++ b/build_apprtc_collider.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Builds the AppRTC collider using the golang toolchain.
+
+The golang toolchain is downloaded by download_golang.py. We use that here
+to build the AppRTC collider server.
+"""
+
+import os
+import shutil
+import subprocess
+import sys
+
+import utils
+
+
+def main():
+  web_samples_dir = os.path.join('webrtc-samples', 'samples', 'web')
+  golang_workspace = os.path.join('src', 'out', 'go-workspace')
+  shutil.rmtree(golang_workspace, ignore_errors=True)
+  golang_workspace_src = os.path.join(golang_workspace, 'src')
+
+  collider_dir = os.path.join(web_samples_dir, 'content', 'apprtc', 'collider')
+  shutil.copytree(collider_dir, golang_workspace_src,
+                  ignore=shutil.ignore_patterns('.svn', '.git'))
+
+  golang_binary = 'go%s' % ('.exe' if utils.GetPlatform() == 'win' else '')
+  golang_path = os.path.join('go', 'bin', golang_binary)
+
+  golang_env = os.environ.copy()
+  golang_env['GOROOT'] = os.path.abspath('go')
+  golang_env['GOPATH'] = os.path.abspath(golang_workspace)
+  golang_env['PATH'] += os.pathsep + os.path.abspath('mercurial')
+  subprocess.check_call([golang_path, 'get', 'collidermain'],
+                        env=golang_env)
+  subprocess.check_call([golang_path, 'build', 'collidermain'],
+                        env=golang_env)
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/build_mercurial_local.py b/build_mercurial_local.py
new file mode 100755
index 0000000..3170641
--- /dev/null
+++ b/build_mercurial_local.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Builds a local mercurial (hg) copy.
+
+This is used by the go toolchain.
+"""
+
+import os
+import shutil
+import subprocess
+import sys
+
+import utils
+
+
+def main():
+  if not os.path.exists('mercurial'):
+    return 'Expected mercurial at %s.' % os.path.abspath('mercurial')
+
+  os.chdir('mercurial')
+
+  if utils.GetPlatform() == 'win':
+    subprocess.check_call(['python', 'setup.py', '--pure', 'build_py', '-c',
+                           '-d', '.', 'build_ext',
+                           '-i', 'build_mo', '--force'])
+    with open('hg.bat', 'w') as put_hg_in_path:
+      # Write a hg.bat since the go toolchain expects to find something called
+      # 'hg' in the path, but Windows only recognizes executables ending with
+      # an extension in PATHEXT. Writing hg.bat effectively makes 'hg' callable
+      # if the mercurial folder is in PATH.
+      mercurial_path = os.path.abspath('hg')
+      put_hg_in_path.write('python %s %%*' % mercurial_path)
+  else:
+    subprocess.check_call(['make', 'local'])
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/download_appengine_and_mercurial.py b/download_appengine_and_mercurial.py
new file mode 100755
index 0000000..e2b3139
--- /dev/null
+++ b/download_appengine_and_mercurial.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# Copyright 2013 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Downloads the appengine SDK from WebRTC storage and unpacks it.
+
+Requires that depot_tools is installed and in the PATH. This script expects
+to run with Chrome's base dir as the working directory, e.g. where the .gclient
+file is. This is what should happen if this script is invoked as a hook action.
+"""
+
+import glob
+import os
+import sys
+import subprocess
+
+import utils
+
+def _DownloadResources(webrtc_deps_path):
+  print 'Downloading files in %s...' % webrtc_deps_path
+
+  extension = 'bat' if 'win32' in sys.platform else 'py'
+  cmd = ['download_from_google_storage.%s' % extension,
+         '--bucket=chromium-webrtc-resources',
+         '--directory', webrtc_deps_path]
+  subprocess.check_call(cmd)
+
+
+def _StripVersionNumberFromMercurialFolder():
+  unpacked_name = glob.glob('mercurial*')
+  assert len(unpacked_name) == 1, 'Should have precisely one mercurial!'
+  os.rename(unpacked_name[0], 'mercurial')
+
+
+def main(argv):
+  if len(argv) == 1:
+    return 'Usage: %s <path to webrtc.DEPS>' % argv[0]
+
+  webrtc_deps_path = argv[1]
+  appengine_zip_path = os.path.join(webrtc_deps_path, 'google-appengine.zip')
+  old_appengine_sha1 = utils.ComputeSHA1(appengine_zip_path)
+
+  mercurial_tar_path = os.path.join(webrtc_deps_path, 'mercurial-src.tar.gz')
+  old_mercurial_sha1 = utils.ComputeSHA1(mercurial_tar_path)
+
+  _DownloadResources(webrtc_deps_path)
+
+  if old_appengine_sha1 != utils.ComputeSHA1(appengine_zip_path):
+    utils.DeleteDirNextToGclient('google_appengine')
+    utils.UnpackToWorkingDir(appengine_zip_path)
+
+  if old_mercurial_sha1 != utils.ComputeSHA1(mercurial_tar_path):
+    utils.DeleteDirNextToGclient('mercurial')
+    utils.UnpackToWorkingDir(mercurial_tar_path)
+    _StripVersionNumberFromMercurialFolder()
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/download_appengine_sdk.py b/download_appengine_sdk.py
deleted file mode 100755
index d4e3b78..0000000
--- a/download_appengine_sdk.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/python
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Downloads the appengine SDK from WebRTC storage and unpacks it.
-
-Requires that depot_tools is installed and in the PATH. This script expects
-to run with Chrome's base dir as the working directory, e.g. where the .gclient
-file is. This is what should happen if this script is invoked as a hook action.
-"""
-
-import hashlib
-import os
-import shutil
-import sys
-import subprocess
-import zipfile
-
-
-def _DownloadAppEngineZipFile(webrtc_deps_path):
-  print 'Downloading files in %s...' % webrtc_deps_path
-
-  extension = 'bat' if 'win32' in sys.platform else 'py'
-  cmd = ['download_from_google_storage.%s' % extension,
-         '--bucket=chromium-webrtc-resources',
-         '--directory', webrtc_deps_path]
-  subprocess.check_call(cmd)
-
-
-def _ComputeSHA1(path):
-  if not os.path.exists(path):
-    return 0
-
-  sha1 = hashlib.sha1()
-  file_to_hash = open(path, 'rb')
-  try:
-    sha1.update(file_to_hash.read())
-  finally:
-    file_to_hash.close()
-
-  return sha1.hexdigest()
-
-
-# This is necessary since Windows won't allow us to unzip onto an existing dir.
-def _DeleteOldAppEngineDir():
-  app_engine_dir = 'google_appengine'
-  print 'Deleting %s in %s...' % (app_engine_dir, os.getcwd())
-  shutil.rmtree(app_engine_dir, ignore_errors=True)
-
-
-def _Unzip(path):
-  print 'Unzipping %s in %s...' % (path, os.getcwd())
-  zip_file = zipfile.ZipFile(path)
-  try:
-    zip_file.extractall()
-  finally:
-    zip_file.close()
-
-
-def main(argv):
-  if len(argv) == 1:
-    return 'Usage: %s <path to webrtc.DEPS>' % argv[0]
-
-  webrtc_deps_path = argv[1]
-  zip_path = os.path.join(webrtc_deps_path, 'google-appengine.zip')
-  old_zip_sha1 = _ComputeSHA1(zip_path)
-
-  _DownloadAppEngineZipFile(webrtc_deps_path)
-
-  if old_zip_sha1 != _ComputeSHA1(zip_path):
-    _DeleteOldAppEngineDir()
-    _Unzip(zip_path)
-
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/download_golang.py b/download_golang.py
new file mode 100755
index 0000000..c61ba00
--- /dev/null
+++ b/download_golang.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Downloads the golang SDK from WebRTC storage and unpacks it.
+
+Requires that depot_tools is installed and in the PATH. This script expects
+to run with Chrome's base dir as the working directory, e.g. where the .gclient
+file is. This is what should happen if this script is invoked as a hook action.
+"""
+
+import os
+import subprocess
+import sys
+import tarfile
+import zipfile
+
+import utils
+
+
+def _DownloadFilesFromGoogleStorage(webrtc_deps_path):
+  print 'Downloading files in %s...' % webrtc_deps_path
+
+  extension = 'bat' if 'win32' in sys.platform else 'py'
+  cmd = ['download_from_google_storage.%s' % extension,
+         '--bucket=chromium-webrtc-resources',
+         '--auto_platform',
+         '--recursive',
+         '--directory', webrtc_deps_path]
+  subprocess.check_call(cmd)
+
+
+def _GetGoArchivePathForPlatform():
+  archive_extension = 'zip' if utils.GetPlatform() == 'win' else 'tar.gz'
+  return os.path.join(utils.GetPlatform(), 'go.%s' % archive_extension)
+
+
+def main(argv):
+  if len(argv) == 1:
+    return 'Usage: %s <path to webrtc.DEPS>' % argv[0]
+  if not os.path.exists('.gclient'):
+    return 'Invoked from wrong dir; invoke from dir with .gclient'
+
+  webrtc_deps_path = argv[1]
+  golang_path = os.path.join(webrtc_deps_path, 'golang')
+  archive_path = os.path.join(golang_path, _GetGoArchivePathForPlatform())
+  old_archive_sha1 = utils.ComputeSHA1(archive_path)
+
+  _DownloadFilesFromGoogleStorage(golang_path)
+
+  if old_archive_sha1 != utils.ComputeSHA1(archive_path):
+    utils.DeleteDirNextToGclient('go')
+    utils.UnpackToWorkingDir(archive_path)
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/golang/linux/go.tar.gz.sha1 b/golang/linux/go.tar.gz.sha1
new file mode 100644
index 0000000..f655489
--- /dev/null
+++ b/golang/linux/go.tar.gz.sha1
@@ -0,0 +1 @@
+14068fbe349db34b838853a7878621bbd2b24646
diff --git a/golang/mac/go.tar.gz.sha1 b/golang/mac/go.tar.gz.sha1
new file mode 100644
index 0000000..c76e704
--- /dev/null
+++ b/golang/mac/go.tar.gz.sha1
@@ -0,0 +1 @@
+be686ec7ba68d588735cc2094ccab8bdd651de9e
diff --git a/golang/win/go.zip.sha1 b/golang/win/go.zip.sha1
new file mode 100644
index 0000000..a6bcbab
--- /dev/null
+++ b/golang/win/go.zip.sha1
@@ -0,0 +1 @@
+ba99083b22e0b22b560bb2d28b9b99b405d01b6b
diff --git a/mercurial-src.tar.gz.sha1 b/mercurial-src.tar.gz.sha1
new file mode 100644
index 0000000..5ef3e9d
--- /dev/null
+++ b/mercurial-src.tar.gz.sha1
@@ -0,0 +1 @@
+a8a51aa412abd5155c7de29fd39c9774decb4d3f
\ No newline at end of file
diff --git a/utils.py b/utils.py
new file mode 100755
index 0000000..1cf998d
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities for all our deps-management stuff."""
+
+import hashlib
+import os
+import shutil
+import sys
+import tarfile
+import zipfile
+
+
+def ComputeSHA1(path):
+  if not os.path.exists(path):
+    return 0
+
+  sha1 = hashlib.sha1()
+  file_to_hash = open(path, 'rb')
+  try:
+    sha1.update(file_to_hash.read())
+  finally:
+    file_to_hash.close()
+
+  return sha1.hexdigest()
+
+
+def DeleteDirNextToGclient(directory):
+  # Sanity check to avoid nuking the wrong dirs.
+  if not os.path.exists('.gclient'):
+    raise Exception('Invoked from wrong dir; invoke from dir with .gclient')
+  print 'Deleting %s in %s...' % (directory, os.getcwd())
+  shutil.rmtree(directory, ignore_errors=True)
+
+
+def UnpackToWorkingDir(archive_path):
+  extension = os.path.splitext(archive_path)[1]
+  if extension == '.zip':
+    _Unzip(archive_path)
+  else:
+    _Untar(archive_path)
+
+
+def _Unzip(path):
+  print 'Unzipping %s in %s...' % (path, os.getcwd())
+  zip_file = zipfile.ZipFile(path)
+  try:
+    zip_file.extractall()
+  finally:
+    zip_file.close()
+
+
+def _Untar(path):
+  print 'Untarring %s in %s...' % (path, os.getcwd())
+  tar_file = tarfile.open(path, 'r:gz')
+  try:
+    tar_file.extractall()
+  finally:
+    tar_file.close()
+
+
+def GetPlatform():
+  if sys.platform.startswith('win'):
+    return 'win'
+  if sys.platform.startswith('linux'):
+    return 'linux'
+  if sys.platform.startswith('darwin'):
+    return 'mac'
+  raise Exception("Can't run on platform %s." % sys.platform)
+