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
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ ENV PYTHONUSERBASE="/home/dev/.local"

COPY --chown=dev:dev . .

RUN pip install --no-cache-dir --root-user-action=ignore --upgrade pip==25.3 \
RUN pip install --no-cache-dir --root-user-action=ignore --upgrade pip==26.0.1 \
&& pip install --no-cache-dir --root-user-action=ignore -e .[development,docs,test,casts,build] \
&& pre-commit install --install-hooks

Expand Down
42 changes: 16 additions & 26 deletions dfetch/commands/format_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@
import pathlib
import re

import patch_ng

import dfetch.commands.command
import dfetch.manifest.project
import dfetch.project
Expand All @@ -40,14 +38,7 @@
from dfetch.project.subproject import SubProject
from dfetch.project.svnsubproject import SvnSubProject
from dfetch.util.util import catch_runtime_exceptions, in_directory
from dfetch.vcs.patch import (
PatchAuthor,
PatchInfo,
add_prefix_to_patch,
convert_patch_to,
dump_patch,
parse_patch,
)
from dfetch.vcs.patch import Patch, PatchAuthor, PatchInfo, PatchType

logger = get_logger(__name__)

Expand Down Expand Up @@ -112,7 +103,7 @@ def __call__(self, args: argparse.Namespace) -> None:
continue

version = subproject.on_disk_version()
for idx, patch in enumerate(subproject.patch, start=1):
for idx, patch_file in enumerate(subproject.patch, start=1):

