(p.3) Cozy pod install herb.svg

06.06.2020
3 min

In the last part, we wrote a small wrapper over the regular CocoaPods and figure out how to skip unnecessary calls. In this part, let's try to automate a couple of interesting cases. The main goal is to run the pods install command and switch to other tasks while it is running.

toolbox.svg Bundler

The first drawback is that sometimes Bundler informs us that it would be nice to call bundler install before calling pods install. Usually, this is happening because someone from other developers changed Gemfile and then you pulled new changes from git.

But why that inconvenient? Because you first need to run pods install. Then notice that you need to call bundler install. Call it and wait for completion. And finally, call pods install again. Not great, but not terrible.

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

The second drawback is that sometimes when calling pods install you may get an error from CocoaPods related to the irrelevance of the local dependency repository. When does this happen? Usually when a dependency has a new version and it is listed in Podfile, but you do not have this version locally yet.

In this case, CocoaPods offers some options:

  • pod repo update and then pod install;
  • pod install --repo-update the same as above, but in one command.

In other words, we need to update the local dependency repository, and then call pods install. As same as the last drawback, it is like a waste of time. Besides, usually updating the local repository takes much longer.

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.

It is worth noting that starting with CocoaPods 1.8 Beta this is no longer a problem. Now cdn is used by default and you no longer need to store the local repository. But not everyone has moved and for someone, the problem is still relevant.

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 Superfast solution

But what if we just always call all the commands in a bunch one after another? Nothing complicated and the whole solution fits in one line:

bundle install && pods repo update && pods install

But the problem is that updating local repositories takes time. And it is a terrible idea always to call these commands. It lasts a few minutes for me and it is pretty slow.

bug.svg Error handling

Let's handle the errors and call updating of the local repositories if needed. In the last post, we already prepared the pod_install function. So, it remains only to add processing to it.

To do this, we will use the while loop and the variable with the number of attempts. Inside the loop, call bundle exec pod install and get the command execution code. Depending on the code, we decide what to do next.

For example, if the code is 7, then we call bundle install, write information about the error and its solution to the console. Then go to the next step of the loop and call bundle exec pod install again. Handle the error and so on.

As a result, we will process all errors known to us and sequentially update all local repositories if necessary.

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 One more thing

There remains only one small problem. When can we stop drinking coffee and watch memes? In other words, how do you know when a command will finish? Of course, you can from time to time check terminal. But it is not convenient.

It would be nice to have a notification of completion. And we will add it!

tput bel

Just add a small command at the very end of the pods_install function. So, we will get a standard sound notification and see the unread message icon on the terminal icon.

rocket.gif How to use it?

I shared the final version on Github Gists. There are combined all the code from the posts and added the commands coloring in the terminal. A little, but nice. Detailed installation instructions:

  • Open .bash_profile;
  • Copy the code from Github Gists to .bash_profile;
  • Apply changes from .bash_profile;
  • Use pods install.
open -a Xcode ~/.bash_profile
# Copy code from Github Gists to .bash_profile
source ~/.bash_profile
pods install

finish.svg The End

What did we get?

  • A small Bash wrapper over CocoaPods;
  • Allows you to call one short command pods install and watch memes switch to other important tasks;
  • All intermediate steps do not require your participation;
  • No need to periodically check terminal — a bell will notify you about completion.

This is where I finish my experiments with CocoaPods and Bash. I solved my problem and was happy to share this with you. It was very interesting to work a bit with scripts and write something unusual for an iOS developer.

idea.svg I have an idea... Perhaps there will be another post with a script on Ruby.


💬 Please, leave some feedback in Twitter post.
It will help me improve posts and continue to publish new ones.