Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Unified Diff: tools/isolate/isolate.py

Issue 9513003: Add target base_unittests_run and tools/isolate/isolate.py. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove directory from 'inputs' Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/isolate/PRESUBMIT.py ('k') | tools/isolate/isolate_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/isolate/isolate.py
diff --git a/tools/isolate/isolate.py b/tools/isolate/isolate.py
new file mode 100755
index 0000000000000000000000000000000000000000..be4f076efa3a3b3ea32eeb11708f4d30faeb366e
--- /dev/null
+++ b/tools/isolate/isolate.py
@@ -0,0 +1,167 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 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.
+
+"""Does one of the following depending on the --mode argument:
+ check verify all the inputs exist, touches the file specified with
+ --result and exits.
+ run recreates a tree with all the inputs files and run the executable
+ in it.
+ remap stores all the inputs files in a directory without running the
+ executable.
+"""
+
+import logging
+import optparse
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+import time
+
+import tree_creator
+
+
+def touch(filename):
+ """Implements the equivalent of the 'touch' command."""
+ if not os.path.exists(filename):
+ open(filename, 'a').close()
+ os.utime(filename, None)
+
+
+def rmtree(root):
+ """Wrapper around shutil.rmtree() to retry automatically on Windows."""
+ if sys.platform == 'win32':
+ for i in range(3):
+ try:
+ shutil.rmtree(root)
+ break
+ except WindowsError: # pylint: disable=E0602
+ delay = (i+1)*2
+ print >> sys.stderr, (
+ 'The test has subprocess outliving it. Sleep %d seconds.' % delay)
+ time.sleep(delay)
+ else:
+ shutil.rmtree(root)
+
+
+def isolate(outdir, root, resultfile, mode, read_only, args):
+ """Main function to isolate a target with its dependencies."""
+ cmd = []
+ if '--' in args:
+ # Strip off the command line from the inputs.
+ i = args.index('--')
+ cmd = args[i+1:]
+ args = args[:i]
+
+ # gyp provides paths relative to cwd. Convert them to be relative to
+ # root.
+ cwd = os.getcwd()
+
+ def make_relpath(i):
+ """Makes an input file a relative path but keeps any trailing slash."""
+ out = os.path.relpath(os.path.join(cwd, i), root)
+ if i.endswith('/'):
+ out += '/'
+ return out
+
+ infiles = [make_relpath(i) for i in args]
+
+ if not infiles:
+ raise ValueError('Need at least one input file to map')
+
+ # Other modes ignore the command.
+ if mode == 'run' and not cmd:
+ print >> sys.stderr, 'Using first input %s as executable' % infiles[0]
+ cmd = [infiles[0]]
+
+ tempdir = None
+ try:
+ if not outdir and mode != 'check':
+ tempdir = tempfile.mkdtemp(prefix='isolate')
+ outdir = tempdir
+ elif outdir:
+ outdir = os.path.abspath(outdir)
+
+ tree_creator.recreate_tree(
+ outdir,
+ os.path.abspath(root),
+ infiles,
+ tree_creator.DRY_RUN if mode == 'check' else tree_creator.HARDLINK,
+ lambda x: re.match(r'.*\.(svn|pyc)$', x))
+
+ if mode != 'check' and read_only:
+ tree_creator.make_writable(outdir, True)
+
+ if mode in ('check', 'remap'):
+ result = 0
+ else:
+ # TODO(maruel): Remove me. Layering violation. Used by
+ # base/base_paths_linux.cc
+ env = os.environ.copy()
+ env['CR_SOURCE_ROOT'] = outdir.encode()
+ # Rebase the command to the right path.
+ cmd[0] = os.path.join(outdir, cmd[0])
+ logging.info('Running %s' % cmd)
+ result = subprocess.call(cmd, cwd=outdir, env=env)
+
+ if not result and resultfile:
+ # Signal the build tool that the test succeeded.
+ touch(resultfile)
+ return result
+ finally:
+ if tempdir and mode == 'isolate':
+ if read_only:
+ tree_creator.make_writable(tempdir, False)
+ rmtree(tempdir)
+
+
+def main():
+ parser = optparse.OptionParser(
+ usage='%prog [options] [inputs] -- [command line]',
+ description=sys.modules[__name__].__doc__)
+ parser.allow_interspersed_args = False
+ parser.format_description = lambda *_: parser.description
+ parser.add_option(
+ '-v', '--verbose', action='count', default=0, help='Use multiple times')
+ parser.add_option(
+ '--mode', choices=['remap', 'check', 'run'],
+ help='Determines the action to be taken')
+ parser.add_option(
+ '--result', metavar='X',
+ help='File to be touched when the command succeeds')
+ parser.add_option('--root', help='Base directory to fetch files, required')
+ parser.add_option(
+ '--outdir', metavar='X',
+ help='Directory used to recreate the tree. Defaults to a /tmp '
+ 'subdirectory')
+ parser.add_option(
+ '--read-only', action='store_true',
+ help='Make the temporary tree read-only')
+
+ options, args = parser.parse_args()
+ level = [logging.ERROR, logging.INFO, logging.DEBUG][min(2, options.verbose)]
+ logging.basicConfig(
+ level=level,
+ format='%(levelname)5s %(module)15s(%(lineno)3d): %(message)s')
+
+ if not options.root:
+ parser.error('--root is required.')
+
+ try:
+ return isolate(
+ options.outdir,
+ options.root,
+ options.result,
+ options.mode,
+ options.read_only,
+ args)
+ except ValueError, e:
+ parser.error(str(e))
+
+
+if __name__ == '__main__':
+ sys.exit(main())
« no previous file with comments | « tools/isolate/PRESUBMIT.py ('k') | tools/isolate/isolate_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698