Skip to content

Commit ac058c9

Browse files
authored
feat(poly diff): print changes for projects and/or bricks (#128)
* feat(poly diff): print affected projects, changed bricks as parseable output that is useful for running tests * bump version to 1.11.0
1 parent 1bdabe2 commit ac058c9

4 files changed

Lines changed: 107 additions & 51 deletions

File tree

components/polylith/diff/collect.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import subprocess
22
from pathlib import Path
3-
from typing import List, Union
3+
from typing import List, Set, Union
44

55
from polylith import repo, workspace
66

@@ -59,3 +59,25 @@ def get_files(tag: str) -> List[Path]:
5959
)
6060

6161
return [Path(p) for p in res.stdout.decode("utf-8").split()]
62+
63+
64+
def _affected(projects_data: List[dict], brick_type: str, bricks: List[str]) -> set:
65+
res = {
66+
p["path"].name: set(p.get(brick_type, [])).intersection(bricks)
67+
for p in projects_data
68+
}
69+
70+
return {k for k, v in res.items() if v}
71+
72+
73+
def get_projects_affected_by_changes(
74+
projects_data: List[dict],
75+
projects: List[str],
76+
bases: List[str],
77+
components: List[str],
78+
) -> Set[str]:
79+
a = _affected(projects_data, "components", components)
80+
b = _affected(projects_data, "bases", bases)
81+
c = set(projects)
82+
83+
return {*a, *b, *c}

components/polylith/diff/report.py

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List
1+
from typing import List, Set
22

33
from polylith import info
44
from polylith.reporting import theme
@@ -22,14 +22,41 @@ def print_diff_details(
2222
console.print(table, overflow="ellipsis")
2323

2424

25-
def print_detected_changes_in_projects(projects: List[str]) -> None:
26-
if not projects:
25+
def print_detected_changes(changes: List[str], markup: str, short: bool) -> None:
26+
if not changes:
2727
return
2828

2929
console = Console(theme=theme.poly_theme)
3030

31-
for project in sorted(projects):
32-
console.print(f"[data]:gear: Changes found in [/][proj]{project}[/]")
31+
if short:
32+
console.print(",".join(changes))
33+
return
34+
35+
for brick in changes:
36+
console.print(f"[data]:gear: Changes found in [/][{markup}]{brick}[/]")
37+
38+
39+
def print_detected_changes_in_bricks(
40+
bases: List[str], components: List[str], short: bool
41+
) -> None:
42+
sorted_bases = sorted(bases)
43+
sorted_components = sorted(components)
44+
45+
if short:
46+
print_detected_changes(sorted_components + sorted_bases, "data", short)
47+
else:
48+
print_detected_changes(sorted_components, "comp", short)
49+
print_detected_changes(sorted_bases, "base", short)
50+
51+
52+
def print_detected_changes_in_projects(projects: List[str], short: bool) -> None:
53+
print_detected_changes(projects, "proj", short)
54+
55+
56+
def print_projects_affected_by_changes(projects: Set[str], short: bool) -> None:
57+
sorted_projects = sorted(list(projects))
58+
59+
print_detected_changes(sorted_projects, "proj", short)
3360

3461

3562
def print_diff_summary(tag: str, bases: List[str], components: List[str]) -> None:
@@ -46,30 +73,3 @@ def print_diff_summary(tag: str, bases: List[str], components: List[str]) -> Non
4673

4774
if bases:
4875
console.print(f"[base]Changed bases[/]: [data]{len(bases)}[/]")
49-
50-
51-
def _changed_projects(
52-
projects_data: List[dict], brick_type: str, bricks: List[str]
53-
) -> set:
54-
res = {
55-
p["path"].name: set(p.get(brick_type, [])).intersection(bricks)
56-
for p in projects_data
57-
}
58-
59-
return {k for k, v in res.items() if v}
60-
61-
62-
def print_short_diff(
63-
projects_data: List[dict],
64-
projects: List[str],
65-
bases: List[str],
66-
components: List[str],
67-
) -> None:
68-
a = _changed_projects(projects_data, "components", components)
69-
b = _changed_projects(projects_data, "bases", bases)
70-
c = set(projects)
71-
72-
res = {*a, *b, *c}
73-
74-
console = Console(theme=theme.poly_theme)
75-
console.print(",".join(res))
Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from pathlib import Path
2+
from typing import List, Set
23

34
from cleo.helpers import option
45
from poetry.console.commands.command import Command
@@ -13,33 +14,66 @@ class DiffCommand(Command):
1314
option(
1415
long_name="short",
1516
short_name="s",
16-
description="Print only changed projects",
17+
description="Print short view",
18+
flag=True,
19+
),
20+
option(
21+
long_name="bricks",
22+
description="Print changed bricks",
1723
flag=True,
1824
),
1925
]
2026

27+
def has_partial_options(self) -> bool:
28+
return any(self.option(k) for k in {"bricks"})
29+
30+
def print_partial_views(
31+
self,
32+
affected_projects: Set[str],
33+
bases: List[str],
34+
components: List[str],
35+
) -> None:
36+
short = self.option("short")
37+
38+
if short and not self.has_partial_options():
39+
diff.report.print_projects_affected_by_changes(affected_projects, short)
40+
41+
return
42+
43+
if self.option("bricks"):
44+
diff.report.print_detected_changes_in_bricks(bases, components, short)
45+
46+
def print_views(self, root: Path, tag: str) -> None:
47+
ns = workspace.parser.get_namespace_from_config(root)
48+
files = diff.collect.get_files(tag)
49+
bases = diff.collect.get_changed_bases(files, ns)
50+
components = diff.collect.get_changed_components(files, ns)
51+
projects = diff.collect.get_changed_projects(files)
52+
all_projects_data = info.get_bricks_in_projects(root, components, bases, ns)
53+
projects_data = [p for p in all_projects_data if info.is_project(p)]
54+
55+
affected_projects = diff.collect.get_projects_affected_by_changes(
56+
projects_data, projects, bases, components
57+
)
58+
59+
short = self.option("short")
60+
61+
if not short and not self.has_partial_options():
62+
diff.report.print_diff_summary(tag, bases, components)
63+
diff.report.print_detected_changes_in_projects(projects, short)
64+
diff.report.print_diff_details(projects_data, bases, components)
65+
66+
return
67+
68+
self.print_partial_views(affected_projects, bases, components)
69+
2170
def handle(self) -> int:
2271
root = repo.get_workspace_root(Path.cwd())
2372
tag = diff.collect.get_latest_tag(root)
2473

2574
if not tag:
2675
self.line("No tags found in repository.")
2776
else:
28-
ns = workspace.parser.get_namespace_from_config(root)
29-
files = diff.collect.get_files(tag)
30-
bases = diff.collect.get_changed_bases(files, ns)
31-
components = diff.collect.get_changed_components(files, ns)
32-
projects = diff.collect.get_changed_projects(files)
33-
all_projects_data = info.get_bricks_in_projects(root, components, bases, ns)
34-
projects_data = [p for p in all_projects_data if info.is_project(p)]
35-
36-
short = self.option("short")
37-
38-
if short:
39-
diff.report.print_short_diff(projects_data, projects, bases, components)
40-
else:
41-
diff.report.print_diff_summary(tag, bases, components)
42-
diff.report.print_detected_changes_in_projects(projects)
43-
diff.report.print_diff_details(projects_data, bases, components)
77+
self.print_views(root, tag)
4478

4579
return 0

projects/poetry_polylith_plugin/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "poetry-polylith-plugin"
3-
version = "1.10.1"
3+
version = "1.11.0"
44
description = "A Poetry plugin that adds tooling support for the Polylith Architecture"
55
authors = ["David Vujic"]
66
homepage = "https://davidvujic.github.io/python-polylith-docs/"

0 commit comments

Comments
 (0)