| Index: isolate/tree_creator.py
|
| ===================================================================
|
| --- isolate/tree_creator.py (revision 0)
|
| +++ isolate/tree_creator.py (revision 0)
|
| @@ -0,0 +1,124 @@
|
| +# 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.
|
| +
|
| +"""Creates a tree of hardlinks."""
|
| +
|
| +import logging
|
| +import os
|
| +import shutil
|
| +import sys
|
| +
|
| +import find_depot_tools # pylint: disable=W0611
|
| +import gclient_utils
|
| +
|
| +
|
| +# Types of action accepted by recreate_tree().
|
| +DRY_RUN, HARDLINK, SYMLINK, COPY = range(5)[1:]
|
| +
|
| +
|
| +def CreateHardLink(src, dst):
|
| + """Add support for os.link() on Windows."""
|
| + import ctypes
|
| + if not ctypes.windll.kernel32.CreateHardLinkW(unicode(dst), unicode(src), 0):
|
| + raise OSError()
|
| +
|
| +
|
| +class Foo(OSError):
|
| + """Failed to recreate the tree."""
|
| + pass
|
| +
|
| +
|
| +def recreate_tree(outdir, indir, infiles, action, blacklist):
|
| + """Creates a new tree with only the input files in it."""
|
| + assert action in (DRY_RUN, HARDLINK, SYMLINK, COPY)
|
| + indir = os.path.normpath(indir)
|
| + outdir = os.path.normpath(outdir)
|
| + logging.info('%s -> %s' % (indir, outdir))
|
| + if not os.path.isdir(indir):
|
| + raise Foo('%s is not a directory' % indir)
|
| + # Do not call abspath until it was verified the directory exists.
|
| + indir = os.path.abspath(indir)
|
| + if os.path.isdir(outdir):
|
| + logging.warn('Deleting %s' % outdir)
|
| + if action != DRY_RUN:
|
| + gclient_utils.RemoveDirectory(outdir)
|
| + if action != DRY_RUN:
|
| + logging.info ('Creating %s' % outdir)
|
| + os.makedirs(outdir)
|
| + # Do not call abspath until the directory exists.
|
| + outdir = os.path.abspath(outdir)
|
| + logging.info ('Created %s' % outdir)
|
| +
|
| + def process(inf, outf):
|
| + inf = os.path.normpath(inf)
|
| + outf = os.path.normpath(outf)
|
| + if action == DRY_RUN:
|
| + print outf
|
| + else:
|
| + logging.debug('%s -> %s' % (inf, outf))
|
| + if not os.path.isfile(inf):
|
| + raise Foo('%s doesn\'t exist' % inf)
|
| + if os.path.isfile(outf):
|
| + raise Foo('%s already exist' % outf)
|
| + if action == COPY:
|
| + shutil.copy(inf, outf)
|
| + elif action == SYMLINK:
|
| + os.symlink(inf, outf)
|
| + try:
|
| + if action == HARDLINK:
|
| + if sys.platform == 'win32':
|
| + CreateHardLink(inf, outf)
|
| + else:
|
| + os.link(inf, outf)
|
| + except OSError:
|
| + # Probably a different file system.
|
| + os.symlink(inf, outf)
|
| +
|
| + # Make the file read-only.
|
| + # TODO(maruel): Implement DACL modification on Windows.
|
| + mode = os.stat(inf).st_mode
|
| + mode = mode & 0500
|
| + if hasattr(os, 'lchmod'):
|
| + # Module 'os' has no 'lchmod' member
|
| + # pylint: disable=E1101
|
| + os.lchmod(outf, mode)
|
| + else:
|
| + os.chmod(outf, mode)
|
| +
|
| + for relfile in infiles:
|
| + infile = os.path.normpath(os.path.join(indir, relfile))
|
| + logging.debug(infile)
|
| + if not infile.startswith(indir):
|
| + raise Foo('Can\'t map file %s outside %s' % (infile, indir))
|
| + if os.path.isdir(infile):
|
| + # Process recursively.
|
| + for dirpath, dirnames, filenames in os.walk(infile):
|
| + insubdir = os.path.normpath(os.path.join(infile, dirpath))
|
| + outsubdir = os.path.normpath(
|
| + os.path.join(outdir, insubdir[len(indir) + 1:]))
|
| + for filename in filenames:
|
| + insubfile = os.path.normpath(os.path.join(infile, dirpath, filename))
|
| + outsubfile = os.path.normpath(os.path.join(outsubdir, filename))
|
| + if blacklist and blacklist(outsubfile):
|
| + continue
|
| + if not os.path.isdir(outsubdir):
|
| + os.makedirs(outsubdir)
|
| + process(insubfile, outsubfile)
|
| + for index, dirname in enumerate(dirnames):
|
| + if blacklist(os.path.normpath(os.path.join(outdir, dirname))):
|
| + del dirnames[index]
|
| + else:
|
| + # TODO(maruel): Is that secure?
|
| + outsubfile = os.path.normpath(os.path.join(outdir, relfile))
|
| + if blacklist and blacklist(outsubfile):
|
| + continue
|
| + outsubdir = os.path.dirname(outsubfile)
|
| + if not os.path.isdir(outsubdir):
|
| + os.makedirs(outsubdir)
|
| + process(infile, outsubfile)
|
| +
|
| + # Then mark all the directories as read-only to inhibit file creation.
|
| + for dirpath, _, _ in os.walk(outdir):
|
| + # TODO(maruel): Implement DACL modification on Windows.
|
| + os.chmod(os.path.join(outdir, dirpath), 0500)
|
|
|
| Property changes on: isolate/tree_creator.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|