git2svn 0.7.1__tar.gz → 0.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {git2svn-0.7.1/git2svn.egg-info → git2svn-0.8.0}/PKG-INFO +1 -1
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/user-guide/commands.md +24 -3
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/_version.py +2 -2
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/cli.py +32 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/core.py +27 -9
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/svn.py +15 -0
- {git2svn-0.7.1 → git2svn-0.8.0/git2svn.egg-info}/PKG-INFO +1 -1
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_cli.py +33 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_core.py +15 -1
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_svn.py +14 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.githooks/pre-commit +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.github/dependabot.yml +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.github/workflows/ci.yml +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.github/workflows/release.yml +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.gitignore +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/.pre-commit-config.yaml +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/CONTRIBUTING.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/LICENSE.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/README.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/arc42/README.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/arc42/adrs.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/arc42/concepts.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/req42.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/user-guide/README.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/user-guide/integration-workflow.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/docs/user-guide/troubleshooting.md +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/__init__.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/__main__.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/colors.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/eol.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/git.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/patcher.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/py.typed +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/setup.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/state.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn/status.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/SOURCES.txt +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/dependency_links.txt +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/entry_points.txt +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/requires.txt +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/scm_file_list.json +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.egg-info/top_level.txt +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/git2svn.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/pyproject.toml +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/setup.cfg +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_colors.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_e2e.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_eol.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_git.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_patcher.py +0 -0
- {git2svn-0.7.1 → git2svn-0.8.0}/tests/test_status.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Command Reference: `
|
|
1
|
+
# Command Reference: `stage`, `diff`, `replay`, `setup` & `status`
|
|
2
2
|
|
|
3
|
-
This document details the usage, flags, and mechanics for
|
|
3
|
+
This document details the usage, flags, and mechanics for all `git2svn` commands.
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
---
|
|
@@ -43,9 +43,30 @@ Compares the full tree of a target Git branch or commit against the SVN workspac
|
|
|
43
43
|
git2svn stage feature/login --snapshot -s /path/to/svn
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
### 1.5 Immediate Diff Preview (`--diff` / `-p`)
|
|
47
|
+
Immediately preview the staged diff upon completion without needing to run a separate command:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git2svn stage main..feature/login --diff
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 2. Command: `diff`
|
|
56
|
+
|
|
57
|
+
Inspect uncommitted changes in the SVN workspace staged by `git2svn stage`.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# View full unified diff of staged changes:
|
|
61
|
+
git2svn diff
|
|
62
|
+
|
|
63
|
+
# View compact diffstat summary:
|
|
64
|
+
git2svn diff --stat
|
|
65
|
+
```
|
|
66
|
+
|
|
46
67
|
---
|
|
47
68
|
|
|
48
|
-
##
|
|
69
|
+
## 3. Command: `replay`
|
|
49
70
|
|
|
50
71
|
Sequentially ports Git commits onto the SVN workspace, creating an **atomic `svn commit` for each** with its original Git commit message, author body, and timestamps.
|
|
51
72
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.8.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 8, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -136,6 +136,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
136
136
|
default=argparse.SUPPRESS,
|
|
137
137
|
help="Mirror the exact tree of ref1 onto SVN without knowing base ref (adds new, removes missing, updates modified)",
|
|
138
138
|
)
|
|
139
|
+
parser_stage.add_argument(
|
|
140
|
+
"--diff",
|
|
141
|
+
"-p",
|
|
142
|
+
action="store_true",
|
|
143
|
+
default=argparse.SUPPRESS,
|
|
144
|
+
help="Immediately show 'svn diff' preview of staged changes after staging",
|
|
145
|
+
)
|
|
139
146
|
|
|
140
147
|
# replay
|
|
141
148
|
parser_replay = subparsers.add_parser(
|
|
@@ -214,6 +221,20 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
214
221
|
help="Path to SVN working copy (optional if already configured or set via --svn-dir)",
|
|
215
222
|
)
|
|
216
223
|
|
|
224
|
+
# diff
|
|
225
|
+
parser_diff = subparsers.add_parser(
|
|
226
|
+
"diff",
|
|
227
|
+
parents=[common_parser],
|
|
228
|
+
help="Inspect uncommitted changes in the SVN workspace (preview after staging)",
|
|
229
|
+
description="Run svn diff on the SVN workspace to inspect uncommitted changes staged by git2svn.",
|
|
230
|
+
)
|
|
231
|
+
parser_diff.add_argument(
|
|
232
|
+
"--stat",
|
|
233
|
+
action="store_true",
|
|
234
|
+
default=False,
|
|
235
|
+
help="Display a diffstat summary of changed files instead of the full patch",
|
|
236
|
+
)
|
|
237
|
+
|
|
217
238
|
# status
|
|
218
239
|
subparsers.add_parser(
|
|
219
240
|
"status",
|
|
@@ -249,6 +270,8 @@ def parse_cli_args(argv: Optional[List[str]] = None) -> argparse.Namespace:
|
|
|
249
270
|
verbose=False,
|
|
250
271
|
copy=False,
|
|
251
272
|
snapshot=False,
|
|
273
|
+
diff=False,
|
|
274
|
+
stat=False,
|
|
252
275
|
replay_action=None,
|
|
253
276
|
update=None,
|
|
254
277
|
)
|
|
@@ -380,6 +403,15 @@ def main(argv: Optional[List[str]] = None) -> int:
|
|
|
380
403
|
use_copy=use_copy,
|
|
381
404
|
snapshot=is_snapshot,
|
|
382
405
|
)
|
|
406
|
+
if getattr(args, "diff", False):
|
|
407
|
+
diff_output = sync_mgr.diff()
|
|
408
|
+
if diff_output.strip():
|
|
409
|
+
print(diff_output, end="")
|
|
410
|
+
elif args.command == "diff":
|
|
411
|
+
show_stat = getattr(args, "stat", False)
|
|
412
|
+
diff_output = sync_mgr.diff(stat=show_stat)
|
|
413
|
+
if diff_output.strip():
|
|
414
|
+
print(diff_output, end="")
|
|
383
415
|
elif args.command == "replay":
|
|
384
416
|
action = getattr(args, "replay_action", None)
|
|
385
417
|
if action == "continue":
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import shutil
|
|
6
6
|
import sys
|
|
7
|
+
import time
|
|
7
8
|
from pathlib import Path
|
|
8
9
|
from typing import Dict, List, Optional
|
|
9
10
|
|
|
@@ -210,6 +211,13 @@ class Synchronizer:
|
|
|
210
211
|
modified_count,
|
|
211
212
|
)
|
|
212
213
|
|
|
214
|
+
def diff(self, stat: bool = False) -> str:
|
|
215
|
+
"""
|
|
216
|
+
Inspect uncommitted changes in the SVN workspace using svn diff.
|
|
217
|
+
Returns the diff output text (or stat summary if stat=True).
|
|
218
|
+
"""
|
|
219
|
+
return self.svn.diff(stat=stat)
|
|
220
|
+
|
|
213
221
|
def replay(self, ref1: str, ref2: Optional[str] = None) -> None:
|
|
214
222
|
"""
|
|
215
223
|
Replay a single commit or range of commits onto SVN, committing each with its Git message.
|
|
@@ -218,6 +226,11 @@ class Synchronizer:
|
|
|
218
226
|
target_spec = f"{start_or_commit}..{end_ref}" if not is_single else start_or_commit
|
|
219
227
|
self.show_identity_banner(target_spec)
|
|
220
228
|
|
|
229
|
+
if not self.dry_run and not self.svn.is_clean():
|
|
230
|
+
raise RuntimeError(
|
|
231
|
+
"SVN workspace has uncommitted changes. Please commit, stash, or revert them before starting a replay."
|
|
232
|
+
)
|
|
233
|
+
|
|
221
234
|
if is_single:
|
|
222
235
|
commit_hash = start_or_commit
|
|
223
236
|
logger.info("Replaying single commit %s", commit_hash)
|
|
@@ -226,11 +239,6 @@ class Synchronizer:
|
|
|
226
239
|
start_ref = start_or_commit
|
|
227
240
|
assert end_ref is not None
|
|
228
241
|
|
|
229
|
-
if not self.dry_run and not self.svn.is_clean():
|
|
230
|
-
raise RuntimeError(
|
|
231
|
-
"SVN workspace has uncommitted changes. Please commit, stash, or revert them before starting a replay."
|
|
232
|
-
)
|
|
233
|
-
|
|
234
242
|
merges = self.git.get_merge_commits(start_ref, end_ref)
|
|
235
243
|
if merges:
|
|
236
244
|
raise RuntimeError(
|
|
@@ -336,6 +344,7 @@ class Synchronizer:
|
|
|
336
344
|
|
|
337
345
|
def _execute_replay_queue(self, commits: List[str], total_commits: int, start_index: int) -> None:
|
|
338
346
|
"""Execute a list of commits sequentially, catching conflicts and persisting state."""
|
|
347
|
+
queue_start = time.perf_counter()
|
|
339
348
|
pad_width = len(str(total_commits))
|
|
340
349
|
for idx, commit_hash in enumerate(commits, start=start_index):
|
|
341
350
|
commit_msg = self.git.get_commit_message(commit_hash)
|
|
@@ -351,19 +360,23 @@ class Synchronizer:
|
|
|
351
360
|
sys.stdout.write(f"{progress_prefix}... ")
|
|
352
361
|
sys.stdout.flush()
|
|
353
362
|
|
|
363
|
+
commit_start = time.perf_counter()
|
|
354
364
|
try:
|
|
355
365
|
self._patch_and_stage_commit(commit_hash)
|
|
356
366
|
self.svn.commit(commit_msg)
|
|
357
|
-
|
|
367
|
+
elapsed = time.perf_counter() - commit_start
|
|
368
|
+
sys.stdout.write(f"OK ({elapsed:.2f}s)\n")
|
|
358
369
|
sys.stdout.flush()
|
|
359
370
|
except SvnError:
|
|
360
|
-
|
|
371
|
+
elapsed = time.perf_counter() - commit_start
|
|
372
|
+
sys.stdout.write(f"FAILED (SVN error, {elapsed:.2f}s)\n")
|
|
361
373
|
sys.stdout.flush()
|
|
362
374
|
# SVN operational failure (e.g. working copy locked, out-of-date, collision)
|
|
363
375
|
# Re-raise directly to display actionable SVN resolution hints
|
|
364
376
|
raise
|
|
365
377
|
except Exception:
|
|
366
|
-
|
|
378
|
+
elapsed = time.perf_counter() - commit_start
|
|
379
|
+
sys.stdout.write(f"CONFLICT ({elapsed:.2f}s)\n")
|
|
367
380
|
sys.stdout.flush()
|
|
368
381
|
remaining = commits[idx - start_index + 1 :]
|
|
369
382
|
state_data = {
|
|
@@ -398,7 +411,12 @@ class Synchronizer:
|
|
|
398
411
|
)
|
|
399
412
|
raise
|
|
400
413
|
clear_replay_state(self.svn.workspace_dir)
|
|
401
|
-
|
|
414
|
+
total_elapsed = time.perf_counter() - queue_start
|
|
415
|
+
logger.info(
|
|
416
|
+
"Replay completed successfully! All %d commits applied in %.2fs.",
|
|
417
|
+
total_commits,
|
|
418
|
+
total_elapsed,
|
|
419
|
+
)
|
|
402
420
|
if self.auto_update:
|
|
403
421
|
self.svn.update()
|
|
404
422
|
|
|
@@ -153,6 +153,21 @@ class SvnWorkspace:
|
|
|
153
153
|
raise parse_svn_error(res.stderr, "check status", self.workspace_dir)
|
|
154
154
|
return not bool(res.stdout.strip())
|
|
155
155
|
|
|
156
|
+
def diff(self, target: Optional[str] = None, stat: bool = False) -> str:
|
|
157
|
+
"""
|
|
158
|
+
Run 'svn diff' on the workspace or a specific target.
|
|
159
|
+
If stat is True, runs 'svn diff --stat' (summarized file changes).
|
|
160
|
+
"""
|
|
161
|
+
args = ["diff"]
|
|
162
|
+
if stat:
|
|
163
|
+
args.append("--stat")
|
|
164
|
+
if target:
|
|
165
|
+
args.append(target)
|
|
166
|
+
res = self.run_cmd(args, check=False)
|
|
167
|
+
if res.returncode != 0:
|
|
168
|
+
raise parse_svn_error(res.stderr, "diff", self.workspace_dir)
|
|
169
|
+
return res.stdout
|
|
170
|
+
|
|
156
171
|
def get_status_summary(self) -> List[str]:
|
|
157
172
|
"""Return lines of uncommitted changes from 'svn status -q'."""
|
|
158
173
|
res = self.run_cmd(["status", "-q"], check=False)
|
|
@@ -193,6 +193,39 @@ class TestCli(unittest.TestCase):
|
|
|
193
193
|
mock_is_file.return_value = False
|
|
194
194
|
self.assertEqual(git2svn.svn.find_svn_binary(), "svn")
|
|
195
195
|
|
|
196
|
+
def test_diff_subcommand_args(self):
|
|
197
|
+
"""Verify diff subcommand argument parsing."""
|
|
198
|
+
args = git2svn.parse_cli_args(["diff", "-s", "/path/to/svn"])
|
|
199
|
+
self.assertEqual(args.command, "diff")
|
|
200
|
+
self.assertFalse(args.stat)
|
|
201
|
+
|
|
202
|
+
args_stat = git2svn.parse_cli_args(["diff", "--stat", "-s", "/path/to/svn"])
|
|
203
|
+
self.assertEqual(args_stat.command, "diff")
|
|
204
|
+
self.assertTrue(args_stat.stat)
|
|
205
|
+
|
|
206
|
+
args_stage_diff = git2svn.parse_cli_args(["stage", "HEAD", "-p", "-s", "/path/to/svn"])
|
|
207
|
+
self.assertEqual(args_stage_diff.command, "stage")
|
|
208
|
+
self.assertTrue(args_stage_diff.diff)
|
|
209
|
+
|
|
210
|
+
def test_diff_command_execution(self):
|
|
211
|
+
"""Verify git2svn diff invokes synchronizer.diff and prints output."""
|
|
212
|
+
git_dir = self.path / "diff_git"
|
|
213
|
+
git_dir.mkdir()
|
|
214
|
+
subprocess.run(["git", "init"], cwd=git_dir, check=True, capture_output=True)
|
|
215
|
+
|
|
216
|
+
svn_dir = self.path / "diff_svn"
|
|
217
|
+
svn_dir.mkdir()
|
|
218
|
+
(svn_dir / ".svn").mkdir()
|
|
219
|
+
|
|
220
|
+
with patch("git2svn.cli.Synchronizer") as mock_sync_cls, patch("sys.stdout", new=io.StringIO()) as fake_out:
|
|
221
|
+
mock_sync = mock_sync_cls.return_value
|
|
222
|
+
mock_sync.diff.return_value = "Index: file.txt\n=== diff content ===\n"
|
|
223
|
+
|
|
224
|
+
code = git2svn.main(["--git-dir", str(git_dir), "--svn-dir", str(svn_dir), "diff"])
|
|
225
|
+
self.assertEqual(code, 0)
|
|
226
|
+
mock_sync.diff.assert_called_once_with(stat=False)
|
|
227
|
+
self.assertIn("=== diff content ===", fake_out.getvalue())
|
|
228
|
+
|
|
196
229
|
|
|
197
230
|
if __name__ == "__main__":
|
|
198
231
|
unittest.main()
|
|
@@ -481,7 +481,7 @@ class TestSynchronizer(unittest.TestCase):
|
|
|
481
481
|
with patch("sys.stdout", new_callable=io.StringIO) as mock_stdout:
|
|
482
482
|
self.sync_mgr.replay(base_hash, feat_hash)
|
|
483
483
|
output = mock_stdout.getvalue()
|
|
484
|
-
self.assertIn(f"[1/1] Applying {feat_hash[:8]}: feat: progress indicator... OK", output)
|
|
484
|
+
self.assertIn(f"[1/1] Applying {feat_hash[:8]}: feat: progress indicator... OK (", output)
|
|
485
485
|
|
|
486
486
|
@patch.object(git2svn.SvnWorkspace, "run_cmd")
|
|
487
487
|
def test_stage_with_git_config_default_range(self, mock_svn_cmd):
|
|
@@ -677,6 +677,20 @@ class TestSynchronizer(unittest.TestCase):
|
|
|
677
677
|
self.assertEqual(res, 1)
|
|
678
678
|
mock_tb.assert_called_once()
|
|
679
679
|
|
|
680
|
+
def test_replay_raises_if_svn_workspace_dirty(self):
|
|
681
|
+
"""Verify replay raises RuntimeError if SVN workspace has uncommitted changes."""
|
|
682
|
+
with patch.object(self.svn_ws, "is_clean", return_value=False):
|
|
683
|
+
with self.assertRaises(RuntimeError) as cm:
|
|
684
|
+
self.sync_mgr.replay("HEAD~1..HEAD")
|
|
685
|
+
self.assertIn("SVN workspace has uncommitted changes", str(cm.exception))
|
|
686
|
+
|
|
687
|
+
def test_replay_single_commit_raises_if_dirty(self):
|
|
688
|
+
"""Verify replay of single commit raises RuntimeError if SVN workspace has uncommitted changes."""
|
|
689
|
+
with patch.object(self.svn_ws, "is_clean", return_value=False):
|
|
690
|
+
with self.assertRaises(RuntimeError) as cm:
|
|
691
|
+
self.sync_mgr.replay("HEAD")
|
|
692
|
+
self.assertIn("SVN workspace has uncommitted changes", str(cm.exception))
|
|
693
|
+
|
|
680
694
|
|
|
681
695
|
if __name__ == "__main__":
|
|
682
696
|
unittest.main()
|
|
@@ -135,6 +135,20 @@ class TestSvnLockAndCollisionHandling(unittest.TestCase):
|
|
|
135
135
|
with self.assertRaises(git2svn.SvnLockError):
|
|
136
136
|
self.workspace.is_clean()
|
|
137
137
|
|
|
138
|
+
@patch.object(git2svn.SvnWorkspace, "run_cmd")
|
|
139
|
+
def test_diff(self, mock_cmd):
|
|
140
|
+
mock_cmd.return_value = subprocess.CompletedProcess([], 0, stdout="Index: file.txt\n", stderr="")
|
|
141
|
+
output = self.workspace.diff()
|
|
142
|
+
self.assertEqual(output, "Index: file.txt\n")
|
|
143
|
+
mock_cmd.assert_called_once_with(["diff"], check=False)
|
|
144
|
+
|
|
145
|
+
@patch.object(git2svn.SvnWorkspace, "run_cmd")
|
|
146
|
+
def test_diff_stat(self, mock_cmd):
|
|
147
|
+
mock_cmd.return_value = subprocess.CompletedProcess([], 0, stdout="file.txt | 2 +-\n", stderr="")
|
|
148
|
+
output = self.workspace.diff(stat=True)
|
|
149
|
+
self.assertEqual(output, "file.txt | 2 +-\n")
|
|
150
|
+
mock_cmd.assert_called_once_with(["diff", "--stat"], check=False)
|
|
151
|
+
|
|
138
152
|
|
|
139
153
|
if __name__ == "__main__":
|
|
140
154
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|