Skip to content

Commit 628810e

Browse files
committed
[chore] Move the templates into v1 and v2 directories
1 parent 6cfda26 commit 628810e

37 files changed

+140
-14
lines changed

dev.py

Lines changed: 140 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,20 @@
1818
from pathlib import Path
1919

2020
THIS_DIRECTORY = Path(__file__).parent.absolute()
21-
EXAMPLE_DIRECTORIES = [d for d in (THIS_DIRECTORY / "examples").iterdir() if d.is_dir()]
21+
VERSIONS = ["v1", "v2"]
22+
EXAMPLE_DIRECTORIES = [
23+
d
24+
for v in VERSIONS
25+
if (THIS_DIRECTORY / "examples" / v).is_dir()
26+
for d in (THIS_DIRECTORY / "examples" / v).iterdir()
27+
if d.is_dir()
28+
]
2229
TEMPLATE_DIRECTORIES = [
23-
THIS_DIRECTORY / "template",
24-
THIS_DIRECTORY / "template-reactless",
30+
d
31+
for v in VERSIONS
32+
if (THIS_DIRECTORY / "templates" / v).is_dir()
33+
for d in (THIS_DIRECTORY / "templates" / v).iterdir()
34+
if d.is_dir()
2535
]
2636

2737

@@ -35,6 +45,97 @@ def run_verbose(cmd_args, *args, **kwargs):
3545
subprocess.run(cmd_args, *args, **kwargs)
3646

3747

48+
def create_sanitized_copies_excluding_gitignored(
49+
source_dir_a: Path,
50+
source_dir_b: Path,
51+
repo_root: Path,
52+
destination_base_dir: Path,
53+
) -> typing.Tuple[Path, Path]:
54+
"""
55+
Create sanitized copies of two directories while excluding files ignored by Git.
56+
57+
This function is intended for robust, cross-platform directory comparisons (e.g.,
58+
git diff --no-index) where we want to ignore anything matched by the repository's
59+
ignore rules (.gitignore, global and excludesfile), but still compare the remaining
60+
content 1:1.
61+
62+
Rationale:
63+
- git diff --no-index does not honor .gitignore rules directly for arbitrary
64+
directory arguments.
65+
- Filtering via Git pathspecs is not supported with --no-index in a portable way.
66+
- By asking Git for the ignored files under source_dir_b (the path inside the
67+
repo) and excluding those relative paths from BOTH copies, we avoid false
68+
positives from OS metadata and any user-ignored files.
69+
70+
Parameters:
71+
- source_dir_a: First directory to compare (e.g., freshly rendered output).
72+
- source_dir_b: Second directory to compare (must be within repo_root).
73+
- repo_root: Root of the Git repository (used to query ignored files).
74+
- destination_base_dir: Directory where sanitized copies will be created.
75+
76+
Returns:
77+
- Tuple[Path, Path]: (sanitized_copy_of_a, sanitized_copy_of_b)
78+
"""
79+
# Compute the list of ignored files under source_dir_b using Git
80+
try:
81+
rel_path_in_repo = source_dir_b.relative_to(repo_root)
82+
ls_cmd = [
83+
"git",
84+
"-C",
85+
str(repo_root),
86+
"ls-files",
87+
"-i", # list ignored files
88+
"--exclude-standard", # honor .gitignore, global ignores, etc.
89+
"--others", # show untracked files as well
90+
"-z", # null-terminate paths to be robust to special characters
91+
"--",
92+
str(rel_path_in_repo),
93+
]
94+
result = subprocess.run(ls_cmd, check=True, stdout=subprocess.PIPE, text=False)
95+
ignored_absolute_paths = [
96+
repo_root / p.decode() for p in result.stdout.split(b"\0") if p
97+
]
98+
except (ValueError, subprocess.CalledProcessError):
99+
# ValueError if source_dir_b is not under repo_root; fallback to no ignores
100+
ignored_absolute_paths = []
101+
102+
ignored_relative_to_b = set(
103+
str(p.relative_to(source_dir_b).as_posix())
104+
for p in ignored_absolute_paths
105+
if hasattr(p, "is_relative_to")
106+
and p.is_relative_to(source_dir_b)
107+
or (str(p).startswith(str(source_dir_b) + os.sep))
108+
)
109+
110+
def build_ignore_filter(source_root: Path):
111+
def _ignore(dirpath: str, names: typing.List[str]) -> typing.List[str]:
112+
rel_dir = Path(dirpath).relative_to(source_root)
113+
to_ignore: typing.List[str] = []
114+
for name in names:
115+
candidate = (rel_dir / name).as_posix()
116+
if candidate in ignored_relative_to_b:
117+
to_ignore.append(name)
118+
return to_ignore
119+
120+
return _ignore
121+
122+
sanitized_a = destination_base_dir / "sanitized-output"
123+
sanitized_b = destination_base_dir / "sanitized-repo"
124+
125+
shutil.copytree(
126+
source_dir_a,
127+
sanitized_a,
128+
ignore=build_ignore_filter(source_dir_a),
129+
)
130+
shutil.copytree(
131+
source_dir_b,
132+
sanitized_b,
133+
ignore=build_ignore_filter(source_dir_b),
134+
)
135+
136+
return sanitized_a, sanitized_b
137+
138+
38139
# Commands
39140
def cmd_all_npm_install(args):
40141
"""Install all node dependencies for all examples"""
@@ -134,10 +235,17 @@ def cmd_all_python_build_package(args):
134235
final_dist_directory = THIS_DIRECTORY / "dist"
135236
final_dist_directory.mkdir(exist_ok=True)
136237
for project_dir in EXAMPLE_DIRECTORIES + TEMPLATE_DIRECTORIES:
137-
run_verbose(
138-
[sys.executable, "setup.py", "bdist_wheel", "--universal", "sdist"],
139-
cwd=str(project_dir),
140-
)
238+
pyproject_file = project_dir / "pyproject.toml"
239+
if pyproject_file.exists():
240+
run_verbose(
241+
[sys.executable, "-m", "build", "--wheel", "--sdist"],
242+
cwd=str(project_dir),
243+
)
244+
else:
245+
run_verbose(
246+
[sys.executable, "setup.py", "bdist_wheel", "--universal", "sdist"],
247+
cwd=str(project_dir),
248+
)
141249

