Pass update() options through to link().
[dotfiles-framework.git] / dotfiles.sh
index cf3af80cbdc0925dea8f49bbd3fd52ff34c49f8d..a1379a33d2d3859c6ce31f777d131e9f93e809c3 100755 (executable)
@@ -130,7 +130,7 @@ function list_files()
        done < <(cd "${DIR}" && find .)
 }
 
-# Global variable to allow passing associative arrats between functions
+# Global variable to allow passing associative arrays between functions
 
 if [ "${BASH_MAJOR}" -ge 4 ]; then
        declare -A REPO_SOURCE_DATA
@@ -232,11 +232,13 @@ function wget_fetch()
 # usage: link_file REPO FILE
 #
 # Create the symbolic link to the version of FILE in the REPO
-# repository, overriding the target if it exists.
+# repository, overriding the target if it exists.  If you want to
+# override the options passed to ${LN}, set LINK_OPTS.
 function link_file()
 {
        REPO=$(nonempty_option 'link_file' 'REPO' "${1}") || return 1
        FILE=$(nonempty_option 'link_file' 'FILE' "${2}") || return 1
+       LINK_OPTS="${LINK_OPTS:--sv}"  # default to `-sv`
        if [ "${BACKUP}" = 'yes' ]; then
                if [ -e "${TARGET}/${FILE}" ] || [ -h "${TARGET}/${FILE}" ]; then
                        if [ "${DRY_RUN}" = 'yes' ]; then
@@ -256,8 +258,9 @@ function link_file()
        if [ "${DRY_RUN}" = 'yes' ]; then
                echo "link ${TARGET}/${FILE} to ${DOTFILES_DIR}/${REPO}/patched-src/${FILE}"
        else
+               SOURCE="${DOTFILES_DIR}/${REPO}/patched-src/${FILE}"
                echo -n 'link '
-               "${LN}" -rsv "${DOTFILES_DIR}/${REPO}/patched-src/${FILE}" "${TARGET}/${FILE}" || return 1
+               "${LN}" ${LINK_OPTS} "${SOURCE}" "${TARGET}/${FILE}" || return 1
        fi
 }
 
@@ -524,7 +527,7 @@ function link_help()
        cat <<-EOF
 
                usage: $0 ${COMMAND} [--force] [--force-dir] [--force-file] [--force-link]
-             [--dry-run] [--no-backup] [REPO]
+                          [--dry-run] [--no-backup] [--relative] [REPO]
 
                Where 'REPO' is the name the dotfiles repository to link.  If it
                is not given, all repositories will be linked.
@@ -533,6 +536,9 @@ function link_help()
                simlinks.  You can optionally overwrite any local stuff by passing
                the --force option.  If you only want to overwrite a particular
                type, use the more granular --force-dir, etc.
+
+               If you have coreutils 8.16 (2012-03-26) or greater, you can set
+               the --relative option to create symlinks that use relative paths.
        EOF
 }
 
@@ -543,6 +549,7 @@ function link()
        FORCE_LINK='no'   # If 'yes', overwrite existing symlinks.
        DRY_RUN='no' # If 'yes', disable any actions that change the filesystem
        BACKUP_OPT='yes'
+       LINK_OPTS='-sv'
        while [ "${1::2}" = '--' ]; do
                case "${1}" in
                        '--force')
@@ -565,6 +572,9 @@ function link()
                        '--no-backup')
                                BACKUP_OPT='no'
                                ;;
+                       '--relative')
+                               LINK_OPTS="${LINK_OPTS} --relative"
+                               ;;
                        *)
                                echo "ERROR: invalid option to link (${1})" >&2
                                return 1
@@ -582,6 +592,9 @@ function link()
                        if [ "${FORCE_LINK}" = 'no' ]; then
                                # don't prompt about --force-link, because this will happen a lot
                                continue  # already simlinked
+                       elif [ ! -h "${TARGET}/${FILE}" ]; then
+                               # target file/dir underneath an already symlinked dir
+                               continue
                        else
                                # don't backup links that already point to the right place
                                BACKUP='no'
@@ -630,7 +643,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"
 
@@ -695,7 +708,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.
@@ -704,13 +717,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
@@ -723,7 +744,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
 }