<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andreas Siegel</title>
    <description>The latest articles on DEV Community by Andreas Siegel (@andreassiegel).</description>
    <link>https://dev.to/andreassiegel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F365631%2F5e5e4faf-2ebe-43fe-a91f-71eb1fdd5408.jpg</url>
      <title>DEV Community: Andreas Siegel</title>
      <link>https://dev.to/andreassiegel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andreassiegel"/>
    <language>en</language>
    <item>
      <title>Connect to a VPN from the Command Line on Mac OS</title>
      <dc:creator>Andreas Siegel</dc:creator>
      <pubDate>Sun, 03 May 2020 15:29:29 +0000</pubDate>
      <link>https://dev.to/andreassiegel/connect-to-a-vpn-from-the-command-line-on-mac-os-1e26</link>
      <guid>https://dev.to/andreassiegel/connect-to-a-vpn-from-the-command-line-on-mac-os-1e26</guid>
      <description>&lt;p&gt;During Corona time, I have to connect to a VPN most of the time in order to work.&lt;br&gt;
I use two different VPNs depending on what I'm working on.&lt;br&gt;
I can select the network to connect to from the status bar at the top of the screen&lt;br&gt;
but there seems to be a bug: Sometimes there isn't anything to select,&lt;br&gt;
so I have to go to the network preferences and connect from there.&lt;/p&gt;

&lt;p&gt;This works, but it also bothers me. Most of what I do frequently can be done from the command line.&lt;br&gt;
There must be a way to also connect to a VPN from there!&lt;/p&gt;

&lt;p&gt;It turned out there are multiple ways, actually.&lt;br&gt;
Prerequisite is that the VPN has been configured in the network preferences.&lt;/p&gt;
&lt;h2&gt;
  
  
  Use &lt;code&gt;networksetup&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;networksetup&lt;/code&gt; command provides access to network settings that are usually configured in the &lt;em&gt;System Preferences&lt;/em&gt; application.&lt;/p&gt;

&lt;p&gt;Use this command to connect the VPN configured with the name "myVPN":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;networksetup &lt;span class="nt"&gt;-connectpppoeservice&lt;/span&gt; &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The following command will disconnect again:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;networksetup &lt;span class="nt"&gt;-disconnectpppoeservice&lt;/span&gt; &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you want to check the connection status, use:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;networksetup &lt;span class="nt"&gt;-showpppoestatus&lt;/span&gt; &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Use &lt;code&gt;scutil&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The "system configuration utility" or &lt;code&gt;scutil&lt;/code&gt; command provides access to network configuration, too.&lt;/p&gt;

&lt;p&gt;To connect to your VPN, use this command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;scutil &lt;span class="nt"&gt;--nc&lt;/span&gt; start &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Execute the following command to disconnect from the VPN:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;scutil &lt;span class="nt"&gt;--nc&lt;/span&gt; stop &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you want to check the connection status, use:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;scutil &lt;span class="nt"&gt;--nc&lt;/span&gt; status &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Connect with Password from Keychain
&lt;/h2&gt;

&lt;p&gt;Both mentioned commands work with the built-in VPN client.&lt;br&gt;
Unfortunately, it is required to enter the password every time I connect because the account password is not stored in the keychain.&lt;br&gt;
People are discussing for years now whether this is actually a bug or a feature of the built-in VPN client in Mac OS.&lt;/p&gt;

&lt;p&gt;Installing another VPN client might solve that problem but you can also use a script as a workaround.&lt;/p&gt;

&lt;p&gt;A script or at least an alias is a good idea anyway because I'd like to have something as short as &lt;code&gt;vpn connect "myVPN"&lt;/code&gt;.&lt;br&gt;
It would be a great plus if that wouldn't even ask me to enter a password but retrieves it from the keychain instead.&lt;/p&gt;

&lt;p&gt;Looking at the keychains in the &lt;em&gt;Keychain Access&lt;/em&gt; application, I see only entries of kind &lt;em&gt;IPSec Shared Secret&lt;/em&gt; in the system keychain and nothing in the login keychain or local items.&lt;br&gt;
Thus, as of now, there isn't anything to retrieve the password from.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add the VPN Account Password to the Keychain
&lt;/h3&gt;

