Bump to version 0.4
[dotfiles-framework.git] / dotfiles.sh
index b8233828cf44112f8e040e9b1914c284646bd71a..5f0c5e5cb9cb8f4202fa42db8fcd4ff7926d65ca 100755 (executable)
@@ -3,7 +3,7 @@
 # Dotfiles management script.  For details, run
 #   $ dotfiles.sh --help
 #
-# Copyright (C) 2011-2012 W. Trevor King <wking@tremily.us>
+# Copyright (C) 2011-2015 W. Trevor King <wking@tremily.us>
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-VERSION='0.2'
+VERSION='0.4'
 DOTFILES_DIR="${PWD}"
 TARGET=~
 CHECK_WGET_TYPE_AND_ENCODING='no'
@@ -26,17 +26,17 @@ CHECK_WGET_TYPE_AND_ENCODING='no'
 #####
 # External utilities
 
-DIFF=$(which diff)
-GIT=$(which git)
-LN=$(which ln)
-MV=$(which mv)
-PATCH=$(which patch)
-SED=$(which sed)
-RM=$(which rm)
-RSYNC=$(which rsync)
-TAR=$(which tar)
-TOUCH=$(which touch)
-WGET=$(which wget)
+DIFF=${DOTFILES_DIFF:-$(command -v diff)}
+GIT=${DOTFILES_GIT:-$(command -v git)}
+LN=${DOTFILES_LN:-$(command -v ln)}
+MV=${DOTFILES_MV:-$(command -v mv)}
+PATCH=${DOTFILES_PATCH:-$(command -v patch)}
+SED=${DOTFILES_SED:-$(command -v sed)}
+RM=${DOTFILES_RM:-$(command -v rm)}
+RSYNC=${DOTFILES_RSYNC:-$(command -v rsync)}
+TAR=${DOTFILES_TAR:-$(command -v tar)}
+TOUCH=${DOTFILES_TOUCH:-$(command -v touch)}
+WGET=${DOTFILES_WGET:-$(command -v wget)}
 
 #####
 # Compatibility checks
@@ -106,7 +106,7 @@ function run_on_all_repos()
        COMMAND="${1}"
        shift
        if [ -z "${REPO}" ]; then  # run on all repositories
-               for REPO in *; do
+               for REPO in *; do
                        if [ "${REPO}" = '*' ]; then
                                break  # no known repositories
                        elif [ -f "${REPO}" ]; then
@@ -172,6 +172,8 @@ function get_repo_source()
                REPO_SOURCE_DATA['repo']="${REPO}"
                if [ -d "${REPO}/.git" ]; then
                        REPO_SOURCE_DATA['transfer']='git'
+                       REPO_SOURCE_DATA['url']=$(
+                               git --git-dir "${REPO}/.git/" config remote.origin.url)
                else
                        echo "ERROR: no source location found for ${REPO}" >&2
                        return 1
@@ -334,6 +336,49 @@ function clone()
        fi
 }
 
+###
+# list command
+
+COMMANDS+=('list')
+
+function list_help()
+{
+       echo 'List current dotfiles repositories.'
+       if [ "${1}" = '--one-line' ]; then return; fi
+
+       cat <<-EOF
+
+               usage: $0 ${COMMAND} [REPO]
+
+               List information for 'REPO' in a form simular to the 'clone'
+               command's arguments.  If 'REPO' is not give, all repositories will
+               be listed.  Examples:
+
+                 $0 list public
+                 public wget http://example.com/public-dotfiles.tar.gz
+                 $0 list
+                 public wget http://example.com/public-dotfiles.tar.gz
+                 private git ssh://example.com/~/private-dotfiles.git
+       EOF
+}
+
+function list()
+{
+       # multi-repo case handled in main() by run_on_all_repos()
+       REPO=$(nonempty_option 'list' 'REPO' "${1}") || return 1
+       maxargs 'list' 1 "${@}" || return 1
+       if [ "${BASH_MAJOR}" -ge 4 ]; then
+               get_repo_source "${REPO}" || return 1
+               TRANSFER=$(nonempty_option 'list' 'TRANSFER' "${REPO_SOURCE_DATA['transfer']}") || return 1
+               URL=$(nonempty_option 'list' 'URL' "${REPO_SOURCE_DATA['url']}") || return 1
+       else
+               echo "WARNING: Bash version < 4.0, cannot use assuming all repos use git transfer" >&2
+               TRANSFER='git'
+               URL=$(git --git-dir "${REPO}/.git/" config remote.origin.url)
+       fi
+       echo "${REPO} ${TRANSFER} ${URL}"
+}
+
 ###
 # fetch command
 
