src/mulle-bootstrap-clean.sh
c81c8721
 #! /usr/bin/env bash
5de2fbd6
 #
d7f96955
 #   Copyright (c) 2015 Nat! - Mulle kybernetiK
 #   All rights reserved.
5de2fbd6
 #
d7f96955
 #   Redistribution and use in source and binary forms, with or without
 #   modification, are permitted provided that the following conditions are met:
 #
 #   Redistributions of source code must retain the above copyright notice, this
 #   list of conditions and the following disclaimer.
 #
 #   Redistributions in binary form must reproduce the above copyright notice,
 #   this list of conditions and the following disclaimer in the documentation
 #   and/or other materials provided with the distribution.
 #
 #   Neither the name of Mulle kybernetiK nor the names of its contributors
 #   may be used to endorse or promote products derived from this software
 #   without specific prior written permission.
 #
 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 #   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 #   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 #   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 #   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 #   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 #   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 #   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 #   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 #   POSSIBILITY OF SUCH DAMAGE.
8f951e19
 #
a3018cdd
 MULLE_BOOTSTRAP_CLEAN_SH="included"
d7f96955
 
5de2fbd6
 
ed001110
 _collect_stashdir()
 {
    log_debug ":_collect_stashdir:" "$*"
 
    # local reposdir="$1"  # ususally .bootstrap.repos
    # local name="$2"      # name of the clone
    # local url="$3"       # URL of the clone
    # local branch="$4"    # branch of the clone
    # local scm="$5"       # scm to use for this clone
    # local tag="$6"       # tag to checkout of the clone
    local stashdir="$7"  # stashdir of this clone (absolute or relative to $PWD)
 
    is_minion_bootstrap_project "${stashdir}" && return
 
d87a5262
    case "${stashdir}" in
       stashes/*)
          return
       ;;
    esac
ed001110
 
    echo "${stashdir}"
 }
 
 
 #
 # MEMO don't walk via .bootstrap.auto here, use information from
 # .bootstrap.repos
 #
 print_stashdir_repositories()
 {
    local permissions
 
    permissions=""
    walk_repos_repositories "${REPOS_DIR}" \
                            "_collect_stashdir" \
                            "${permissions}"
 }
 
 
 print_embedded_stashdir_repositories()
 {
    local permissions
 
    permissions=""
    walk_repos_repositories "${EMBEDDED_REPOS_DIR}" \
                             "_collect_stashdir" \
                             "${permissions}"
 }
 
 
 print_stashdir_deep_embedded_repositories()
 {
    local permissions
 
    permissions="minion"
    walk_deep_embedded_repos_repositories "_collect_stashdir" \
                                          "${permissions}"
 }
 
 
 _collect_embedded_stashdir()
 {
    # local reposdir="$1"  # ususally .bootstrap.repos
    # local name="$2"      # name of the clone
    # local url="$3"       # URL of the clone
    # local branch="$4"    # branch of the clone
    # local scm="$5"       # scm to use for this clone
    # local tag="$6"       # tag to checkout of the clone
    local stashdir="$7"  # stashdir of this clone (absolute or relative to $PWD)
 
    stashparentdir="`dirname -- "${stashdir}"`"
 
    [ "${stashparentdir}" = "${STASHES_DEFAULT_DIR}" ] && return
    echo "${stashdir}"
 }
 
 
 print_stashdir_embedded_repositories()
 {
    walk_auto_repositories "embedded_repositories" \
0fc9abbe
                           "_collect_embedded_stashdir" \
                           "" \
                           "${EMBEDDED_REPOS_DIR}"
ed001110
 }
 
 
096b64ec
 setup_clean_environment()
 {
e5b54e85
    [ -z "${DEPENDENCIES_DIR}"  ]   && internal_fail "DEPENDENCIES_DIR is empty"
0fc9abbe
    [ -z "${CLONESBUILD_DIR}" ]     && internal_fail "CLONESBUILD_DIR is empty"
e5b54e85
    [ -z "${ADDICTIONS_DIR}" ]      && internal_fail "ADDICTIONS_DIR is empty"
    [ -z "${STASHES_DEFAULT_DIR}" ] && internal_fail "STASHES_DEFAULT_DIR is empty"
821cd36e
 
096b64ec
    CLEAN_EMPTY_PARENTS="`read_config_setting "clean_empty_parent_folders" "YES"`"
 
4a9f82b9
    OUTPUT_CLEANABLE_FILES="${REPOS_DIR}/.build_done"
2f8d42a5
 
d87a5262
    BUILD_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "clean_folders" "${CLONESBUILD_DIR}
bba581f8
 ${DEPENDENCIES_DIR}/tmp"`"
    OUTPUT_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "output_clean_folders" "${DEPENDENCIES_DIR}"`"
    INSTALL_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "install_clean_folders" "${REPOS_DIR}
f1f83418
 ${STASHES_DEFAULT_DIR}
096b64ec
 .bootstrap.auto"`"
ed001110
    DIST_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "dist_clean_folders" \
 "${REPOS_DIR}
bba581f8
 ${ADDICTIONS_DIR}
f1f83418
 ${STASHES_DEFAULT_DIR}
ed001110
 ${BOOTSTRAP_DIR}.auto"`"
 
    # scrub old stuff
    if [ -d ".repos" ]
    then
       DIST_CLEANABLE_SUBDIRS="`add_line "${DIST_CLEANABLE_SUBDIRS}" ".repos"`"
    fi
 
    [ -z "${MULLE_BOOTSTRAP_REPOSITORIES_SH}" ] && . mulle-bootstrap-repositories.sh
 
    #
    # as a master we don't throw the minions out
    #
    local stashes
 
    stashes="`print_stashdir_repositories`"
    DIST_CLEANABLE_SUBDIRS="`add_line "${DIST_CLEANABLE_SUBDIRS}" "${stashes}"`"
096b64ec
 
ed001110
    stashes="`print_stashdir_embedded_repositories`"
    DIST_CLEANABLE_SUBDIRS="`add_line "${DIST_CLEANABLE_SUBDIRS}" "${stashes}"`"
 
    stashes="`print_stashdir_deep_embedded_repositories`"
    DIST_CLEANABLE_SUBDIRS="`add_line "${DIST_CLEANABLE_SUBDIRS}" "${stashes}"`"
096b64ec
 }
 
 
151c6f06
 clean_usage()
40fe269d
 {
151c6f06
    cat <<EOF >&2
 usage:
    mulle-bootstrap clean [build|dist|install|output]
 
 EOF
 
096b64ec
    setup_clean_environment
3c8ec4d2
 
096b64ec
    cat <<EOF >&2
ed001110
    build : remove intermediate build files to conserve space. It deletes
 `echo "${BUILD_CLEANABLE_SUBDIRS}" | sort | sed '/^$/d' | sed -e 's/^/      /'`
 
    output : useful to rebuild. It deletes
 `echo "${BUILD_CLEANABLE_SUBDIRS}
 ${OUTPUT_CLEANABLE_FILES}
 ${OUTPUT_CLEANABLE_SUBDIRS}"  | sort| sed '/^$/d' | sed -e 's/^/      /'`
3c8ec4d2
 
ed001110
    install : keep only addictions and dependencies
 `echo "${BUILD_CLEANABLE_SUBDIRS}
 ${OUTPUT_CLEANABLE_FILES}
 ${INSTALL_CLEANABLE_SUBDIRS}" | sort | sed '/^$/d' | sed -e 's/^/      /'`
821cd36e
 
ed001110
    dist : remove all clones, dependencies, addictions. It deletes
 `echo "${BUILD_CLEANABLE_SUBDIRS}
e5b54e85
 ${OUTPUT_CLEANABLE_SUBDIRS}
ed001110
 ${DIST_CLEANABLE_SUBDIRS}"    | sort | sed '/^$/d' | sed -e 's/^/      /'`
3c8ec4d2
 EOF
096b64ec
 
a3018cdd
    exit 1
40fe269d
 }
 
 
3be635de
 clean_asserted_folder()
 {
c6e7156e
    if [ -d "$1" ]
    then
       log_info "Deleting \"$1\""
a7b563e1
 
       rmdir_safer "$1"
c6e7156e
    else
       log_fluff "\"$1\" doesn't exist"
    fi
 }
 
 
2f8d42a5
 clean_asserted_file()
 {
    if [ -f "$1" ]
    then
       log_info "Deleting \"$1\""
 
       remove_file_if_present "$1"
    else
       log_fluff "\"$1\" doesn't exist"
    fi
 }
 
 
28ed6b30
 clean_parent_folders_if_empty()
 {
ed001110
    local dir="$1"
    local stop="$2"
28ed6b30
 
    if [ "${CLEAN_EMPTY_PARENTS}" = "YES" ]
    then
       local parent
 
       parent="${dir}"
       while :
       do
a203984b
          parent="`dirname -- "${parent}"`"
28ed6b30
          if [ "${parent}" = "." -o "${parent}" = "${stop}" ]
          then
              break
          fi
 
8f77be37
          if dir_is_empty "${parent}"
28ed6b30
          then
             assert_sane_subdir_path "${parent}"
8ca22e9e
             log_info "Deleting \"${parent}\" because it was empty. "
bba581f8
             log_fluff "Set \"${BOOTSTRAP_DIR}/config/clean_empty_parent_folders\" to NO if you don't like it."
28ed6b30
             exekutor rmdir "${parent}"
          fi
       done
    fi
 }
 
 
2f8d42a5
 clean_files()
 {
ed001110
    local files="$1"
2f8d42a5
 
    local file
 
    IFS="
 "
    for file in ${files}
    do
5c06c0e8
       IFS="${DEFAULT_IFS}"
2f8d42a5
 
       clean_asserted_file "${file}"
    done
 
5c06c0e8
    IFS="${DEFAULT_IFS}"
2f8d42a5
 }
 
 
ec2b9bc2
 clean_directories()
 {
ed001110
    local directories="$1"
ec2b9bc2
 
    local directory
 
    IFS="
 "
    for directory in ${directories}
    do
5c06c0e8
       IFS="${DEFAULT_IFS}"
 
ec2b9bc2
       clean_asserted_folder "${directory}"
       clean_parent_folders_if_empty "${directory}" "${PWD}"
    done
9339a58a
 
ed001110
    IFS="${DEFAULT_IFS}"
4805e856
 }
 
 
096b64ec
 #
 # for mingw its faster, if we have separate clean functions
5de2fbd6
 #
 # cleanability is checked, because in some cases its convenient
 # to have other tools provide stuff besides /include and /lib
 # and sometimes  projects install other stuff into /share
e3bb0c25
 #
ed001110
 clean_execute()
8e817cc1
 {
151c6f06
    local style="$1"
 
f1f83418
    [ -z "${DEPENDENCIES_DIR}"  ]   && internal_fail "DEPENDENCIES_DIR is empty"
d87a5262
    [ -z "${CLONESBUILD_DIR}" ]  && internal_fail "CLONESBUILD_DIR is empty"
f1f83418
    [ -z "${ADDICTIONS_DIR}"   ]    && internal_fail "ADDICTIONS_DIR is empty"
    [ -z "${STASHES_DEFAULT_DIR}" ] && internal_fail "STASHES_DEFAULT_DIR is empty"
c6e7156e
 
ed001110
    setup_clean_environment
2f8d42a5
 
151c6f06
    case "${style}" in
ec2b9bc2
       build)
d87a5262
          BUILD_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "clean_folders" "${CLONESBUILD_DIR}
bba581f8
 ${DEPENDENCIES_DIR}/tmp"`"
ed001110
          clean_directories "${BUILD_CLEANABLE_SUBDIRS}"
ec2b9bc2
          return
       ;;
8e817cc1
 
ec2b9bc2
       dist|output|install)
d87a5262
          BUILD_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "clean_folders" "${CLONESBUILD_DIR}
bba581f8
 ${DEPENDENCIES_DIR}/tmp"`"
ed001110
 
          clean_directories "${BUILD_CLEANABLE_SUBDIRS}"
ec2b9bc2
       ;;
151c6f06
 
       *)
          internal_fail "Unknown clean style \"${style}\""
       ;;
ec2b9bc2
    esac
5de2fbd6
 
151c6f06
    case "${style}" in
ec2b9bc2
       output)
bba581f8
          OUTPUT_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "output_clean_folders" "${DEPENDENCIES_DIR}"`"
ed001110
 
          clean_directories "${OUTPUT_CLEANABLE_SUBDIRS}"
2f8d42a5
          clean_files "${OUTPUT_CLEANABLE_FILES}"
ec2b9bc2
          return
       ;;
5de2fbd6
 
ec2b9bc2
       dist)
bba581f8
          OUTPUT_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "output_clean_folders" "${DEPENDENCIES_DIR}"`"
ed001110
 
          clean_directories "${OUTPUT_CLEANABLE_SUBDIRS}"
2f8d42a5
          clean_files "${OUTPUT_CLEANABLE_FILES}"
ec2b9bc2
       ;;
    esac
 
151c6f06
    case "${style}" in
ec2b9bc2
       install)
bba581f8
          INSTALL_CLEANABLE_SUBDIRS="`read_sane_config_path_setting "install_clean_folders" "${REPOS_DIR}
ec2b9bc2
 .bootstrap.auto"`"
ed001110
 
          clean_directories "${INSTALL_CLEANABLE_SUBDIRS}"
ec2b9bc2
          return
       ;;
    esac
 
151c6f06
    case "${style}" in
ec2b9bc2
       dist)
ed001110
          clean_directories "${DIST_CLEANABLE_SUBDIRS}"
ec2b9bc2
       ;;
    esac
 }
821cd36e
 
c6e7156e
 
0fc9abbe
 #
 # clean embedded repositories out of minion
 #
 clean_minion()
 {
    local minion="$1"
 
    local directories
 
    [ -z "${MULLE_BOOTSTRAP_REPOSITORIES_SH}" ] && . mulle-bootstrap-repositories.sh
 
    directories="`_all_repository_stashes "${REPOS_DIR}/.deep/${minion}.d"`"
    clean_directories "${directories}"
    clean_directories "${REPOS_DIR}/.deep/${minion}.d"
 }
 
 
ec2b9bc2
 #
 # don't rename these settings anymore, the consequences can be catastrophic
 # for users of previous versions.
 # Also don't change the search paths for read_sane_config_path_setting
 #
a3018cdd
 clean_main()
8e817cc1
 {
9339a58a
    log_debug "::: clean :::"
c6e7156e
 
0fc9abbe
    local MINION_NAME
 
151c6f06
    [ -z "${MULLE_BOOTSTRAP_SETTINGS_SH}" ]        && . mulle-bootstrap-settings.sh
8f951e19
    [ -z "${MULLE_BOOTSTRAP_COMMON_SETTINGS_SH}" ] && . mulle-bootstrap-common-settings.sh
ed001110
    [ -z "${MULLE_BOOTSTRAP_REPOSITORIES_SH}" ]    && . mulle-bootstrap-repositories.sh
a3018cdd
 
fcf4306a
    [ -z "${DEFAULT_IFS}" ] && internal_fail "IFS fail"
 
096b64ec
    while [ $# -ne 0 ]
    do
       case "$1" in
          -h|-help|--help)
151c6f06
             clean_usage
096b64ec
          ;;
 
0fc9abbe
 
          -m|--minion)
             shift
             [ $# -ne 0 ] || clean_usage
 
             MINION_NAME="${1}"
          ;;
 
096b64ec
          -*)
f67f6857
             log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown clean option $1"
151c6f06
             clean_usage
096b64ec
          ;;
 
          *)
             break
          ;;
       esac
 
       shift
    done
 
151c6f06
    local style
096b64ec
 
151c6f06
    style=${1:-"output"}
a3018cdd
 
3ee7ef17
    case "${style}" in
       "output"|"dist"|"build"|"install")
0fc9abbe
 
          if [ -z "${MINION_NAME}" ]
          then
             clean_execute "${style}"
          else
             clean_minion "${MINION_NAME}"
          fi
a3018cdd
       ;;
ec2b9bc2
 
096b64ec
       help)
          clean_usage
       ;;
 
a3018cdd
       *)
151c6f06
          log_error "Unknown clean style \"${style}\""
1fddbf4e
          clean_usage
a3018cdd
       ;;
    esac
8e817cc1
 }