patch_info = PatchInfo(
author=PatchAuthor(
Expand All @@ -125,20 +116,19 @@ def __call__(self, args: argparse.Namespace) -> None:
revision="" if not version else version.revision,
)

corrected_patch = convert_patch_to(
parse_patch(patch), _determine_target_patch_type(subproject)
patch = Patch.from_file(patch_file).convert_type(
_determine_target_patch_type(subproject)
)
prefixed_patch = add_prefix_to_patch(
corrected_patch,
path_prefix=re.split(r"\*", subproject.source, 1)[0].rstrip(
"/"
),
patch.add_prefix(
re.split(r"\*", subproject.source, 1)[0].rstrip("/")
)

output_patch_file = output_dir_path / pathlib.Path(patch).name
output_patch_file = (
output_dir_path / pathlib.Path(patch_file).name
)
output_patch_file.write_text(
subproject.create_formatted_patch_header(patch_info)
+ dump_patch(prefixed_patch)
patch.dump_header(patch_info) + patch.dump(),
encoding="utf-8",
)

logger.print_info_line(
Expand All @@ -150,13 +140,13 @@ def __call__(self, args: argparse.Namespace) -> None:
raise RuntimeError("\n".join(exceptions))


def _determine_target_patch_type(subproject: SubProject) -> str:
def _determine_target_patch_type(subproject: SubProject) -> PatchType:
"""Determine the subproject type for the patch."""
if isinstance(subproject, GitSubProject):
required_type = patch_ng.GIT
required_type = PatchType.GIT
elif isinstance(subproject, SvnSubProject):
required_type = patch_ng.SVN
required_type = PatchType.SVN
else:
required_type = patch_ng.PLAIN
required_type = PatchType.PLAIN

return str(required_type)
return required_type
5 changes: 0 additions & 5 deletions dfetch/project/gitsubproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from dfetch.project.subproject import SubProject
from dfetch.util.util import safe_rmtree
from dfetch.vcs.git import GitLocalRepo, GitRemote, get_git_version
from dfetch.vcs.patch import PatchInfo

logger = get_logger(__name__)

Expand Down Expand Up @@ -112,7 +111,3 @@ def _determine_fetched_version(self, version: Version, fetched_sha: str) -> Vers
def get_default_branch(self) -> str: # type: ignore
"""Get the default branch of this repository."""
return self._remote_repo.get_default_branch()

def create_formatted_patch_header(self, patch_info: PatchInfo) -> str:
"""Create a formatted patch header for the given patch info."""
return patch_info.to_git_header()
12 changes: 3 additions & 9 deletions dfetch/project/gitsuperproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from dfetch.project.superproject import RevisionRange, SuperProject
from dfetch.util.util import resolve_absolute_path
from dfetch.vcs.git import GitLocalRepo
from dfetch.vcs.patch import reverse_patch

logger = get_logger(__name__)

Expand Down Expand Up @@ -138,14 +137,9 @@ def diff(
combined_diff += [diff_since_revision]

untracked_files_patch = local_repo.untracked_files_patch(ignore)
if untracked_files_patch:
if not untracked_files_patch.is_empty():
if reverse:
reversed_patch = reverse_patch(untracked_files_patch.encode("utf-8"))
if not reversed_patch:
raise RuntimeError(
"Failed to reverse untracked files patch; patch parsing returned empty."
)
untracked_files_patch = reversed_patch
combined_diff += [untracked_files_patch]
untracked_files_patch.reverse()
combined_diff += [untracked_files_patch.dump()]

return "\n".join(combined_diff)
10 changes: 2 additions & 8 deletions dfetch/project/subproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from dfetch.project.metadata import Metadata
from dfetch.util.util import hash_directory, safe_rm
from dfetch.util.versions import latest_tag_from_list
from dfetch.vcs.patch import PatchInfo, apply_patch
from dfetch.vcs.patch import Patch

logger = get_logger(__name__)

Expand Down Expand Up @@ -161,7 +161,7 @@ def _apply_patches(self, count: int = -1) -> list[str]:
normalized_patch_path = str(relative_patch_path.as_posix())

self._log_project(f'Applying patch "{normalized_patch_path}"')
result = apply_patch(normalized_patch_path, root=self.local_path)
result = Patch.from_file(normalized_patch_path).apply(root=self.local_path)

if result.encoding_warning:
self._log_project(
Expand Down Expand Up @@ -395,9 +395,3 @@ def is_license_file(filename: str) -> bool:
fnmatch.fnmatch(filename.lower(), pattern)
for pattern in SubProject.LICENSE_GLOBS
)

@abstractmethod
def create_formatted_patch_header(self, patch_info: PatchInfo) -> str:
"""Create a formatted patch header for the given patch info."""
del patch_info
return ""
5 changes: 0 additions & 5 deletions dfetch/project/svnsubproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
find_non_matching_files,
safe_rm,
)
from dfetch.vcs.patch import PatchInfo
from dfetch.vcs.svn import SvnRemote, SvnRepo, get_svn_version

logger = get_logger(__name__)
Expand Down Expand Up @@ -180,7 +179,3 @@ def _get_revision(self, branch: str) -> str:
def get_default_branch(self) -> str:
"""Get the default branch of this repository."""
return SvnRepo.DEFAULT_BRANCH

def create_formatted_patch_header(self, patch_info: PatchInfo) -> str:
"""Create a formatted patch header for the given patch info."""
return patch_info.to_svn_header()
26 changes: 9 additions & 17 deletions dfetch/project/svnsuperproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@
in_directory,
resolve_absolute_path,
)
from dfetch.vcs.patch import (
combine_patches,
create_svn_patch_for_new_file,
reverse_patch,
)
from dfetch.vcs.patch import Patch, PatchType
from dfetch.vcs.svn import SvnRepo

logger = get_logger(__name__)
Expand Down Expand Up @@ -116,22 +112,18 @@ def diff(
if new:
new, old = old, new

filtered = repo.create_diff(old, new, ignore)
patch = repo.create_diff(old, new, ignore)

if new:
return filtered
return patch.dump()

patches: list[bytes] = [filtered.encode("utf-8")] if filtered else []
with in_directory(path):
for file_path in repo.untracked_files(".", ignore):
patch = create_svn_patch_for_new_file(file_path)
if patch:
patches.append(patch.encode("utf-8"))

patch_str = combine_patches(patches)
patch.extend(
Patch.for_new_files(repo.untracked_files(".", ignore), PatchType.SVN)
)

# SVN has no way of producing a reverse working copy patch, reverse ourselves
if reverse and not new:
patch_str = reverse_patch(patch_str.encode("UTF-8"))
if reverse:
patch.reverse()

return patch_str
return patch.dump()
11 changes: 5 additions & 6 deletions dfetch/vcs/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from dfetch.log import get_logger
from dfetch.util.cmdline import SubprocessCommandError, run_on_cmdline
from dfetch.util.util import in_directory, safe_rmtree
from dfetch.vcs.patch import create_git_patch_for_new_file
from dfetch.vcs.patch import Patch, PatchType

logger = get_logger(__name__)

Expand Down Expand Up @@ -457,7 +457,7 @@ def any_changes_or_untracked(path: str) -> bool:
.splitlines()
)

def untracked_files_patch(self, ignore: Sequence[str] | None = None) -> str:
def untracked_files_patch(self, ignore: Sequence[str] | None = None) -> Patch:
"""Create a diff for untracked files."""
with in_directory(self._path):
untracked_files = (
Expand All @@ -476,10 +476,9 @@ def untracked_files_patch(self, ignore: Sequence[str] | None = None) -> str:
]

if untracked_files:
return "\n".join(
[create_git_patch_for_new_file(file) for file in untracked_files]
)
return ""
return Patch.for_new_files(untracked_files, PatchType.GIT)

return Patch.empty()

@staticmethod
def submodules() -> list[Submodule]:
Expand Down
Loading
Loading