Skip to content

Commit 782b36c

Browse files
committed
Keep metadata out of patch & remove svn patch prefix
Fixes #267
1 parent 0f2f643 commit 782b36c

12 files changed

Lines changed: 112 additions & 27 deletions

File tree

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Release 0.11.0 (unreleased)
1515
* Handle SVN tags with special characters (#811)
1616
* Don't return non-zero exit code if tool not found during environment (#701)
1717
* Create standalone binaries for Linux, Mac & Windows (#705)
18+
* Don't make metadata file part of diff (#267)
19+
* Fix unneeded project prefix in SVN diffs (#886)
1820

1921
Release 0.10.0 (released 2025-03-12)
2022
====================================

dfetch/commands/diff.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ def _diff_from_repo(repo: VCS, project: ProjectEntry, revs: list[str]) -> str:
184184
if len(revs) == 1:
185185
revs.append("")
186186

187-
return repo.get_diff(*revs)
187+
return repo.get_diff(
188+
old_revision=revs[0], new_revision=revs[1], ignore=(Metadata.FILENAME,)
189+
)
188190

189191

190192
def _dump_patch(

dfetch/project/git.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import os
44
import pathlib
5+
from collections.abc import Sequence
56
from functools import lru_cache
67
from typing import Optional
78

@@ -50,9 +51,11 @@ def current_revision(self) -> str:
5051
"""Get the revision of the metadata file."""
5152
return str(self._local_repo.get_current_hash())
5253

53-
def get_diff(self, old_revision: str, new_revision: Optional[str]) -> str:
54+
def get_diff(
55+
self, old_revision: str, new_revision: Optional[str], ignore: Sequence[str]
56+
) -> str:
5457
"""Get the diff of two revisions."""
55-
return str(self._local_repo.create_diff(old_revision, new_revision))
58+
return str(self._local_repo.create_diff(old_revision, new_revision, ignore))
5659

5760
@staticmethod
5861
def revision_is_enough() -> bool:

dfetch/project/svn.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pathlib
55
import re
66
import urllib.parse
7+
from collections.abc import Sequence
78
from typing import NamedTuple, Optional
89

910
from dfetch.log import get_logger
@@ -16,6 +17,7 @@
1617
in_directory,
1718
safe_rm,
1819
)
20+
from dfetch.vcs.patch import filter_patch
1921

2022
logger = get_logger(__name__)
2123

@@ -246,7 +248,7 @@ def _fetch_impl(self, version: Version) -> Version:
246248
SvnRepo._export(complete_path, rev_arg, self.local_path)
247249

248250
if file_pattern:
249-
for file in find_non_matching_files(self.local_path, file_pattern):
251+
for file in find_non_matching_files(self.local_path, (file_pattern,)):
250252
os.remove(file)
251253
if not os.listdir(self.local_path):
252254
logger.warning(
@@ -366,13 +368,18 @@ def current_revision(self) -> str:
366368
"""Get the current revision of the repo."""
367369
return self._get_last_changed_revision(self.local_path)
368370

369-
def get_diff(self, old_revision: str, new_revision: Optional[str]) -> str:
371+
def get_diff(
372+
self, old_revision: str, new_revision: Optional[str], ignore: Sequence[str]
373+
) -> str:
370374
"""Get the diff between two revisions."""
371-
cmd = f"svn diff {self.local_path} -r {old_revision}"
375+
cmd = ["svn", "diff", "--non-interactive", ".", "-r", old_revision]
372376
if new_revision:
373-
cmd += f":{new_revision}"
377+
cmd[-1] += f":{new_revision}"
374378

375-
return "\n".join(run_on_cmdline(logger, cmd).stdout.decode().splitlines())
379+
with in_directory(self.local_path):
380+
patch_text = run_on_cmdline(logger, cmd).stdout
381+
382+
return filter_patch(patch_text, ignore)
376383

377384
def get_default_branch(self) -> str:
378385
"""Get the default branch of this repository."""

dfetch/project/vcs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,9 @@ def current_revision(self) -> str:
365365
"""Get the revision of the metadata file."""
366366

367367
@abstractmethod
368-
def get_diff(self, old_revision: str, new_revision: Optional[str]) -> str: # noqa
368+
def get_diff(
369+
self, old_revision: str, new_revision: Optional[str], ignore: Sequence[str]
370+
) -> str: # noqa
369371
"""Get the diff of two revisions."""
370372

371373
@abstractmethod

dfetch/util/util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ def _remove_readonly(func: Any, path: str, _: Any) -> None:
2121
raise # pylint: disable=misplaced-bare-raise
2222

2323

24-
def find_non_matching_files(directory: str, pattern: str) -> Iterator[str]:
25-
"""Find files NOT matching the given pattern."""
24+
def find_non_matching_files(directory: str, patterns: Sequence[str]) -> Iterator[str]:
25+
"""Find files NOT matching the given patterns."""
2626
for root, _, files in os.walk(directory):
2727
for basename in files:
28-
if not fnmatch.fnmatch(basename, pattern):
28+
if not any(fnmatch.fnmatch(basename, pattern) for pattern in patterns):
2929
yield os.path.join(root, basename)
3030

3131

dfetch/vcs/git.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,9 @@ def get_remote_url() -> str:
314314

315315
return decoded_result
316316

317-
def create_diff(self, old_hash: str, new_hash: Optional[str]) -> str:
317+
def create_diff(
318+
self, old_hash: str, new_hash: Optional[str], ignore: Sequence[str]
319+
) -> str:
318320
"""Generate a relative diff patch."""
319321
with in_directory(self._path):
320322
cmd = [
@@ -328,6 +330,11 @@ def create_diff(self, old_hash: str, new_hash: Optional[str]) -> str:
328330
]
329331
if new_hash:
330332
cmd.append(new_hash)
333+
334+
if ignore:
335+
cmd.extend(["--", "."])
336+
for ignore_path in ignore:
337+
cmd.append(f":(exclude){ignore_path}")
331338
result = run_on_cmdline(logger, cmd)
332339

333340
return str(result.stdout.decode())

dfetch/vcs/patch.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""Various patch utilities for VCS systems."""
2+
3+
from collections.abc import Sequence
4+
5+
import patch_ng
6+
7+
8+
def filter_patch(patch_text: bytes, ignore: Sequence[str]) -> str:
9+
"""Filter out files from a patch text."""
10+
if not patch_text:
11+
return ""
12+
13+
filtered_patchset = patch_ng.PatchSet()
14+
unfiltered_patchset = patch_ng.fromstring(patch_text) or []
15+
16+
for patch in unfiltered_patchset:
17+
if patch.target.decode("utf-8") not in ignore:
18+
filtered_patchset.items += [patch]
19+
20+
return dump_patch(filtered_patchset)
21+
22+
23+
def dump_patch(patch_set: patch_ng.PatchSet) -> str:
24+
"""Dump a patch to string."""
25+
patch_lines: list[str] = []
26+
for p in patch_set.items:
27+
for headline in p.header:
28+
patch_lines.append(headline.rstrip(b"\n").decode("utf-8"))
29+
patch_lines.append(f"--- {p.source.decode('utf-8')}")
30+
patch_lines.append(f"+++ {p.target.decode('utf-8')}")
31+
for h in p.hunks:
32+
patch_lines.append(
33+
f"@@ -{h.startsrc},{h.linessrc} +{h.starttgt},{h.linestgt} @@"
34+
)
35+
for line in h.text:
36+
patch_lines.append(line.rstrip(b"\n").decode("utf-8"))
37+
return "\n".join(patch_lines)

features/diff-in-git.feature

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,12 @@ Feature: Diff in git
7575
Generated file for SomeProject.git
7676
+An important sentence for the README!
7777
"""
78+
79+
Scenario: Metadata is not part of diff
80+
Given the metadata file ".dfetch_data.yaml" of "MyProject/SomeProject" is changed
81+
When I run "dfetch diff SomeProject"
82+
Then the output shows
83+
"""
84+
Dfetch (0.10.0)
85+
SomeProject : No diffs found since 59efb91396fd369eb113b43382783294dc8ed6d2
86+
"""

features/diff-in-svn.feature

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ Feature: Diff in svn
2121
"""
2222
An important sentence for the README!
2323
"""
24-
When I run "dfetch diff SomeProject" in MySvnProject
24+
When I run "dfetch -v diff SomeProject" in MySvnProject
2525
Then the patch file 'MySvnProject/SomeProject.patch' is generated
2626
"""
27-
Index: SomeProject/README.md
27+
Index: README.md
2828
===================================================================
29-
--- SomeProject/README.md (revision 1)
30-
+++ SomeProject/README.md (working copy)
31-
@@ -1 +1,2 @@
29+
--- README.md
30+
+++ README.md
31+
@@ -1,1 +1,2 @@
3232
some content
3333
+An important sentence for the README!
3434
"""
@@ -43,11 +43,11 @@ Feature: Diff in svn
4343
When I run "dfetch diff SomeProject" in MySvnProject
4444
Then the patch file 'MySvnProject/SomeProject.patch' is generated
4545
"""
46-
Index: SomeProject/NEWFILE.md
46+
Index: NEWFILE.md
4747
===================================================================
48-
--- SomeProject/NEWFILE.md (nonexistent)
49-
+++ SomeProject/NEWFILE.md (revision 2)
50-
@@ -0,0 +1 @@
48+
--- NEWFILE.md
49+
+++ NEWFILE.md
50+
@@ -0,0 +1,1 @@
5151
+A completely new untracked file.
5252
"""
5353

@@ -67,11 +67,20 @@ Feature: Diff in svn
6767
When I run "dfetch diff SomeProject" in MySvnProject
6868
Then the patch file 'MySvnProject/SomeProject.patch' is generated
6969
"""
70-
Index: SomeProject/README.md
70+
Index: README.md
7171
===================================================================
72-
--- SomeProject/README.md (revision 1)
73-
+++ SomeProject/README.md (working copy)
74-
@@ -1 +1,2 @@
72+
--- README.md
73+
+++ README.md
74+
@@ -1,1 +1,2 @@
7575
some content
7676
+An important sentence for the README!
7777
"""
78+
79+
Scenario: Metadata is not part of diff
80+
Given the metadata file ".dfetch_data.yaml" of "MySvnProject/SomeProject" is changed
81+
When I run "dfetch diff SomeProject"
82+
Then the output shows
83+
"""
84+
Dfetch (0.10.0)
85+
SomeProject : No diffs found since 1
86+
"""

0 commit comments

Comments
 (0)