Oct 12, 2010

Update: Fast path switching between projects

Yesterday I overheard a couple co-workers talking about this cool script they found for quickly switching between development projects.  Turns out they were talking about my old post so I thought I’d share the latest version of the script.

Back in December I posted the script I use when switching from one project to another (…/2009/12/29/fast-path-switching-between-projects). With this script trying different versions of things that are wired into the command line path is fast and easy.

I’ve updated the use script so now you can pass in more than one
component/version pair. Like this

    use grails 1.3 tomcat 6.0.29 maven 2.2.1

And calling use with no arguments echos all of the *_HOME vars. Like this

    yaal.local[535]> use
        ANT_HOME      /Users/amiller/devtools/ant/current     -> ant-1.8.1
        CATALINA_HOME /Users/amiller/devtools/tomcat/current  -> tomcat-6.0.29
        EMACS_HOME    /Users/amiller/devtools/emacs/current   -> emacs-23.2.app
        GRAILS_HOME   /Users/amiller/devtools/grails/current  -> grails-1.3.4
        GROOVY_HOME   /Users/amiller/devtools/groovy/current  -> groovy-1.7.5
        JAVA_HOME     /Users/amiller/devtools/jdk/current     -> jdk-1.6.0
        TOMCAT_HOME   /Users/amiller/devtools/tomcat/current  -> tomcat-6.0.29
    yaal.local[536]>

Here’s the modified script…

#!/bin/sh
#
# sets a symlink by convention...
#
# For example,
#   in a directory names ~/devtools/grails with
#     ~/devtools/grails/grails-1.1.2 and
#     ~/devtools/grails/grails-1.2,
#   executing `use 1.2`
#   will create a symlink ~/devtools/grails/current -> ~/devtools/grails/grails-1.2
#
# You can pass in more than one component/version pair...
#   `use grails 1.3 tomcat 6.0.29 maven 2.2.1`
#
# Set your path to include ~/devtools/grails/current/bin.  Got it?
#
DEFAULT_TOOL_DIR=~/devtools

#~ functions ----------------------------------------------------------------------------------

setCurrentLink() {
    rm -f current
    ln -s $1 current
    # this will echo the link to the console...
    #ls -l current | awk '{ printf "%s %s %s", $9, $10, $11 }'
}

useComponentVersion()
{
    COMPONENT=$1
    VERSION=$2

    #echo "default_tool_dir = $DEFAULT_TOOL_DIR"
    cd $DEFAULT_TOOL_DIR/$COMPONENT

    USE=$COMPONENT-$VERSION
    if [ ! -d $USE ]; then
        # maybe there is a missing .0 ?
        USE=$COMPONENT-$VERSION.0
    fi

    if [ -d $USE ]; then
        if [ -h current ]; then
            CURRENT=`ls -l current | awk '{ print $11 }'`
            if [ "$CURRENT" = "$USE" ]; then
                echo "using $CURRENT"
            else
                echo "switching from $CURRENT to $USE"
                setCurrentLink $USE
            fi
        else
            echo "using $USE"
            setCurrentLink $USE
        fi
    else
        echo "ERROR: missing directory for $@"
        echo "ERROR: available version are..."
        find . -name $COMPONENT-* -depth 1

        if [ -h current ]; then
            CURRENT=`ls -l current | awk '{ print $11 }'`
            echo "WARNING: keeping $CURRENT"
        else
            echo "WARNING: current not set."
        fi
        exit -1
    fi
}

echoCurrentHomeVars() {
    #echo "The current _HOME vars are..."
    for home_var in `printenv | grep _HOME | sort`; do
        home_var_name=`echo $home_var | awk -F= '{ print $1 }'`
        home_var_value=`echo $home_var | awk -F= '{ print $2 }'`
        if [ -h $home_var_value ]; then
        # echo out what symbolic links are pointing to...
            echo "    $home_var_name    `ls -l $home_var_value | awk '{ printf "%s -> %sn", $9, $11 }'`"
        else
            echo "    $home_var_name    $home_var_value"
        fi
    done
}

#~ main body of the script --------------------------------------------------------------------

#echo

if [ $# -eq 0 ]; then
    echoCurrentHomeVars
    exit -1
elif [ $# -eq 1 ]; then
    echo "WARNING: Assuming you are making a link in the current directory."
    useComponentVersion `basename $PWD` $1
else
    # use each component/version pair
    while [ $# -gt 0 ]; do
        useComponentVersion $1 $2
        shift
        shift
    done
fi

#~ END OF FILE --------------------------------------------------------------------------------

Three things come together to make this work.

First, I keep a directory called devtools full of different versions of tools. Like this…

    ~/devtools/
        ant/
            ant-1.7.1/
            ant-1.8.1/
            current -> ant-1.8.1
        jdk/
            jdk-1.5.0/
            jdk-1.6.0/
            current -> jdk-1.5.0
        grails/
            grails-1.2.2/
            grails-1.3.4/
            current -> grails-1.3.4
        ...

and so on. I keep this in my home directory so it is easy for me to replicate across machines. You might want to keep it in some system specific location; like /usr/local.

Second, in my .profile I set up a bunch of environment variables to point to the current symlinks (for example: export GRAILS_HOME=~/devtools/grails/current). Also in .profile, my path is configured to include GRAILS_HOME/bin.

And third, the use script (see below) sets the current symbolic links.

With these three things in place I can quickly switch between projects with aliases that call the use script. For example…

    alias iaap="use jdk 1.5.0 grails 1.1.1; cd ~/opi/clients/mdh/iaap"
    alias buyer="use jdk 1.6.0 grails 1.2.0; cd ~/opi/clients/buyer"
    alias mtm="use jdk 1.6.0 grails 1.3.4; cd ~/dev/mtm"
    ...

There have got to be a million ways to do this kind of thing, but with this script I can try out different versions of things really fast. And it is especially useful when I have to go back and pick up an old project for doing a demo, debugging or whatever.

About the Author

Object Partners profile.

One thought on “Update: Fast path switching between projects

Leave a Reply

Your email address will not be published.

Related Blog Posts
Natively Compiled Java on Google App Engine
Google App Engine is a platform-as-a-service product that is marketed as a way to get your applications into the cloud without necessarily knowing all of the infrastructure bits and pieces to do so. Google App […]
Building Better Data Visualization Experiences: Part 2 of 2
If you don't have a Ph.D. in data science, the raw data might be difficult to comprehend. This is where data visualization comes in.
Unleashing Feature Flags onto Kafka Consumers
Feature flags are a tool to strategically enable or disable functionality at runtime. They are often used to drive different user experiences but can also be useful in real-time data systems. In this post, we’ll […]
A security model for developers
Software security is more important than ever, but developing secure applications is more confusing than ever. TLS, mTLS, RBAC, SAML, OAUTH, OWASP, GDPR, SASL, RSA, JWT, cookie, attack vector, DDoS, firewall, VPN, security groups, exploit, […]