142250
wheel_file = next(project_dir.glob("dist/*.whl"))
143251
shutil.copy(wheel_file, final_dist_directory)
@@ -172,7 +280,13 @@ def cmd_example_check_deps(args):
172280
"""Checks that dependencies of examples match the template"""
173281
template_deps = json.loads(
174282
(
175-
THIS_DIRECTORY / "template" / "my_component" / "frontend" / "package.json"
283+
THIS_DIRECTORY
284+
/ "templates"
285+
/ "v1"
286+
/ "template"
287+
/ "my_component"
288+
/ "frontend"
289+
/ "package.json"
176290
).read_text()
177291
)
178292
examples_package_jsons = sorted(
@@ -220,19 +334,22 @@ def cmd_check_test_utils(args):
220334
class CookiecutterVariant(typing.NamedTuple):
221335
replay_file: Path
222336
repo_directory: Path
337+
cookiecutter_dir: Path
223338

224339

225340
COOKIECUTTER_VARIANTS = [
226341
CookiecutterVariant(
227342
replay_file=THIS_DIRECTORY / ".github" / "replay-files" / "template.json",
228-
repo_directory=THIS_DIRECTORY / "template",
343+
repo_directory=THIS_DIRECTORY / "templates" / "v1" / "template",
344+
cookiecutter_dir=THIS_DIRECTORY / "cookiecutter" / "v1",
229345
),
230346
CookiecutterVariant(
231347
replay_file=THIS_DIRECTORY
232348
/ ".github"
233349
/ "replay-files"
234350
/ "template-reactless.json",
235-
repo_directory=THIS_DIRECTORY / "template-reactless",
351+
repo_directory=THIS_DIRECTORY / "templates" / "v1" / "template-reactless",
352+
cookiecutter_dir=THIS_DIRECTORY / "cookiecutter" / "v1",
236353
),
237354
]
238355

@@ -256,7 +373,7 @@ def cmd_check_templates_using_cookiecutter(args):
256373
str(cookiecutter_variant.replay_file),
257374
"--output-dir",
258375
str(output_dir),
259-
str(THIS_DIRECTORY / "cookiecutter" / "v1"),
376+
str(cookiecutter_variant.cookiecutter_dir),
260377
]
261378
)
262379
try:
@@ -267,14 +384,23 @@ def cmd_check_templates_using_cookiecutter(args):
267384
Path(output_dir)
268385
/ replay_file_content["cookiecutter"]["package_name"]
269386
)
387+
# Create sanitized copies excluding all files ignored by git in the repo
388+
sanitized_output, sanitized_repo = (
389+
create_sanitized_copies_excluding_gitignored(
390+
output_template,
391+
cookiecutter_variant.repo_directory,
392+
THIS_DIRECTORY,
393+
Path(output_dir),
394+
)
395+
)
270396
run_verbose(
271397
[
272398
"git",
273399
"--no-pager",
274400
"diff",
275401
"--no-index",
276-
str(output_template),
277-
str(cookiecutter_variant.repo_directory),
402+
str(sanitized_output),
403+
str(sanitized_repo),
278404
]
279405
)
280406
except subprocess.CalledProcessError:
@@ -311,7 +437,7 @@ def cmd_update_templates(args):
311437
str(cookiecutter_variant.replay_file),
312438
"--output-dir",
313439
str(output_dir),
314-
str(THIS_DIRECTORY / "cookiecutter" / "v1"),
440+
str(cookiecutter_variant.cookiecutter_dir),
315441
]
316442
)
317443
print(
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

template-reactless/my_component/frontend/.prettierrc renamed to templates/v1/template-reactless/my_component/frontend/.prettierrc

File renamed without changes.

0 commit comments

Comments
 (0)