]>
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 ###############################################################################
31 Fundamental data type used to build file system tree structures.
33 If CHILDREN is None, then the node represents a file. Otherwise, CHILDREN
34 is a list of the nodes representing that directory's children.
36 NAME is simply the name of the file or directory. CONTENTS is a string
37 holding the file's contents (if a file).
41 def __init__(self
, name
, children
=None, contents
=None):
42 assert children
is None or contents
is None
45 self
.children
= children
46 self
.contents
= contents
49 def add_child(self
, newchild
):
50 assert not self
.is_file()
51 for a
in self
.children
:
52 if a
.name
== newchild
.name
:
53 if newchild
.is_file():
54 a
.contents
= newchild
.contents
55 a
.path
= os
.path
.join(self
.path
, newchild
.name
)
57 for i
in newchild
.children
:
61 self
.children
.append(newchild
)
62 newchild
.path
= os
.path
.join(self
.path
, newchild
.name
)
64 def get_child(self
, name
):
66 If the given TreeNode directory NODE contains a child named NAME,
67 return the child; else, return None.
70 for n
in self
.children
:
75 return self
.children
is None
78 print(" * Node name: %s" % self
.name
)
79 print(" Path: %s" % self
.path
)
80 print(" Contents: %s" % self
.contents
)
82 print(" Children: is a file.")
84 print(" Children: %d" % len(self
.children
))
90 self
.removed_files
= []
91 self
.modified_files
= []
92 self
.touched_files
= []
94 def append(self
, other
):
95 self
.added_files
.extend(other
.added_files
)
96 self
.removed_files
.extend(other
.removed_files
)
97 self
.modified_files
.extend(other
.modified_files
)
98 self
.touched_files
.extend(other
.touched_files
)
100 def ignore_directories(self
):
101 """Removes directories from our lists of found differences."""
102 not_dir
= lambda x
: x
[-1] != "/"
103 self
.added_files
= filter(not_dir
, self
.added_files
)
104 self
.removed_files
= filter(not_dir
, self
.removed_files
)
105 self
.modified_files
= filter(not_dir
, self
.modified_files
)
106 self
.touched_files
= filter(not_dir
, self
.touched_files
)
108 def pprint(self
, file=sys
.stdout
):
109 file.write("Added files : %s\n" % self
.added_files
)
110 file.write("Removed files : %s\n" % self
.removed_files
)
111 file.write("Modified files: %s\n" % self
.modified_files
)
112 file.write("Touched files : %s\n" % self
.touched_files
)
115 return not (self
.added_files
or self
.removed_files
or
116 self
.modified_files
or self
.touched_files
)
119 def build_tree(path
):
121 Takes PATH as the folder path, walks the file system below that path, and
122 creates a tree structure based on any files and folders found there.
123 Returns the prepared tree structure plus the maximum file modification
124 timestamp under the given folder.
127 return _handle_dir(os
.path
.normpath(path
))
130 def tree_difference(a
, b
):
131 """Compare TreeNodes A and B, and create a TreeDifference instance."""
132 return _do_tree_difference(a
, b
, "", True)
135 def _do_tree_difference(a
, b
, parent_path
, root
=False):
136 """Internal recursive worker function for tree_difference()."""
138 # We do not want to list root node names.
140 assert not parent_path
141 assert not a
.is_file()
142 assert not b
.is_file()
145 assert a
.name
== b
.name
146 full_path
= parent_path
+ a
.name
147 result
= TreeDifference()
149 # A and B are both files.
150 if a
.is_file() and b
.is_file():
151 if a
.contents
!= b
.contents
:
152 result
.modified_files
.append(full_path
)
153 elif a
.mtime
!= b
.mtime
:
154 result
.touched_files
.append(full_path
)
157 # Directory converted to file.
158 if not a
.is_file() and b
.is_file():
159 result
.removed_files
.extend(_traverse_tree(a
, parent_path
))
160 result
.added_files
.append(full_path
)
162 # File converted to directory.
163 elif a
.is_file() and not b
.is_file():
164 result
.removed_files
.append(full_path
)
165 result
.added_files
.extend(_traverse_tree(b
, parent_path
))
167 # A and B are both directories.
171 accounted_for
= [] # Children present in both trees.
172 for a_child
in a
.children
:
173 b_child
= b
.get_child(a_child
.name
)
175 accounted_for
.append(b_child
)
176 result
.append(_do_tree_difference(a_child
, b_child
, full_path
))
178 result
.removed_files
.append(full_path
+ a_child
.name
)
179 for b_child
in b
.children
:
180 if b_child
not in accounted_for
:
181 result
.added_files
.extend(_traverse_tree(b_child
, full_path
))
186 def _traverse_tree(t
, parent_path
):
187 """Returns a list of all names in a tree."""
188 assert not parent_path
or parent_path
[-1] == "/"
189 full_node_name
= parent_path
+ t
.name
191 result
= [full_node_name
]
193 name_prefix
= full_node_name
+ "/"
194 result
= [name_prefix
]
196 result
.extend(_traverse_tree(i
, name_prefix
))
201 """Return a string with the textual contents of a file at PATH."""
209 def _handle_dir(path
):
211 Main recursive worker function for build_tree(). Returns a newly created
212 tree node representing the given normalized folder path as well as the
213 maximum file/folder modification time detected under the same path.
218 node
= TreeNode(os
.path
.basename(path
), children
=[])
219 max_mtime
= node
.mtime
= os
.stat(path
).st_mtime
221 # List files & folders.
222 for f
in os
.listdir(path
):
223 f
= os
.path
.join(path
, f
)
226 elif os
.path
.isfile(f
):
229 # Add a child node for each file.
231 fcontents
= _get_text(f
)
232 new_file_node
= TreeNode(os
.path
.basename(f
), contents
=fcontents
)
233 new_file_node
.mtime
= os
.stat(f
).st_mtime
234 max_mtime
= max(max_mtime
, new_file_node
.mtime
)
235 node
.add_child(new_file_node
)
237 # For each subdir, create a node, walk its tree, add it as a child.
239 new_dir_node
, new_max_mtime
= _handle_dir(d
)
240 max_mtime
= max(max_mtime
, new_max_mtime
)
241 node
.add_child(new_dir_node
)
243 return node
, max_mtime