in build/fbcode_builder/getdeps/fetcher.py [0:0]
def mirror(self, fbsource_root, dest_root) -> ChangeStatus:
self._minimize_roots()
self._sort_mapping()
change_status = ChangeStatus()
# Record the full set of files that should be in the tree
full_file_list = set()
if sys.platform == "win32":
# Let's not assume st_dev has a consistent value on Windows.
def st_dev(path):
return 1
else:
def st_dev(path):
return os.lstat(path).st_dev
for fbsource_subdir in self.roots:
dir_to_mirror = os.path.join(fbsource_root, fbsource_subdir)
root_dev = st_dev(dir_to_mirror)
prefetch_dir_if_eden(dir_to_mirror)
if not os.path.exists(dir_to_mirror):
raise Exception(
"%s doesn't exist; check your sparse profile!" % dir_to_mirror
)
for root, dirs, files in os.walk(dir_to_mirror):
dirs[:] = [d for d in dirs if root_dev == st_dev(os.path.join(root, d))]
for src_file in files:
full_name = os.path.join(root, src_file)
rel_name = os.path.relpath(full_name, fbsource_root)
norm_name = rel_name.replace("\\", "/")
target_name = self._map_name(norm_name, dest_root)
if target_name:
full_file_list.add(target_name)
if copy_if_different(full_name, target_name):
change_status.record_change(target_name)
# Compare the list of previously shipped files; if a file is
# in the old list but not the new list then it has been
# removed from the source and should be removed from the
# destination.
# Why don't we simply create this list by walking dest_root?
# Some builds currently have to be in-source builds and
# may legitimately need to keep some state in the source tree :-/
installed_name = os.path.join(dest_root, ".shipit_shipped")
if os.path.exists(installed_name):
with open(installed_name, "rb") as f:
for name in f.read().decode("utf-8").splitlines():
name = name.strip()
if name not in full_file_list:
print("Remove %s" % name)
os.unlink(name)
change_status.record_change(name)
with open(installed_name, "wb") as f:
for name in sorted(list(full_file_list)):
f.write(("%s\n" % name).encode("utf-8"))
return change_status