&lt;p&gt;To fix that, we first of all add the account password to the login keychain:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;security add-generic-password &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="s2"&gt;"VPN account password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"myVPN"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"myUserAccount@myVPN"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"mySuperStrongPassword"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-T&lt;/span&gt; &lt;span class="s2"&gt;"/usr/bin/security"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-a&lt;/code&gt; specifies your VPN account name (required)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-D&lt;/code&gt; specifies the kind of the keychain entry (optional, default is "application password")&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-s&lt;/code&gt; specifies the service name (the name of the keychain entry, required)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-T&lt;/code&gt; specifies an application which may access the keychain entry (multiple &lt;code&gt;-T&lt;/code&gt; options are possible)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-w&lt;/code&gt; specified your VPN account password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;-s&lt;/code&gt; option should match the name of your configured VPN because we will use it to retrieve the account password from the keychain.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a Utility Script
&lt;/h3&gt;

&lt;p&gt;Next, we will create a utility script that uses the keychain entry we just created:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'#!/bin/bash'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/vpnConnection.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/vpnConnection.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This creates the &lt;code&gt;vpnConnection.sh&lt;/code&gt; bash script in the home directory and makes it executable.&lt;/p&gt;

&lt;p&gt;Open the script in an editor, and add this code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;With that script, you can now use these commands:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/vpnConnection.sh list&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show all VPN connections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/vpnConnection.sh connect "myVPN"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;connect to the VPN "myVPN" and automatically enter the password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/vpnConnection.sh disconnect "myVPN"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;disconnect to the VPN "myVPN"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;~/vpnConnection.sh status "myVPN"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;show the connection status for VPN "myVPN"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Configure Privacy
&lt;/h3&gt;

&lt;p&gt;If you run the script now, you might get an error like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;execution error: System Events got an error: osascript is not allowed to send keystrokes. (1002)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this case, you will have to &lt;a href="https://support.apple.com/guide/mac-help/allow-accessibility-apps-to-access-your-mac-mh43185/mac"&gt;configure your &lt;em&gt;Privacy&lt;/em&gt; settings&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;em&gt;System Preferences &amp;gt; Security &amp;amp; Privacy&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Select the &lt;em&gt;Privacy&lt;/em&gt; tab&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;Accessibility&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Unlock the configuration if necessary&lt;/li&gt;
&lt;li&gt;Click the &lt;em&gt;+&lt;/em&gt; button&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Cmd+Shift+G&lt;/code&gt; in the Finder window that opens&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;/usr/bin/osascript&lt;/code&gt; and click &lt;em&gt;Go&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;Open&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This will allow &lt;code&gt;osascript&lt;/code&gt; to control your computer, i.e.,&lt;br&gt;
to automatically interact with the Mac OS user interface.&lt;/p&gt;

&lt;p&gt;You might also have to add your terminal application (e.g., &lt;em&gt;iTerm&lt;/em&gt;) to that list.&lt;/p&gt;
&lt;h3&gt;
  
  
  Set an Alias
&lt;/h3&gt;

&lt;p&gt;With that, it is already pretty convenient to manage VPN connections.&lt;br&gt;
To make it even more convenient, we will also set an alias so that we can type &lt;code&gt;vpn&lt;/code&gt; instead of &lt;code&gt;~/vpnConnection.sh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add the following line to the configuration of your shell, e.g., &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;vpn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"~/vpnConnection.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, using VPN connections is as easy as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;vpn list
&lt;span class="nv"&gt;$ &lt;/span&gt;vpn connect &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vpn status &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vpn disconnect &lt;span class="s2"&gt;"myVPN"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This post has initially been published on &lt;a href="https://4ndrs.xyz/posts/macos-vpn-command-line/"&gt;4ndrs.xyz&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>macos</category>
      <category>vpn</category>
      <category>keychain</category>
      <category>commandline</category>
    </item>
    <item>
      <title>Multiple Tool Versions via Homebrew</title>
      <dc:creator>Andreas Siegel</dc:creator>
      <pubDate>Mon, 13 Apr 2020 09:20:05 +0000</pubDate>
      <link>https://dev.to/andreassiegel/multiple-tool-versions-via-homebrew-5d08</link>
      <guid>https://dev.to/andreassiegel/multiple-tool-versions-via-homebrew-5d08</guid>
      <description>&lt;p&gt;Recently, I started using &lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt; with an older project.&lt;br&gt;
