Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion components/polylith/diff/collect.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import subprocess
from pathlib import Path
from typing import List, Union
from typing import List, Set, Union

from polylith import repo, workspace

Expand Down Expand Up @@ -59,3 +59,25 @@ def get_files(tag: str) -> List[Path]:
)

return [Path(p) for p in res.stdout.decode("utf-8").split()]


def _affected(projects_data: List[dict], brick_type: str, bricks: List[str]) -> set:
res = {
p["path"].name: set(p.get(brick_type, [])).intersection(bricks)
for p in projects_data
}

return {k for k, v in res.items() if v}


def get_projects_affected_by_changes(
projects_data: List[dict],
projects: List[str],
bases: List[str],
components: List[str],
) -> Set[str]:
a = _affected(projects_data, "components", components)
b = _affected(projects_data, "bases", bases)
c = set(projects)

return {*a, *b, *c}
64 changes: 32 additions & 32 deletions components/polylith/diff/report.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Set

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


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

console = Console(theme=theme.poly_theme)

for project in sorted(projects):
console.print(f"[data]:gear: Changes found in [/][proj]{project}[/]")
if short:
console.print(",".join(changes))
return

for brick in changes:
console.print(f"[data]:gear: Changes found in [/][{markup}]{brick}[/]")


def print_detected_changes_in_bricks(
bases: List[str], components: List[str], short: bool
) -> None:
sorted_bases = sorted(bases)
sorted_components = sorted(components)

if short:
print_detected_changes(sorted_components + sorted_bases, "data", short)
else:
print_detected_changes(sorted_components, "comp", short)
print_detected_changes(sorted_bases, "base", short)


def print_detected_changes_in_projects(projects: List[str], short: bool) -> None:
print_detected_changes(projects, "proj", short)


def print_projects_affected_by_changes(projects: Set[str], short: bool) -> None:
sorted_projects = sorted(list(projects))

print_detected_changes(sorted_projects, "proj", short)


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

if bases:
console.print(f"[base]Changed bases[/]: [data]{len(bases)}[/]")


def _changed_projects(
projects_data: List[dict], brick_type: str, bricks: List[str]
) -> set:
res = {
p["path"].name: set(p.get(brick_type, [])).intersection(bricks)
for p in projects_data
}

return {k for k, v in res.items() if v}


def print_short_diff(
projects_data: List[dict],
projects: List[str],
bases: List[str],
components: List[str],
) -> None:
a = _changed_projects(projects_data, "components", components)
b = _changed_projects(projects_data, "bases", bases)
c = set(projects)

res = {*a, *b, *c}

console = Console(theme=theme.poly_theme)
console.print(",".join(res))
68 changes: 51 additions & 17 deletions components/polylith/poetry/commands/diff.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pathlib import Path
from typing import List, Set

from cleo.helpers import option
from poetry.console.commands.command import Command
Expand All @@ -13,33 +14,66 @@ class DiffCommand(Command):
option(
long_name="short",
short_name="s",
description="Print only changed projects",
description="Print short view",
flag=True,
),
option(
long_name="bricks",
description="Print changed bricks",
flag=True,
),
]

def has_partial_options(self) -> bool:
return any(self.option(k) for k in {"bricks"})

def print_partial_views(
self,
affected_projects: Set[str],
bases: List[str],
components: List[str],
) -> None:
short = self.option("short")

if short and not self.has_partial_options():
diff.report.print_projects_affected_by_changes(affected_projects, short)

return

if self.option("bricks"):
diff.report.print_detected_changes_in_bricks(bases, components, short)

def print_views(self, root: Path, tag: str) -> None:
ns = workspace.parser.get_namespace_from_config(root)
files = diff.collect.get_files(tag)
bases = diff.collect.get_changed_bases(files, ns)
components = diff.collect.get_changed_components(files, ns)
projects = diff.collect.get_changed_projects(files)
all_projects_data = info.get_bricks_in_projects(root, components, bases, ns)
projects_data = [p for p in all_projects_data if info.is_project(p)]

affected_projects = diff.collect.get_projects_affected_by_changes(
projects_data, projects, bases, components
)

short = self.option("short")

if not short and not self.has_partial_options():
diff.report.print_diff_summary(tag, bases, components)
diff.report.print_detected_changes_in_projects(projects, short)
diff.report.print_diff_details(projects_data, bases, components)

return

self.print_partial_views(affected_projects, bases, components)

def handle(self) -> int:
root = repo.get_workspace_root(Path.cwd())
tag = diff.collect.get_latest_tag(root)

if not tag:
self.line("No tags found in repository.")
else:
ns = workspace.parser.get_namespace_from_config(root)
files = diff.collect.get_files(tag)
bases = diff.collect.get_changed_bases(files, ns)
components = diff.collect.get_changed_components(files, ns)
projects = diff.collect.get_changed_projects(files)
all_projects_data = info.get_bricks_in_projects(root, components, bases, ns)
projects_data = [p for p in all_projects_data if info.is_project(p)]

short = self.option("short")

if short:
diff.report.print_short_diff(projects_data, projects, bases, components)
else:
diff.report.print_diff_summary(tag, bases, components)
diff.report.print_detected_changes_in_projects(projects)
diff.report.print_diff_details(projects_data, bases, components)
self.print_views(root, tag)

return 0
2 changes: 1 addition & 1 deletion projects/poetry_polylith_plugin/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "poetry-polylith-plugin"
version = "1.10.1"
version = "1.11.0"
description = "A Poetry plugin that adds tooling support for the Polylith Architecture"
authors = ["David Vujic"]
homepage = "https://davidvujic.github.io/python-polylith-docs/"
Expand Down