18925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org#!/usr/bin/env python
28925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
38925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org#
48925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# Use of this source code is governed by a BSD-style license
58925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# that can be found in the LICENSE file in the root of the source
68925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# tree. An additional intellectual property rights grant can be found
78925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# in the file PATENTS.  All contributing project authors may
88925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# be found in the AUTHORS file in the root of the source tree.
98925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org"""Setup links to a Chromium checkout for WebRTC.
118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgWebRTC standalone shares a lot of dependencies and build tools with Chromium.
138925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgTo do this, many of the paths of a Chromium checkout is emulated by creating
148925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgsymlinks to files and directories. This script handles the setup of symlinks to
158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgachieve this.
168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgIt also handles cleanup of the legacy Subversion-based approach that was used
188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgbefore Chrome switched over their master repo from Subversion to Git.
198925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org"""
208925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
218925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
228925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport ctypes
238925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport errno
248925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport logging
258925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport optparse
268925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport os
278925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport shelve
288925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport shutil
298925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport subprocess
308925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport sys
318925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgimport textwrap
328925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
338925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
348925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgDIRECTORIES = [
358925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'build',
368925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'buildtools',
378925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'testing',
388925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/binutils',
398925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/boringssl',
408925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/colorama',
418925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/drmemory',
428925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/expat',
43a9a1d2acaf71281a6f09cd85acb6bc21b02e5ce4hbos  'third_party/ffmpeg',
444e4fe4f9ae4160e917400616567cf6c41f585d58kjellander@webrtc.org  'third_party/instrumented_libraries',
458925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/jsoncpp',
4626ab91b73fa1a2628a5cc049f29bb52926e230baHenrik Kjellander  'third_party/libc++-static',
478925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/libjpeg',
488925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/libjpeg_turbo',
498925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/libsrtp',
507d4e6d012c16bbe8b7958abf5341193afc1629e6kjellander@webrtc.org  'third_party/libudev',
51d6024e3c34bf5ebce5624c4dc8930a5b4ae63d36kjellander  'third_party/libvpx_new',
528925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/libyuv',
538925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/llvm-build',
54c92c23d99ad9ffe152370f6e17ad482d1613cad8Patrik Höglund  'third_party/lss',
558925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/nss',
563a63a3c35d93616606c23d27583b83a198b94a3etkchin@webrtc.org  'third_party/ocmock',
57a9a1d2acaf71281a6f09cd85acb6bc21b02e5ce4hbos  'third_party/openh264',
588925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/openmax_dl',
598925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/opus',
60c92c23d99ad9ffe152370f6e17ad482d1613cad8Patrik Höglund  'third_party/proguard',
618925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/protobuf',
628925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/sqlite',
638925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/syzygy',
648925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/usrsctp',
658925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/yasm',
663bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org  'third_party/zlib',
678925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/clang',
688925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/generate_library_loader',
698925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/gn',
708925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/gyp',
718925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/memory',
728925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/protoc_wrapper',
738925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/python',
748925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/swarming_client',
758925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/valgrind',
7665de7d266cbe13363dd7ee40063417daf1bc6614Andrew MacDonald  'tools/vim',
778925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'tools/win',
789589e2af1642fce385fb8c47e3726a5c416a4e02Henrik Kjellander  'tools/xdisplaycheck',
798925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org]
808925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
813bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.orgfrom sync_chromium import get_target_os_list
82ca8430208de9db1b9ef548014942549e7136682dHenrik Kjellandertarget_os = get_target_os_list()
83ca8430208de9db1b9ef548014942549e7136682dHenrik Kjellanderif 'android' in target_os:
843bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org  DIRECTORIES += [
853bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org    'base',
8694a12324841629749cadc60d91ced8e93e88ff1dHenrik Kjellander    'third_party/android_platform',
873bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org    'third_party/android_tools',
88cbe7ca8796a3e0c6b56910640e76943ba4224118kjellander@webrtc.org    'third_party/appurify-python',
89b8caf6a5042e4a8bf0230b8a202a0fbfc414fb59kjellander@webrtc.org    'third_party/ashmem',
9034a7054fd68b0347e60c7529ae94b868a190f255kjellander    'third_party/catapult',
915376100d00f23f27b2640343136be70da895f8ffkjellander    'third_party/icu',
92eecbab7cd54814b189fe1b5fdf2ba2afa4df4fbfHenrik Kjellander    'third_party/ijar',
93b8caf6a5042e4a8bf0230b8a202a0fbfc414fb59kjellander@webrtc.org    'third_party/jsr-305',
9410ba3eec5a268d359260e331fcc2608f818d5236Henrik Kjellander    'third_party/junit',
95b8caf6a5042e4a8bf0230b8a202a0fbfc414fb59kjellander@webrtc.org    'third_party/libevent',
96b8caf6a5042e4a8bf0230b8a202a0fbfc414fb59kjellander@webrtc.org    'third_party/libxml',
9710ba3eec5a268d359260e331fcc2608f818d5236Henrik Kjellander    'third_party/mockito',
98b8caf6a5042e4a8bf0230b8a202a0fbfc414fb59kjellander@webrtc.org    'third_party/modp_b64',
99cbe7ca8796a3e0c6b56910640e76943ba4224118kjellander@webrtc.org    'third_party/requests',
10010ba3eec5a268d359260e331fcc2608f818d5236Henrik Kjellander    'third_party/robolectric',
1013bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org    'tools/android',
102bfdee69d486e05af5bb9f3e4f68f6c79028eca9ekjellander@webrtc.org    'tools/grit',
10334a7054fd68b0347e60c7529ae94b868a190f255kjellander    'tools/telemetry',
1043bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org  ]
105ca8430208de9db1b9ef548014942549e7136682dHenrik Kjellanderif 'ios' in target_os:
106ca8430208de9db1b9ef548014942549e7136682dHenrik Kjellander  DIRECTORIES.append('third_party/class-dump')
1073bd4156d75b12c084026e8e31c12fd4b982374d3kjellander@webrtc.org
1088925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgFILES = {
109d6d27e7340bca1598973e2197cf08d79ce9aeb04Henrik Kjellander  'tools/isolate_driver.py': None,
1108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  'third_party/BUILD.gn': None,
1118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org}
1128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
113e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.orgROOT_DIR = os.path.dirname(os.path.abspath(__file__))
1148925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgCHROMIUM_CHECKOUT = os.path.join('chromium', 'src')
1158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgLINKS_DB = 'links'
1168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# Version management to make future upgrades/downgrades easier to support.
1188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgSCHEMA_VERSION = 1
1198925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1208925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1218925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgdef query_yes_no(question, default=False):
1228925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  """Ask a yes/no question via raw_input() and return their answer.
1238925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1248925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  Modified from http://stackoverflow.com/a/3041990.
1258925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  """
1268925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  prompt = " [%s/%%s]: "
1278925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  prompt = prompt % ('Y' if default is True  else 'y')
1288925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  prompt = prompt % ('N' if default is False else 'n')
1298925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1308925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  if default is None:
1318925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    default = 'INVALID'
1328925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1338925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  while True:
1348925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    sys.stdout.write(question + prompt)
1358925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    choice = raw_input().lower()
1368925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if choice == '' and default != 'INVALID':
1378925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      return default
1388925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1398925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if 'yes'.startswith(choice):
1408925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      return True
1418925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    elif 'no'.startswith(choice):
1428925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      return False
1438925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1448925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    print "Please respond with 'yes' or 'no' (or 'y' or 'n')."
1458925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1468925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1478925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# Actions
1488925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass Action(object):
1498925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, dangerous):
1508925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self.dangerous = dangerous
1518925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1528925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def announce(self, planning):
1538925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    """Log a description of this action.
1548925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1558925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    Args:
1568925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      planning - True iff we're in the planning stage, False if we're in the
1578925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                 doit stage.
1588925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    """
1598925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    pass
1608925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1618925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def doit(self, links_db):
1628925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    """Execute the action, recording what we did to links_db, if necessary."""
1638925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    pass
1648925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1658925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1668925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass Remove(Action):
1678925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, path, dangerous):
1688925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    super(Remove, self).__init__(dangerous)
1698925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._priority = 0
1708925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._path = path
1718925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1728925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def announce(self, planning):
1738925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    log = logging.warn
1748925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    filesystem_type = 'file'
1758925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not self.dangerous:
1768925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      log = logging.info
1778925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      filesystem_type = 'link'
1788925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if planning:
1798925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      log('Planning to remove %s: %s', filesystem_type, self._path)
1808925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    else:
1818925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      log('Removing %s: %s', filesystem_type, self._path)
1828925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
18357e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellander  def doit(self, _):
1848925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    os.remove(self._path)
1858925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1868925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1878925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass Rmtree(Action):
1888925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, path):
1898925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    super(Rmtree, self).__init__(dangerous=True)
1908925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._priority = 0
1918925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._path = path
1928925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
1938925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def announce(self, planning):
1948925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if planning:
1958925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.warn('Planning to remove directory: %s', self._path)
1968925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    else:
1978925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.warn('Removing directory: %s', self._path)
1988925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
19957e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellander  def doit(self, _):
2008925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if sys.platform.startswith('win'):
2018925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      # shutil.rmtree() doesn't work on Windows if any of the directories are
2028925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      # read-only, which svn repositories are.
2038925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      subprocess.check_call(['rd', '/q', '/s', self._path], shell=True)
2048925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    else:
2058925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      shutil.rmtree(self._path)
2068925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2078925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2088925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass Makedirs(Action):
2098925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, path):
2108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    super(Makedirs, self).__init__(dangerous=False)
2118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._priority = 1
2128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._path = path
2138925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
21457e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellander  def doit(self, _):
2158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    try:
2168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      os.makedirs(self._path)
2178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    except OSError as e:
2188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if e.errno != errno.EEXIST:
2198925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        raise
2208925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2218925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2228925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass Symlink(Action):
2238925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, source_path, link_path):
2248925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    super(Symlink, self).__init__(dangerous=False)
2258925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._priority = 2
2268925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._source_path = source_path
2278925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._link_path = link_path
2288925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2298925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def announce(self, planning):
2308925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if planning:
2318925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.info(
2328925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          'Planning to create link from %s to %s', self._link_path,
2338925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          self._source_path)
2348925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    else:
2358925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.debug(
2368925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          'Linking from %s to %s', self._link_path, self._source_path)
2378925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2388925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def doit(self, links_db):
2398925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    # Files not in the root directory need relative path calculation.
2408925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    # On Windows, use absolute paths instead since NTFS doesn't seem to support
2418925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    # relative paths for symlinks.
2428925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if sys.platform.startswith('win'):
2438925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      source_path = os.path.abspath(self._source_path)
2448925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    else:
2458925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if os.path.dirname(self._link_path) != self._link_path:
2468925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        source_path = os.path.relpath(self._source_path,
2478925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                                      os.path.dirname(self._link_path))
2488925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2498925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    os.symlink(source_path, os.path.abspath(self._link_path))
2508925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    links_db[self._source_path] = self._link_path
2518925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2528925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2538925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgclass LinkError(IOError):
2548925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  """Failed to create a link."""
2558925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  pass
2568925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2578925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2588925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org# Handles symlink creation on the different platforms.
2598925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgif sys.platform.startswith('win'):
2608925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def symlink(source_path, link_path):
2618925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    flag = 1 if os.path.isdir(source_path) else 0
2628925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not ctypes.windll.kernel32.CreateSymbolicLinkW(
2638925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        unicode(link_path), unicode(source_path), flag):
2648925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      raise OSError('Failed to create symlink to %s. Notice that only NTFS '
2658925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    'version 5.0 and up has all the needed APIs for '
2668925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    'creating symlinks.' % source_path)
2678925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  os.symlink = symlink
2688925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2698925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
27057e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellanderclass WebRTCLinkSetup(object):
2718925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def __init__(self, links_db, force=False, dry_run=False, prompt=False):
2728925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._force = force
2738925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._dry_run = dry_run
2748925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._prompt = prompt
2758925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    self._links_db = links_db
2768925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2778925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def CreateLinks(self, on_bot):
2788925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    logging.debug('CreateLinks')
2798925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    # First, make a plan of action
2808925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    actions = []
2818925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
2828925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    for source_path, link_path in FILES.iteritems():
2838925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      actions += self._ActionForPath(
2848925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          source_path, link_path, check_fn=os.path.isfile, check_msg='files')
2858925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    for source_dir in DIRECTORIES:
2868925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      actions += self._ActionForPath(
2878925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          source_dir, None, check_fn=os.path.isdir,
2888925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          check_msg='directories')
2898925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
290e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org    if not on_bot and self._force:
291e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org      # When making the manual switch from legacy SVN checkouts to the new
292e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org      # Git-based Chromium DEPS, the .gclient_entries file that contains cached
293e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org      # URLs for all DEPS entries must be removed to avoid future sync problems.
294e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org      entries_file = os.path.join(os.path.dirname(ROOT_DIR), '.gclient_entries')
295e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org      if os.path.exists(entries_file):
296e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org        actions.append(Remove(entries_file, dangerous=True))
297e94f83a1919120deb48e97bc91955d0ca12e43fekjellander@webrtc.org
2988925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    actions.sort()
2998925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3008925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if self._dry_run:
3018925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      for action in actions:
3028925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        action.announce(planning=True)
3038925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.info('Not doing anything because dry-run was specified.')
3048925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      sys.exit(0)
3058925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3068925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if any(a.dangerous for a in actions):
3078925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.warn('Dangerous actions:')
3088925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      for action in (a for a in actions if a.dangerous):
3098925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        action.announce(planning=True)
3108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      print
3118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if not self._force:
3138925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        logging.error(textwrap.dedent("""\
3148925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
3158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                              A C T I O N     R E Q I R E D
3168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
3178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        Because chromium/src is transitioning to Git (from SVN), we needed to
3198925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        change the way that the WebRTC standalone checkout works. Instead of
3208925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        individually syncing subdirectories of Chromium in SVN, we're now
3218925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        syncing Chromium (and all of its DEPS, as defined by its own DEPS file),
3228925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        into the `chromium/src` directory.
3238925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3248925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        As such, all Chromium directories which are currently pulled by DEPS are
3258925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        now replaced with a symlink into the full Chromium checkout.
3268925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3278925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        To avoid disrupting developers, we've chosen to not delete your
3288925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        directories forcibly, in case you have some work in progress in one of
3298925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        them :).
3308925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3318925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        ACTION REQUIRED:
3328925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        Before running `gclient sync|runhooks` again, you must run:
3338925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        %s%s --force
3348925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3358925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        Which will replace all directories which now must be symlinks, after
3368925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        prompting with a summary of the work-to-be-done.
3378925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        """), 'python ' if sys.platform.startswith('win') else '', sys.argv[0])
3388925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        sys.exit(1)
3398925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      elif self._prompt:
3408925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        if not query_yes_no('Would you like to perform the above plan?'):
3418925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          sys.exit(1)
3428925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3438925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    for action in actions:
3448925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      action.announce(planning=False)
3458925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      action.doit(self._links_db)
3468925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3478925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not on_bot and self._force:
3488925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.info('Completed!\n\nNow run `gclient sync|runhooks` again to '
3498925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                   'let the remaining hooks (that probably were interrupted) '
3508925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                   'execute.')
3518925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3528925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def CleanupLinks(self):
3538925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    logging.debug('CleanupLinks')
3548925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    for source, link_path  in self._links_db.iteritems():
3558925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if source == 'SCHEMA_VERSION':
3568925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        continue
3578925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if os.path.islink(link_path) or sys.platform.startswith('win'):
3588925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        # os.path.islink() always returns false on Windows
3598925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        # See http://bugs.python.org/issue13143.
3608925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        logging.debug('Removing link to %s at %s', source, link_path)
3618925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        if not self._dry_run:
3628925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          if os.path.exists(link_path):
3638925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org            if sys.platform.startswith('win') and os.path.isdir(link_path):
364c444de627656ffaef2d97285eb55656cc866cc6eHenrik Kjellander              subprocess.check_call(['rmdir', '/q', '/s', link_path],
365c444de627656ffaef2d97285eb55656cc866cc6eHenrik Kjellander                                    shell=True)
3668925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org            else:
3678925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org              os.remove(link_path)
3688925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org          del self._links_db[source]
3698925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3708925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  @staticmethod
3718925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  def _ActionForPath(source_path, link_path=None, check_fn=None,
3728925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                     check_msg=None):
3738925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    """Create zero or more Actions to link to a file or directory.
3748925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3758925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    This will be a symlink on POSIX platforms. On Windows this requires
3768925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    that NTFS is version 5.0 or higher (Vista or newer).
3778925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3788925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    Args:
3798925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      source_path: Path relative to the Chromium checkout root.
3808925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        For readability, the path may contain slashes, which will
3818925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        automatically be converted to the right path delimiter on Windows.
3828925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      link_path: The location for the link to create. If omitted it will be the
3838925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        same path as source_path.
3848925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      check_fn: A function returning true if the type of filesystem object is
3858925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        correct for the attempted call. Otherwise an error message with
3868925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        check_msg will be printed.
3878925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      check_msg: String used to inform the user of an invalid attempt to create
3888925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        a file.
3898925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    Returns:
3908925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      A list of Action objects.
3918925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    """
3928925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    def fix_separators(path):
3938925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if sys.platform.startswith('win'):
3948925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        return path.replace(os.altsep, os.sep)
3958925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      else:
3968925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        return path
3978925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
3988925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    assert check_fn
3998925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    assert check_msg
4008925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    link_path = link_path or source_path
4018925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    link_path = fix_separators(link_path)
4028925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4038925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    source_path = fix_separators(source_path)
4048925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    source_path = os.path.join(CHROMIUM_CHECKOUT, source_path)
4058925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if os.path.exists(source_path) and not check_fn:
4068925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      raise LinkError('_LinkChromiumPath can only be used to link to %s: '
4078925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                      'Tried to link to: %s' % (check_msg, source_path))
4088925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4098925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not os.path.exists(source_path):
4108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.debug('Silently ignoring missing source: %s. This is to avoid '
4118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    'errors on platform-specific dependencies.', source_path)
4128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      return []
4138925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4148925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    actions = []
4158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if os.path.exists(link_path) or os.path.islink(link_path):
4178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      if os.path.islink(link_path):
4188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        actions.append(Remove(link_path, dangerous=False))
4198925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      elif os.path.isfile(link_path):
4208925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        actions.append(Remove(link_path, dangerous=True))
4218925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      elif os.path.isdir(link_path):
4228925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        actions.append(Rmtree(link_path))
4238925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      else:
4248925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        raise LinkError('Don\'t know how to plan: %s' % link_path)
4258925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4268925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    # Create parent directories to the target link if needed.
4278925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    target_parent_dirs = os.path.dirname(link_path)
4288925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if (target_parent_dirs and
4298925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        target_parent_dirs != link_path and
4308925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        not os.path.exists(target_parent_dirs)):
4318925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      actions.append(Makedirs(target_parent_dirs))
4328925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4338925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    actions.append(Symlink(source_path, link_path))
4348925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4358925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    return actions
4368925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4378925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgdef _initialize_database(filename):
4388925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  links_database = shelve.open(filename)
4398925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4408925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  # Wipe the database if this version of the script ends up looking at a
4418925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  # newer (future) version of the links db, just to be sure.
4428925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  version = links_database.get('SCHEMA_VERSION')
4438925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  if version and version != SCHEMA_VERSION:
4448925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    logging.info('Found database with schema version %s while this script only '
4458925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                 'supports %s. Wiping previous database contents.', version,
4468925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                 SCHEMA_VERSION)
4478925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    links_database.clear()
4488925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  links_database['SCHEMA_VERSION'] = SCHEMA_VERSION
4498925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  return links_database
4508925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4518925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4528925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgdef main():
4538925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  on_bot = os.environ.get('CHROME_HEADLESS') == '1'
4548925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4558925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser = optparse.OptionParser()
4568925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser.add_option('-d', '--dry-run', action='store_true', default=False,
4578925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    help='Print what would be done, but don\'t perform any '
4588925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'operations. This will automatically set logging to '
4598925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'verbose.')
4608925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser.add_option('-c', '--clean-only', action='store_true', default=False,
4618925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    help='Only clean previously created links, don\'t create '
4628925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'new ones. This will automatically set logging to '
4638925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'verbose.')
4648925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser.add_option('-f', '--force', action='store_true', default=on_bot,
4658925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    help='Force link creation. CAUTION: This deletes existing '
4668925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'folders and files in the locations where links are '
4678925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                         'about to be created.')
4688925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser.add_option('-n', '--no-prompt', action='store_false', dest='prompt',
4698925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    default=(not on_bot),
4708925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    help='Prompt if we\'re planning to do a dangerous action')
4718925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  parser.add_option('-v', '--verbose', action='store_const',
4728925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    const=logging.DEBUG, default=logging.INFO,
4738925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    help='Print verbose output for debugging.')
4748925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  options, _ = parser.parse_args()
4758925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4768925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  if options.dry_run or options.force or options.clean_only:
4778925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    options.verbose = logging.DEBUG
4788925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  logging.basicConfig(format='%(message)s', level=options.verbose)
4798925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4808925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  # Work from the root directory of the checkout.
4818925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  script_dir = os.path.dirname(os.path.abspath(__file__))
4828925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  os.chdir(script_dir)
4838925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4848925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  if sys.platform.startswith('win'):
4858925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    def is_admin():
4868925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      try:
4878925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        return os.getuid() == 0
4888925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      except AttributeError:
4898925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org        return ctypes.windll.shell32.IsUserAnAdmin() != 0
4908925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not is_admin():
4918925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      logging.error('On Windows, you now need to have administrator '
4928925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    'privileges for the shell running %s (or '
4938925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                    '`gclient sync|runhooks`).\nPlease start another command '
49457e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellander                    'prompt as Administrator and try again.', sys.argv[0])
4958925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      return 1
4968925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
4978925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  if not os.path.exists(CHROMIUM_CHECKOUT):
4988925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    logging.error('Cannot find a Chromium checkout at %s. Did you run "gclient '
4998925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                  'sync" before running this script?', CHROMIUM_CHECKOUT)
5008925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    return 2
5018925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
5028925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  links_database = _initialize_database(LINKS_DB)
5038925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  try:
5048925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    symlink_creator = WebRTCLinkSetup(links_database, options.force,
5058925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org                                      options.dry_run, options.prompt)
5068925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    symlink_creator.CleanupLinks()
5078925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    if not options.clean_only:
5088925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org      symlink_creator.CreateLinks(on_bot)
5098925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  except LinkError as e:
5108925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    print >> sys.stderr, e.message
5118925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    return 3
5128925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  finally:
5138925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org    links_database.close()
5148925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  return 0
5158925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
5168925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org
5178925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.orgif __name__ == '__main__':
5188925662318ca10d841e92f4dc20bbf0c53aea865kjellander@webrtc.org  sys.exit(main())
519