xref: /aosp_15_r20/external/crosvm/tools/contrib/cargo_refactor.py (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker# Copyright 2021 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker# found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker# Refactoring tools for moving around crates and updating dependencies
6*bb4ee6a4SAndroid Build Coastguard Worker# in toml files.
7*bb4ee6a4SAndroid Build Coastguard Worker#
8*bb4ee6a4SAndroid Build Coastguard Worker# Contains the last run refactoring for reference. Don't run this script, it'll
9*bb4ee6a4SAndroid Build Coastguard Worker# fail, but use it as a foundation for other refactorings.
10*bb4ee6a4SAndroid Build Coastguard Worker
11*bb4ee6a4SAndroid Build Coastguard Workerfrom contextlib import contextmanager
12*bb4ee6a4SAndroid Build Coastguard Workerfrom pathlib import Path
13*bb4ee6a4SAndroid Build Coastguard Workerimport os
14*bb4ee6a4SAndroid Build Coastguard Workerimport re
15*bb4ee6a4SAndroid Build Coastguard Workerimport shutil
16*bb4ee6a4SAndroid Build Coastguard Workerimport subprocess
17*bb4ee6a4SAndroid Build Coastguard Workerfrom typing import Callable, List, Tuple, Union
18*bb4ee6a4SAndroid Build Coastguard Worker
19*bb4ee6a4SAndroid Build Coastguard Worker
20*bb4ee6a4SAndroid Build Coastguard WorkerSearchPattern = Union[str, re.Pattern[str]]
21*bb4ee6a4SAndroid Build Coastguard WorkerReplacement = Union[str, Callable[[re.Match[str]], str]]
22*bb4ee6a4SAndroid Build Coastguard Worker
23*bb4ee6a4SAndroid Build Coastguard Worker
24*bb4ee6a4SAndroid Build Coastguard Workerdef append_to_file(file_path: Path, appendix: str):
25*bb4ee6a4SAndroid Build Coastguard Worker    contents = file_path.read_text()
26*bb4ee6a4SAndroid Build Coastguard Worker    file_path.write_text(contents.rstrip() + "\n" + appendix + "\n")
27*bb4ee6a4SAndroid Build Coastguard Worker
28*bb4ee6a4SAndroid Build Coastguard Worker
29*bb4ee6a4SAndroid Build Coastguard Workerdef replace_in_file(file_path: Path, search: SearchPattern, replace: Replacement):
30*bb4ee6a4SAndroid Build Coastguard Worker    if not file_path.exists():
31*bb4ee6a4SAndroid Build Coastguard Worker        print(f"WARNING: Does not exist {file_path}")
32*bb4ee6a4SAndroid Build Coastguard Worker        return
33*bb4ee6a4SAndroid Build Coastguard Worker    if isinstance(search, str):
34*bb4ee6a4SAndroid Build Coastguard Worker        search = re.escape(search)
35*bb4ee6a4SAndroid Build Coastguard Worker    contents = file_path.read_text()
36*bb4ee6a4SAndroid Build Coastguard Worker    (contents, count) = re.subn(search, replace, contents)
37*bb4ee6a4SAndroid Build Coastguard Worker    if count > 0:
38*bb4ee6a4SAndroid Build Coastguard Worker        print(f"replacing '{search}' with '{replace}' in {file_path}")
39*bb4ee6a4SAndroid Build Coastguard Worker        file_path.write_text(contents)
40*bb4ee6a4SAndroid Build Coastguard Worker
41*bb4ee6a4SAndroid Build Coastguard Worker
42*bb4ee6a4SAndroid Build Coastguard Workerdef replace_in_files(glob: str, replacements: List[Tuple[SearchPattern, Replacement]]):
43*bb4ee6a4SAndroid Build Coastguard Worker    for file in Path().glob(glob):
44*bb4ee6a4SAndroid Build Coastguard Worker        for search, replace in replacements:
45*bb4ee6a4SAndroid Build Coastguard Worker            replace_in_file(file, search, replace)
46*bb4ee6a4SAndroid Build Coastguard Worker
47*bb4ee6a4SAndroid Build Coastguard Worker
48*bb4ee6a4SAndroid Build Coastguard Workerdef replace_path_in_all_cargo_toml(old_path: Path, new_path: Path):
49*bb4ee6a4SAndroid Build Coastguard Worker    "Replace path in all cargo.toml files, accounting for relative paths."
50*bb4ee6a4SAndroid Build Coastguard Worker    for toml in Path().glob("**/Cargo.toml"):
51*bb4ee6a4SAndroid Build Coastguard Worker        crate_dir = toml.parent
52*bb4ee6a4SAndroid Build Coastguard Worker        old_rel = os.path.relpath(old_path, crate_dir)
53*bb4ee6a4SAndroid Build Coastguard Worker        new_rel = os.path.relpath(new_path, crate_dir)
54*bb4ee6a4SAndroid Build Coastguard Worker        replace_in_file(toml, re.escape(f'path = "{old_rel}"'), f'path = "{new_rel}"')
55*bb4ee6a4SAndroid Build Coastguard Worker
56*bb4ee6a4SAndroid Build Coastguard Worker
57*bb4ee6a4SAndroid Build Coastguard Workerdef update_path_deps(toml: Path, from_path: Path, to_path: Path):
58*bb4ee6a4SAndroid Build Coastguard Worker    "Update path deps in toml file after moving it"
59*bb4ee6a4SAndroid Build Coastguard Worker    contents = toml.read_text()
60*bb4ee6a4SAndroid Build Coastguard Worker    for old_dep in re.findall('{ path = "([^"]+)"', contents):
61*bb4ee6a4SAndroid Build Coastguard Worker        new_dep = os.path.relpath((from_path / old_dep).resolve(), to_path)
62*bb4ee6a4SAndroid Build Coastguard Worker        contents = contents.replace(f'path = "{old_dep}"', f'path = "{new_dep}"')
63*bb4ee6a4SAndroid Build Coastguard Worker    toml.write_text(contents)
64*bb4ee6a4SAndroid Build Coastguard Worker
65*bb4ee6a4SAndroid Build Coastguard Worker
66*bb4ee6a4SAndroid Build Coastguard Workerdef move_crate(from_path: Path, to_path: Path):
67*bb4ee6a4SAndroid Build Coastguard Worker    "Move crate and update dependencies"
68*bb4ee6a4SAndroid Build Coastguard Worker    print(f"{from_path} -> {to_path}")
69*bb4ee6a4SAndroid Build Coastguard Worker    if to_path.exists():
70*bb4ee6a4SAndroid Build Coastguard Worker        shutil.rmtree(to_path)
71*bb4ee6a4SAndroid Build Coastguard Worker    shutil.copytree(str(from_path), str(to_path))
72*bb4ee6a4SAndroid Build Coastguard Worker    update_path_deps(to_path / "Cargo.toml", from_path, to_path)
73*bb4ee6a4SAndroid Build Coastguard Worker    replace_in_files("**/*/Cargo.toml", [(str(from_path), str(to_path))])
74*bb4ee6a4SAndroid Build Coastguard Worker    replace_in_file(Path("Cargo.toml"), str(from_path), str(to_path))
75*bb4ee6a4SAndroid Build Coastguard Worker
76*bb4ee6a4SAndroid Build Coastguard Worker
77*bb4ee6a4SAndroid Build Coastguard Workerdef update_workspace_members():
78*bb4ee6a4SAndroid Build Coastguard Worker    members: list[str] = []
79*bb4ee6a4SAndroid Build Coastguard Worker    members.append("members = [")
80*bb4ee6a4SAndroid Build Coastguard Worker    for toml in sorted(Path().glob("*/Cargo.toml")):
81*bb4ee6a4SAndroid Build Coastguard Worker        members.append(f'    "{toml.parent}",')
82*bb4ee6a4SAndroid Build Coastguard Worker    for toml in sorted(Path().glob("common/*/Cargo.toml")):
83*bb4ee6a4SAndroid Build Coastguard Worker        members.append(f'    "{toml.parent}",')
84*bb4ee6a4SAndroid Build Coastguard Worker    members.append('    "third_party/vmm_vhost",')
85*bb4ee6a4SAndroid Build Coastguard Worker
86*bb4ee6a4SAndroid Build Coastguard Worker    members.append("]")
87*bb4ee6a4SAndroid Build Coastguard Worker    replace_in_file(Path("Cargo.toml"), re.compile(r"members = \[[^\]]+\]"), "\n".join(members))
88*bb4ee6a4SAndroid Build Coastguard Worker
89*bb4ee6a4SAndroid Build Coastguard Worker
90*bb4ee6a4SAndroid Build Coastguard Worker@contextmanager
91*bb4ee6a4SAndroid Build Coastguard Workerdef chdir(path: Union[Path, str]):
92*bb4ee6a4SAndroid Build Coastguard Worker    origin = Path().absolute()
93*bb4ee6a4SAndroid Build Coastguard Worker    try:
94*bb4ee6a4SAndroid Build Coastguard Worker        os.chdir(path)
95*bb4ee6a4SAndroid Build Coastguard Worker        yield
96*bb4ee6a4SAndroid Build Coastguard Worker    finally:
97*bb4ee6a4SAndroid Build Coastguard Worker        os.chdir(origin)
98*bb4ee6a4SAndroid Build Coastguard Worker
99*bb4ee6a4SAndroid Build Coastguard Worker
100*bb4ee6a4SAndroid Build Coastguard Workerdef copy_crate_src_to_module(source: str, destination: str):
101*bb4ee6a4SAndroid Build Coastguard Worker    shutil.rmtree(destination, ignore_errors=True)
102*bb4ee6a4SAndroid Build Coastguard Worker    shutil.copytree(source, destination)
103*bb4ee6a4SAndroid Build Coastguard Worker    with chdir(destination):
104*bb4ee6a4SAndroid Build Coastguard Worker        Path("lib.rs").rename("mod.rs")
105*bb4ee6a4SAndroid Build Coastguard Worker
106*bb4ee6a4SAndroid Build Coastguard Worker
107*bb4ee6a4SAndroid Build Coastguard WorkerIMPORT = """pub mod linux;
108*bb4ee6a4SAndroid Build Coastguard Worker
109*bb4ee6a4SAndroid Build Coastguard Worker#[cfg(windows)]
110*bb4ee6a4SAndroid Build Coastguard Workerpub mod windows;
111*bb4ee6a4SAndroid Build Coastguard Worker"""
112*bb4ee6a4SAndroid Build Coastguard Worker
113*bb4ee6a4SAndroid Build Coastguard WorkerBUILD_RS = """\
114*bb4ee6a4SAndroid Build Coastguard Worker// Copyright 2022 The ChromiumOS Authors
115*bb4ee6a4SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
116*bb4ee6a4SAndroid Build Coastguard Worker// found in the LICENSE file.
117*bb4ee6a4SAndroid Build Coastguard Worker
118*bb4ee6a4SAndroid Build Coastguard Workerfn main() {
119*bb4ee6a4SAndroid Build Coastguard Worker    cc::Build::new()
120*bb4ee6a4SAndroid Build Coastguard Worker        .file("src/windows/stdio_fileno.c")
121*bb4ee6a4SAndroid Build Coastguard Worker        .compile("stdio_fileno");
122*bb4ee6a4SAndroid Build Coastguard Worker}
123*bb4ee6a4SAndroid Build Coastguard Worker"""
124*bb4ee6a4SAndroid Build Coastguard Worker
125*bb4ee6a4SAndroid Build Coastguard Worker
126*bb4ee6a4SAndroid Build Coastguard Workerdef main():
127*bb4ee6a4SAndroid Build Coastguard Worker    os.chdir(Path(__file__).parent.parent.parent)
128*bb4ee6a4SAndroid Build Coastguard Worker    update_workspace_members()
129*bb4ee6a4SAndroid Build Coastguard Worker
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Workermain()
132