mirror of
https://github.com/facebook/proxygen.git
synced 2025-08-05 19:55:47 +03:00
Summary: X-link: https://github.com/facebookincubator/fizz/pull/155 X-link: https://github.com/facebookincubator/zstrong/pull/1085 getdeps windows file copy is very slow, speed it up Reviewed By: bigfootjon Differential Revision: D66830544 fbshipit-source-id: 43213e258c71ae706bb059600619e276e7491a90
100 lines
3.0 KiB
Python
100 lines
3.0 KiB
Python
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
#
|
|
# This source code is licensed under the MIT license found in the
|
|
# LICENSE file in the root directory of this source tree.
|
|
|
|
# pyre-unsafe
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
|
|
from .platform import is_windows
|
|
from .runcmd import run_cmd
|
|
|
|
|
|
PREFETCHED_DIRS = set()
|
|
|
|
|
|
def containing_repo_type(path):
|
|
while True:
|
|
if os.path.exists(os.path.join(path, ".git")):
|
|
return ("git", path)
|
|
if os.path.exists(os.path.join(path, ".hg")):
|
|
return ("hg", path)
|
|
|
|
parent = os.path.dirname(path)
|
|
if parent == path:
|
|
return None, None
|
|
path = parent
|
|
|
|
|
|
def find_eden_root(dirpath):
|
|
"""If the specified directory is inside an EdenFS checkout, returns
|
|
the canonical absolute path to the root of that checkout.
|
|
|
|
Returns None if the specified directory is not in an EdenFS checkout.
|
|
"""
|
|
if is_windows():
|
|
repo_type, repo_root = containing_repo_type(dirpath)
|
|
if repo_root is not None:
|
|
if os.path.exists(os.path.join(repo_root, ".eden", "config")):
|
|
return repo_root
|
|
return None
|
|
|
|
try:
|
|
return os.readlink(os.path.join(dirpath, ".eden", "root"))
|
|
except OSError:
|
|
return None
|
|
|
|
|
|
def prefetch_dir_if_eden(dirpath) -> None:
|
|
"""After an amend/rebase, Eden may need to fetch a large number
|
|
of trees from the servers. The simplistic single threaded walk
|
|
performed by copytree makes this more expensive than is desirable
|
|
so we help accelerate things by performing a prefetch on the
|
|
source directory"""
|
|
global PREFETCHED_DIRS
|
|
if dirpath in PREFETCHED_DIRS:
|
|
return
|
|
root = find_eden_root(dirpath)
|
|
if root is None:
|
|
return
|
|
glob = f"{os.path.relpath(dirpath, root).replace(os.sep, '/')}/**"
|
|
print(f"Prefetching {glob}")
|
|
subprocess.call(["edenfsctl", "prefetch", "--repo", root, glob, "--background"])
|
|
PREFETCHED_DIRS.add(dirpath)
|
|
|
|
|
|
def simple_copytree(src_dir, dest_dir, symlinks=False):
|
|
"""A simple version of shutil.copytree() that can delegate to native tools if faster"""
|
|
if is_windows():
|
|
os.makedirs(dest_dir, exist_ok=True)
|
|
cmd = [
|
|
"robocopy.exe",
|
|
src_dir,
|
|
dest_dir,
|
|
# copy directories, including empty ones
|
|
"/E",
|
|
# Ignore Extra files in destination
|
|
"/XX",
|
|
# enable parallel copy
|
|
"/MT",
|
|
# be quiet
|
|
"/NFL",
|
|
"/NDL",
|
|
"/NJH",
|
|
"/NJS",
|
|
"/NP",
|
|
]
|
|
if symlinks:
|
|
cmd.append("/SL")
|
|
# robocopy exits with code 1 if it copied ok, hence allow_fail
|
|
# https://learn.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/return-codes-used-robocopy-utility
|
|
exit_code = run_cmd(cmd, allow_fail=True)
|
|
if exit_code > 1:
|
|
raise subprocess.CalledProcessError(exit_code, cmd)
|
|
return dest_dir
|
|
else:
|
|
return shutil.copytree(src_dir, dest_dir, symlinks=symlinks)
|