2021-10-19 23:54:37 +00:00
|
|
|
# Copyright 2021 The Chromium OS Authors. All rights reserved.
|
|
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
|
|
# found in the LICENSE file.
|
|
|
|
|
|
|
|
# Refactoring tools for moving around crates and updating dependencies
|
|
|
|
# in toml files.
|
|
|
|
#
|
|
|
|
# Contains the last run refactoring for reference. Don't run this script, it'll
|
|
|
|
# fail, but use it as a foundation for other refactorings.
|
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
from contextlib import contextmanager
|
2021-10-19 23:54:37 +00:00
|
|
|
from pathlib import Path
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import shutil
|
|
|
|
import subprocess
|
2022-03-16 19:04:57 +00:00
|
|
|
from typing import Callable, List, Tuple, Union
|
|
|
|
|
2021-10-19 23:54:37 +00:00
|
|
|
|
2022-03-16 18:48:22 +00:00
|
|
|
SearchPattern = Union[str, re.Pattern[str]]
|
2022-03-16 19:04:57 +00:00
|
|
|
Replacement = Union[str, Callable[[re.Match[str]], str]]
|
|
|
|
|
2021-10-19 23:54:37 +00:00
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
def append_to_file(file_path: Path, appendix: str):
|
|
|
|
contents = file_path.read_text()
|
|
|
|
file_path.write_text(contents.rstrip() + "\n" + appendix + "\n")
|
2022-03-16 18:48:22 +00:00
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
|
|
|
|
def replace_in_file(file_path: Path, search: SearchPattern, replace: Replacement):
|
2022-03-16 18:48:22 +00:00
|
|
|
if not file_path.exists():
|
|
|
|
print(f"WARNING: Does not exist {file_path}")
|
|
|
|
return
|
|
|
|
if isinstance(search, str):
|
|
|
|
search = re.escape(search)
|
2022-03-16 19:04:57 +00:00
|
|
|
contents = file_path.read_text()
|
2021-10-19 23:54:37 +00:00
|
|
|
(contents, count) = re.subn(search, replace, contents)
|
|
|
|
if count > 0:
|
2022-03-16 18:48:22 +00:00
|
|
|
print(f"replacing '{search}' with '{replace}' in {file_path}")
|
2022-03-16 19:04:57 +00:00
|
|
|
file_path.write_text(contents)
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
def replace_in_files(glob: str, replacements: List[Tuple[SearchPattern, Replacement]]):
|
2022-03-16 18:48:22 +00:00
|
|
|
for file in Path().glob(glob):
|
|
|
|
for (search, replace) in replacements:
|
|
|
|
replace_in_file(file, search, replace)
|
|
|
|
|
|
|
|
|
2021-10-19 23:54:37 +00:00
|
|
|
def replace_path_in_all_cargo_toml(old_path: Path, new_path: Path):
|
|
|
|
"Replace path in all cargo.toml files, accounting for relative paths."
|
2022-03-16 18:48:22 +00:00
|
|
|
for toml in Path().glob("**/Cargo.toml"):
|
2021-10-19 23:54:37 +00:00
|
|
|
crate_dir = toml.parent
|
|
|
|
old_rel = os.path.relpath(old_path, crate_dir)
|
|
|
|
new_rel = os.path.relpath(new_path, crate_dir)
|
2022-03-16 18:48:22 +00:00
|
|
|
replace_in_file(toml, re.escape(f'path = "{old_rel}"'), f'path = "{new_rel}"')
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
def update_path_deps(toml: Path, from_path: Path, to_path: Path):
|
|
|
|
"Update path deps in toml file after moving it"
|
2022-03-16 19:04:57 +00:00
|
|
|
contents = toml.read_text()
|
2021-10-19 23:54:37 +00:00
|
|
|
for old_dep in re.findall('{ path = "([^"]+)"', contents):
|
|
|
|
new_dep = os.path.relpath((from_path / old_dep).resolve(), to_path)
|
2022-03-16 18:48:22 +00:00
|
|
|
contents = contents.replace(f'path = "{old_dep}"', f'path = "{new_dep}"')
|
2022-03-16 19:04:57 +00:00
|
|
|
toml.write_text(contents)
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
def move_crate(from_path: Path, to_path: Path):
|
|
|
|
"Move crate and update dependencies"
|
|
|
|
print(f"{from_path} -> {to_path}")
|
|
|
|
if to_path.exists():
|
|
|
|
shutil.rmtree(to_path)
|
2022-03-17 18:12:53 +00:00
|
|
|
shutil.copytree(str(from_path), str(to_path))
|
2021-10-19 23:54:37 +00:00
|
|
|
update_path_deps(to_path / "Cargo.toml", from_path, to_path)
|
2022-03-16 18:48:22 +00:00
|
|
|
replace_in_files("**/*/Cargo.toml", [(str(from_path), str(to_path))])
|
|
|
|
replace_in_file(Path("Cargo.toml"), str(from_path), str(to_path))
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
def update_workspace_members():
|
|
|
|
members: list[str] = []
|
|
|
|
members.append("members = [")
|
2022-03-16 18:48:22 +00:00
|
|
|
for toml in sorted(Path().glob("*/Cargo.toml")):
|
2021-10-19 23:54:37 +00:00
|
|
|
members.append(f' "{toml.parent}",')
|
2022-03-16 18:48:22 +00:00
|
|
|
members.append(' "third_party/vmm_vhost",')
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
members.append("]")
|
2022-03-16 18:48:22 +00:00
|
|
|
replace_in_file(Path("Cargo.toml"), re.compile(r"members = \[[^\]]+\]"), "\n".join(members))
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
exclude: list[str] = []
|
|
|
|
exclude.append("exclude = [")
|
2022-03-16 18:48:22 +00:00
|
|
|
for toml in sorted(Path().glob("common/*/Cargo.toml")):
|
2021-10-19 23:54:37 +00:00
|
|
|
exclude.append(f' "{toml.parent}",')
|
|
|
|
exclude.append("]")
|
2022-03-16 18:48:22 +00:00
|
|
|
replace_in_file(Path("Cargo.toml"), re.compile(r"exclude = \[[^\]]+\]"), "\n".join(exclude))
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
@contextmanager
|
|
|
|
def chdir(path: Union[Path, str]):
|
|
|
|
origin = Path().absolute()
|
|
|
|
try:
|
|
|
|
os.chdir(path)
|
|
|
|
yield
|
|
|
|
finally:
|
|
|
|
os.chdir(origin)
|
|
|
|
|
|
|
|
|
|
|
|
def copy_crate_src_to_module(source: str, destination: str):
|
|
|
|
shutil.rmtree(destination, ignore_errors=True)
|
|
|
|
shutil.copytree(source, destination)
|
|
|
|
with chdir(destination):
|
|
|
|
Path("lib.rs").rename("mod.rs")
|
|
|
|
|
|
|
|
|
2022-03-21 18:31:38 +00:00
|
|
|
IMPORT = """pub mod unix;
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
pub mod windows;
|
|
|
|
"""
|
|
|
|
|
|
|
|
BUILD_RS = """\
|
|
|
|
// Copyright 2022 The Chromium OS Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
cc::Build::new()
|
|
|
|
.file("src/windows/stdio_fileno.c")
|
|
|
|
.compile("stdio_fileno");
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
2021-10-19 23:54:37 +00:00
|
|
|
def main():
|
2022-03-16 18:48:22 +00:00
|
|
|
os.chdir(Path(__file__).parent.parent.parent)
|
2021-10-19 23:54:37 +00:00
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
subprocess.check_call(["git", "checkout", "-f", "--", "base"])
|
|
|
|
|
|
|
|
# Move crates to base
|
2022-03-21 18:31:38 +00:00
|
|
|
move_crate(Path("common/win_util"), Path("win_util"))
|
|
|
|
copy_crate_src_to_module("common/win_sys_util/src", "base/src/windows")
|
|
|
|
Path("base/build.rs").write_text(BUILD_RS)
|
2022-03-16 19:04:57 +00:00
|
|
|
|
2022-03-21 18:31:38 +00:00
|
|
|
# Load the added module
|
|
|
|
replace_in_file(Path("base/src/lib.rs"), "pub mod unix;", IMPORT)
|
2022-03-16 19:04:57 +00:00
|
|
|
|
|
|
|
# Flatten all imports for easier replacements
|
|
|
|
subprocess.check_call(
|
|
|
|
["rustfmt", "+nightly", "--config=imports_granularity=item", "base/src/lib.rs"]
|
|
|
|
)
|
|
|
|
|
2022-03-21 18:31:38 +00:00
|
|
|
# Update references to the above crates in base:
|
|
|
|
replace_in_files(
|
|
|
|
"base/src/**/*.rs",
|
|
|
|
[
|
|
|
|
("sys_util_core::", "crate::common::"),
|
|
|
|
("win_sys_util::", "crate::platform::"),
|
|
|
|
("crate::unix::", "crate::platform::"),
|
|
|
|
("use poll_token_derive::", "use base_poll_token_derive::"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2022-03-16 19:04:57 +00:00
|
|
|
# Fixup macros since they like to have special treatement.
|
|
|
|
macros = [
|
|
|
|
"debug",
|
|
|
|
"error",
|
|
|
|
"handle_eintr_errno",
|
|
|
|
"info",
|
|
|
|
"ioctl_io_nr",
|
|
|
|
"ioctl_ior_nr",
|
|
|
|
"ioctl_iow_nr",
|
|
|
|
"ioctl_iowr_nr",
|
|
|
|
"syscall",
|
|
|
|
"warn",
|
|
|
|
"volatile_at_impl",
|
|
|
|
"volatile_impl",
|
|
|
|
"generate_scoped_event",
|
2022-03-21 18:31:38 +00:00
|
|
|
"syslog_lock",
|
|
|
|
"CHRONO_TIMESTAMP_FIXED_FMT",
|
2022-03-16 19:04:57 +00:00
|
|
|
]
|
|
|
|
for macro in macros:
|
|
|
|
# Update use statments. #[macro_export] exports them on the crate scoped
|
|
|
|
replace_in_files(
|
2022-03-21 18:31:38 +00:00
|
|
|
"base/src/windows/**/*.rs",
|
2022-03-16 19:04:57 +00:00
|
|
|
[
|
2022-03-21 18:31:38 +00:00
|
|
|
(f"crate::common::{macro}", f"crate::{macro}"),
|
|
|
|
(f"super::super::{macro}", f"crate::{macro}"),
|
2022-03-16 19:04:57 +00:00
|
|
|
(f"super::{macro}", f"crate::{macro}"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
|
2022-03-21 18:31:38 +00:00
|
|
|
# Replace $crate:: with $crate::windows (unless it's a macro invocation..)
|
|
|
|
def replace_references_in_macros(match: re.Match[str]):
|
|
|
|
name = match.group(0)
|
|
|
|
if not name.endswith("!"):
|
|
|
|
return name.replace("$crate", f"$crate::platform")
|
|
|
|
return name
|
2022-03-16 19:04:57 +00:00
|
|
|
|
|
|
|
replace_in_files(
|
2022-03-21 18:31:38 +00:00
|
|
|
f"base/src/windows/**/*.rs",
|
2022-03-22 20:04:31 +00:00
|
|
|
[
|
|
|
|
(
|
|
|
|
re.compile(r"([\w\*\_\$]+\:\:)+([\w\*\_\!]+)"),
|
|
|
|
replace_references_in_macros,
|
|
|
|
)
|
|
|
|
],
|
2022-03-16 19:04:57 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
# Unflatten imports again
|
|
|
|
subprocess.check_call(
|
|
|
|
["rustfmt", "+nightly", "--config=imports_granularity=crate", "base/src/lib.rs"]
|
|
|
|
)
|
2021-10-19 23:54:37 +00:00
|
|
|
|
2022-03-21 18:31:38 +00:00
|
|
|
subprocess.check_call(["git", "rm", "-r", "common/win_sys_util", "common/win_util"])
|
|
|
|
|
2021-10-19 23:54:37 +00:00
|
|
|
|
|
|
|
main()
|