Skip to content

Commit 101c330

Browse files
ben-ednaspoorcc
authored andcommitted
Simplify diff
1 parent 6b8a726 commit 101c330

3 files changed

Lines changed: 59 additions & 66 deletions

File tree

dfetch/commands/diff.py

Lines changed: 36 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,9 @@
9898
import pathlib
9999

100100
import dfetch.commands.command
101-
import dfetch.project
102101
from dfetch.log import get_logger
103-
from dfetch.manifest.project import ProjectEntry
104-
from dfetch.project.git import GitSubProject
105-
from dfetch.project.subproject import SubProject
106102
from dfetch.project.superproject import SuperProject
107-
from dfetch.project.svn import SvnSubProject
108103
from dfetch.util.util import catch_runtime_exceptions, in_directory
109-
from dfetch.vcs.git import GitLocalRepo
110-
from dfetch.vcs.svn import SvnRepo
111104

112105
logger = get_logger(__name__)
113106

@@ -143,7 +136,7 @@ def create_menu(subparsers: dfetch.commands.command.SubparserActionType) -> None
143136
def __call__(self, args: argparse.Namespace) -> None:
144137
"""Perform the diff."""
145138
superproject = SuperProject()
146-
revs = [r for r in args.revs.strip(":").split(":", maxsplit=1) if r]
139+
old_rev, new_rev = self._parse_revs(args.revs)
147140

148141
with in_directory(superproject.root_directory):
149142
exceptions: list[str] = []
@@ -153,49 +146,44 @@ def __call__(self, args: argparse.Namespace) -> None:
153146
f"No (such) project found! {', '.join(args.projects)}"
154147
)
155148
for project in projects:
156-
patch_name = f"{project.name}.patch"
157149
with catch_runtime_exceptions(exceptions) as exceptions:
158-
patch = _get_sub_project(superproject, project).diff(revs)
159-
160-
_dump_patch(
161-
superproject.root_directory, revs, project, patch_name, patch
162-
)
150+
if not os.path.exists(project.destination):
151+
raise RuntimeError(
152+
"You cannot generate a diff of a project that was never fetched"
153+
)
154+
subproject = superproject.get_sub_project(project)
155+
156+
if subproject is None:
157+
raise RuntimeError(
158+
"Can only create patch if your project is an SVN or Git repo",
159+
)
160+
old_rev = old_rev or subproject.metadata_revision()
161+
patch = subproject.diff(old_rev, new_rev)
162+
163+
msg = self._rev_msg(old_rev, new_rev)
164+
if patch:
165+
patch_path = pathlib.Path(f"{project.name}.patch")
166+
logger.print_info_line(
167+
project.name,
168+
f"Generating patch {patch_path} {msg} in {superproject.root_directory}",
169+
)
170+
patch_path.write_text(patch, encoding="UTF-8")
171+
else:
172+
logger.print_info_line(project.name, f"No diffs found {msg}")
163173

164174
if exceptions:
165175
raise RuntimeError("\n".join(exceptions))
166176

177+
@staticmethod
178+
def _parse_revs(revs_arg: str) -> tuple[str, str]:
179+
revs = [r for r in revs_arg.strip(":").split(":", maxsplit=1) if r]
167180

168-
def _get_sub_project(superproject: SuperProject, project: ProjectEntry) -> SubProject:
169-
"""Get the subproject in the same vcs type as the superproject."""
170-
if not os.path.exists(project.destination):
171-
raise RuntimeError(
172-
"You cannot generate a diff of a project that was never fetched"
173-
)
174-
if GitLocalRepo(superproject.root_directory).is_git():
175-
return GitSubProject(project)
176-
if SvnRepo(superproject.root_directory).is_svn():
177-
return SvnSubProject(project)
178-
179-
raise RuntimeError(
180-
"Can only create patch if your project is an SVN or Git repo",
181-
)
182-
183-
184-
def _dump_patch(
185-
path: str, revs: list[str], project: ProjectEntry, patch_name: str, patch: str
186-
) -> None:
187-
"""Dump the patch to a file."""
188-
if patch:
189-
rev_range = f"from {revs[0]} to {revs[1]}" if revs[1] else f"since {revs[0]}"
190-
logger.print_info_line(
191-
project.name,
192-
f"Generating patch {patch_name} {rev_range} in {os.path.dirname(path)}",
193-
)
194-
pathlib.Path(patch_name).write_text(patch, encoding="UTF-8")
195-
else:
196-
if revs[1]:
197-
msg = f"No diffs found from {revs[0]} to {revs[1]}"
198-
else:
199-
msg = f"No diffs found since {revs[0]}"
200-
201-
logger.print_info_line(project.name, msg)
181+
if len(revs) == 0:
182+
return "", ""
183+
if len(revs) == 1:
184+
return revs[0], ""
185+
return revs[0], revs[1]
186+
187+
@staticmethod
188+
def _rev_msg(old_rev: str, new_rev: str) -> str:
189+
return f"from {old_rev} to {new_rev}" if new_rev else f"since {old_rev}"

dfetch/project/subproject.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -393,23 +393,13 @@ def is_license_file(filename: str) -> bool:
393393
for pattern in SubProject.LICENSE_GLOBS
394394
)
395395

396-
def diff(self, revs: list[str]) -> str:
396+
def diff(self, old_rev: str, new_rev: str) -> str:
397397
"""Generate a relative diff for a subproject."""
398-
if len(revs) > 2:
399-
raise RuntimeError(f"Too many revisions given! {revs}")
400-
401-
if not revs:
402-
revs.append(self.metadata_revision())
403-
if not revs[-1]:
404-
raise RuntimeError(
405-
"When not providing any revisions, dfetch starts from"
406-
f" the last revision to {Metadata.FILENAME} in {self.local_path}."
407-
" Please either revision this, or specify a revision to start from with --revs"
408-
)
409-
410-
if len(revs) == 1:
411-
revs.append("")
398+
if not old_rev:
399+
raise RuntimeError(
400+
"When not providing any revisions, dfetch starts from"
401+
f" the last revision to {Metadata.FILENAME} in {self.local_path}."
402+
" Please either revision this, or specify a revision to start from with --revs"
403+
)
412404

413-
return self._diff_impl(
414-
old_revision=revs[0], new_revision=revs[1], ignore=(Metadata.FILENAME,)
415-
)
405+
return self._diff_impl(old_rev, new_rev, ignore=(Metadata.FILENAME,))

dfetch/project/superproject.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212

1313
from dfetch.log import get_logger
1414
from dfetch.manifest.manifest import Manifest, find_manifest
15+
from dfetch.manifest.project import ProjectEntry
1516
from dfetch.manifest.validate import validate
17+
from dfetch.project.git import GitSubProject
18+
from dfetch.project.subproject import SubProject
19+
from dfetch.project.svn import SvnSubProject
20+
from dfetch.vcs.git import GitLocalRepo
21+
from dfetch.vcs.svn import SvnRepo
1622

1723
logger = get_logger(__name__)
1824

@@ -44,3 +50,12 @@ def root_directory(self) -> str:
4450
def manifest(self) -> Manifest:
4551
"""The manifest of the super project."""
4652
return self._manifest
53+
54+
def get_sub_project(self, project: ProjectEntry) -> SubProject | None:
55+
"""Get the subproject in the same vcs type as the superproject."""
56+
if GitLocalRepo(self.root_directory).is_git():
57+
return GitSubProject(project)
58+
if SvnRepo(self.root_directory).is_svn():
59+
return SvnSubProject(project)
60+
61+
return None

0 commit comments

Comments
 (0)