]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/test/tree.py
1 # Copyright 2003 Dave Abrahams
2 # Copyright 2001, 2002 Vladimir Prus
3 # Copyright 2012 Jurko Gospodnetic
4 # Distributed under the Boost Software License, Version 1.0.
5 # (See accompanying file LICENSE_1_0.txt or copy at
6 # http://www.boost.org/LICENSE_1_0.txt)
8 ###############################################################################
10 # Based in part on an old Subversion tree.py source file (tools for comparing
11 # directory trees). See http://subversion.tigris.org for more information.
13 # Copyright (c) 2001 Sam Tobin-Hochstadt. All rights reserved.
15 # This software is licensed as described in the file COPYING, which you should
16 # have received as part of this distribution. The terms are also available at
17 # http://subversion.tigris.org/license-1.html. If newer versions of this
18 # license are posted there, you may use a newer version instead, at your
21 ###############################################################################
23 from __future__
import print_function
33 Fundamental data type used to build file system tree structures.
35 If CHILDREN is None, then the node represents a file. Otherwise, CHILDREN
36 is a list of the nodes representing that directory's children.
38 NAME is simply the name of the file or directory. CONTENTS is a string
39 holding the file's contents (if a file).
43 def __init__(self
, name
, children
=None, contents
=None):
44 assert children
is None or contents
is None
47 self
.children
= children
48 self
.contents
= contents
51 def add_child(self
, newchild
):
52 assert not self
.is_file()
53 for a
in self
.children
:
54 if a
.name
== newchild
.name
:
55 if newchild
.is_file():
56 a
.contents
= newchild
.contents
57 a
.path
= os
.path
.join(self
.path
, newchild
.name
)
59 for i
in newchild
.children
:
63 self
.children
.append(newchild
)
64 newchild
.path
= os
.path
.join(self
.path
, newchild
.name
)
66 def get_child(self
, name
):
68 If the given TreeNode directory NODE contains a child named NAME,
69 return the child; else, return None.
72 for n
in self
.children
:
77 return self
.children
is None
80 print(" * Node name: %s" % self
.name
)
81 print(" Path: %s" % self
.path
)
82 print(" Contents: %s" % self
.contents
)
84 print(" Children: is a file.")
86 print(" Children: %d" % len(self
.children
))
92 self
.removed_files
= []
93 self
.modified_files
= []
94 self
.touched_files
= []
96 def append(self
, other
):
97 self
.added_files
.extend(other
.added_files
)
98 self
.removed_files
.extend(other
.removed_files
)
99 self
.modified_files
.extend(other
.modified_files
)
100 self
.touched_files
.extend(other
.touched_files
)
102 def ignore_directories(self
):
103 """Removes directories from our lists of found differences."""
104 not_dir
= lambda x
: x
[-1] != "/"
105 self
.added_files
= list(filter(not_dir
, self
.added_files
))
106 self
.removed_files
= list(filter(not_dir
, self
.removed_files
))
107 self
.modified_files
= list(filter(not_dir
, self
.modified_files
))
108 self
.touched_files
= list(filter(not_dir
, self
.touched_files
))
110 def pprint(self
, file=sys
.stdout
):
111 file.write("Added files : %s\n" % self
.added_files
)
112 file.write("Removed files : %s\n" % self
.removed_files
)
113 file.write("Modified files: %s\n" % self
.modified_files
)
114 file.write("Touched files : %s\n" % self
.touched_files
)
117 return not (self
.added_files
or self
.removed_files
or
118 self
.modified_files
or self
.touched_files
)
121 def build_tree(path
):
123 Takes PATH as the folder path, walks the file system below that path, and
124 creates a tree structure based on any files and folders found there.
125 Returns the prepared tree structure plus the maximum file modification
126 timestamp under the given folder.
129 return _handle_dir(os
.path
.normpath(path
))
132 def tree_difference(a
, b
):
133 """Compare TreeNodes A and B, and create a TreeDifference instance."""
134 return _do_tree_difference(a
, b
, "", True)
137 def _do_tree_difference(a
, b
, parent_path
, root
=False):
138 """Internal recursive worker function for tree_difference()."""
140 # We do not want to list root node names.
142 assert not parent_path
143 assert not a
.is_file()
144 assert not b
.is_file()
147 assert a
.name
== b
.name
148 full_path
= parent_path
+ a
.name
149 result
= TreeDifference()
151 # A and B are both files.
152 if a
.is_file() and b
.is_file():
153 if a
.contents
!= b
.contents
:
154 result
.modified_files
.append(full_path
)
155 elif a
.mtime
!= b
.mtime
:
156 result
.touched_files
.append(full_path
)
159 # Directory converted to file.
160 if not a
.is_file() and b
.is_file():
161 result
.removed_files
.extend(_traverse_tree(a
, parent_path
))
162 result
.added_files
.append(full_path
)
164 # File converted to directory.
165 elif a
.is_file() and not b
.is_file():
166 result
.removed_files
.append(full_path
)
167 result
.added_files
.extend(_traverse_tree(b
, parent_path
))
169 # A and B are both directories.
173 accounted_for
= [] # Children present in both trees.
174 for a_child
in a
.children
:
175 b_child
= b
.get_child(a_child
.name
)
177 accounted_for
.append(b_child
)
178 result
.append(_do_tree_difference(a_child
, b_child
, full_path
))
180 result
.removed_files
.append(full_path
+ a_child
.name
)
181 for b_child
in b
.children
:
182 if b_child
not in accounted_for
:
183 result
.added_files
.extend(_traverse_tree(b_child
, full_path
))
188 def _traverse_tree(t
, parent_path
):
189 """Returns a list of all names in a tree."""
190 assert not parent_path
or parent_path
[-1] == "/"
191 full_node_name
= parent_path
+ t
.name
193 result
= [full_node_name
]
195 name_prefix
= full_node_name
+ "/"
196 result
= [name_prefix
]
198 result
.extend(_traverse_tree(i
, name_prefix
))
203 """Return a string with the textual contents of a file at PATH."""
204 fp
= open(path
, 'rb')
211 def _handle_dir(path
):
213 Main recursive worker function for build_tree(). Returns a newly created
214 tree node representing the given normalized folder path as well as the
215 maximum file/folder modification time detected under the same path.
220 node
= TreeNode(os
.path
.basename(path
), children
=[])
221 max_mtime
= node
.mtime
= os
.stat(path
).st_mtime
223 # List files & folders.
224 for f
in os
.listdir(path
):
225 f
= os
.path
.join(path
, f
)
228 elif os
.path
.isfile(f
):
231 # Add a child node for each file.
233 fcontents
= _get_text(f
)
234 new_file_node
= TreeNode(os
.path
.basename(f
), contents
=fcontents
)
235 new_file_node
.mtime
= os
.stat(f
).st_mtime
236 max_mtime
= max(max_mtime
, new_file_node
.mtime
)
237 node
.add_child(new_file_node
)
239 # For each subdir, create a node, walk its tree, add it as a child.
241 new_dir_node
, new_max_mtime
= _handle_dir(d
)
242 max_mtime
= max(max_mtime
, new_max_mtime
)
243 node
.add_child(new_dir_node
)
245 return node
, max_mtime