| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python2.4 | |
| 2 # Copyright 2008, Google Inc. | |
| 3 # All rights reserved. | |
| 4 # | |
| 5 # Redistribution and use in source and binary forms, with or without | |
| 6 # modification, are permitted provided that the following conditions are | |
| 7 # met: | |
| 8 # | |
| 9 # * Redistributions of source code must retain the above copyright | |
| 10 # notice, this list of conditions and the following disclaimer. | |
| 11 # * Redistributions in binary form must reproduce the above | |
| 12 # copyright notice, this list of conditions and the following disclaimer | |
| 13 # in the documentation and/or other materials provided with the | |
| 14 # distribution. | |
| 15 # * Neither the name of Google Inc. nor the names of its | |
| 16 # contributors may be used to endorse or promote products derived from | |
| 17 # this software without specific prior written permission. | |
| 18 # | |
| 19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 30 | |
| 31 """Replicate tool for SCons.""" | |
| 32 | |
| 33 | |
| 34 import re | |
| 35 | |
| 36 | |
| 37 def Replicate(env, target, source, **kw): | |
| 38 """Replicates (copies) source files/directories to the target directory. | |
| 39 | |
| 40 Much like env.Install(), with the following differences: | |
| 41 * If the source is a directory, recurses through it and calls | |
| 42 env.Install() on each source file, rather than copying the entire | |
| 43 directory at once. This provides more opportunity for hard linking, and | |
| 44 also makes the destination files/directories all writable. | |
| 45 * Can take sources which contain env.Glob()-style wildcards. | |
| 46 * Can take multiple target directories; will copy to all of them. | |
| 47 * Handles duplicate requests. | |
| 48 | |
| 49 Args: | |
| 50 env: Environment in which to operate. | |
| 51 target: Destination(s) for copy. Must evaluate to a directory via | |
| 52 env.Dir(), or a list of directories. If more than one directory is | |
| 53 passed, the entire source list will be copied to each target | |
| 54 directory. | |
| 55 source: Source file(s) to copy. May be a string, Node, or a list of | |
| 56 mixed strings or Nodes. Strings will be passed through env.Glob() to | |
| 57 evaluate wildcards. If a source evaluates to a directory, the entire | |
| 58 directory will be recursively copied. | |
| 59 | |
| 60 From env: | |
| 61 REPLICATE_REPLACE: A list of pairs of regex search and replacement strings. | |
| 62 Each full destination path has substitution performed on each pair | |
| 63 (search_regex, replacement) in order. | |
| 64 | |
| 65 env.Replicate('destdir', ['footxt.txt'], REPLICATE_REPLACE = [ | |
| 66 ('\\.txt', '.bar'), ('est', 'ist')]) | |
| 67 will copy to 'distdir/footxt.bar' | |
| 68 | |
| 69 In the example above, note the use of \\ to escape the '.' character, | |
| 70 so that it doesn't act like the regexp '.' and match any character. | |
| 71 | |
| 72 Returns: | |
| 73 A list of the destination nodes from the calls to env.Install(). | |
| 74 """ | |
| 75 replace_list = kw.get('REPLICATE_REPLACE', env.get('REPLICATE_REPLACE', [])) | |
| 76 | |
| 77 dest_nodes = [] | |
| 78 for target_entry in env.Flatten(target): | |
| 79 for source_entry in env.Flatten(source): | |
| 80 if type(source_entry) == str: | |
| 81 # Search for matches for each source entry | |
| 82 source_nodes = env.Glob(source_entry) | |
| 83 else: | |
| 84 # Source entry is already a file or directory node; no need to glob it | |
| 85 source_nodes = [source_entry] | |
| 86 for s in source_nodes: | |
| 87 target_name = env.Dir(target_entry).abspath + '/' + s.name | |
| 88 # We need to use the following incantation rather than s.isdir() in | |
| 89 # order to handle chained replicates (A -> B -> C). The isdir() | |
| 90 # function is not properly defined in all of the Node type classes in | |
| 91 # SCons. This change is particularly crucial if hardlinks are present, | |
| 92 # in which case using isdir() can cause files to be unintentionally | |
| 93 # deleted. | |
| 94 # TODO(bradnelson): Look into fixing the innards of SCons so this isn't | |
| 95 # needed. | |
| 96 if str(s.__class__) == 'SCons.Node.FS.Dir': | |
| 97 # Recursively copy all files in subdir. Since glob('*') doesn't | |
| 98 # match dot files, also glob('.*'). | |
| 99 dest_nodes += env.Replicate( | |
| 100 target_name, [s.abspath + '/*', s.abspath + '/.*'], | |
| 101 REPLICATE_REPLACE=replace_list) | |
| 102 else: | |
| 103 # Apply replacement strings, if any | |
| 104 for r in replace_list: | |
| 105 target_name = re.sub(r[0], r[1], target_name) | |
| 106 target = env.File(target_name) | |
| 107 if (target.has_builder() | |
| 108 and hasattr(target.get_builder(), 'name') | |
| 109 and target.get_builder().name == 'InstallBuilder' | |
| 110 and target.sources == [s]): | |
| 111 # Already installed that file, so pass through the destination node | |
| 112 # TODO(rspangler): Is there a better way to determine if this is a | |
| 113 # duplicate install? | |
| 114 dest_nodes += [target] | |
| 115 else: | |
| 116 dest_nodes += env.InstallAs(target_name, s) | |
| 117 | |
| 118 # Return list of destination nodes | |
| 119 return dest_nodes | |
| 120 | |
| 121 | |
| 122 def generate(env): | |
| 123 # NOTE: SCons requires the use of this name, which fails gpylint. | |
| 124 """SCons entry point for this tool.""" | |
| 125 | |
| 126 env.AddMethod(Replicate) | |
| OLD | NEW |