riplex 1.0.1__tar.gz → 1.0.2__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-1.0.1/src/riplex.egg-info → riplex-1.0.2}/PKG-INFO +1 -1
- {riplex-1.0.1 → riplex-1.0.2}/docs/changelog.md +10 -0
- riplex-1.0.2/issues/organize-preview-match-override.md +87 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/organizer.py +29 -0
- {riplex-1.0.1 → riplex-1.0.2/src/riplex.egg-info}/PKG-INFO +1 -1
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/SOURCES.txt +1 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/scm_file_list.json +1 -0
- riplex-1.0.2/src/riplex.egg-info/scm_version.json +8 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/organize_preview.py +22 -1
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_organizer.py +99 -0
- riplex-1.0.1/src/riplex.egg-info/scm_version.json +0 -8
- {riplex-1.0.1 → riplex-1.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/ISSUE_TEMPLATE/crash_report.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/agents/riplex.agent.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/contributors-overrides.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/copilot-instructions.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/workflows/publish.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/workflows/release.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.github/workflows/update-contributors.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.gitignore +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/.vscode/settings.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/CONTRIBUTORS.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/LICENSE +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/README.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/RELEASE_NOTES_v1.0.0.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/architecture.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/cli-guide/lookup.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/cli-guide/orchestrate.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/cli-guide/organize.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/cli-guide/workflow.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/development/testing.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/getting-started/configuration.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/getting-started/installation.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/gui-guide/gui-walkthrough.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/index.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/naming-rules.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/reference/cli.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/docs/troubleshooting.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/issues/debug-artifacts-consolidation.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/issues/manual-rip-and-organize-escape-hatch.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/issues/one-season-at-a-time.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/issues/orchestrate-dvdcompare-fallback.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/issues/planned-features.md +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/mkdocs.yml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/pyproject.toml +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/0_Rip_Flow_BTTF.gif +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/1_Welcome_Screen.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/2_Disc_Detection_BTTF.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/3_Metadata_Lookup_BTTF.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/4_Disc_Release_BTTF.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/5_Multi_Disc_Overview_BTTF.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/screenshots/5_Select_Title_to_RIP_BTTF.png +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/scripts/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/scripts/gen_gui_fixtures.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/scripts/update_contributors.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/setup.cfg +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/cache.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/config.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/dedup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/detect.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/disc/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/disc/analysis.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/disc/makemkv.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/disc/provider.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/formatter.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/lookup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/manifest.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/matcher.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/autosearch.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/planner.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/provider.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/sources/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/metadata/sources/tmdb.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/models.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/normalize.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/organize_by_group.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/resume.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/scanner.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/snapshot.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/splitter.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/tagger.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/title.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/ui.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex/updater.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/dependency_links.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/entry_points.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/requires.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex.egg-info/top_level.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/bug_report.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/crash_dump.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/keep_awake.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/main.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/disc_detection.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/disc_overview.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/disc_swap.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/done.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/folder_picker.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/metadata.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/orchestrate_done.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/organize_done.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/progress.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/release.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/season_select.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/selection.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/update.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_app/screens/welcome.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/lookup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/orchestrate.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/organize.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/rip.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/commands/setup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/formatting.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/src/riplex_cli/main.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/conftest.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/chernobyl_disc1.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/2001-a-space-odyssey-1968.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/akira-1988.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/back-to-the-future-1985.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/back-to-the-future-part-ii-1989.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/back-to-the-future-part-iii-1990.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/blade-1998.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/blade-runner-2049-2017.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/chernobyl-2019.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/d-day-normandy-1944-2014.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/final-destination-bloodlines-2025.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/flight-of-the-butterflies-2012.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/inception-2010.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/independence-day-1996.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/journey-to-space-2015.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/journey-to-the-south-pacific-2013.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/jurassic-park-1993.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/king-kong-2005.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/mad-max-fury-road-2015.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/march-of-the-penguins-2005.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/national-parks-adventure-2016.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/oceans-our-blue-planet-2018.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/psych-season-01.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/psych-season-03.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/psych-season-04.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/psych-the-movie-2017.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/space-station-3d-2002.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-godfather-1972.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-last-reef-cities-beneath-the-sea-2012.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-matrix-1999.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-matrix-reloaded-2003.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-mummy-1999.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-mummy-returns-2001.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-mummy-tomb-of-the-dragon-emperor-2008.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-patriot-2000.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/the-thing-1982.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/gui/scenarios/wonders-of-the-arctic-2014.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/makemkvcon_frozen_planet_ii_d2.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/fixtures/makemkvcon_list.txt +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/conftest.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_cli_lookup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_cli_organize.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_cli_parser.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_fixture_scenarios.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_errors.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_media_types.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_movie_orchestrate.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_organize.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_resume_prefill.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_tv_orchestrate.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_flow_welcome.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/integration/test_screen_build_smoke.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/Batman Begins.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/Blade Runner (Blu-ray 4k).snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/Blade Runner The Final Cut.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/Seven Worlds One Planet.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/The Dark Knight Rises.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/The Dark Knight.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/snapshots/Waterworld.snapshot.json +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/__init__.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/cli.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/driver.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/fake_page.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/fixtures.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/provider_mocks.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/support/sync_runtime.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_app_main.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_autosearch.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_cache.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_cli_utils.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_config.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_dedup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_detect.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_disc_analysis.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_disc_detection_screen.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_disc_fixtures.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_disc_provider.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_folder_picker.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_formatter.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_lookup.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_lookup_resolve_groups.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_makemkv.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_manifest_prefill_ids.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_manifest_session.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_matcher.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_metadata_screen.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_normalize.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_organize_by_group.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_organize_cli.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_organize_session_fanout.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_planner.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_progress.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_release_screen.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_resume.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_rip_guide.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_scanner.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_season_select_screen.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_snapshot.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_splitter.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_tagger.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_tmdb_provider.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_ui.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_update_contributors.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_updater.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_updater_selfupdate.py +0 -0
- {riplex-1.0.1 → riplex-1.0.2}/tests/test_welcome_screen.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
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
|
|
@@ -8,6 +8,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
8
8
|
|
|
9
9
|
### Fixed
|
|
10
10
|
|
|
11
|
+
- **TV episodes with parenthetical titles (or filed under extras) no longer land in `Other/`.** When organizing a TV rip, the destination is now chosen from the authoritative `SxxEyy` classification recorded in each disc's rip manifest at rip time, taking priority over the re-derived dvdcompare match label. Previously an episode whose title contains a parenthetical (e.g. *Shawn and Gus in Drag (Racing)*), or one that dvdcompare files under a disc's extras (e.g. an *(Extended Version)* listing such as *Romeo and Juliet and Juliet* or *Dual Spires*), was misread as an extra and dropped into `Other/` instead of its season folder — even though orchestrate had already classified it correctly (e.g. Psych S5 E01/E05/E12).
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Durations on the organize preview.** Each matched file now shows its runtime next to the matched episode/target's expected runtime; a divergence of more than a minute is highlighted so an incorrect match is easy to spot before you execute.
|
|
16
|
+
|
|
17
|
+
## v1.0.1 — 2026-07-20
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
11
21
|
- **Out-of-order episode matching.** When dvdcompare files an “(Extended Version)” of an episode under a disc's *extras*, TMDb enrichment promotes it to an episode but leaves it positioned after the real episode list, so the episode entries arrive out of broadcast order. Positional episode alignment now sorts episodes by their canonical `SxxEyy` number before matching disc titles, so a disc whose titles are in broadcast order maps correctly. Previously the misordered list could orphan a title to a generic “Episode” label and shift the following episodes by one (e.g. Psych S6 D3).
|
|
12
22
|
|
|
13
23
|
## v1.0.0 — 2026-07-18
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# GUI: override a wrong match on the organize preview
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
The organize preview is the last checkpoint before files are moved into Plex
|
|
6
|
+
layout, but it is read-only. When the user spots a wrong match there — a title
|
|
7
|
+
routed to the wrong episode, an episode dropped into `Other/`, an extra
|
|
8
|
+
mislabeled — they have **no recourse**. Their only options are to execute a
|
|
9
|
+
plan they know is wrong, or go back and re-rip / re-pick metadata, neither of
|
|
10
|
+
which fixes a single bad row.
|
|
11
|
+
|
|
12
|
+
We hit this with Psych S5: three episodes with parenthetical titles or filed
|
|
13
|
+
by dvdcompare under a disc's extras (`Shawn and Gus in Drag (Racing)`,
|
|
14
|
+
`Romeo and Juliet and Juliet`, `Dual Spires`) landed in `Other/`. The
|
|
15
|
+
underlying misclassification is now fixed (organize honors the rip-time
|
|
16
|
+
`SxxEyy` classification from the manifest), and the new duration columns on
|
|
17
|
+
the preview make a bad match visible — but "visible" still isn't "fixable."
|
|
18
|
+
|
|
19
|
+
## Goal
|
|
20
|
+
|
|
21
|
+
Let the user correct an individual row on the organize preview before
|
|
22
|
+
executing, without leaving the screen or re-running the whole flow.
|
|
23
|
+
|
|
24
|
+
## Proposed UX
|
|
25
|
+
|
|
26
|
+
Each matched / unmatched / (optionally) split row gets an **Edit** affordance
|
|
27
|
+
(pencil icon or click-to-expand). Activating it opens an inline picker for
|
|
28
|
+
that one file:
|
|
29
|
+
|
|
30
|
+
- **Target dropdown** populated from the current plan:
|
|
31
|
+
- Each episode in the resolved `PlannedShow` (`S05E05 - Shawn and Gus in
|
|
32
|
+
Drag (Racket)`), grouped by season.
|
|
33
|
+
- The movie main feature / editions for a `PlannedMovie`.
|
|
34
|
+
- Extras folders: `Featurettes`, `Behind The Scenes`, `Deleted Scenes`,
|
|
35
|
+
`Interviews`, `Trailers`, `Shorts`, `Other`.
|
|
36
|
+
- `Skip (leave unmatched)`.
|
|
37
|
+
- The dropdown defaults to the current assignment and shows each option's
|
|
38
|
+
expected runtime next to the file's runtime (reuse the duration formatting
|
|
39
|
+
just added), so the correct episode is easy to pick.
|
|
40
|
+
- Confirming rebuilds just that row's destination and re-renders the preview
|
|
41
|
+
(updating the summary counts). No other rows are recomputed.
|
|
42
|
+
|
|
43
|
+
## Where the logic lives (CLI/GUI parity)
|
|
44
|
+
|
|
45
|
+
Per `.github/copilot-instructions.md`, the override resolution must be a plain
|
|
46
|
+
function in `src/riplex/`, not GUI code. Sketch:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
# src/riplex/organizer.py (or a new override.py)
|
|
50
|
+
def apply_move_override(
|
|
51
|
+
plan: OrganizePlan,
|
|
52
|
+
source_path: str,
|
|
53
|
+
target: MoveOverride, # episode (s,e) | movie edition | extras folder | skip
|
|
54
|
+
planned: PlannedMovie | PlannedShow,
|
|
55
|
+
output_root: Path,
|
|
56
|
+
) -> OrganizePlan:
|
|
57
|
+
"""Return a new OrganizePlan with the one file re-routed per `target`."""
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The GUI preview becomes a thin caller (`state[...] = apply_move_override(...)`
|
|
61
|
+
then re-render); a future CLI `--fix FILE=TARGET` flag could call the same
|
|
62
|
+
function. Destination computation should reuse `_compute_destination` / the
|
|
63
|
+
episode + extras-folder helpers rather than duplicating path logic.
|
|
64
|
+
|
|
65
|
+
## Scope / decisions to settle
|
|
66
|
+
|
|
67
|
+
- **Persistence:** session-only (re-route affects just this execute), or write
|
|
68
|
+
the corrected `SxxEyy` back into the file's `_rip_manifest.json` so a later
|
|
69
|
+
re-organize keeps the fix? Recommend session-only first; manifest write-back
|
|
70
|
+
is a follow-up.
|
|
71
|
+
- **Split rows:** overriding a chapter-split move is more complex (N
|
|
72
|
+
destinations). Start with matched + unmatched single-file rows; leave split
|
|
73
|
+
overrides out of v1.
|
|
74
|
+
- **Validation:** picking an episode that another row already claims should
|
|
75
|
+
warn (duplicate destination) but not hard-block — the user may be fixing a
|
|
76
|
+
swap and will correct the other row next.
|
|
77
|
+
- **Testing:** unit-test `apply_move_override` in `tests/test_organizer.py`
|
|
78
|
+
(episode re-route, extras re-route, skip). Drive the picker end to end in the
|
|
79
|
+
GUI integration harness (`tests/support/`), asserting the summary counts and
|
|
80
|
+
the corrected destination.
|
|
81
|
+
|
|
82
|
+
## Related
|
|
83
|
+
|
|
84
|
+
- Fixed: organize honors rip-time `SxxEyy` classification over the dvdcompare
|
|
85
|
+
label (Psych S5 E01/E05/E12 → `Other/`).
|
|
86
|
+
- Added: source + target durations on the organize preview (highlights
|
|
87
|
+
mismatches), which pairs naturally with this override picker.
|
|
@@ -152,6 +152,8 @@ class FileMove:
|
|
|
152
152
|
label: str # what this file was matched to
|
|
153
153
|
confidence: str
|
|
154
154
|
delta_seconds: int = 0 # |file_runtime - target_runtime|, for diagnostics
|
|
155
|
+
file_duration_seconds: int = 0 # source file runtime, for preview display
|
|
156
|
+
target_runtime_seconds: int = 0 # matched target runtime, for preview display
|
|
155
157
|
|
|
156
158
|
|
|
157
159
|
@dataclass
|
|
@@ -532,6 +534,8 @@ def build_organize_plan(
|
|
|
532
534
|
label=candidate.matched_label,
|
|
533
535
|
confidence=candidate.confidence,
|
|
534
536
|
delta_seconds=candidate.delta_seconds,
|
|
537
|
+
file_duration_seconds=candidate.file_duration_seconds,
|
|
538
|
+
target_runtime_seconds=candidate.matched_runtime_seconds,
|
|
535
539
|
)
|
|
536
540
|
)
|
|
537
541
|
|
|
@@ -565,6 +569,7 @@ def build_organize_plan(
|
|
|
565
569
|
destination=str(dest),
|
|
566
570
|
label=f"(unmatched extra) {f.name}",
|
|
567
571
|
confidence="none",
|
|
572
|
+
file_duration_seconds=f.duration_seconds,
|
|
568
573
|
)
|
|
569
574
|
)
|
|
570
575
|
else:
|
|
@@ -595,6 +600,30 @@ def _compute_destination(
|
|
|
595
600
|
label = candidate.matched_label
|
|
596
601
|
log.debug("_compute_destination: label='%s'", label)
|
|
597
602
|
|
|
603
|
+
# SE-first: the rip-time classification is authoritative. When the
|
|
604
|
+
# classifier tagged this file with a TMDb-enriched "SxxEyy - Title"
|
|
605
|
+
# prefix (recorded in the manifest at rip time), route directly by
|
|
606
|
+
# (season, episode) — before consulting the dvdcompare match label.
|
|
607
|
+
# The label loses episode identity when the episode title carries a
|
|
608
|
+
# parenthetical (e.g. "Shawn and Gus in Drag (Racing)", which the
|
|
609
|
+
# feature-type branch below mistakes for an extra) or when dvdcompare
|
|
610
|
+
# files the episode under a disc's extras (e.g. an "(Extended
|
|
611
|
+
# Version)" listing). Honoring the manifest avoids re-deriving — and
|
|
612
|
+
# mis-deriving — a match that was already correct at rip time.
|
|
613
|
+
if isinstance(plan, PlannedShow):
|
|
614
|
+
se_ep = _episode_from_classification_se(plan, candidate.classification)
|
|
615
|
+
if se_ep is not None:
|
|
616
|
+
fname = episode_file_name(
|
|
617
|
+
plan.canonical_title, plan.year,
|
|
618
|
+
se_ep.season_number, se_ep.episode_number, se_ep.title,
|
|
619
|
+
)
|
|
620
|
+
dest = base / season_folder_name(se_ep.season_number) / fname
|
|
621
|
+
log.debug(
|
|
622
|
+
" -> episode by SE-in-classification '%s' (pre-label): %s",
|
|
623
|
+
candidate.classification, dest,
|
|
624
|
+
)
|
|
625
|
+
return dest
|
|
626
|
+
|
|
598
627
|
# Movie main file
|
|
599
628
|
if "(movie)" in label:
|
|
600
629
|
edition = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riplex
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
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
|
|
@@ -32,6 +32,7 @@ issues/debug-artifacts-consolidation.md
|
|
|
32
32
|
issues/manual-rip-and-organize-escape-hatch.md
|
|
33
33
|
issues/one-season-at-a-time.md
|
|
34
34
|
issues/orchestrate-dvdcompare-fallback.md
|
|
35
|
+
issues/organize-preview-match-override.md
|
|
35
36
|
issues/planned-features.md
|
|
36
37
|
screenshots/0_Rip_Flow_BTTF.gif
|
|
37
38
|
screenshots/1_Welcome_Screen.png
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"issues/one-season-at-a-time.md",
|
|
93
93
|
"issues/debug-artifacts-consolidation.md",
|
|
94
94
|
"issues/planned-features.md",
|
|
95
|
+
"issues/organize-preview-match-override.md",
|
|
95
96
|
"tests/test_organize_cli.py",
|
|
96
97
|
"tests/test_formatter.py",
|
|
97
98
|
"tests/test_metadata_screen.py",
|
|
@@ -19,6 +19,16 @@ from riplex.snapshot import save_from_scanned, save_organized_marker
|
|
|
19
19
|
log = logging.getLogger(__name__)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _fmt_duration(seconds: int) -> str:
|
|
23
|
+
"""Format seconds as ``m:ss`` (or ``h:mm:ss`` for hour-plus runtimes)."""
|
|
24
|
+
seconds = int(seconds or 0)
|
|
25
|
+
h, rem = divmod(seconds, 3600)
|
|
26
|
+
m, s = divmod(rem, 60)
|
|
27
|
+
if h:
|
|
28
|
+
return f"{h}:{m:02d}:{s:02d}"
|
|
29
|
+
return f"{m}:{s:02d}"
|
|
30
|
+
|
|
31
|
+
|
|
22
32
|
class OrganizePreviewScreen:
|
|
23
33
|
def __init__(self, app):
|
|
24
34
|
self.app = app
|
|
@@ -282,13 +292,24 @@ class OrganizePreviewScreen:
|
|
|
282
292
|
padding=ft.Padding(left=6, right=6, top=2, bottom=2),
|
|
283
293
|
border_radius=4,
|
|
284
294
|
)
|
|
295
|
+
# Durations make a bad match obvious at a glance: the source
|
|
296
|
+
# file's runtime beside the matched target's expected runtime,
|
|
297
|
+
# highlighted when they diverge by more than a minute.
|
|
298
|
+
file_dur = getattr(move, "file_duration_seconds", 0)
|
|
299
|
+
tgt_dur = getattr(move, "target_runtime_seconds", 0)
|
|
300
|
+
dur_mismatch = tgt_dur > 0 and abs(file_dur - tgt_dur) > 60
|
|
301
|
+
dur_color = ft.Colors.ORANGE if dur_mismatch else ft.Colors.GREY_500
|
|
302
|
+
src_dur_text = _fmt_duration(file_dur) if file_dur else ""
|
|
303
|
+
tgt_dur_text = f"({_fmt_duration(tgt_dur)})" if tgt_dur else ""
|
|
285
304
|
move_rows.append(
|
|
286
305
|
ft.Row([
|
|
287
306
|
ft.Icon(ft.Icons.CHECK_CIRCLE, color=conf_color, size=16),
|
|
288
307
|
conf_chip,
|
|
289
|
-
ft.Text(f"{src_name}", size=12, width=
|
|
308
|
+
ft.Text(f"{src_name}", size=12, width=180, no_wrap=True),
|
|
309
|
+
ft.Text(src_dur_text, size=11, width=54, no_wrap=True, color=dur_color),
|
|
290
310
|
ft.Icon(ft.Icons.ARROW_FORWARD, size=14, color=ft.Colors.GREY_500),
|
|
291
311
|
ft.Text(f"{dest_folder}/{dest_name}", size=12, expand=True, no_wrap=True),
|
|
312
|
+
ft.Text(tgt_dur_text, size=11, no_wrap=True, color=dur_color),
|
|
292
313
|
], spacing=6)
|
|
293
314
|
)
|
|
294
315
|
|
|
@@ -504,6 +504,39 @@ class TestBuildOrganizePlanShow:
|
|
|
504
504
|
assert "TV Shows" in dest
|
|
505
505
|
assert "Planet Earth III (2023) - s01e01 - Coasts.mkv" in dest
|
|
506
506
|
|
|
507
|
+
def test_move_carries_file_and_target_durations(self):
|
|
508
|
+
"""The preview surfaces duration mismatches, so each FileMove
|
|
509
|
+
must carry both the source file's runtime and the matched
|
|
510
|
+
target's expected runtime."""
|
|
511
|
+
result = OrganizeResult(
|
|
512
|
+
matched=[
|
|
513
|
+
MatchCandidate(
|
|
514
|
+
file_name="d1_t00.mkv",
|
|
515
|
+
file_duration_seconds=3141,
|
|
516
|
+
matched_label="Disc 1: Coasts",
|
|
517
|
+
matched_runtime_seconds=3120,
|
|
518
|
+
delta_seconds=21,
|
|
519
|
+
confidence="high",
|
|
520
|
+
),
|
|
521
|
+
],
|
|
522
|
+
)
|
|
523
|
+
plan = PlannedShow(
|
|
524
|
+
canonical_title="Planet Earth III",
|
|
525
|
+
year=2023,
|
|
526
|
+
seasons=[
|
|
527
|
+
PlannedSeason(
|
|
528
|
+
season_number=1,
|
|
529
|
+
episodes=[
|
|
530
|
+
PlannedEpisode(season_number=1, episode_number=1, title="Coasts", runtime="52m"),
|
|
531
|
+
],
|
|
532
|
+
),
|
|
533
|
+
],
|
|
534
|
+
)
|
|
535
|
+
op = build_organize_plan(result, plan, Path("E:/Media"))
|
|
536
|
+
assert len(op.moves) == 1
|
|
537
|
+
assert op.moves[0].file_duration_seconds == 3141
|
|
538
|
+
assert op.moves[0].target_runtime_seconds == 3120
|
|
539
|
+
|
|
507
540
|
def test_tv_episode_disc_label_no_tmdb_match_is_unmatched(self):
|
|
508
541
|
"""Episode not in TMDb data is treated as unmatched."""
|
|
509
542
|
result = OrganizeResult(
|
|
@@ -586,6 +619,72 @@ class TestBuildOrganizePlanShow:
|
|
|
586
619
|
assert len(op.moves) == 1
|
|
587
620
|
assert "Trailers" in op.moves[0].destination
|
|
588
621
|
|
|
622
|
+
def test_tv_episode_with_parenthetical_title_routes_by_se_classification(self):
|
|
623
|
+
"""Psych S5: an episode whose *title* contains a parenthetical
|
|
624
|
+
(``Shawn and Gus in Drag (Racing)``) — or an episode dvdcompare
|
|
625
|
+
files under a disc's extras (``Romeo and Juliet and Juliet
|
|
626
|
+
(Extended Version)``, ``Dual Spires (Extended Version)``) — must
|
|
627
|
+
still route to its Plex episode path. The dvdcompare match label
|
|
628
|
+
looks like an extra (trailing parenthetical), so the pre-fix code
|
|
629
|
+
sent these to ``Other/``. The rip-time ``SxxEyy`` classification
|
|
630
|
+
recorded in the manifest is authoritative and now wins.
|
|
631
|
+
"""
|
|
632
|
+
result = OrganizeResult(
|
|
633
|
+
matched=[
|
|
634
|
+
MatchCandidate(
|
|
635
|
+
file_name="C1_t00.mkv",
|
|
636
|
+
file_duration_seconds=2585,
|
|
637
|
+
matched_label="Disc 2: Shawn and Gus in Drag (Racing)",
|
|
638
|
+
matched_runtime_seconds=2590,
|
|
639
|
+
delta_seconds=5,
|
|
640
|
+
confidence="high",
|
|
641
|
+
classification="S05E05 - Shawn and Gus in Drag (Racing) (1080p)",
|
|
642
|
+
),
|
|
643
|
+
MatchCandidate(
|
|
644
|
+
file_name="C1_t00.mkv",
|
|
645
|
+
file_duration_seconds=2894,
|
|
646
|
+
matched_label="Disc 1: Romeo and Juliet and Juliet ((Extended Version))",
|
|
647
|
+
matched_runtime_seconds=2898,
|
|
648
|
+
delta_seconds=4,
|
|
649
|
+
confidence="high",
|
|
650
|
+
classification="S05E01 - Romeo and Juliet and Juliet (1080p)",
|
|
651
|
+
),
|
|
652
|
+
MatchCandidate(
|
|
653
|
+
file_name="D2_t03.mkv",
|
|
654
|
+
file_duration_seconds=3275,
|
|
655
|
+
matched_label="Disc 3: Dual Spires ((Extended Version))",
|
|
656
|
+
matched_runtime_seconds=3279,
|
|
657
|
+
delta_seconds=4,
|
|
658
|
+
confidence="high",
|
|
659
|
+
classification="S05E12 - Dual Spires (1080p)",
|
|
660
|
+
),
|
|
661
|
+
],
|
|
662
|
+
)
|
|
663
|
+
plan = PlannedShow(
|
|
664
|
+
canonical_title="Psych",
|
|
665
|
+
year=2006,
|
|
666
|
+
seasons=[
|
|
667
|
+
PlannedSeason(
|
|
668
|
+
season_number=5,
|
|
669
|
+
episodes=[
|
|
670
|
+
PlannedEpisode(season_number=5, episode_number=1, title="Romeo and Juliet and Juliet", runtime="48m"),
|
|
671
|
+
PlannedEpisode(season_number=5, episode_number=5, title="Shawn and Gus in Drag (Racket)", runtime="43m"),
|
|
672
|
+
PlannedEpisode(season_number=5, episode_number=12, title="Dual Spires", runtime="54m"),
|
|
673
|
+
],
|
|
674
|
+
),
|
|
675
|
+
],
|
|
676
|
+
)
|
|
677
|
+
output = Path("E:/Media")
|
|
678
|
+
op = build_organize_plan(result, plan, output)
|
|
679
|
+
dests = sorted(m.destination for m in op.moves)
|
|
680
|
+
assert len(op.moves) == 3
|
|
681
|
+
# None land in Other/.
|
|
682
|
+
assert all("Other" not in d for d in dests)
|
|
683
|
+
assert all("Season 05" in d for d in dests)
|
|
684
|
+
assert any(d.endswith("s05e01 - Romeo and Juliet and Juliet.mkv") for d in dests)
|
|
685
|
+
assert any(d.endswith("s05e05 - Shawn and Gus in Drag (Racket).mkv") for d in dests)
|
|
686
|
+
assert any(d.endswith("s05e12 - Dual Spires.mkv") for d in dests)
|
|
687
|
+
|
|
589
688
|
def test_tv_episode_fuzzy_title_match(self):
|
|
590
689
|
"""dvdcompare titles diverging from TMDb still route correctly.
|
|
591
690
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|