@@ -376,7 +421,7 @@ function fetch()
 }
 
 ###
-# fetch command
+# diff command
 
 COMMANDS+=('diff')
 
@@ -414,7 +459,7 @@ function diff()
                        '--removed')
                                MODE='removed'
                                ;;
-                       '--local-patch')
+                       '--local-patch')
                                MODE='local-patch'
                                ;;
                        *)
@@ -643,7 +688,7 @@ function disconnect_help()
 function disconnect()
 {
        # multi-repo case handled in main() by run_on_all_repos()
-       REPO=$(nonempty_option 'link' 'REPO' "${1}") || return 1
+       REPO=$(nonempty_option 'disconnect' 'REPO' "${1}") || return 1
        maxargs 'disconnect' 1 "${@}" || return 1
        DOTFILES_SRC="${DOTFILES_DIR}/${REPO}/patched-src"
 
@@ -708,7 +753,7 @@ function update_help()
 
        cat <<-EOF
 
-               usage: $0 ${COMMAND} [REPO]
+               usage: $0 ${COMMAND} [options] [REPO]
 
                Where 'REPO' is the name the dotfiles repository to update.
                If it is not given, all repositories will be updateed.
@@ -717,13 +762,21 @@ function update_help()
                to bring them in sync with the central repositories.  Keeps track
                of the last update time to avoid multiple fetches in the same
                week.
+
+               ${COMMAND} passes any options it receives through to the link
+               command.
        EOF
 }
 
 function update()
 {
+       LINK_OPTS=''
+       while [ "${1::2}" = '--' ]; do
+               LINK_OPTS="${LINK_FN_OPTS} ${1}"
+               shift
+       done
        # multi-repo case handled in main() by run_on_all_repos()
-       REPO=$(nonempty_option 'link' 'REPO' "${1}") || return 1
+       REPO=$(nonempty_option 'update' 'REPO' "${1}") || return 1
        maxargs 'disconnect' 1 "${@}" || return 1
 
        # Update once a week from our remote repository.  Mark updates by
@@ -736,7 +789,7 @@ function update()
                "${TOUCH}" "${UPDATE_FILE}" || return 1
                fetch "${REPO}" || return 1
                patch "${REPO}" || return 1
-               link "${REPO}" || return 1
+               link ${LINK_OPTS} "${REPO}" || return 1
                echo "${REPO} dotfiles updated"
        fi
 }
@@ -787,8 +840,8 @@ function main()
                                echo "${VERSION}"
                                return
                                ;;
-                       '--dotfiles-dir')
-                                       DOTFILES_DIR="${2}"
+                       '--dotfiles-dir')
+                               DOTFILES_DIR="${2}"
                                shift
                                ;;
                        '--target')
@@ -817,10 +870,10 @@ function main()
                        shift
                done
                if [ "${#}" -eq 0 ]; then
-                       run_on_all_repos "${COMMAND}" "${OPTIONS[@]}" || return 1
+                       run_on_all_repos "${COMMAND}" "${OPTIONS[@]}" || return 1
                else
                        maxargs "${0}" 1 "${@}" || return 1
-                       "${COMMAND}" "${OPTIONS[@]}" "${1}" || return 1
+                       "${COMMAND}" "${OPTIONS[@]}" "${1}" || return 1
                fi
        fi
 }