riplex 0.2.4__tar.gz → 0.2.5__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.2.4/src/riplex.egg-info → riplex-0.2.5}/PKG-INFO +2 -2
- {riplex-0.2.4 → riplex-0.2.5}/README.md +1 -1
- {riplex-0.2.4 → riplex-0.2.5/src/riplex.egg-info}/PKG-INFO +2 -2
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/welcome.py +92 -10
- {riplex-0.2.4 → riplex-0.2.5}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/.github/agents/riplex.agent.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/.github/copilot-instructions.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/.github/workflows/publish.yml +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/.github/workflows/release.yml +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/.gitignore +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/MONOREPO_PLAN.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/PLANNED_FEATURES.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/REFACTOR_PLAN.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/architecture.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/changelog.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/getting-started/configuration.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/getting-started/installation.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/guide/lookup.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/guide/orchestrate.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/guide/organize.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/guide/workflow.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/index.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/naming-rules.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/docs/reference/cli.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/issues/cross-disc-dvdcompare-matching.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/mkdocs.yml +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/plex_naming_rules.md +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/pyproject.toml +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/setup.cfg +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/cache.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/config.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/dedup.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/detect.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/disc/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/disc/analysis.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/disc/makemkv.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/disc/provider.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/formatter.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/lookup.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/manifest.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/matcher.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/metadata/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/metadata/planner.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/metadata/provider.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/metadata/sources/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/metadata/sources/tmdb.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/models.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/normalize.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/organizer.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/scanner.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/snapshot.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/splitter.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/tagger.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/title.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex/ui.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex.egg-info/SOURCES.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex.egg-info/dependency_links.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex.egg-info/entry_points.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex.egg-info/requires.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex.egg-info/top_level.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/main.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/disc_detection.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/done.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/folder_picker.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/metadata.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/organize_done.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/organize_preview.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/progress.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/release.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/screens/selection.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_app/updater.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/lookup.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/orchestrate.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/organize.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/rip.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/commands/setup.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/formatting.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/src/riplex_cli/main.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/__init__.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/fixtures/makemkvcon_frozen_planet_ii_d2.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/fixtures/makemkvcon_list.txt +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/Batman Begins.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/Blade Runner (Blu-ray 4k).snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/Blade Runner The Final Cut.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/Seven Worlds One Planet.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/The Dark Knight Rises.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/The Dark Knight.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/snapshots/Waterworld.snapshot.json +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_cache.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_cli_utils.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_config.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_dedup.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_detect.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_disc_analysis.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_disc_provider.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_formatter.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_makemkv.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_matcher.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_normalize.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_organizer.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_planner.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_rip_guide.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_scanner.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_snapshot.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_splitter.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_tagger.py +0 -0
- {riplex-0.2.4 → riplex-0.2.5}/tests/test_ui.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
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
|
|
@@ -19,7 +19,7 @@ Requires-Dist: flet>=0.84; extra == "gui"
|
|
|
19
19
|
|
|
20
20
|
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.
|
|
21
21
|
|
|
22
|
-
## Desktop App
|
|
22
|
+
## Desktop App
|
|
23
23
|
|
|
24
24
|
If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
|
|
25
25
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
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.
|
|
4
4
|
|
|
5
|
-
## Desktop App
|
|
5
|
+
## Desktop App
|
|
6
6
|
|
|
7
7
|
If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
|
|
8
8
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
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
|
|
@@ -19,7 +19,7 @@ Requires-Dist: flet>=0.84; extra == "gui"
|
|
|
19
19
|
|
|
20
20
|
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.
|
|
21
21
|
|
|
22
|
-
## Desktop App
|
|
22
|
+
## Desktop App
|
|
23
23
|
|
|
24
24
|
If you'd rather use a simple graphical interface instead of the command line, download the pre-built app from the [Releases page](https://github.com/AnyCredit5518/riplex/releases/latest):
|
|
25
25
|
|
|
@@ -31,6 +31,14 @@ class WelcomeScreen:
|
|
|
31
31
|
("mkvmerge", has_mkvmerge),
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
+
missing_tools = []
|
|
35
|
+
if not has_makemkv:
|
|
36
|
+
missing_tools.append("makemkvcon")
|
|
37
|
+
if not has_ffprobe:
|
|
38
|
+
missing_tools.append("ffprobe")
|
|
39
|
+
if not has_mkvmerge:
|
|
40
|
+
missing_tools.append("mkvmerge")
|
|
41
|
+
|
|
34
42
|
status_rows = []
|
|
35
43
|
for label, ok in checks:
|
|
36
44
|
icon = ft.Icon(ft.Icons.CHECK_CIRCLE, color=ft.Colors.GREEN) if ok else ft.Icon(ft.Icons.ERROR, color=ft.Colors.RED)
|
|
@@ -38,6 +46,41 @@ class WelcomeScreen:
|
|
|
38
46
|
ft.Row([icon, ft.Text(label, size=14)], spacing=8)
|
|
39
47
|
)
|
|
40
48
|
|
|
49
|
+
# Install tools section (shown when tools are missing)
|
|
50
|
+
self._install_status = ft.Text("", size=12, color=ft.Colors.GREY_400)
|
|
51
|
+
install_section = ft.Container(
|
|
52
|
+
ft.Column([
|
|
53
|
+
ft.Text(
|
|
54
|
+
"Some tools are missing. Click below to install them automatically, "
|
|
55
|
+
"or use the links to download manually.",
|
|
56
|
+
size=13,
|
|
57
|
+
color=ft.Colors.ORANGE,
|
|
58
|
+
),
|
|
59
|
+
ft.Container(height=4),
|
|
60
|
+
ft.Row([
|
|
61
|
+
ft.ElevatedButton(
|
|
62
|
+
"Install Missing Tools",
|
|
63
|
+
icon=ft.Icons.DOWNLOAD,
|
|
64
|
+
on_click=lambda _: self._install_tools(missing_tools),
|
|
65
|
+
),
|
|
66
|
+
ft.TextButton(
|
|
67
|
+
"MakeMKV ↗",
|
|
68
|
+
url="https://www.makemkv.com/download/",
|
|
69
|
+
),
|
|
70
|
+
ft.TextButton(
|
|
71
|
+
"FFmpeg ↗",
|
|
72
|
+
url="https://ffmpeg.org/download.html",
|
|
73
|
+
),
|
|
74
|
+
ft.TextButton(
|
|
75
|
+
"MKVToolNix ↗",
|
|
76
|
+
url="https://mkvtoolnix.download/downloads.html",
|
|
77
|
+
),
|
|
78
|
+
], spacing=8, wrap=True),
|
|
79
|
+
self._install_status,
|
|
80
|
+
], spacing=4),
|
|
81
|
+
visible=bool(missing_tools),
|
|
82
|
+
)
|
|
83
|
+
|
|
41
84
|
# Rip requires all tools; organize only needs ffprobe + config
|
|
42
85
|
can_rip = all(ok for _, ok in checks)
|
|
43
86
|
can_organize = has_config and has_ffprobe
|
|
@@ -123,15 +166,6 @@ class WelcomeScreen:
|
|
|
123
166
|
visible=not has_config,
|
|
124
167
|
)
|
|
125
168
|
|
|
126
|
-
# Tool warning
|
|
127
|
-
tool_warning = ft.Container(
|
|
128
|
-
ft.Text(
|
|
129
|
-
"Some required tools are missing. Install them and restart the app.",
|
|
130
|
-
color=ft.Colors.ORANGE,
|
|
131
|
-
),
|
|
132
|
-
visible=not can_rip and has_config,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
169
|
# Workflow buttons
|
|
136
170
|
rip_button = ft.ElevatedButton(
|
|
137
171
|
"Rip Disc",
|
|
@@ -191,9 +225,9 @@ class WelcomeScreen:
|
|
|
191
225
|
ft.Container(height=5),
|
|
192
226
|
ft.Text("Status", size=18, weight=ft.FontWeight.BOLD),
|
|
193
227
|
ft.Column(status_rows, spacing=4),
|
|
228
|
+
install_section,
|
|
194
229
|
ft.Container(height=10),
|
|
195
230
|
setup_section,
|
|
196
|
-
tool_warning,
|
|
197
231
|
ft.Container(expand=True),
|
|
198
232
|
ft.Text("What would you like to do?", size=16, weight=ft.FontWeight.BOLD),
|
|
199
233
|
ft.Row([rip_button, organize_button], spacing=20),
|
|
@@ -250,6 +284,54 @@ class WelcomeScreen:
|
|
|
250
284
|
url = get_download_url(self._update_info)
|
|
251
285
|
webbrowser.open(url)
|
|
252
286
|
|
|
287
|
+
def _install_tools(self, missing: list[str]):
|
|
288
|
+
"""Install missing tools via system package manager in background."""
|
|
289
|
+
import platform
|
|
290
|
+
import subprocess
|
|
291
|
+
import sys
|
|
292
|
+
|
|
293
|
+
system = platform.system()
|
|
294
|
+
packages = {
|
|
295
|
+
"Windows": {"makemkvcon": "MakeMKV.MakeMKV", "ffprobe": "Gyan.FFmpeg", "mkvmerge": "MKVToolNix.MKVToolNix"},
|
|
296
|
+
"Darwin": {"makemkvcon": "makemkv", "ffprobe": "ffmpeg", "mkvmerge": "mkvtoolnix"},
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
pkg_map = packages.get(system, {})
|
|
300
|
+
to_install = sorted(set(pkg_map[t] for t in missing if pkg_map.get(t)))
|
|
301
|
+
if not to_install:
|
|
302
|
+
self._install_status.value = "Auto-install not supported on this platform. Use the links above."
|
|
303
|
+
self.app.page.update()
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
def _do_install():
|
|
307
|
+
async def _update_status(msg):
|
|
308
|
+
self._install_status.value = msg
|
|
309
|
+
self.app.page.update()
|
|
310
|
+
|
|
311
|
+
try:
|
|
312
|
+
if system == "Windows":
|
|
313
|
+
for pkg in to_install:
|
|
314
|
+
self.app.page.run_task(lambda p=pkg: _update_status(f"Installing {p}..."))
|
|
315
|
+
subprocess.run(
|
|
316
|
+
["winget", "install", "--accept-source-agreements",
|
|
317
|
+
"--accept-package-agreements", pkg],
|
|
318
|
+
check=True,
|
|
319
|
+
creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
|
|
320
|
+
)
|
|
321
|
+
elif system == "Darwin":
|
|
322
|
+
self.app.page.run_task(lambda: _update_status("Installing via brew..."))
|
|
323
|
+
subprocess.run(["brew", "install"] + to_install, check=True)
|
|
324
|
+
|
|
325
|
+
self.app.page.run_task(
|
|
326
|
+
lambda: _update_status("Done! Restart the app for changes to take effect.")
|
|
327
|
+
)
|
|
328
|
+
except (subprocess.CalledProcessError, FileNotFoundError) as exc:
|
|
329
|
+
self.app.page.run_task(
|
|
330
|
+
lambda: _update_status(f"Install failed: {exc}. Try the manual links above.")
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
threading.Thread(target=_do_install, daemon=True).start()
|
|
334
|
+
|
|
253
335
|
def _save_config(self, e):
|
|
254
336
|
"""Write config from the setup fields."""
|
|
255
337
|
from riplex.config import save_config
|
|
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
|