After I pulled the code and ran &lt;code&gt;hugo&lt;/code&gt;, it failed.&lt;br&gt;
It turned out it was not yet compatible with the latest version that got automatically installed via &lt;a href="%5Bhttps://%5D(https://brew.sh/)"&gt;Homebrew&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Well, no big deal, Homebrew allows for installing older versions of formulae.&lt;br&gt;
So I got it working.&lt;/p&gt;

&lt;p&gt;Shortly after that, I started another new project (this blog, BTW).&lt;br&gt;
Guess what happened? It broke again, this time because the installed version of &lt;code&gt;hugo&lt;/code&gt; was too old and not compatible with the configured theme.&lt;/p&gt;

&lt;p&gt;Well, that is a bit of a problem, but there is hope:&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing an old Version
&lt;/h2&gt;

&lt;p&gt;First of all, let's see how to install the old version in the first place.&lt;/p&gt;

&lt;p&gt;The nice thing is that Homebrew entirely relies on files from a &lt;a href="https://github.com/Homebrew/homebrew-core"&gt;public repository on GitHub&lt;/a&gt;.&lt;br&gt;
The bad thing is that &lt;strong&gt;all&lt;/strong&gt; default formulae come from this repository, and we have to inspect the commit history to find the desired version of a tool. This is a task that is most likely going to overwhelm the GitHub UI at some point.&lt;/p&gt;
&lt;h3&gt;
  
  
  Get the Last Versions from Homebrew
&lt;/h3&gt;

&lt;p&gt;Each formula is &lt;code&gt;*.rb&lt;/code&gt; file in the &lt;code&gt;Formula&lt;/code&gt; directory of the Git repository and each commit contains information about a tool and version.&lt;/p&gt;

&lt;p&gt;Hence, we only need to find the respective commit for what we want to install.&lt;br&gt;
For that, we can use either Homebrew itself or Git commands.&lt;/p&gt;
&lt;h4&gt;
  
  
  Using Homebrew
&lt;/h4&gt;

&lt;p&gt;Cloning and pulling the Homebrew repository just to inspect the history might seem a bit too much,&lt;br&gt;
and luckily has us covered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew log &lt;span class="nt"&gt;--oneline&lt;/span&gt; hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will output the last commits for the formula.&lt;br&gt;
However, the installation of Homebrew relies on a shallow clone of the corresponding Git repository, which means there is only partial data available, i.e., the desired version we want to install might not be included in the result anymore.&lt;/p&gt;

&lt;p&gt;If we are lucky, and the version is included in the output, we can proceed with the next step: &lt;a href="https://dev.to%7B%7B&amp;lt;%20relref%20"&gt;}}"&amp;gt;Find the Formula&lt;/a&gt;.&lt;br&gt;
Otherwise, we have to use Git to access the full history.&lt;/p&gt;
&lt;h4&gt;
  
  
  Using Git
&lt;/h4&gt;

&lt;p&gt;In order to be able to have a look at the full history from the command line, we have to clone the repository,&lt;br&gt;
even though we only need to retrieve the commit history, i.e.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We don't need any actual files.&lt;/li&gt;
&lt;li&gt;We don't need an actual checkout.&lt;/li&gt;
&lt;li&gt;We're only interested in the &lt;code&gt;master&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following command gives us exactly that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;blob:none &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--no-checkout&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--single-branch&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--branch&lt;/span&gt; master &lt;span class="se"&gt;\&lt;/span&gt;
  https://github.com/Homebrew/homebrew-core.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Although we did not check out any branch, we still received more than 260 MB of commit history data.&lt;br&gt;
Obviously, we would like to avoid that, if possible.&lt;/p&gt;

