Extract common functions into a separate file

This is the start of an effort to organize devstack's code
to better document the requirements for configuring the individual
components.

Change-Id: I3476b76b9d1f9ee63687fb9898a98729118cbd84
diff --git a/functions b/functions
new file mode 100644
index 0000000..01c4758
--- /dev/null
+++ b/functions
@@ -0,0 +1,91 @@
+# functions - Common functions used by DevStack components
+
+
+# apt-get wrapper to set arguments correctly
+# apt_get package [package ...]
+function apt_get() {
+    [[ "$OFFLINE" = "True" ]] && return
+    local sudo="sudo"
+    [[ "$(id -u)" = "0" ]] && sudo="env"
+    $sudo DEBIAN_FRONTEND=noninteractive \
+        http_proxy=$http_proxy https_proxy=$https_proxy \
+        apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
+}
+
+
+# Gracefully cp only if source file/dir exists
+# cp_it source destination
+function cp_it {
+    if [ -e $1 ] || [ -d $1 ]; then
+        cp -pRL $1 $2
+    fi
+}
+
+
+# git clone only if directory doesn't exist already.  Since ``DEST`` might not
+# be owned by the installation user, we create the directory and change the
+# ownership to the proper user.
+# Set global RECLONE=yes to simulate a clone when dest-dir exists
+# git_clone remote dest-dir branch
+function git_clone {
+    [[ "$OFFLINE" = "True" ]] && return
+
+    GIT_REMOTE=$1
+    GIT_DEST=$2
+    GIT_BRANCH=$3
+
+    if echo $GIT_BRANCH | egrep -q "^refs"; then
+        # If our branch name is a gerrit style refs/changes/...
+        if [[ ! -d $GIT_DEST ]]; then
+            git clone $GIT_REMOTE $GIT_DEST
+        fi
+        cd $GIT_DEST
+        git fetch $GIT_REMOTE $GIT_BRANCH && git checkout FETCH_HEAD
+    else
+        # do a full clone only if the directory doesn't exist
+        if [[ ! -d $GIT_DEST ]]; then
+            git clone $GIT_REMOTE $GIT_DEST
+            cd $GIT_DEST
+            # This checkout syntax works for both branches and tags
+            git checkout $GIT_BRANCH
+        elif [[ "$RECLONE" == "yes" ]]; then
+            # if it does exist then simulate what clone does if asked to RECLONE
+            cd $GIT_DEST
+            # set the url to pull from and fetch
+            git remote set-url origin $GIT_REMOTE
+            git fetch origin
+            # remove the existing ignored files (like pyc) as they cause breakage
+            # (due to the py files having older timestamps than our pyc, so python
+            # thinks the pyc files are correct using them)
+            find $GIT_DEST -name '*.pyc' -delete
+            git checkout -f origin/$GIT_BRANCH
+            # a local branch might not exist
+            git branch -D $GIT_BRANCH || true
+            git checkout -b $GIT_BRANCH
+        fi
+    fi
+}
+
+
+# pip install wrapper to set cache and proxy environment variables
+# pip_install package [package ...]
+function pip_install {
+    [[ "$OFFLINE" = "True" ]] && return
+    sudo PIP_DOWNLOAD_CACHE=/var/cache/pip \
+        HTTP_PROXY=$http_proxy \
+        HTTPS_PROXY=$https_proxy \
+        pip install --use-mirrors $@
+}
+
+
+# Normalize config values to True or False
+# VAR=`trueorfalse default-value test-value`
+function trueorfalse() {
+    local default=$1
+    local testval=$2
+
+    [[ -z "$testval" ]] && { echo "$default"; return; }
+    [[ "0 no false False FALSE" =~ "$testval" ]] && { echo "False"; return; }
+    [[ "1 yes true True TRUE" =~ "$testval" ]] && { echo "True"; return; }
+    echo "$default"
+}