Перейти к содержимому

Blade Runner - пет-проект

Blade Runner poster

В последнее время я занимался расчисткой своих жестких дисков. Знаете это чувство, когда у вас есть папка backup внутри папки backup final, которая находится внутри еще одной папки backup final (1). У меня множество таких рекурсивных бэкапов, они мигрируют с одного диска на другой, с одного компьютера на другой.

Одна из самых больших директорий — это директория со всеми моими фотографиями и видео. Каждый бэкап содержит эту папку с фотографиями на всякий случай.

Итак, есть проблема. Контент скопирован множество раз, копии занимают гигабайты, с каждой итерацией становится все сложнее. У меня нет желания разбираться с этим вручную.

Я подумал, что это отличный пример проблемы, которую я могу решить с помощью своих навыков программирования и внести вклад в мир open-source. Просто небольшая утилита для пет-проекта, делающая всю эту работу. Её можно рассматривать как понятный пример для новичков о том, как написать консольную утилиту и предоставить её пользователям.

Более того, октябрь — это месяц Hacktoberfest. Самое время довести дела до конца.

Todo

Что нам нужно сделать? Давайте определим задачу.

  • Читать файлы один за другим и копировать их в результирующую директорию, если файл уникален;
  • Определять, уникален ли файл, используя кэшированные хэши всех прочитанных файлов;
  • Клоны должны быть уничтожены в результирующей директории (именование важно, репликанты должны быть уничтожены).

Добавим несколько дополнительных задач.

  • Получить список всех клонов без удаления;
  • Возможность удалять клоны из заданной директории;
  • Основная команда должна копировать все уникальные файлы из входной директории в выходную, пытаясь сохранить структуру директорий и имена файлов;
  • Опция flatten для копирования всех уникальных файлов в одну директорию без сохранения структуры;
  • Сделать возможным переименование скопированных файлов по какому-то оптимальному правилу, например по дате;
  • Для файлов фотографий можно использовать дату, когда фото было сделано.

Инструменты

Я люблю Kotlin. Может показаться, что это не лучший язык для написания консольных утилит, но почему бы и нет? Используя Kotlin, я значительно сокращаю время на разработку. По моему опыту, пет-проекты часто забрасываются, потому что не хватает времени их закончить.

Я хотел создать консольную утилиту с простым синтаксисом с аргументами. Clikt отлично подходит для этого. Он делает написание интерфейса командной строки действительно интуитивным. Мне нравится, как он создает все эти справочные сообщения без моего участия. Программист просто пишет типизированные аргументы, а Clikt делает все остальное.

MetadataExtractor — отличная библиотека для работы с медиа-файлами. Основная цель bladerunner для меня — копировать уникальные фотографии, поэтому мне нужно что-то для работы с метаданными фотографий. Она используется для получения даты съемки фотографии, так что мне не нужно думать об этом.

Вот, в принципе, и все. В качестве вишенки на торте я хотел написать юнит-тесты. Junit5 и AssertJ — мой выбор для этого проекта. Библиотека Assert — это вопрос вашей привычки или личного чувства прекрасного.

Github Actions используется как мой CI/CD инструмент.

Синтаксис

Есть три основные команды

Run

Копирует все уникальные файлы в выходную директорию.

Usage: bladerunner run [OPTIONS]

Options:
  -din, --directory-in DIRECTORY   Path to root directory of input
  -dout, --directory-out DIRECTORY
                                   Path to output directory
  -ns, --naming-strategy [DEFAULT|DATE_MODIFIED|PHOTO_TAKEN]
                                   Naming strategy for created files
  -o, --out FILE                   Path to output file
  -s, --silent                     Do not log activity
  -f, --flatten                    Copy all files into out directory without
                                   saving directory tree
  -h, --help                       Show this message and exit

Naming strategy

Пара слов о том, как создаются имена для скопированных файлов.

  • DEFAULT использует оригинальное имя файла. DEFAULT — это дефолтное поведение.
  • DATE_MODIFIED использует дату последней модификации файла.
  • PHOTO_TAKEN получает дату съемки фотографии из EXIF файла, если возможно, иначе использует fallback.

Случайная UUID-строка добавляется как суффикс к имени файла, если в выходной директории уже есть файл с таким же именем.

Clean

Удаляет все неуникальные файлы из заданной директории.

Usage: bladerunner clean [OPTIONS]

Options:
  -din, --directory-in DIRECTORY  Path to root directory of input
  -o, --out FILE                  Path to output file
  -s, --silent                    Do not log activity
  -h, --help                      Show this message and exit

Find

Выводит информацию о том, является ли файл клоном или нет, для всех файлов в заданной директории.

Usage: bladerunner find [OPTIONS]

Options:
  -din, --directory-in DIRECTORY  Path to root directory of input
  -o, --out FILE                  Path to output file
  -h, --help                      Show this message and exit

Результат

Теперь у меня есть хороший репозиторий pavelkorolevxyz/bladerunner-desktop в профиле. Последние артефакты bladerunner можно найти на странице Releases.

Каждый push в основную ветку разработки автоматически тестируется и собирается с помощью Github Actions. На данный момент проект выглядит довольно завершенным с точки зрения функционала, документации и тестов. Мне это нравится.

Наконец, самое главное — теперь у меня папки с бэкапами чистые и без тонн клонов.