&lt;p&gt;After cloning the repository (history information), we can check the logs for commits related to the tool and version we are interested in, &lt;code&gt;hugo&lt;/code&gt; and version &lt;code&gt;0.41&lt;/code&gt; in this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git log --oneline | grep hugo | grep -F 0.41
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Get the commit history in one-line format&lt;/li&gt;
&lt;li&gt;Filter all commits related to &lt;code&gt;hugo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Filter all commits related to version &lt;code&gt;0.41&lt;/code&gt; (using a fixed string, otherwise the &lt;code&gt;.&lt;/code&gt; had to be escaped.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This returns the following result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b1e187384b hugo: update 0.41 bottle.
824a875022 hugo 0.41
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are only interested in the most recent commit for the version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Find the Formula
&lt;/h3&gt;

&lt;p&gt;With the commit ID, we can identify the file required for the installation of the version at that time, if necessary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git diff-tree &lt;span class="nt"&gt;--no-commit-id&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; b1e187384b
Formula/hugo.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Usually, this result should not be a big surprise since all formulae are located in the &lt;code&gt;Formula&lt;/code&gt; directory and the information about a formula also cover this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew info hugo
hugo: stable 0.69.0 &lt;span class="o"&gt;(&lt;/span&gt;bottled&lt;span class="o"&gt;)&lt;/span&gt;, HEAD
Configurable static site generator
https://gohugo.io/
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/hugo.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Install from File Path via Homebrew
&lt;/h3&gt;

&lt;p&gt;Now, we can use the retrieved information to install that the formula at a specific version via Homebrew,&lt;br&gt;
regardless of how old it actually is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;https://raw.githubusercontent.com/Homebrew/homebrew-core/824a875022/Formula/hugo.rb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Bringing it all together with &lt;code&gt;${FORMULA}&lt;/code&gt; and &lt;code&gt;${VERSION}&lt;/code&gt; representing what we want to install,&lt;br&gt;
we can use the following snippet to install a formula based on the Git commit history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ COMMIT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FORMULA&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'FNR==1 { print $1 }'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff-tree &lt;span class="nt"&gt;--no-commit-id&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COMMIT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"https://raw.githubusercontent.com/Homebrew/homebrew-core/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;COMMIT_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FILE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Prevent old Version from Upgrades
&lt;/h2&gt;

&lt;p&gt;If you only want to ensure that the installed old version does not get overridden by automatic upgrades that get installed via &lt;code&gt;brew upgrade&lt;/code&gt;, you can "pin" this version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew pin hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This can be undone with the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew unpin hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Install latest Version
&lt;/h2&gt;

&lt;p&gt;After we have successfully installed the outdated version of our tool,&lt;br&gt;
let's have look at how to install the latest version without upgrading, i.e., overriding the previous version.&lt;/p&gt;
&lt;h3&gt;
  
  
  Unlink the installed Version
&lt;/h3&gt;

&lt;p&gt;By unlinking the previously installed version, we simulate the state without the tool being installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;sh brew &lt;span class="nb"&gt;unlink &lt;/span&gt;hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, it will not be possible to use the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hugo version
zsh: &lt;span class="nb"&gt;command &lt;/span&gt;not found: hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Install new Version
&lt;/h3&gt;

&lt;p&gt;To install the latest version, first, get the latest formulae and then install it using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew update
&lt;span class="nv"&gt;$ &lt;/span&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we run the &lt;code&gt;version&lt;/code&gt; command again, we will get the expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;hugo version
Hugo Static Site Generator v0.69.0/extended darwin/amd64 BuildDate: unknown
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Switch between Installed Versions
&lt;/h2&gt;

&lt;p&gt;Now that we have multiple versions of our desired tool available, it is possible to switch between them whenever needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check available Versions
&lt;/h3&gt;

&lt;p&gt;To check which versions are actually available, use this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew list &lt;span class="nt"&gt;--versions&lt;/span&gt; hugo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Switch to another Version
&lt;/h3&gt;

&lt;p&gt;Assuming that you are still using the latest version that was last installed, we can use the following command to switch back to the outdated version used before that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;brew switch hugo 0.41
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That's all!&lt;/p&gt;

&lt;p&gt;Internally, Homebrew is updating symlinks to point to the respective version we are specifying in the &lt;code&gt;switch&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post has initially been published on &lt;a href="https://4ndrs.xyz"&gt;4ndrs.xyz&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tools</category>
      <category>homebrew</category>
      <category>shell</category>
      <category>devlive</category>
    </item>
  </channel>
</rss>
