diff --git a/api/funkwhale_api/music/factories.py b/api/funkwhale_api/music/factories.py index 2dd4ba3038593cc2bb2c60610735caeb7f61bc8f..c8f4bf322dbb6be91383f022e52f5e027a096714 100644 --- a/api/funkwhale_api/music/factories.py +++ b/api/funkwhale_api/music/factories.py @@ -89,6 +89,7 @@ class ImportJobFactory(factory.django.DjangoModelFactory): batch = factory.SubFactory(ImportBatchFactory) source = factory.Faker("url") mbid = factory.Faker("uuid4") + replace_if_duplicate = factory.Faker("boolean") class Meta: model = "music.ImportJob" diff --git a/api/funkwhale_api/providers/audiofile/management/commands/import_files.py b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py index c3fabd7f6eae4cf9681f1b9c180a4e37c986e0a1..b59c0046fa154e2e8f8c1e62aba6ce283416e232 100644 --- a/api/funkwhale_api/providers/audiofile/management/commands/import_files.py +++ b/api/funkwhale_api/providers/audiofile/management/commands/import_files.py @@ -214,7 +214,9 @@ class Command(BaseCommand): return batch, errors def import_file(self, path, batch, import_handler, options): - job = batch.jobs.create(source="file://" + path) + job = batch.jobs.create( + source="file://" + path, replace_if_duplicate=options["replace"] + ) if not options["in_place"]: name = os.path.basename(path) with open(path, "rb") as f: diff --git a/api/tests/music/test_tasks.py b/api/tests/music/test_tasks.py index 71d605b2b3768ab7b5dafa73738c0d4fb5af8c2d..e91594d4727146c45f7cc36123c406e4524a8f5d 100644 --- a/api/tests/music/test_tasks.py +++ b/api/tests/music/test_tasks.py @@ -118,7 +118,7 @@ def test_run_import_skipping_accoustid(factories, mocker): path = os.path.join(DATA_DIR, "test.ogg") job = factories["music.FileImportJob"](audio_file__path=path) tasks.import_job_run(import_job_id=job.pk, use_acoustid=False) - m.assert_called_once_with(job, False, use_acoustid=False) + m.assert_called_once_with(job, use_acoustid=False) def test__do_import_skipping_accoustid(factories, mocker): @@ -130,7 +130,7 @@ def test__do_import_skipping_accoustid(factories, mocker): path = os.path.join(DATA_DIR, "test.ogg") job = factories["music.FileImportJob"](mbid=None, audio_file__path=path) p = job.audio_file.path - tasks._do_import(job, replace=False, use_acoustid=False) + tasks._do_import(job, use_acoustid=False) m.assert_called_once_with(p) @@ -144,10 +144,27 @@ def test__do_import_skipping_accoustid_if_no_key(factories, mocker, preferences) path = os.path.join(DATA_DIR, "test.ogg") job = factories["music.FileImportJob"](mbid=None, audio_file__path=path) p = job.audio_file.path - tasks._do_import(job, replace=False, use_acoustid=False) + tasks._do_import(job, use_acoustid=False) m.assert_called_once_with(p) +def test__do_import_replace_if_duplicate(factories, mocker): + existing_file = factories["music.TrackFile"]() + existing_track = existing_file.track + path = os.path.join(DATA_DIR, "test.ogg") + mocker.patch( + "funkwhale_api.providers.audiofile.tasks.import_track_data_from_path", + return_value=existing_track, + ) + job = factories["music.FileImportJob"]( + replace_if_duplicate=True, audio_file__path=path + ) + tasks._do_import(job) + with pytest.raises(existing_file.__class__.DoesNotExist): + existing_file.refresh_from_db() + assert existing_file.creation_date != job.track_file.creation_date + + def test_import_job_skip_if_already_exists(artists, albums, tracks, factories, mocker): path = os.path.join(DATA_DIR, "test.ogg") mbid = "9968a9d6-8d92-4051-8f76-674e157b6eed" diff --git a/api/tests/test_import_audio_file.py b/api/tests/test_import_audio_file.py index b5ed01e3cdc9b8660c5fdb2bbe24d707cd2e09af..43e596ff7c14a27b6b2db69f1ab7c7206632355c 100644 --- a/api/tests/test_import_audio_file.py +++ b/api/tests/test_import_audio_file.py @@ -6,6 +6,7 @@ from django.core.management import call_command from django.core.management.base import CommandError from funkwhale_api.providers.audiofile import tasks +from funkwhale_api.music.models import ImportJob DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "files") @@ -115,6 +116,19 @@ def test_import_with_multiple_argument(factories, mocker): mocked_filter.assert_called_once_with([path1, path2]) +def test_import_with_replace_flag(factories, mocker): + factories["users.User"](username="me") + path = os.path.join(DATA_DIR, "dummy_file.ogg") + mocked_job_run = mocker.patch("funkwhale_api.music.tasks.import_job_run") + call_command("import_files", path, username="me", replace=True, interactive=False) + created_job = ImportJob.objects.latest("id") + + assert created_job.replace_if_duplicate is True + mocked_job_run.assert_called_once_with( + import_job_id=created_job.id, use_acoustid=False + ) + + def test_import_files_creates_a_batch_and_job(factories, mocker): m = mocker.patch("funkwhale_api.music.tasks.import_job_run") user = factories["users.User"](username="me") diff --git a/changes/changelog.d/222.feature b/changes/changelog.d/222.feature new file mode 100644 index 0000000000000000000000000000000000000000..ab10749f9cfcf99b7d0409a447cf6484864a49cd --- /dev/null +++ b/changes/changelog.d/222.feature @@ -0,0 +1 @@ +Added replace flag during import to replace already present tracks with a new version of their track file (#222)