riplex 0.9.2__tar.gz → 0.9.3__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.
- {riplex-0.9.2/src/riplex.egg-info → riplex-0.9.3}/PKG-INFO +1 -1
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/scanner.py +31 -2
- {riplex-0.9.2 → riplex-0.9.3/src/riplex.egg-info}/PKG-INFO +1 -1
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/scm_version.json +2 -2
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_scanner.py +60 -1
- {riplex-0.9.2 → riplex-0.9.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.github/ISSUE_TEMPLATE/crash_report.yml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.github/agents/riplex.agent.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.github/copilot-instructions.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.github/workflows/publish.yml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.github/workflows/release.yml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.gitignore +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/.vscode/settings.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/CONTRIBUTORS.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/LICENSE +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/README.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/architecture.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/changelog.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/cli-guide/lookup.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/cli-guide/orchestrate.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/cli-guide/organize.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/cli-guide/workflow.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/getting-started/configuration.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/getting-started/installation.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/gui-guide/gui-walkthrough.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/index.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/naming-rules.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/reference/cli.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/docs/troubleshooting.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/issues/debug-artifacts-consolidation.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/issues/manual-rip-and-organize-escape-hatch.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/issues/orchestrate-dvdcompare-fallback.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/issues/planned-features.md +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/mkdocs.yml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/pyproject.toml +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/0_Rip_Flow_BTTF.gif +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/1_Welcome_Screen.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/2_Disc_Detection_BTTF.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/3_Metadata_Lookup_BTTF.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/4_Disc_Release_BTTF.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/5_Multi_Disc_Overview_BTTF.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/screenshots/5_Select_Title_to_RIP_BTTF.png +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/setup.cfg +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/cache.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/config.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/dedup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/detect.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/disc/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/disc/analysis.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/disc/makemkv.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/disc/provider.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/formatter.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/lookup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/manifest.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/matcher.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/metadata/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/metadata/planner.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/metadata/provider.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/metadata/sources/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/metadata/sources/tmdb.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/models.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/normalize.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/organizer.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/snapshot.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/splitter.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/tagger.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/title.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/ui.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex/updater.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/SOURCES.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/dependency_links.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/entry_points.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/requires.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/scm_file_list.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex.egg-info/top_level.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/bug_report.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/crash_dump.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/keep_awake.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/main.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/disc_detection.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/disc_overview.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/disc_swap.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/done.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/folder_picker.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/metadata.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/orchestrate_done.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/organize_done.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/organize_preview.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/progress.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/release.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/selection.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/update.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_app/screens/welcome.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/lookup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/orchestrate.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/organize.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/rip.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/commands/setup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/formatting.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/src/riplex_cli/main.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/__init__.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/fixtures/chernobyl_disc1.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/fixtures/makemkvcon_frozen_planet_ii_d2.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/fixtures/makemkvcon_list.txt +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/Batman Begins.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/Blade Runner (Blu-ray 4k).snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/Blade Runner The Final Cut.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/Seven Worlds One Planet.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/The Dark Knight Rises.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/The Dark Knight.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/snapshots/Waterworld.snapshot.json +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_app_main.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_cache.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_cli_utils.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_config.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_dedup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_detect.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_disc_analysis.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_disc_detection_screen.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_disc_fixtures.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_disc_provider.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_formatter.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_lookup.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_makemkv.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_matcher.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_normalize.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_organizer.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_planner.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_release_screen.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_rip_guide.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_snapshot.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_splitter.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_tagger.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_tmdb_provider.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_ui.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_updater.py +0 -0
- {riplex-0.9.2 → riplex-0.9.3}/tests/test_welcome_screen.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
+
import os
|
|
7
8
|
import platform
|
|
8
9
|
import shutil
|
|
9
10
|
import subprocess
|
|
@@ -30,16 +31,44 @@ _FFPROBE_SEARCH_PATHS = [
|
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
|
|
34
|
+
def _windows_ffprobe_candidates() -> list[Path]:
|
|
35
|
+
"""Return likely ``ffprobe.exe`` locations from winget and manual installs.
|
|
36
|
+
|
|
37
|
+
riplex installs FFmpeg via ``winget install Gyan.FFmpeg``, which is a
|
|
38
|
+
portable package: winget drops a shim under ``WinGet\\Links`` and unpacks
|
|
39
|
+
the payload under ``WinGet\\Packages\\Gyan.FFmpeg*\\...\\bin``. Neither is on
|
|
40
|
+
PATH in the current process right after install, so check them directly.
|
|
41
|
+
"""
|
|
42
|
+
candidates: list[Path] = []
|
|
43
|
+
local_appdata = os.environ.get("LOCALAPPDATA")
|
|
44
|
+
if local_appdata:
|
|
45
|
+
winget = Path(local_appdata) / "Microsoft" / "WinGet"
|
|
46
|
+
candidates.append(winget / "Links" / "ffprobe.exe")
|
|
47
|
+
packages = winget / "Packages"
|
|
48
|
+
if packages.is_dir():
|
|
49
|
+
candidates.extend(packages.glob("Gyan.FFmpeg*/**/bin/ffprobe.exe"))
|
|
50
|
+
# Common manual install spots
|
|
51
|
+
candidates.append(Path(r"C:\ffmpeg\bin\ffprobe.exe"))
|
|
52
|
+
candidates.append(Path(r"C:\Program Files\ffmpeg\bin\ffprobe.exe"))
|
|
53
|
+
return candidates
|
|
54
|
+
|
|
55
|
+
|
|
33
56
|
def find_ffprobe() -> str | None:
|
|
34
57
|
"""Locate the ffprobe executable.
|
|
35
58
|
|
|
36
59
|
Checks PATH first, then ``~/.riplex/bin/``, ``/usr/local/bin/``,
|
|
37
|
-
and ``/opt/homebrew/bin/``.
|
|
60
|
+
and ``/opt/homebrew/bin/``. On Windows, also checks the winget
|
|
61
|
+
portable install locations (the ``WinGet\\Links`` shim and the
|
|
62
|
+
``WinGet\\Packages\\Gyan.FFmpeg*`` payload) and common manual install
|
|
63
|
+
folders. Returns the path string or *None*.
|
|
38
64
|
"""
|
|
39
65
|
path = shutil.which("ffprobe")
|
|
40
66
|
if path:
|
|
41
67
|
return path
|
|
42
|
-
|
|
68
|
+
candidates = list(_FFPROBE_SEARCH_PATHS)
|
|
69
|
+
if platform.system() == "Windows":
|
|
70
|
+
candidates.extend(_windows_ffprobe_candidates())
|
|
71
|
+
for candidate in candidates:
|
|
43
72
|
if candidate.is_file():
|
|
44
73
|
return str(candidate)
|
|
45
74
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.3
|
|
4
4
|
Summary: Automates the tedious manual work around MakeMKV: figuring out what to rip, which MKV files are actually what, and organizing everything into Plex-compatible folder structures.
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -6,7 +6,7 @@ from unittest.mock import patch
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
from riplex.models import ScannedFile
|
|
9
|
-
from riplex.scanner import _probe_file, scan_folder
|
|
9
|
+
from riplex.scanner import _probe_file, find_ffprobe, scan_folder
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@pytest.fixture
|
|
@@ -103,3 +103,62 @@ class TestScanFolder:
|
|
|
103
103
|
for disc in discs:
|
|
104
104
|
for f in disc.files:
|
|
105
105
|
assert Path(f.path).is_absolute()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class TestFindFfprobe:
|
|
109
|
+
def test_returns_path_when_on_path(self):
|
|
110
|
+
with patch("riplex.scanner.shutil.which", return_value="/usr/bin/ffprobe"):
|
|
111
|
+
assert find_ffprobe() == "/usr/bin/ffprobe"
|
|
112
|
+
|
|
113
|
+
def test_returns_none_when_not_found(self, monkeypatch):
|
|
114
|
+
monkeypatch.setattr("riplex.scanner.shutil.which", lambda _: None)
|
|
115
|
+
monkeypatch.setattr("riplex.scanner.platform.system", lambda: "Linux")
|
|
116
|
+
monkeypatch.setattr("riplex.scanner._FFPROBE_SEARCH_PATHS", [])
|
|
117
|
+
assert find_ffprobe() is None
|
|
118
|
+
|
|
119
|
+
def test_finds_winget_links_shim_on_windows(self, tmp_path, monkeypatch):
|
|
120
|
+
local_appdata = tmp_path / "AppData" / "Local"
|
|
121
|
+
links = local_appdata / "Microsoft" / "WinGet" / "Links"
|
|
122
|
+
links.mkdir(parents=True)
|
|
123
|
+
shim = links / "ffprobe.exe"
|
|
124
|
+
shim.write_text("", encoding="utf-8")
|
|
125
|
+
|
|
126
|
+
monkeypatch.setattr("riplex.scanner.shutil.which", lambda _: None)
|
|
127
|
+
monkeypatch.setattr("riplex.scanner.platform.system", lambda: "Windows")
|
|
128
|
+
monkeypatch.setattr("riplex.scanner._FFPROBE_SEARCH_PATHS", [])
|
|
129
|
+
monkeypatch.setenv("LOCALAPPDATA", str(local_appdata))
|
|
130
|
+
|
|
131
|
+
assert find_ffprobe() == str(shim)
|
|
132
|
+
|
|
133
|
+
def test_finds_winget_package_payload_on_windows(self, tmp_path, monkeypatch):
|
|
134
|
+
local_appdata = tmp_path / "AppData" / "Local"
|
|
135
|
+
bin_dir = (
|
|
136
|
+
local_appdata / "Microsoft" / "WinGet" / "Packages"
|
|
137
|
+
/ "Gyan.FFmpeg_Microsoft.Winget.Source_abc"
|
|
138
|
+
/ "ffmpeg-7.0-full_build" / "bin"
|
|
139
|
+
)
|
|
140
|
+
bin_dir.mkdir(parents=True)
|
|
141
|
+
exe = bin_dir / "ffprobe.exe"
|
|
142
|
+
exe.write_text("", encoding="utf-8")
|
|
143
|
+
|
|
144
|
+
monkeypatch.setattr("riplex.scanner.shutil.which", lambda _: None)
|
|
145
|
+
monkeypatch.setattr("riplex.scanner.platform.system", lambda: "Windows")
|
|
146
|
+
monkeypatch.setattr("riplex.scanner._FFPROBE_SEARCH_PATHS", [])
|
|
147
|
+
monkeypatch.setenv("LOCALAPPDATA", str(local_appdata))
|
|
148
|
+
|
|
149
|
+
assert find_ffprobe() == str(exe)
|
|
150
|
+
|
|
151
|
+
def test_windows_candidates_skipped_on_non_windows(self, monkeypatch):
|
|
152
|
+
monkeypatch.setattr("riplex.scanner.shutil.which", lambda _: None)
|
|
153
|
+
monkeypatch.setattr("riplex.scanner.platform.system", lambda: "Linux")
|
|
154
|
+
monkeypatch.setattr("riplex.scanner._FFPROBE_SEARCH_PATHS", [])
|
|
155
|
+
called = {"hit": False}
|
|
156
|
+
|
|
157
|
+
def _should_not_run():
|
|
158
|
+
called["hit"] = True
|
|
159
|
+
return []
|
|
160
|
+
|
|
161
|
+
monkeypatch.setattr("riplex.scanner._windows_ffprobe_candidates", _should_not_run)
|
|
162
|
+
assert find_ffprobe() is None
|
|
163
|
+
assert called["hit"] is False
|
|
164
|
+
|
|
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
|
|
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
|
|
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
|
|
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
|