summaryrefslogtreecommitdiffstats
path: root/media/libyuv/setup_links.py
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /media/libyuv/setup_links.py
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'media/libyuv/setup_links.py')
-rw-r--r--media/libyuv/setup_links.py497
1 files changed, 497 insertions, 0 deletions
diff --git a/media/libyuv/setup_links.py b/media/libyuv/setup_links.py
new file mode 100644
index 000000000..b2b459e60
--- /dev/null
+++ b/media/libyuv/setup_links.py
@@ -0,0 +1,497 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+"""Setup links to a Chromium checkout for WebRTC.
+
+WebRTC standalone shares a lot of dependencies and build tools with Chromium.
+To do this, many of the paths of a Chromium checkout is emulated by creating
+symlinks to files and directories. This script handles the setup of symlinks to
+achieve this.
+
+It also handles cleanup of the legacy Subversion-based approach that was used
+before Chrome switched over their master repo from Subversion to Git.
+"""
+
+
+import ctypes
+import errno
+import logging
+import optparse
+import os
+import shelve
+import shutil
+import subprocess
+import sys
+import textwrap
+
+
+DIRECTORIES = [
+ 'build',
+ 'buildtools',
+ 'mojo', # TODO(kjellander): Remove, see webrtc:5629.
+ 'native_client',
+ 'net',
+ 'testing',
+ 'third_party/binutils',
+ 'third_party/drmemory',
+ 'third_party/instrumented_libraries',
+ 'third_party/libjpeg',
+ 'third_party/libjpeg_turbo',
+ 'third_party/llvm-build',
+ 'third_party/lss',
+ 'third_party/yasm',
+ 'third_party/WebKit', # TODO(kjellander): Remove, see webrtc:5629.
+ 'tools/clang',
+ 'tools/gn',
+ 'tools/gyp',
+ 'tools/memory',
+ 'tools/python',
+ 'tools/swarming_client',
+ 'tools/valgrind',
+ 'tools/vim',
+ 'tools/win',
+]
+
+from sync_chromium import get_target_os_list
+target_os = get_target_os_list()
+if 'android' in target_os:
+ DIRECTORIES += [
+ 'base',
+ 'third_party/android_platform',
+ 'third_party/android_tools',
+ 'third_party/appurify-python',
+ 'third_party/ashmem',
+ 'third_party/catapult',
+ 'third_party/icu',
+ 'third_party/ijar',
+ 'third_party/jsr-305',
+ 'third_party/junit',
+ 'third_party/libxml',
+ 'third_party/mockito',
+ 'third_party/modp_b64',
+ 'third_party/protobuf',
+ 'third_party/requests',
+ 'third_party/robolectric',
+ 'tools/android',
+ 'tools/grit',
+ ]
+if 'ios' in target_os:
+ DIRECTORIES.append('third_party/class-dump')
+
+FILES = {
+ 'tools/isolate_driver.py': None,
+ 'third_party/BUILD.gn': None,
+}
+
+ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
+CHROMIUM_CHECKOUT = os.path.join('chromium', 'src')
+LINKS_DB = 'links'
+
+# Version management to make future upgrades/downgrades easier to support.
+SCHEMA_VERSION = 1
+
+
+def query_yes_no(question, default=False):
+ """Ask a yes/no question via raw_input() and return their answer.
+
+ Modified from http://stackoverflow.com/a/3041990.
+ """
+ prompt = " [%s/%%s]: "
+ prompt = prompt % ('Y' if default is True else 'y')
+ prompt = prompt % ('N' if default is False else 'n')
+
+ if default is None:
+ default = 'INVALID'
+
+ while True:
+ sys.stdout.write(question + prompt)
+ choice = raw_input().lower()
+ if choice == '' and default != 'INVALID':
+ return default
+
+ if 'yes'.startswith(choice):
+ return True
+ elif 'no'.startswith(choice):
+ return False
+
+ print "Please respond with 'yes' or 'no' (or 'y' or 'n')."
+
+
+# Actions
+class Action(object):
+ def __init__(self, dangerous):
+ self.dangerous = dangerous
+
+ def announce(self, planning):
+ """Log a description of this action.
+
+ Args:
+ planning - True iff we're in the planning stage, False if we're in the
+ doit stage.
+ """
+ pass
+
+ def doit(self, links_db):
+ """Execute the action, recording what we did to links_db, if necessary."""
+ pass
+
+
+class Remove(Action):
+ def __init__(self, path, dangerous):
+ super(Remove, self).__init__(dangerous)
+ self._priority = 0
+ self._path = path
+
+ def announce(self, planning):
+ log = logging.warn
+ filesystem_type = 'file'
+ if not self.dangerous:
+ log = logging.info
+ filesystem_type = 'link'
+ if planning:
+ log('Planning to remove %s: %s', filesystem_type, self._path)
+ else:
+ log('Removing %s: %s', filesystem_type, self._path)
+
+ def doit(self, _):
+ os.remove(self._path)
+
+
+class Rmtree(Action):
+ def __init__(self, path):
+ super(Rmtree, self).__init__(dangerous=True)
+ self._priority = 0
+ self._path = path
+
+ def announce(self, planning):
+ if planning:
+ logging.warn('Planning to remove directory: %s', self._path)
+ else:
+ logging.warn('Removing directory: %s', self._path)
+
+ def doit(self, _):
+ if sys.platform.startswith('win'):
+ # shutil.rmtree() doesn't work on Windows if any of the directories are
+ # read-only, which svn repositories are.
+ subprocess.check_call(['rd', '/q', '/s', self._path], shell=True)
+ else:
+ shutil.rmtree(self._path)
+
+
+class Makedirs(Action):
+ def __init__(self, path):
+ super(Makedirs, self).__init__(dangerous=False)
+ self._priority = 1
+ self._path = path
+
+ def doit(self, _):
+ try:
+ os.makedirs(self._path)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+
+class Symlink(Action):
+ def __init__(self, source_path, link_path):
+ super(Symlink, self).__init__(dangerous=False)
+ self._priority = 2
+ self._source_path = source_path
+ self._link_path = link_path
+
+ def announce(self, planning):
+ if planning:
+ logging.info(
+ 'Planning to create link from %s to %s', self._link_path,
+ self._source_path)
+ else:
+ logging.debug(
+ 'Linking from %s to %s', self._link_path, self._source_path)
+
+ def doit(self, links_db):
+ # Files not in the root directory need relative path calculation.
+ # On Windows, use absolute paths instead since NTFS doesn't seem to support
+ # relative paths for symlinks.
+ if sys.platform.startswith('win'):
+ source_path = os.path.abspath(self._source_path)
+ else:
+ if os.path.dirname(self._link_path) != self._link_path:
+ source_path = os.path.relpath(self._source_path,
+ os.path.dirname(self._link_path))
+
+ os.symlink(source_path, os.path.abspath(self._link_path))
+ links_db[self._source_path] = self._link_path
+
+
+class LinkError(IOError):
+ """Failed to create a link."""
+ pass
+
+
+# Handles symlink creation on the different platforms.
+if sys.platform.startswith('win'):
+ def symlink(source_path, link_path):
+ flag = 1 if os.path.isdir(source_path) else 0
+ if not ctypes.windll.kernel32.CreateSymbolicLinkW(
+ unicode(link_path), unicode(source_path), flag):
+ raise OSError('Failed to create symlink to %s. Notice that only NTFS '
+ 'version 5.0 and up has all the needed APIs for '
+ 'creating symlinks.' % source_path)
+ os.symlink = symlink
+
+
+class WebRTCLinkSetup(object):
+ def __init__(self, links_db, force=False, dry_run=False, prompt=False):
+ self._force = force
+ self._dry_run = dry_run
+ self._prompt = prompt
+ self._links_db = links_db
+
+ def CreateLinks(self, on_bot):
+ logging.debug('CreateLinks')
+ # First, make a plan of action
+ actions = []
+
+ for source_path, link_path in FILES.iteritems():
+ actions += self._ActionForPath(
+ source_path, link_path, check_fn=os.path.isfile, check_msg='files')
+ for source_dir in DIRECTORIES:
+ actions += self._ActionForPath(
+ source_dir, None, check_fn=os.path.isdir,
+ check_msg='directories')
+
+ if not on_bot and self._force:
+ # When making the manual switch from legacy SVN checkouts to the new
+ # Git-based Chromium DEPS, the .gclient_entries file that contains cached
+ # URLs for all DEPS entries must be removed to avoid future sync problems.
+ entries_file = os.path.join(os.path.dirname(ROOT_DIR), '.gclient_entries')
+ if os.path.exists(entries_file):
+ actions.append(Remove(entries_file, dangerous=True))
+
+ actions.sort()
+
+ if self._dry_run:
+ for action in actions:
+ action.announce(planning=True)
+ logging.info('Not doing anything because dry-run was specified.')
+ sys.exit(0)
+
+ if any(a.dangerous for a in actions):
+ logging.warn('Dangerous actions:')
+ for action in (a for a in actions if a.dangerous):
+ action.announce(planning=True)
+ print
+
+ if not self._force:
+ logging.error(textwrap.dedent("""\
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ A C T I O N R E Q I R E D
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ Because chromium/src is transitioning to Git (from SVN), we needed to
+ change the way that the WebRTC standalone checkout works. Instead of
+ individually syncing subdirectories of Chromium in SVN, we're now
+ syncing Chromium (and all of its DEPS, as defined by its own DEPS file),
+ into the `chromium/src` directory.
+
+ As such, all Chromium directories which are currently pulled by DEPS are
+ now replaced with a symlink into the full Chromium checkout.
+
+ To avoid disrupting developers, we've chosen to not delete your
+ directories forcibly, in case you have some work in progress in one of
+ them :).
+
+ ACTION REQUIRED:
+ Before running `gclient sync|runhooks` again, you must run:
+ %s%s --force
+
+ Which will replace all directories which now must be symlinks, after
+ prompting with a summary of the work-to-be-done.
+ """), 'python ' if sys.platform.startswith('win') else '', sys.argv[0])
+ sys.exit(1)
+ elif self._prompt:
+ if not query_yes_no('Would you like to perform the above plan?'):
+ sys.exit(1)
+
+ for action in actions:
+ action.announce(planning=False)
+ action.doit(self._links_db)
+
+ if not on_bot and self._force:
+ logging.info('Completed!\n\nNow run `gclient sync|runhooks` again to '
+ 'let the remaining hooks (that probably were interrupted) '
+ 'execute.')
+
+ def CleanupLinks(self):
+ logging.debug('CleanupLinks')
+ for source, link_path in self._links_db.iteritems():
+ if source == 'SCHEMA_VERSION':
+ continue
+ if os.path.islink(link_path) or sys.platform.startswith('win'):
+ # os.path.islink() always returns false on Windows
+ # See http://bugs.python.org/issue13143.
+ logging.debug('Removing link to %s at %s', source, link_path)
+ if not self._dry_run:
+ if os.path.exists(link_path):
+ if sys.platform.startswith('win') and os.path.isdir(link_path):
+ subprocess.check_call(['rmdir', '/q', '/s', link_path],
+ shell=True)
+ else:
+ os.remove(link_path)
+ del self._links_db[source]
+
+ @staticmethod
+ def _ActionForPath(source_path, link_path=None, check_fn=None,
+ check_msg=None):
+ """Create zero or more Actions to link to a file or directory.
+
+ This will be a symlink on POSIX platforms. On Windows this requires
+ that NTFS is version 5.0 or higher (Vista or newer).
+
+ Args:
+ source_path: Path relative to the Chromium checkout root.
+ For readability, the path may contain slashes, which will
+ automatically be converted to the right path delimiter on Windows.
+ link_path: The location for the link to create. If omitted it will be the
+ same path as source_path.
+ check_fn: A function returning true if the type of filesystem object is
+ correct for the attempted call. Otherwise an error message with
+ check_msg will be printed.
+ check_msg: String used to inform the user of an invalid attempt to create
+ a file.
+ Returns:
+ A list of Action objects.
+ """
+ def fix_separators(path):
+ if sys.platform.startswith('win'):
+ return path.replace(os.altsep, os.sep)
+ else:
+ return path
+
+ assert check_fn
+ assert check_msg
+ link_path = link_path or source_path
+ link_path = fix_separators(link_path)
+
+ source_path = fix_separators(source_path)
+ source_path = os.path.join(CHROMIUM_CHECKOUT, source_path)
+ if os.path.exists(source_path) and not check_fn:
+ raise LinkError('_LinkChromiumPath can only be used to link to %s: '
+ 'Tried to link to: %s' % (check_msg, source_path))
+
+ if not os.path.exists(source_path):
+ logging.debug('Silently ignoring missing source: %s. This is to avoid '
+ 'errors on platform-specific dependencies.', source_path)
+ return []
+
+ actions = []
+
+ if os.path.exists(link_path) or os.path.islink(link_path):
+ if os.path.islink(link_path):
+ actions.append(Remove(link_path, dangerous=False))
+ elif os.path.isfile(link_path):
+ actions.append(Remove(link_path, dangerous=True))
+ elif os.path.isdir(link_path):
+ actions.append(Rmtree(link_path))
+ else:
+ raise LinkError('Don\'t know how to plan: %s' % link_path)
+
+ # Create parent directories to the target link if needed.
+ target_parent_dirs = os.path.dirname(link_path)
+ if (target_parent_dirs and
+ target_parent_dirs != link_path and
+ not os.path.exists(target_parent_dirs)):
+ actions.append(Makedirs(target_parent_dirs))
+
+ actions.append(Symlink(source_path, link_path))
+
+ return actions
+
+def _initialize_database(filename):
+ links_database = shelve.open(filename)
+
+ # Wipe the database if this version of the script ends up looking at a
+ # newer (future) version of the links db, just to be sure.
+ version = links_database.get('SCHEMA_VERSION')
+ if version and version != SCHEMA_VERSION:
+ logging.info('Found database with schema version %s while this script only '
+ 'supports %s. Wiping previous database contents.', version,
+ SCHEMA_VERSION)
+ links_database.clear()
+ links_database['SCHEMA_VERSION'] = SCHEMA_VERSION
+ return links_database
+
+
+def main():
+ on_bot = os.environ.get('CHROME_HEADLESS') == '1'
+
+ parser = optparse.OptionParser()
+ parser.add_option('-d', '--dry-run', action='store_true', default=False,
+ help='Print what would be done, but don\'t perform any '
+ 'operations. This will automatically set logging to '
+ 'verbose.')
+ parser.add_option('-c', '--clean-only', action='store_true', default=False,
+ help='Only clean previously created links, don\'t create '
+ 'new ones. This will automatically set logging to '
+ 'verbose.')
+ parser.add_option('-f', '--force', action='store_true', default=on_bot,
+ help='Force link creation. CAUTION: This deletes existing '
+ 'folders and files in the locations where links are '
+ 'about to be created.')
+ parser.add_option('-n', '--no-prompt', action='store_false', dest='prompt',
+ default=(not on_bot),
+ help='Prompt if we\'re planning to do a dangerous action')
+ parser.add_option('-v', '--verbose', action='store_const',
+ const=logging.DEBUG, default=logging.INFO,
+ help='Print verbose output for debugging.')
+ options, _ = parser.parse_args()
+
+ if options.dry_run or options.force or options.clean_only:
+ options.verbose = logging.DEBUG
+ logging.basicConfig(format='%(message)s', level=options.verbose)
+
+ # Work from the root directory of the checkout.
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ os.chdir(script_dir)
+
+ if sys.platform.startswith('win'):
+ def is_admin():
+ try:
+ return os.getuid() == 0
+ except AttributeError:
+ return ctypes.windll.shell32.IsUserAnAdmin() != 0
+ if not is_admin():
+ logging.error('On Windows, you now need to have administrator '
+ 'privileges for the shell running %s (or '
+ '`gclient sync|runhooks`).\nPlease start another command '
+ 'prompt as Administrator and try again.', sys.argv[0])
+ return 1
+
+ if not os.path.exists(CHROMIUM_CHECKOUT):
+ logging.error('Cannot find a Chromium checkout at %s. Did you run "gclient '
+ 'sync" before running this script?', CHROMIUM_CHECKOUT)
+ return 2
+
+ links_database = _initialize_database(LINKS_DB)
+ try:
+ symlink_creator = WebRTCLinkSetup(links_database, options.force,
+ options.dry_run, options.prompt)
+ symlink_creator.CleanupLinks()
+ if not options.clean_only:
+ symlink_creator.CreateLinks(on_bot)
+ except LinkError as e:
+ print >> sys.stderr, e.message
+ return 3
+ finally:
+ links_database.close()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())