Search code examples
gitbashgithooksyui-compressor

Bash script for YUI Compressor to be used with Git


I'd like to make my website as efficient as possible, and part of that is minifying my CSS and JavaScript files. My goal is to be able to use the unminified files in development, but the minified files in production. So my thought is to have my unminified filenames be normal (foo.css) and my minified filenames be the same, only with an underscore at the beginning (_foo.css).

Since the development environment doesn't use the minified files, I don't have to worry about keeping the minified files up-to-date. The only time they should ever be generated is when I'm making a commit to the website's Git repository. So it makes sense to make it a Git hook, which is something I've never done before. I'd like this hook to be in place for my co-workers as well. I'm on a Mac and they're on Linux. I have a working shell script, but there are two things that will need to be modified in order for it to be used as a Git hook and to be used by my co-workers. These two things are what I need help with. But first, the code:

#!/bin/bash

# The files to ignore are already minified.

css_files_to_ignore=(
    "jquery.colorbox-min.css"
);

js_files_to_ignore=(
    "jquery.colorbox-min.js"
);

base_folder=/Applications/MAMP/htdocs/my_project/app/webroot
yuicompressor_path=/Applications/yuicompressor.jar

function process_assets() {
    extension=$1
    files_minified=0

    for infile in $(echo "$base_folder/$extension/*.$extension")
    do
        [[ -f $infile ]] || continue

        filename=${infile##*/}

        # If the filename starts with an underscore, that means that the file is a
        # minified file that was previously generated.

        [[ ${filename:0:1} != "_" ]] || continue

        ignore_this_file=false

        files_to_ignore=$extension"_files_to_ignore"

        for i in $(eval echo \${$files_to_ignore[@]})
        do
            if [[ $i == $filename ]]; then
                ignore_this_file=true
                break
            fi
        done

        if [ $ignore_this_file == false ]; then
            minified_file="$base_folder/$extension/_$filename"

            if [ ! -f "$minified_file" ] || test $infile -nt $minified_file; then
                java -jar $yuicompressor_path "$infile" -o "$minified_file"
                ((files_minified++))
            fi
        fi
    done

    if [ $extension == "css" ]; then
        file_type=CSS
    else
        file_type=JavaScript
    fi

    echo -n "$files_minified $file_type file"

    if [ "$files_minified" == "1" ]; then
        echo -n " was"
    else
        echo -n "s were"
    fi

    echo " minified"
}

if [ -f $yuicompressor_path ]; then
    process_assets css
    process_assets js
else
    echo "YUI Compressor was not found. Aborting."
    exit 1
fi

The first thing that I need help with is how to handle the base_folder variable. Since this will be a Git hook, how should this variable be set? Will the current working directory at the time the commit is made affect the script?

The second thing I need help with is how to handle the yuicompressor_path variable. As I said earlier, I'm on a Mac and my co-workers are on Linux. I'd like the Git hook to work for all of us, if possible. Can I set that variable in a way that would work for all of us?

Thank you!


Solution

  • You can build your variable content based off of the path of the Git repository.

    base_folder="$(git rev-parse --show-toplevel)"
    

    will set base_folder equal to the path to the top level of the Git repository. If you need to set it to a sub path, just add that afterwards, e.g. if your Git repo were at the my_project folder level, you might do...

    base_folder="$(git rev-parse --show-toplevel)/app/webroot"
    

    This should work on both OS X and Linux.


    Setting the path for yuicompressor is slightly trickier. What I'd recommend is either having people set it manually when they install the hook on their local system, or (if yuicompressor is in the path), use which.