(ч.3) Удобный pod install herb.svg

06.06.2020
3 мин

В прошлой части мы написали небольшую обертку над обычным CocoaPods и научились не вызывать его без необходимости. И даже при необходимости chto_podelat.svg.

В этой части давайте попробуем автоматизировать пару интересных моментов. Основная цель запустить команду pods install и спокойно переключиться на другие задачи до её завершения.

toolbox.svg Bundler

Первая неприятность заключается в том, что иногда Bundler сообщает нам, что неплохо бы вызвать bundler install перед вызовом pods install. Обычно это связанно с тем, что кто-то из других разработчиков изменил Gemfile и затем вы подтянули новые изменения из git.

Чем это неудобно? Тем, что сначала нужно запустить pods install. Затем заметить, что нужно вызвать bundler install. Вызвать его и подождать пока он выполнится. И наконец, опять вызвать pods install. Не отлично, но и не ужасно.

pods install
Could not find gem 'cocoapods (= 1.9.2)' in any of the gem sources listed in your Gemfile.
Run `bundle install` to install missing gems.

calendar2.svg Out of date source repos

Вторая неприятность в том, что иногда при вызове pods install вы можете получить ошибку от CocoaPods, связанную с неактуальностью локального репозитория зависимостей. Когда такое бывает? Обычно когда у зависимости появилась новая версия и она указанна в Podfile, но у вас ещё нет этой версии локально.

В этой ситуации CocoaPods предлагает несколько вариантов:

  • pod repo update и затем pod install;
  • pod install --repo-update то же самое, что и выше, но одной командой.

Другими словами нам нужно обновить локальный репозиторий зависимостей, а затем уже вызывать pods install. По степени неудобности это примерно на том же месте, что и прошлая проблема. Правда обычно обновление локального репозитория всех зависимостей занимает намного больше времени.

pods install
Analyzing dependencies
[!] CocoaPods could not find compatible versions for pod "Frog":
In Podfile:
Frog (~> 1.3.0)
None of your spec sources contain a spec satisfying the dependency: `Frog (~> 1.3.0)`.
You have either:
* out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
* mistyped the name or version.
* not added the source repo that hosts the Podspec to your Podfile.

Стоит отметить, что начиная с CocoaPods 1.8 Beta это уже не проблема. Теперь по умолчанию используется cdn и больше не нужно хранить локальный репозиторий. Но, ещё не все переехали и для кого-то проблема пока актуальна.

A CDN is a Content Delivery Network - what this means for CocoaPods is that using CocoaPods won't require you to have a local copy of all the public Podspecs on your computer. Saving you about a GB of file storage, and shaving a lot of time off pod installs.

lightning.svg Супер быстрое решение

А что если мы просто всегда будем вызывать все команды в связке друг за дружкой? Ничего сложного и все решение поместится в одну строку:

bundle install && pods repo update && pods install

Но проблема в том, что обновление локальных репозиториев тоже занимает время. Причем у меня это происходит несколько минут. Получается решение не такое уж и быстрое.

bug.svg Обработка ошибок

Давайте будем обрабатывать ошибки, и в зависимости от кода вызывать обновление локальных репозиториев. В прошлой статье мы уже подготовили функцию pod_install, осталось только добавить в неё обработку.

Для этого будем использовать цикл while и переменную с количеством попыток. Внутри цикла вызываем bundle exec pod install и получаем код выполнения команды. В зависимости от кода принимаем решение, что делать дальше.

К примеру, если код 7, то вызываем bundle install и пишем в консоль информацию об ошибке и её решении. Далее переходим на следующий шаг цикла и опять вызываем bundle exec pod install. Обрабатываем ошибку и тд.

В итоге обработаем все известные нам ошибки и последовательно обновим все локальные репозитории при необходимости.

tries=2
while (( $tries > 0 ))
do
bundle exec pod install "$@"
error=$?
if (( error == 7 )) ; then
echo -e "\n⚠️ Error code: ${error}"
echo -e "🚑 Let's try bundle install\n"
bundle install
elif (( error == 31 )) ; then
echo -e "\n⚠️ Error code: ${error}"
echo -e "🚑 Let's try --repo-update\n"
bundle exec pod install --repo-update
elif (( error != 0 )) ; then
echo -e "\n⚠️ Error code: ${error}"
break
else
echo -e "party.png Everything fine."
break
fi
tries=$(( $tries - 1 ))
done

loudspeaker.svg И напоследок

Осталась лишь одна небольшая проблема. Когда нам можно прекращать пить кофе и смотреть котиков? Другими словами, как узнать когда выполнение команды закончится? Можно конечно периодически проверять, но это не удобно.

Неплохо бы иметь нотификацию о завершении. И мы её добавим!

tput bel

Просто допишем небольшую команду в самый конец функции pods_install. Так мы получим стандартное звуковое уведомление и увидим значок непрочитанного сообщения на иконке терминала.

rocket.gif Как использовать?

Финальную версию я выложил на Github Gists. В ней я объединил весь код из статей и добавил раскраску команд в терминале. Мелочь, а приятно. Подробная инструкция по установке:

  • Открываем .bash_profile;
  • Копируем код из Github Gists в .bash_profile;
  • Применяем изменения из .bash_profile;
  • Используем pods install.
open -a Xcode ~/.bash_profile
# Копируем код из Github Gists в .bash_profile
source ~/.bash_profile
pods install

finish.svg The End

Что получилось в итоге?

  • Небольшая Bash обертка над CocoaPods;
  • Позволяет вызвать одну короткую команду pods install и смотреть котиков переключиться на другие важные задачи;
  • Все промежуточные шаги не требуют вашего участия;
  • Не нужно периодически проверять работу команды — вас оповестит колокольчик.

На этом я пока заканчиваю свои эксперименты с CocoaPods и Bash. Я решил свою проблему и был рад поделиться этим с вами. Было очень интересно немного поработать со скриптами и написать что-то необычное.

idea.svg Есть у меня идея... Возможно будет ещё одна статья со скриптом на Ruby.


💬 И, как всегда, вы можете оставить свой фидбек в этом твите: