src/mulle-bootstrap-fetch.sh
c81c8721
 #! /usr/bin/env bash
5de2fbd6
 #
 #   Copyright (c) 2015 Nat! - Mulle kybernetiK
 #   All rights reserved.
 #
 #   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.
c81c8721
 #
5de2fbd6
 
a3018cdd
 MULLE_BOOTSTRAP_FETCH_SH="included"
 
5de2fbd6
 #
 # this script installs the proper git clones into "clones"
 # it does not to git subprojects.
 # You can also specify a list of "brew" dependencies. That
 # will be third party libraries, you don't tag or debug
 #
8f951e19
 #
 # ## NOTE ##
 #
 # There is a canonical argument passing scheme, which gets passed to and
 # forwarded by most function
 #
 # reposdir="$1"   # ususally .bootstrap.repos
 # name="$2"       # name of the clone
 # url="$3"        # URL of the clone
 # branch="$4"     # branch of the clone
 # scm="$5"        # scm to use for this clone
 # tag="$6"        # tag to checkout of the clone
 # stashdir="$7"     # stashdir of this clone (absolute or relative to $PWD)
 #
a3018cdd
 
 fetch_usage()
40fe269d
 {
eff55101
    cat <<EOF >&2
4eff2e57
 Usage:
    ${MULLE_EXECUTABLE} ${COMMAND} [options] [repositories]
55a86360
 
4eff2e57
    You can specify the names of the repositories to update.
55a86360
 
4eff2e57
 Commands:
55a86360
    install  :  clone or symlink non-exisiting repositories and other resources
8f951e19
    update   :  execute a "fetch" in already fetched repositories
    upgrade  :  execute a "pull" in fetched repositories
40fe269d
 
4eff2e57
 Options:
    --caches            :  use CACHES_PATH to locate local repositories
    --check-usr-local   :  check /usr/local for duplicates
    --embedded-only     :  fetch embedded repositories only
 
    --symlinks          :  allow symlinking instead of cloning
    --embedded-symlinks :  allow embedded symlinks (very experimental)
    --follow-symlinks   :  follow symlinks when updating (not recommended)
    --no-caches         :  don't use caches. Useful to counter flag -y
402c4cb7
    --no-git-mirror     :  don't mirror fetched git repositories
4eff2e57
    --no-symlinks       :  don't create symlinks. Useful to counter flag -y
 
40fe269d
 EOF
cf2eebc9
 
    local  repositories
 
8f951e19
    repositories="`all_repository_names`"
cf2eebc9
    if [ -z "${repositories}" ]
55a86360
    then
       echo "Currently available repositories are:"
cf2eebc9
       echo "${repositories}" | sed 's/^/   /'
55a86360
    fi
a3018cdd
    exit 1
40fe269d
 }
 
 
8f951e19
 assert_sane_parameters()
1e8d5d86
 {
8f951e19
    local  empty_reposdir_is_ok="$1"
1e8d5d86
 
8f951e19
    [ ! -z "${empty_reposdir_is_ok}" -a -z "${reposdir}" ] && internal_fail "parameter: reposdir is empty"
    [ -z "${empty_reposdir_is_ok}" -a ! -d "${reposdir}" ] && internal_fail "parameter: reposdir does not exist ($reposdir)"
fcf4306a
 
8f951e19
    [ -z "${url}" ]      && internal_fail "parameter: url is empty"
    [ -z "${name}" ]     && internal_fail "parameter: name is empty"
    [ -z "${stashdir}" ] && internal_fail "parameter: stashdir is empty"
1e8d5d86
 
8f951e19
    :
1e8d5d86
 }
 
 #
 # future, download tarballs...
422c21da
 # we check for existance during fetch, but install during build
fe01cf28
 #
1e8d5d86
 check_tars()
 {
    local tarballs
    local tar
 
    log_fluff "Looking for tarballs"
 
8f951e19
    tarballs="`read_root_setting "tarballs" | sort | sort -u`"
11a51a36
    if [ ! -z "${tarballs}" ]
1e8d5d86
    then
fcf4306a
       [ -z "${DEFAULT_IFS}" ] && internal_fail "IFS fail"
1e8d5d86
       IFS="
 "
       for tar in ${tarballs}
       do
5c06c0e8
          IFS="${DEFAULT_IFS}"
 
1e8d5d86
          if [ ! -f "$tar" ]
          then
             fail "tarball \"$tar\" not found"
          fi
          log_fluff "tarball \"$tar\" found"
       done
5c06c0e8
       IFS="${DEFAULT_IFS}"
 
1e8d5d86
    else
       log_fluff "No tarballs found"
    fi
 }
 
 
8f951e19
 log_action()
 {
    local action="$1" ; shift
 
    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)
 
    assert_sane_parameters "empty reposdir is ok"
 
    local info
 
    if [ -L "${url}" ]
    then
       info=" symlinked "
    else
       info=" "
    fi
 
    log_fluff "Perform ${action}${info}${url} into ${stashdir} ..."
 }
 
f1f83418
 
1e8d5d86
 #
 ###
 #
5de2fbd6
 link_command()
 {
f1f83418
 #   local reposdir="$1"  # ususally .bootstrap.repos
 #   local name="$2"      # name of the clone
8f951e19
    local url="$3"       # URL of the clone
    local branch="$4"    # branch of the clone
f1f83418
 #   local scm="$5"       # scm to use for this clone
8f951e19
    local tag="$6"       # tag to checkout of the clone
    local stashdir="$7"  # stashdir of this clone (absolute or relative to $PWD)
5de2fbd6
 
8f951e19
    assert_sane_parameters "empty reposdir is ok"
d34d04ad
 
f1f83418
    local absolute
 
    absolute="`read_config_setting "absolute_symlinks" "NO"`"
11a51a36
    if ! exekutor create_symlink "${url}" "${stashdir}" "${absolute}"
    then
       return 1
    fi
f1f83418
 
d34d04ad
    local branchlabel
 
    branchlabel="branch"
    if [ -z "${branch}" -a ! -z "${tag}" ]
    then
       branchlabel="tag"
       branch="${tag}"
    fi
5de2fbd6
 
ea74a237
    if [ "${branch}" != "master" ]
8f951e19
    then
4eff2e57
       log_warning "The intended ${branchlabel} ${C_RESET_BOLD}${branch}${C_WARNING} \
 will be ignored, because the repository is symlinked.
 If you want to checkout this ${branchlabel} do:
    ${C_RESET_BOLD}(cd ${stashdir}; git checkout ${GITOPTIONS} \"${branch}\" )${C_WARNING}"
5de2fbd6
    fi
 }
 
 
e5b54e85
 can_symlink_it()
5de2fbd6
 {
e5b54e85
    local  directory="$1"
d9c7fdec
 
e5b54e85
    if [ "${OPTION_ALLOW_CREATING_SYMLINKS}" != "YES" ]
5de2fbd6
    then
0fc9abbe
       log_fluff "Can't symlink it, because forbidden"
e5b54e85
       return 1
5de2fbd6
    fi
 
e5b54e85
    case "${UNAME}" in
       minwgw)
0fc9abbe
          log_fluff "Can't symlink it, because symlinking is unavailable on this platform"
e5b54e85
          return 1
       ;;
    esac
 
    if git_is_repository "${directory}"
5de2fbd6
    then
f146fd2e
        # if bare repo, we can only clone anyway
e5b54e85
       if git_is_bare_repository "${directory}"
f146fd2e
       then
402c4cb7
          log_verbose "${directory} is a bare git repository. So no symlinking"
f146fd2e
          return 1
       fi
e5b54e85
    else
402c4cb7
       log_info "${directory} is not a git repository (yet ?)
 So symlinking is the only way to go."
e5b54e85
    fi
f146fd2e
 
e5b54e85
   return 0
 }
a75ed0ba
 
 
550b5448
 _search_for_git_repository_in_cache()
602ae7d9
 {
8f951e19
    local directory
602ae7d9
    local name
    local branch
 
8f951e19
    [ $# -ne 3 ] && internal_fail "fail"
bba581f8
 
8f951e19
    directory="$1"
    name="$2"
    branch="$3"
602ae7d9
 
    local found
 
0fc9abbe
    if [ "${MULLE_FLAG_LOG_CACHE}" = "YES" ]
    then
       log_trace "Checking cache path \"${directory}\""
    fi
 
602ae7d9
    if [ ! -z "${branch}" ]
    then
8f951e19
       found="${directory}/${name}.${branch}"
       log_fluff "Looking for \"${found}\""
 
602ae7d9
       if [ -d "${found}" ]
       then
8f951e19
          log_fluff "Found \"${name}.${branch}\" in \"${directory}\""
 
602ae7d9
          echo "${found}"
          return
       fi
    fi
 
550b5448
    found="${directory}/${name}.git"
    log_fluff "Looking for \"${found}\""
    if [ -d "${found}" ]
    then
       log_fluff "Found \"${name}.git\" in \"${directory}\""
 
       echo "${found}"
       return
    fi
 
8f951e19
    found="${directory}/${name}"
    log_fluff "Looking for \"${found}\""
602ae7d9
    if [ -d "${found}" ]
    then
8f951e19
       log_fluff "Found \"${name}\" in \"${directory}\""
 
602ae7d9
       echo "${found}"
       return
    fi
550b5448
 }
602ae7d9
 
550b5448
 
 search_for_git_repository_in_caches()
 {
cbe9e1a7
    log_debug "search_for_git_repository_in_caches" "$@" "(${CACHES_PATH})"
 
550b5448
    local found
    local directory
0b9e9e49
    local realdir
    local curdir
550b5448
 
0fc9abbe
    if [ "${MULLE_FLAG_LOG_CACHE}" = "YES" -a -z "${CACHES_PATH}" ]
    then
       log_trace "CACHES_PATH is empty"
    fi
 
0b9e9e49
    curdir="`pwd -P`"
550b5448
    IFS=":"
    for directory in ${CACHES_PATH}
    do
       IFS="${DEFAULT_IFS}"
 
23dc6164
       if [ ! -d "${directory}" ]
550b5448
       then
0fc9abbe
          if [ "${MULLE_FLAG_LOG_CACHE}" = "YES" ]
          then
             log_trace2 "Cache path \"${realdir}\" does not exist"
          fi
23dc6164
          continue
       fi
 
       realdir="`realpath "${directory}"`"
       if [ "${realdir}" = "${curdir}" ]
       then
4eff2e57
          fail "config setting \"search_path\" mistakenly contains \"${directory}\", which is the current directory"
23dc6164
       fi
 
       found="`_search_for_git_repository_in_cache "${realdir}" "$@"`" || exit 1
       if [ ! -z "${found}" ]
       then
402c4cb7
          echo "${found}"
23dc6164
          return
550b5448
       fi
    done
 
    IFS="${DEFAULT_IFS}"
    return 1
 }
 
 
 _search_for_archive_in_caches()
 {
cbe9e1a7
    log_debug "_search_for_archive_in_caches" "$@"
 
550b5448
    local directory="$1"
    local name="$2"
    local filename="$3"
 
    [ $# -ne 3 ] && internal_fail "fail"
 
    local found
 
    found="${directory}/${name}-${filename}"
8f951e19
    log_fluff "Looking for \"${found}\""
db28bb90
    if [ -f "${found}" ]
602ae7d9
    then
550b5448
       log_fluff "Found \"${name}\" in \"${directory}\" as \"${found}\""
 
       echo "${found}"
       return
    fi
 
    found="${directory}/${filename}"
    log_fluff "Looking for \"${found}\""
db28bb90
    if [ -f "${found}" ]
550b5448
    then
       log_fluff "Found \"${name}\" in \"${directory}\" as \"${found}\""
8f951e19
 
602ae7d9
       echo "${found}"
       return
    fi
 }
 
 
550b5448
 search_for_archive_in_caches()
1e8d5d86
 {
cbe9e1a7
    log_debug "search_for_archive_in_caches" "$@" "(${CACHES_PATH})"
 
550b5448
    local name="$1"
    local filename="$2"
 
8f951e19
    local found
e5b54e85
    local directory
1e8d5d86
 
e5b54e85
    IFS=":"
    for directory in ${CACHES_PATH}
    do
       IFS="${DEFAULT_IFS}"
 
550b5448
       found="`_search_for_archive_in_caches "${directory}" "${name}" "${filename}"`" || exit 1
e5b54e85
       if [ ! -z "${found}" ]
       then
550b5448
          found="`absolutepath "${found}"`"
          echo "file:///${found}"
e5b54e85
          return
       fi
    done
 
    IFS="${DEFAULT_IFS}"
550b5448
    return 1
8f951e19
 }
1e8d5d86
 
 
8f951e19
 mkdir_stashparent_if_missing()
 {
    local stashdir="$1"
1e8d5d86
 
8f951e19
    local stashparent
 
    stashparent="`dirname -- "${stashdir}"`"
    case "${stashparent}" in
       ""|"\.")
       ;;
 
       *)
          mkdir_if_missing "${stashparent}"
          echo "${stashparent}"
       ;;
    esac
 }
 
f1f83418
 
550b5448
 get_cache_item()
 {
    local reposdir="$1"  # ususally .bootstrap.repos
    local name="$2"      # name of the clone, extensionless
    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)
 
    if [ "${OPTION_ALLOW_SEARCH_CACHES}" = "NO" ]
    then
0fc9abbe
       log_fluff "Not searching caches because --no-caches"
550b5448
       return
    fi
 
    case "${scm}" in
       git*)
          search_for_git_repository_in_caches "${name}" "${branch}"
       ;;
 
       tar*|zip*)
          search_for_archive_in_caches "${name}" "`basename -- "${url}"`"
       ;;
0fc9abbe
 
       *)
          log_fluff "Not searching caches because scm is \"${scm}\""
       ;;
550b5448
    esac
 }
 
 
8f951e19
 clone_or_symlink()
 {
    local reposdir="$1"  # ususally .bootstrap.repos
f1f83418
    local name="$2"      # name of the clone, extensionless
8f951e19
    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)
 
0fc9abbe
 
8f951e19
    assert_sane_parameters "empty reposdir is ok"
 
    [ $# -le 7 ] || internal_fail "too many parameters"
1e8d5d86
 
7fdfcd11
    local operation
bf4c7902
    local scmflagsdefault
7fdfcd11
 
bf4c7902
    case "${scm}" in
1461fe52
       git*)
7fdfcd11
          operation="git_clone"
8f951e19
       ;;
 
1461fe52
       svn*)
c2e2e596
          operation="svn_checkout"
       ;;
 
550b5448
       zip*)
          operation="zip_unpack"
       ;;
 
       tar*)
          operation="tar_unpack"
       ;;
 
7fdfcd11
       *)
f543b0c7
          fail "Unknown scm system \"${scm}\""
8f951e19
       ;;
7fdfcd11
    esac
 
8f951e19
    local stashparent
 
    stashparent="`mkdir_stashparent_if_missing "${stashdir}"`"
 
7fdfcd11
    local found
    local script
 
8f951e19
    script="`find_root_setting_file "bin/clone.sh"`"
1e8d5d86
 
    if [ ! -z "${script}" ]
    then
d87a5262
       run_script "${script}" "$@"
8f951e19
       return $?
    fi
1e8d5d86
 
8f951e19
    case "${url}" in
       /*)
ba567f56
          if can_symlink_it "${directory}"
8f951e19
          then
             operation=link_command
          fi
       ;;
 
       #
       # don't move up using url
       #
       */\.\./*|\.\./*|*/\.\.|\.\.)
          internal_fail "Faulty url \"${url}\" should have been caught before"
       ;;
 
       *)
550b5448
          found="`get_cache_item "${reposdir}" \
                                 "${name}" \
                                 "${url}" \
                                 "${branch}" \
                                 "${scm}" \
                                 "${tag}" \
                                 "${stashdir}"`"
1e8d5d86
 
550b5448
          if [ ! -z "${found}" ]
          then
ba567f56
             url="${found}"
 
             case "${scm}" in
1461fe52
                git*)
ba567f56
                   if can_symlink_it "${url}"
                   then
                      operation=link_command
                   fi
                ;;
             esac
 
             case "${operation}" in
                link_command)
402c4cb7
                  log_verbose "Using symlink to cached item \"${found}\""
 
                  # compatible to earlier code
                  found="`symlink_relpath "${found}" "${ROOT_DIR}"`"
ba567f56
                ;;
 
                *)
402c4cb7
                  log_verbose "Using cached item \"${found}\""
ba567f56
                ;;
             esac
8f951e19
          fi
       ;;
    esac
602ae7d9
 
11a51a36
    local rval
 
    if ! "${operation}" "${reposdir}" \
                        "${name}" \
                        "${url}" \
                        "${branch}" \
                        "${scm}" \
                        "${tag}" \
                        "${stashdir}"
    then
e400db11
       log_debug "Clone \"${operation}\" failed"
e3244671
       return 1
11a51a36
    fi
096b64ec
 
151c6f06
    if [ "${DONT_WARN_SCRIPTS}" != "YES" ]
    then
       [ -z "${MULLE_BOOTSTRAP_WARN_SCRIPTS_SH}" ] && . mulle-bootstrap-warn-scripts.sh
 
       warn_scripts_main "${stashdir}/.bootstrap" "${stashdir}" || fail "Ok, aborted"  #sic
    fi
ea74a237
 
    if [ "${operation}" = "link_command" ]
    then
e400db11
       log_debug "Symlink \"${operation}\" successful"
ea74a237
       return 2
    fi
 
e400db11
    log_debug "Clone \"${operation}\" successful"
ea74a237
    return 0
40fe269d
 }
 
8f951e19
 ##
 ## CLONE
 ##
151c6f06
 clone_repository()
fcf4306a
 {
8f951e19
    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)
fcf4306a
 
8f951e19
    [ $# -eq 7 ] || internal_fail "fail"
fcf4306a
 
151c6f06
    log_action "clone" "$@"
 
8f951e19
    assert_sane_parameters "empty is ok"
fcf4306a
 
f67f6857
    if [ "${OPTION_CHECK_USR_LOCAL_INCLUDE}" = "YES" ] && has_usr_local_include "${name}"
fcf4306a
    then
8f951e19
       log_info "${C_MAGENTA}${C_BOLD}${name}${C_INFO} is a system library, so not fetching it"
       return 1
fcf4306a
    fi
2279ad91
 
4805e856
    if [ -e "${stashdir}" ]
    then
f67f6857
       if [ "${url}" = "${stashdir}" ]
       then
          if is_master_bootstrap_project
          then
             is_minion_bootstrap_project "${stashdir}" || fail "\"${stashdir}\" \
 should be a minion but it isn't.
 Suggested fix:
4eff2e57
    ${C_RESET}${C_BOLD}cd \"${stashdir}\" ; ${MULLE_EXECUTABLE} defer \"\
f1f83418
 `symlink_relpath "${PWD}" "${stashdir}"`\
f67f6857
 \""
             log_info "${C_MAGENTA}${C_BOLD}${name}${C_INFO} is a minion, so cloning is skipped"
             return 1
          fi
       fi
0fc9abbe
       bury_stash "${reposdir}" "${name}" "${stashdir}"
4805e856
    fi
602ae7d9
 
ea74a237
    clone_or_symlink "$@"   # pass thru rval
602ae7d9
 }
 
79a901e7
 
8f951e19
 ##
 ## CHECKOUT
 ##
151c6f06
 checkout_repository()
40fe269d
 {
8f951e19
    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)
bf4c7902
 
151c6f06
    log_action "checkout" "$@"
 
8f951e19
    local operation
40fe269d
 
8f951e19
    case "${scm}" in
1461fe52
       git*)
8f951e19
          operation="git_checkout"
       ;;
1461fe52
       svn*)
8f951e19
          operation="svn_checkout"
       ;;
c2e2e596
       zip*|tar*)
          log_info "No checkout for \"${scm}\""
          return
       ;;
8f951e19
       *)
f543b0c7
          fail "Unknown scm system \"${scm}\""
8f951e19
       ;;
    esac
e18eee6f
 
8f951e19
    script="`find_build_setting_file "${name}" "bin/checkout.sh"`"
    if [ ! -z "${script}" ]
40fe269d
    then
d87a5262
       run_script "${script}" "$@"
e18eee6f
    else
8f951e19
       "${operation}" "$@"
e18eee6f
    fi
8f951e19
 }
1e8d5d86
 
 
8f951e19
 ##
 ## UPDATE
f1f83418
 ## this like git fetch, does not update repository
8f951e19
 ##
151c6f06
 update_repository()
8f951e19
 {
    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)
a75ed0ba
 
151c6f06
    log_action "update" "$@"
 
8f951e19
    local operation
79a901e7
 
8f951e19
    case "${scm}" in
1461fe52
       git*)
8f951e19
          operation="git_fetch"
       ;;
1461fe52
       svn*|zip*|tar*)
c2e2e596
          log_info "No update for \"${scm}\""
8f951e19
          return
       ;;
       *)
f543b0c7
          fail "Unknown scm system \"${scm}\""
8f951e19
       ;;
    esac
2f8d42a5
 
8f951e19
    script="`find_build_setting_file "${name}" "bin/update.sh"`"
    if [ ! -z "${script}" ]
    then
d87a5262
       run_script "${script}" "$@"
8f951e19
    else
       "${operation}" "$@"
    fi
40fe269d
 }
 
 
8f951e19
 ##
f1f83418
 ## UPGRADE
 ## This is a pull
5de2fbd6
 
151c6f06
 upgrade_repository()
8f951e19
 {
    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)
5de2fbd6
 
151c6f06
    log_action "upgrade" "$@"
 
8f951e19
    local operation
e3bb0c25
 
8f951e19
    case "${scm}" in
ea74a237
       git)
8f951e19
          operation="git_pull"
       ;;
c2e2e596
       svn|zip*|tar*)
          log_info "No upgrade for \"${scm}\""
8f951e19
          return
       ;;
       *)
f543b0c7
          fail "Unknown scm system \"${scm}\""
8f951e19
       ;;
    esac
fcf4306a
 
8f951e19
    script="`find_build_setting_file "${name}" "bin/upgrade.sh"`"
    if [ ! -z "${script}" ]
    then
d87a5262
       run_script "${script}" "$@"
8f951e19
    else
       "${operation}" "$@"
    fi
 }
5c06c0e8
 
1e8d5d86
 
e18eee6f
 #
8f951e19
 # Walk repositories with a callback function
e18eee6f
 #
ea74a237
 _update_operation_walk_repositories()
40fe269d
 {
ea74a237
    local operation="$1"
3ed530a3
 
8f951e19
    local permissions
3ed530a3
 
ed001110
    permissions="minion"
    walk_auto_repositories "repositories"  \
                           "${operation}" \
                           "${permissions}" \
                           "${REPOS_DIR}"
fe9be2f4
 
    permissions="minion"
    walk_auto_repositories "additional_repositories"  \
                           "${operation}" \
                           "${permissions}" \
                           "${REPOS_DIR}"
8f951e19
 }
7fdfcd11
 
 
ea74a237
 _update_operation_walk_embedded_repositories()
8f951e19
 {
ea74a237
    local operation="$1"
c6e7156e
 
8f951e19
    local permissions
6a672446
 
ed001110
    permissions="minion"
8f951e19
    #
    # embedded repositories can't be symlinked by default
    # embedded repositories are by default not put into
    # stashes (for backwards compatibility)
    #
    (
f1f83418
       STASHES_ROOT_DIR=""
       STASHES_DEFAULT_DIR=""
f67f6857
       OPTION_ALLOW_CREATING_SYMLINKS="${OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS}" ;
8f951e19
 
ed001110
       walk_auto_repositories "embedded_repositories"  \
                              "${operation}" \
                              "${permissions}" \
                              "${EMBEDDED_REPOS_DIR}"
8f951e19
    ) || exit 1
 }
fcf4306a
 
6a672446
 
ed001110
 _update_operation_walk_deep_embedded_auto_repositories()
8f951e19
 {
ea74a237
    local operation="$1"
6a672446
 
8f951e19
    local permissions
6a672446
 
ed001110
    permissions="minion"
58c301d4
 
8f951e19
    (
f67f6857
       OPTION_ALLOW_CREATING_SYMLINKS="${OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS}" ;
8f951e19
 
ed001110
       walk_deep_embedded_auto_repositories "${operation}" \
                                            "${permissions}"
8f951e19
    ) || exit 1
40fe269d
 }
 
 
8f951e19
 ##
 ## UPDATE
 ##
 update_repositories()
 {
ea74a237
    _update_operation_walk_repositories "update_repository"
8f951e19
 }
 
40fe269d
 
8f951e19
 update_embedded_repositories()
 {
ea74a237
    _update_operation_walk_embedded_repositories "update_repository"
8f951e19
 }
6a672446
 
40fe269d
 
8f951e19
 update_deep_embedded_repositories()
 {
ed001110
    _update_operation_walk_deep_embedded_auto_repositories "update_repository"
8f951e19
 }
1e8d5d86
 
fcfae396
 
8f951e19
 ##
 ## UPGRADE
 ##
 upgrade_repositories()
 {
ea74a237
    _update_operation_walk_repositories "upgrade_repository"
8f951e19
 }
602ae7d9
 
2279ad91
 
8f951e19
 upgrade_embedded_repositories()
 {
ea74a237
    _update_operation_walk_embedded_repositories "upgrade_repository"
1e8d5d86
 }
 
 
8f951e19
 upgrade_deep_embedded_repositories()
1e8d5d86
 {
ed001110
    _update_operation_walk_deep_embedded_auto_repositories "upgrade_repository"
8f951e19
 }
1e8d5d86
 
 
40fe269d
 
8f951e19
 ##
 ##
 ##
 required_action_for_clone()
40fe269d
 {
8f951e19
    local newclone="$1" ; shift
bba581f8
 
8f951e19
    local newreposdir="$1"  # ususally .bootstrap.repos
    local newname="$2"      # name of the clone
    local newurl="$3"       # URL of the clone
    local newbranch="$4"    # branch of the clone
    local newscm="$5"       # scm to use for this clone
    local newtag="$6"       # tag to checkout of the clone
    local newstashdir="$7"  # stashdir of this clone (absolute or relative to $PWD)
bba581f8
 
40fe269d
    local clone
5de2fbd6
 
8f951e19
    clone="`clone_of_repository "${reposdir}" "${name}"`"
    if [ -z "${clone}" ]
40fe269d
    then
8f951e19
       log_fluff "${url} is new"
       echo "clone"
       return
    fi
fcf4306a
 
8f951e19
    if [ "${clone}" = "${newclone}" ]
    then
e5b54e85
       if [ -e "${newstashdir}" ]
       then
          log_fluff "URL ${url} repository line is unchanged"
          return
       fi
 
       log_fluff "\"${newstashdir}\" is missing, reget."
       echo "clone"
8f951e19
       return
    fi
bba581f8
 
8f951e19
    local reposdir
ea74a237
 
    reposdir="${newreposdir}"
 
8f951e19
    local name
    local url
    local branch
    local scm
    local tag
    local stashdir
1e8d5d86
 
8f951e19
    parse_clone "${clone}"
fcf4306a
 
ea74a237
    log_debug "Change: \"${clone}\" -> \"${newclone}\""
 
8f951e19
    if [ "${scm}" != "${newscm}" ]
    then
db28bb90
       if ! [ "${scm}" = "symlink" -a "${newscm}" = "git" ]
       then
          log_fluff "SCM has changed from \"${scm}\" to \"${newscm}\", need to refetch"
0b9e9e49
 
          if [ "${scm}" != "minion" ]
          then
             log_fluff "Not removing \"${stashdir}\" because it's a minion"
             echo "remove"
          fi
 
          echo "clone"
db28bb90
          return
       fi
4805e856
    fi
 
f1f83418
    if [ "${stashdir}" != "${newstashdir}" ]
8f951e19
    then
3ee7ef17
       if [ -e "${newstashdir}" ]
       then
0b9e9e49
          log_fluff "Destination \"${newstashdir}\" already exists. Remove old."
3ee7ef17
          echo "remove"
 
0b9e9e49
          # detect unlucky hacque
3ee7ef17
          if is_minion_bootstrap_project "${newstashdir}"
          then
0b9e9e49
             fail "\"${stashdir}\" was renamed to minion \"${newstashdir}\""
3ee7ef17
          fi
       else
          log_fluff "Destination has changed from \"${stashdir}\" to \"${newstashdir}\", need to move"
ea74a237
 
3ee7ef17
          local oldstashdir
ea74a237
 
3ee7ef17
          oldstashdir="`get_old_stashdir "${reposdir}" "${name}"`"
          if [ "${oldstashdir}" != "${newstashdir}" ]
151c6f06
          then
3ee7ef17
             if [ -d "${oldstashdir}" ]
             then
                echo "move ${oldstashdir}"
             else
                log_warning "Can't find ${name} in ${oldstashdir}. Will clone again"
                echo "clone"
             fi
151c6f06
          fi
ea74a237
       fi
6a672446
    fi
 
db28bb90
    #
    # if scm is not git, don't try to be clever
    #
1461fe52
    case "${scm}" in
       git*)
       ;;
 
       symlink*)
          if [ -e "${newstashdir}" ]
          then
             log_fluff "\"${stashdir}\" is symlink. Ignoring possible differences."
             return
          fi
 
          log_fluff "\"${newstashdir}\" is missing, reget."
          echo "clone"
d87a5262
          return
1461fe52
       ;;
d87a5262
 
1461fe52
       *)
          log_fluff "Reget because scm is \"${scm}\"."
          echo "clone"
          return
       ;;
    esac
d87a5262
 
8f951e19
    if [ "${branch}" != "${newbranch}" ]
    then
f67f6857
       log_fluff "Branch has changed from \"${branch}\" to \"${newbranch}\", need to fetch"
f1f83418
       echo "upgrade"
8f951e19
    fi
 
    if [ "${tag}" != "${newtag}" ]
    then
f67f6857
       log_fluff "Tag has changed from \"${tag}\" to \"${newtag}\", need to check-out"
8f951e19
       echo "checkout"
    fi
 
    if [ "${url}" != "${newurl}" ]
    then
f67f6857
       log_fluff "URL has changed from \"${url}\" to \"${newurl}\", need to set remote url and fetch"
8f951e19
       echo "set-remote"
f1f83418
       echo "upgrade"
    fi
 }
 
 
 get_old_stashdir()
 {
    local reposdir="$1"
    local name="$2"
 
ea74a237
    [ -z "${reposdir}" ] && internal_fail "reposdir empty"
    [ -z "${name}" ]     && internal_fail "reposdir empty"
 
f1f83418
    local oldstashdir
ea74a237
    local oldparent
f1f83418
 
ea74a237
    oldclone="`clone_of_repository "${reposdir}" "${name}"`"
f1f83418
 
ea74a237
    [ -z "${oldclone}" ] && fail "Old clone information for \"${name}\" in \"${reposdir}\" is missing"
f1f83418
 
ea74a237
    url="`_url_part_from_clone "${oldclone}"`"
    name="`_canonical_clone_name "${url}"`"
    dstdir="`_dstdir_part_from_clone "${oldclone}"`"
f1f83418
 
ea74a237
    oldparent="`parentclone_of_repository "${reposdir}" "${name}"`"
    if [ ! -z "${oldparent}" ]
    then
       # figure out what the old stashdir prefix was and remove it
       oldprefix="`_dstdir_part_from_clone "${oldparent}"`"
       dstdir="${dstdir#$oldprefix/}"
8f951e19
    fi
f1f83418
 
6924181d
    oldstashdir="`computed_stashdir "${name}" "${dstdir}"`"
ea74a237
 
f1f83418
    echo "${oldstashdir}"
8f951e19
 }
 
 
0fc9abbe
 auto_update_minions()
0b9e9e49
 {
    local minions="$1"
 
    local minion
 
0fc9abbe
    log_debug ":auto_update_minions: (${minions})"
0b9e9e49
 
    IFS="
 "
    for minion in ${minions}
    do
       IFS="${DEFAULT_IFS}"
 
       if [ -z "${minion}" ]
       then
          continue
       fi
 
0fc9abbe
       log_debug "${C_INFO}Updating minion \"${minion}\" ..."
0b9e9e49
 
       [ ! -d "${minion}" ] && fail "Minion \"${minion}\" is gone"
 
       bootstrap_auto_update "${minion}" "${minion}"
    done
 
    IFS="${DEFAULT_IFS}"
 }
 
 
8f951e19
 work_clones()
 {
    local reposdir="$1"
    local clones="$2"
e3244671
    local required_clones="$3"
    local autoupdate="$4"
8f951e19
 
    local clone
83a2eec3
    local name
    local url
6a672446
    local branch
83a2eec3
    local scm
    local tag
8f951e19
    local stashdir
ea74a237
    local dstdir
83a2eec3
 
8f951e19
    local actionitems
f1f83418
    local remember
8f951e19
    local repotype
83ce7c54
    local oldstashdir
6a672446
 
8f951e19
    case "${reposdir}" in
       *embedded)
         repotype="embedded "
       ;;
 
       *)
         repotype=""
       ;;
    esac
6a672446
 
ea74a237
    log_debug "Working \"${clones}\""
 
8f951e19
    IFS="
 "
    for clone in ${clones}
6a672446
    do
8f951e19
       IFS="${DEFAULT_IFS}"
6a672446
 
8f951e19
       if [ -z "${clone}" ]
       then
          continue
       fi
4aa41e69
 
ed9b7e19
       #
9339a58a
       # optimization, try not to redo fetches
ed9b7e19
       #
       echo "${__IGNORE__}" | fgrep -s -q -x "${clone}" > /dev/null
       if [ $? -eq 0 ]
       then
          continue
       fi
4805e856
 
0fc9abbe
       log_debug "${C_INFO}Doing clone \"${clone}\" ..."
9339a58a
 
ed9b7e19
       __REFRESHED__="`add_line "${__REFRESHED__}" "${clone}"`"
 
9339a58a
       parse_raw_clone "${clone}"
ea74a237
       process_raw_clone
 
       stashdir="${dstdir}"
       [ -z "${stashdir}" ] && internal_fail "empty stashdir"
8f951e19
 
0b9e9e49
       case "${name}" in
          http:*|https:*)
             internal_fail "failed name: ${name}"
       esac
f1f83418
 
0b9e9e49
       case "${stashdir}" in
          http:*|https:*)
             internal_fail "failed stashdir: ${stashdir}"
       esac
58c301d4
 
e400db11
       local skip
 
       skip="NO"
 
0b9e9e49
       if is_minion_bootstrap_project "${name}"
       then
e400db11
          log_fluff "\"${name}\" is a minion, ignoring possible changes"
0b9e9e49
          clone="`echo "${name};${name};${branch};minion;${tag}" | sed 's/;*$//'`"
f1f83418
          remember="YES"
0b9e9e49
       else
          actionitems="`required_action_for_clone "${clone}" \
                                                  "${reposdir}" \
                                                  "${name}" \
                                                  "${url}" \
                                                  "${branch}" \
                                                  "${scm}" \
                                                  "${tag}" \
                                                  "${stashdir}"`" || exit 1
 
          log_debug "${C_INFO}Actions for \"${name}\": ${actionitems:-none}"
 
          IFS="
 "
          for item in ${actionitems}
          do
             IFS="${DEFAULT_IFS}"
 
             remember="YES"
 
             case "${item}" in
                "checkout")
e400db11
                   if ! checkout_repository "${reposdir}" \
                                            "${name}" \
                                            "${url}" \
                                            "${branch}" \
                                            "${scm}" \
                                            "${tag}" \
                                            "${stashdir}"
                   then
                      fail "Failed to checkout"
                   fi
0b9e9e49
                ;;
 
                "clone")
                   clone_repository "${reposdir}" \
bba581f8
                                    "${name}" \
                                    "${url}" \
                                    "${branch}" \
                                    "${scm}" \
8f951e19
                                    "${tag}" \
                                    "${stashdir}"
83a2eec3
 
0b9e9e49
                   case "$?" in
                      1)
e3244671
                         #
                         # check if clone is an optional install component
                         # it is if it doesn't show up in "required"
                         # required is built by mulle-bootstrap usually
                         # you specify optionals, by specifying the required
                         # clones and leaving the optional out
                         #
                         if ! echo "${required_clones}" | fgrep -s -q -x "${name}" > /dev/null
                         then
                            log_info "${C_MAGENTA}${C_BOLD}${name}${C_INFO} is missing, but it's not required."
 
                            merge_line_into_file "${REPOS_DIR}/.missing" "${name}"
                            skip="YES"
                            continue
                         fi
 
e400db11
                         log_debug "don't continue, because a required fetch failed"
e3244671
                         exit 1  # means exit
0b9e9e49
                      ;;
e3244671
 
0b9e9e49
                      2)
                         # if we used a symlink, we want to memorize that
                         scm="symlink"
                      ;;
                   esac
                ;;
 
                "ignore")
                   remember="NO"
                ;;
 
                move*)
                   oldstashdir="${item:5}"
 
                   log_info "Moving ${repotype}stash ${C_MAGENTA}${C_BOLD}${name}${C_INFO} from \"${oldstashdir}\" to \"${stashdir}\""
 
402c4cb7
                   mkdir_stashparent_if_missing "${stashdir}"
0b9e9e49
                   if ! exekutor mv ${COPYMOVEFLAGS} "${oldstashdir}" "${stashdir}"  >&2
                   then
                      fail "Move failed!"
                   fi
                ;;
 
                "upgrade")
                   upgrade_repository "${reposdir}" \
                                      "${name}" \
                                      "${url}" \
                                      "${branch}" \
                                      "${scm}" \
                                      "${tag}" \
0fc9abbe
                                      "${stashdir}"
0b9e9e49
                ;;
 
                remove*)
                   oldstashdir="${item:7}"
                   if [ -z "${oldstashdir}" ]
                   then
                      oldstashdir="`get_old_stashdir "${reposdir}" "${name}"`"
                   fi
 
0fc9abbe
                   bury_stash "${reposdir}" "${name}" "${oldstashdir}"
0b9e9e49
                ;;
 
                "set-remote")
                   log_info "Changing ${repotype}remote to \"${url}\""
 
                   local remote
 
                   remote="`git_get_default_remote "${stashdir}"`"
                   if [ -z "${remote}" ]
                   then
                      fail "Could not figure out a remote for \"$PWD/${stashdir}\""
                   fi
                   git_set_url "${stashdir}" "${remote}" "${url}"
                ;;
 
                *)
                   internal_fail "Unknown action item \"${item}\""
                ;;
             esac
          done
 
          if [ "${autoupdate}" = "YES" ]
          then
             bootstrap_auto_update "${name}" "${stashdir}"
          fi
8f951e19
 
0b9e9e49
          # create clone as it is now
          clone="`echo "${url};${dstdir};${branch};${scm};${tag}" | sed 's/;*$//'`"
83ce7c54
       fi
73f50c63
 
e3244671
       if [ "${skip}" = "YES" ]
       then
e400db11
          log_debug "skipping to next clone because..."
e3244671
          continue
       fi
 
83ce7c54
       #
f1f83418
       # always remember, what we have now (except if its a minion)
83ce7c54
       #
f1f83418
       if [ "${remember}" = "YES" ]
83ce7c54
       then
9339a58a
          # branch could be overwritten
1a85f08e
          log_debug "${C_INFO}Remembering ${clone} ..."
9339a58a
 
ea74a237
          remember_stash_of_repository "${clone}" \
f1f83418
                                       "${reposdir}" \
                                       "${name}"  \
ea74a237
                                       "${stashdir}" \
                                       "${PARENT_CLONE}"
e400db11
       else
          log_debug "ignoring because..."
83ce7c54
       fi
f1f83418
       mark_stash_as_alive "${reposdir}" "${name}"
8f951e19
    done
73f50c63
 
8f951e19
    IFS="${DEFAULT_IFS}"
7be3796e
 }
 
49ce4e18
 #
 #
 #
f1f83418
 fetch_once_embedded_repositories()
49ce4e18
 {
9339a58a
    log_debug "fetch_once_embedded_repositories"
 
f1f83418
    (
       STASHES_DEFAULT_DIR=""
       STASHES_ROOT_DIR=""
       OPTION_ALLOW_CREATING_SYMLINKS="${OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS}" ;
49ce4e18
 
f1f83418
       local clones
e3244671
       local required_clones
f1f83418
 
       clones="`read_root_setting "embedded_repositories"`" ;
e3244671
       required_clones="`read_root_setting "embedded_required"`" ;
       work_clones "${EMBEDDED_REPOS_DIR}" "${clones}" "${required_clones}" "NO"
0fc9abbe
    ) || exit 1
 }
 
 
 #
 #
 #
 fetch_once_minions_embedded_repositories()
 {
    log_debug "fetch_once_minions_embedded_repositories"
 
    local minions
 
c8c107a7
    minions="`read_root_setting "minions"`"
0fc9abbe
 
    local minion
 
    IFS="
 "
    for minion in ${minions}
    do
       IFS="${DEFAULT_IFS}"
 
       if [ -z "${minion}" ]
       then
          continue
       fi
 
       log_debug "${C_INFO}Doing minion \"${minion}\" ..."
 
       local autodir
 
       autodir="${BOOTSTRAP_DIR}.auto/.deep/${minion}.d"
 
       if [ ! -d "${autodir}" ]
       then
          log_fluff "${autodir} not present, so done"
          continue
       fi
 
       local autodir
 
       reposdir="${REPOS_DIR}/.deep/${minion}.d"
 
       (
          STASHES_DEFAULT_DIR=""
          STASHES_ROOT_DIR=""
          OPTION_ALLOW_CREATING_SYMLINKS="${OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS}" ;
 
          local clones
e3244671
          local required_clones
0fc9abbe
 
          clones="`read_setting "${autodir}/embedded_repositories"`" ;
e3244671
          required_clones="`read_setting "${autodir}/embedded_required"`" ;
          work_clones "${reposdir}" "${clones}" "${required_clones}" "NO"
0fc9abbe
       ) || exit 1
    done
 
    IFS="${DEFAULT_IFS}"
f1f83418
 }
 
 
0fc9abbe
 _fetch_once_deep_embedded_repository()
f1f83418
 {
    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)
 
    local autodir
 
    autodir="${BOOTSTRAP_DIR}.auto/.deep/${name}.d"
 
    if [ ! -d "${autodir}" ]
    then
151c6f06
       log_fluff "${autodir} not present, so done"
f1f83418
       return
    fi
49ce4e18
 
f1f83418
    reposdir="${reposdir}/.deep/${name}.d"
8f951e19
    (
f1f83418
       STASHES_DEFAULT_DIR=""
ea74a237
       STASHES_ROOT_DIR="${stashdir}"  # hackish
f67f6857
       OPTION_ALLOW_CREATING_SYMLINKS="${OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS}" ;
ea74a237
       PARENT_REPOSITORY_NAME="${name}"
       PARENT_CLONE="${clone}"
49ce4e18
 
f1f83418
       local clones
e3244671
       local required_clones
f1f83418
 
e5b54e85
       # ugliness
       clones="`read_setting "${autodir}/embedded_repositories"`" ;
e3244671
       required_clones="`read_setting "${autodir}/embedded_required"`" ;
       work_clones "${reposdir}" "${clones}" "${required_clones}" "NO"
8f951e19
    ) || exit 1
f1f83418
 }
49ce4e18
 
2f8d42a5
 
0fc9abbe
 # but not minions
f1f83418
 fetch_once_deep_embedded_repositories()
 {
9339a58a
    log_debug "fetch_once_deep_embedded_repositories"
8f951e19
 
0fc9abbe
    local permissions
 
ed001110
    walk_auto_repositories "repositories"  \
0fc9abbe
                           "_fetch_once_deep_embedded_repository" \
                           "${permissions}" \
                           "${REPOS_DIR}"
f1f83418
 }
ed9b7e19
 
8f951e19
 
0b9e9e49
 extract_minion_precis()
 {
    local minions
 
c8c107a7
    minions="`read_root_setting "minions"`"
0fc9abbe
    auto_update_minions "${minions}"
0b9e9e49
 }
 
 
f1f83418
 fetch_loop_repositories()
 {
    local loops
    local before
    local after
fe9be2f4
    local auxbefore
    local auxafter
e3244671
    local required
8f951e19
 
9339a58a
    log_debug "fetch_loop_repositories"
ed9b7e19
 
f1f83418
    loops=""
    before=""
fe9be2f4
    auxbefore=""
8f951e19
 
f1f83418
    __IGNORE__=""
ed9b7e19
 
f1f83418
    while :
    do
       loops="${loops}X"
       case "${loops}" in
          XXXXXXXXXXXXXXXX)
             internal_fail "Loop overflow in worker loop"
          ;;
       esac
8f951e19
 
f1f83418
       after="${before}"
ea74a237
       before="`read_root_setting "repositories" | sort`"
fe9be2f4
       auxafter="${auxbefore}"
       auxbefore="`read_root_setting "additional_repositories" | sort`"
 
       if [ "${after}" = "${before}" -a "${auxafter}" = "${auxbefore}" ]
8f951e19
       then
fe9be2f4
          log_fluff "Repositories files are unchanged, so done"
f1f83418
          break
8f951e19
       fi
f1f83418
 
151c6f06
       if [ -z "${__IGNORE__}" ]
       then
          log_fluff "Get back in the ring to take another swing"
       fi
 
f1f83418
       __REFRESHED__=""
 
e3244671
       required="`read_root_setting "required"`"
       work_clones "${REPOS_DIR}" "${before}" "${required}" "YES"
fe9be2f4
       work_clones "${REPOS_DIR}" "${auxbefore}" "${required}" "YES"
f1f83418
 
       __IGNORE__="`add_line "${__IGNORE__}" "${__REFRESHED__}"`"
 
    done
cf2eebc9
 }
 
8f951e19
                       #----#
 ### Main fetch loop   #    #    #----#
                       #----#    #----#    #----#
cf2eebc9
 
83ce7c54
 assume_stashes_are_zombies()
cf2eebc9
 {
ea74a237
    if [ -d "${REPOS_DIR}" ]
    then
       zombify_embedded_repository_stashes
       [ "${OPTION_EMBEDDED_ONLY}" = "YES" ] && return
e5b54e85
 
ea74a237
       zombify_repository_stashes
       zombify_deep_embedded_repository_stashes
    fi
49ce4e18
 }
 
 
8f951e19
 bury_zombies_in_graveyard()
8f77be37
 {
ea74a237
    if [ -d "${REPOS_DIR}" ]
    then
       bury_embedded_repository_zombies
       [ "${OPTION_EMBEDDED_ONLY}" = "YES" ] && return
e5b54e85
 
ea74a237
       bury_repository_zombies
       bury_deep_embedded_repository_zombies
    fi
8f951e19
 }
8f77be37
 
 
8f951e19
 #
 # the main fetch loop as documented somewhere with graphviz
 #
 fetch_loop()
 {
4805e856
    unpostpone_trace
 
470b3d4b
    # tell this for windows, it's so slow..
    log_info "Checking dependencies ..."
 
e5b54e85
    # this is wrong, we just do "stashes" though
    assume_stashes_are_zombies
83ce7c54
 
8f951e19
    bootstrap_auto_create
8f77be37
 
0fc9abbe
    if is_master_bootstrap_project
    then
1a85f08e
      log_info "Extracting minions' precis ..."
0fc9abbe
 
       extract_minion_precis
0b9e9e49
 
0fc9abbe
       fetch_once_minions_embedded_repositories
    fi
0b9e9e49
 
1a85f08e
    log_info "Checking repositories ..."
ed001110
 
151c6f06
    fetch_once_embedded_repositories
f1f83418
 
e5b54e85
    if [ "${OPTION_EMBEDDED_ONLY}" = "NO" ]
f1f83418
    then
151c6f06
       fetch_loop_repositories
9339a58a
 
151c6f06
       fetch_once_deep_embedded_repositories || exit 1
f1f83418
    fi
8f77be37
 
8f951e19
    bootstrap_auto_final
8f77be37
 
ea74a237
    bury_zombies_in_graveyard
8f77be37
 }
 
8f951e19
 #
 # the three commands
 #
 _common_fetch()
8f77be37
 {
4805e856
 
151c6f06
    fetch_loop "${REPOS_DIR}"
4805e856
 
    #
    # do this afterwards, because brews will have been composited
    # now
    #
8f951e19
    case "${BREW_PERMISSIONS}" in
       fetch|update|upgrade)
9405b614
          brew_install_brews "install"
8f951e19
       ;;
    esac
bba581f8
 
8f951e19
    check_tars
 }
8f77be37
 
 
8f951e19
 _common_update()
 {
    case "${BREW_PERMISSIONS}" in
       update|upgrade)
          brew_update_main
       ;;
    esac
8f77be37
 
0fc9abbe
    update_embedded_repositories
e5b54e85
    [ "${OPTION_EMBEDDED_ONLY}" = "YES" ] && return
8f77be37
 
0fc9abbe
    update_repositories "$@"
    update_deep_embedded_repositories
8f77be37
 }
 
 
8f951e19
 _common_upgrade()
fe01cf28
 {
8f951e19
    case "${BREW_PERMISSIONS}" in
       upgrade)
          brew_upgrade_main
       ;;
    esac
fcfae396
 
8f951e19
    upgrade_embedded_repositories
e5b54e85
    [ "${OPTION_EMBEDDED_ONLY}" = "YES" ] && return
7fdfcd11
 
151c6f06
    upgrade_repositories "$@"
8f951e19
    upgrade_deep_embedded_repositories
5fb25a38
 
8f951e19
    _common_fetch  # update what needs to be update
 }
58c301d4
 
213c25c7
 
8f951e19
 _common_main()
 {
    [ -z "${MULLE_BOOTSTRAP_REPOSITORIES_SH}" ]      && . mulle-bootstrap-repositories.sh
    [ -z "${MULLE_BOOTSTRAP_LOCAL_ENVIRONMENT_SH}" ] && . mulle-bootstrap-local-environment.sh
    [ -z "${MULLE_BOOTSTRAP_SETTINGS_SH}" ]          && . mulle-bootstrap-settings.sh
83a2eec3
 
e5b54e85
    local OPTION_CHECK_USR_LOCAL_INCLUDE="NO"
ed001110
    local MULLE_FLAG_FOLLOW_SYMLINKS="NO"
e5b54e85
    local OPTION_ALLOW_CREATING_SYMLINKS="NO"
    local OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS="NO"
d87a5262
    local OPTION_ALLOW_SEARCH_CACHES="YES"
402c4cb7
    local OPTION_ALLOW_GIT_MIRROR="YES"
53f4ddd2
    local OPTION_ALLOW_REFRESH_GIT_MIRROR="YES"
e5b54e85
    local OPTION_EMBEDDED_ONLY="NO"
9339a58a
    local OVERRIDE_BRANCH
151c6f06
    local DONT_WARN_SCRIPTS="NO"
f67f6857
 
3ee7ef17
    local ROOT_DIR="`pwd -P`"
23dc6164
 
f67f6857
    OPTION_CHECK_USR_LOCAL_INCLUDE="`read_config_setting "check_usr_local_include" "NO"`"
9339a58a
    OVERRIDE_BRANCH="`read_config_setting "override_branch"`"
30474aff
    if [ ! -z "${OVERRIDE_BRANCH}" ]
    then
       log_info "All fetched branches will be overriden to \
 \"${OVERRIDE_BRANCH}\" as config \"override_branch\" is set."
    fi
d87a5262
 
151c6f06
    DONT_WARN_SCRIPTS="`read_config_setting "dont_warn_scripts" "${MULLE_FLAG_ANSWER:-NO}"`"
 
    if [ "${DONT_WARN_SCRIPTS}" = "YES" ]
    then
       log_verbose "Script checking disabled"
    fi
 
8f951e19
    case "${UNAME}" in
       mingw)
       ;;
7fdfcd11
 
8f951e19
       *)
d87a5262
          OPTION_ALLOW_CREATING_SYMLINKS="`read_config_setting "symlinks" "${MULLE_FLAG_ANSWER}"`"
          OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS="`read_config_setting "embedded_symlinks" "NO"`"
8f951e19
       ;;
    esac
fe01cf28
 
751a6002
    #
    # it is useful, that fetch understands build options and
    # ignores them
    #
6704c86d
    while [ $# -ne 0 ]
a3018cdd
    do
       case "$1" in
          -h|-help|--help)
55a86360
             ${USAGE}
a3018cdd
          ;;
 
ea74a237
          -cu|--check-usr-local|--check-usr-local)
f67f6857
             OPTION_CHECK_USR_LOCAL_INCLUDE="YES"
f1f83418
          ;;
5447bf9a
 
751a6002
          -e|--embedded-only)
f67f6857
             OPTION_EMBEDDED_ONLY="YES"
751a6002
          ;;
 
ed001110
          # update symlinks, dangerous (duplicate to flags for laziness reasons)
          --follow-symlinks)
             MULLE_FLAG_FOLLOW_SYMLINKS="YES"
e94fa243
          ;;
 
d87a5262
          # allow creating symlinks instead of clones for repositories
          -l|--symlink-creation|--symlinks)
e5b54e85
             OPTION_ALLOW_CREATING_SYMLINKS="YES"
          ;;
 
ed001110
          #
ea74a237
          # create symlinks instead of clones for embedded_repositories
ed001110
          # and deep embedded_repositories. If the clones are symlinked
          # this will be ignored, except if follow-symlinks is
          # active. --follow-symlinks is really not safe!
          #
ea74a237
          --embedded-symlink-creation|--embedded-symlinks)
e5b54e85
             OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS="YES"
fcf4306a
          ;;
 
402c4cb7
          --no-git-mirror)
             OPTION_ALLOW_GIT_MIRROR="NO"
          ;;
 
53f4ddd2
          --no-refresh-git_mirror)
             OPTION_ALLOW_REFRESH_GIT_MIRROR="NO"
          ;;
 
ea74a237
          --no-caches)
e5b54e85
             OPTION_ALLOW_SEARCH_CACHES="NO"
8f951e19
          ;;
 
ea74a237
          --no-symlink-creation|--no-symlinks)
ed001110
             MULLE_FLAG_FOLLOW_SYMLINKS="NO"
e5b54e85
             OPTION_ALLOW_CREATING_SYMLINKS="NO"
d87a5262
             OPTION_ALLOW_CREATING_EMBEDDED_SYMLINKS="NO"
6704c86d
          ;;
 
ed001110
          # TODO: outdated!
5c06c0e8
          # build options with no parameters
a7e78ccb
          -K|--clean|-k|--no-clean|--use-prefix-libraries|--debug|--release)
751a6002
             if [ -z "${MULLE_BOOTSTRAP_WILL_BUILD}" ]
             then
f67f6857
                log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown fetch option $1"
751a6002
                ${USAGE}
             fi
          ;;
 
8879298e
          # build options with one parameter
ed001110
          # TODO: outdated!
8879298e
          -j|--cores|-c|--configuration|--prefix)
5c06c0e8
             if [ -z "${MULLE_BOOTSTRAP_WILL_BUILD}" ]
             then
f67f6857
                log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown fetch option $1"
5c06c0e8
                ${USAGE}
             fi
 
             if [ $# -eq 1 ]
             then
f67f6857
                log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Missing parameter to fetch option $1"
5c06c0e8
                ${USAGE}
             fi
             shift
          ;;
 
a3018cdd
          -*)
f67f6857
             log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown fetch option $1"
55a86360
             ${USAGE}
a3018cdd
          ;;
 
55a86360
          *)
a3018cdd
             break
          ;;
       esac
 
       shift
    done
 
f1f83418
    [ -z "${MULLE_BOOTSTRAP_AUTO_UPDATE_SH}" ]     && . mulle-bootstrap-auto-update.sh
8f951e19
    [ -z "${MULLE_BOOTSTRAP_COMMON_SETTINGS_SH}" ] && . mulle-bootstrap-common-settings.sh
    [ -z "${MULLE_BOOTSTRAP_SCM_SH}" ]             && . mulle-bootstrap-scm.sh
    [ -z "${MULLE_BOOTSTRAP_SCRIPTS_SH}" ]         && . mulle-bootstrap-scripts.sh
    [ -z "${MULLE_BOOTSTRAP_ZOMBIFY_SH}" ]         && . mulle-bootstrap-zombify.sh
8f77be37
 
402c4cb7
    #
    # "repository" caches can and usually are outside the project folder
    # this can be multiple paths!
53f4ddd2
    if [ "${OPTION_ALLOW_SEARCH_CACHES}" = "YES" ]
402c4cb7
    then
       CACHES_PATH="`read_config_setting "search_path" "${MULLE_BOOTSTRAP_CACHES_PATH}"`"
       CACHES_PATH="`add_path "${CACHES_PATH}" "${CLONE_CACHE}"`"
    fi
 
53f4ddd2
    if [ "${OPTION_ALLOW_GIT_MIRROR}" = "YES" ]
402c4cb7
    then
53f4ddd2
       git_enable_mirroring "${OPTION_ALLOW_REFRESH_GIT_MIRROR}"
402c4cb7
    fi
 
a75ed0ba
    #
    # should we check for '/usr/local/include/<name>' and don't fetch if
    # present (somewhat dangerous, because we do not check versions)
    #
 
55a86360
    if [ "${COMMAND}" = "fetch" ]
40fe269d
    then
1e8d5d86
       if [ $# -ne 0 ]
       then
bba581f8
          log_error "Additional parameters not allowed for fetch (" "$@" ")"
55a86360
          ${USAGE}
1e8d5d86
       fi
602ae7d9
    fi
 
    #
    # Run prepare scripts if present
    #
8f951e19
    case "${COMMAND}" in
       update|upgrade)
          if dir_is_empty "${REPOS_DIR}"
          then
             log_info "Nothing to update, fetch first"
1e8d5d86
 
8f951e19
             return 0
          fi
       ;;
    esac
602ae7d9
 
e400db11
 
8f951e19
    local default_permissions
30941060
 
8f951e19
    #
    # possible values none|fetch|update|upgrade
    # the local scheme with addictions really works
    # best on darwin, linux can't use bottles locally
    #
    default_permissions="none"
    case "${UNAME}" in
       darwin|linux)
          default_permissions="upgrade"
       ;;
    esac
1fddbf4e
 
8f951e19
    BREW_PERMISSIONS="`read_config_setting "brew_permissions" "${default_permissions}"`"
    case "${BREW_PERMISSIONS}" in
       none|fetch|update|upgrade)
       ;;
360a4aae
 
8f951e19
       *)
         fail "brew_permissions must be either: none|fetch|update|upgrade)"
       ;;
    esac
 
cbe9e1a7
    remove_file_if_present "${REPOS_DIR}/.build_done.orig"
ba567f56
    remove_file_if_present "${REPOS_DIR}/.build_done"
e400db11
    remove_file_if_present "${REPOS_DIR}/.fetch_done"
53f4ddd2
    remove_file_if_present "${REPOS_DIR}/.uptodate-mirrors"
e400db11
    create_file_if_missing "${REPOS_DIR}/.fetch_started"
818b5aa7
 
8f951e19
    if [ "${BREW_PERMISSIONS}" != "none" ]
    then
       [ -z "${MULLE_BOOTSTRAP_BREW_SH}" ] && . mulle-bootstrap-brew.sh
40fe269d
    fi
5de2fbd6
 
8f951e19
    [ -z "${DEFAULT_IFS}" ] && internal_fail "IFS fail"
 
    case "${COMMAND}" in
       update)
          _common_update "$@"
       ;;
 
       upgrade)
          _common_upgrade "$@"
       ;;
    esac
a7b563e1
 
f1f83418
    _common_fetch "$@"
 
e400db11
    remove_file_if_present "${REPOS_DIR}/.fetch_started"
151c6f06
 
    #
    # only say we are done if a build_order was created
    #
    if [ -f "${BOOTSTRAP_DIR}.auto/build_order" ]
    then
e400db11
       create_file_if_missing "${REPOS_DIR}/.fetch_done"
151c6f06
    fi
602ae7d9
 
8f951e19
    if read_yes_no_config_setting "upgrade_gitignore" "YES"
a7b563e1
    then
       if [ -d .git ]
       then
bba581f8
          append_dir_to_gitignore_if_needed "${BOOTSTRAP_DIR}.auto"
          append_dir_to_gitignore_if_needed "${BOOTSTRAP_DIR}.local"
4805e856
          append_dir_to_gitignore_if_needed "${DEPENDENCIES_DIR}"
8f951e19
          if [ "${brew_permissions}" != "none" ]
          then
             append_dir_to_gitignore_if_needed "${ADDICTIONS_DIR}"
          fi
bba581f8
          append_dir_to_gitignore_if_needed "${REPOS_DIR}"
f1f83418
          if [ ! -z "${STASHES_DEFAULT_DIR}" -a -d "${STASHES_DEFAULT_DIR}"  ]
8f951e19
          then
f1f83418
             append_dir_to_gitignore_if_needed "${STASHES_DEFAULT_DIR}"
8f951e19
          fi
a7b563e1
       fi
    fi
8f951e19
 }
5ec25abc
 
 
8f951e19
 fetch_main()
 {
9339a58a
    log_debug "::: fetch begin :::"
8f951e19
 
    USAGE="fetch_usage"
    COMMAND="fetch"
    _common_main "$@"
 
9339a58a
    log_debug "::: fetch end :::"
55a86360
 }
 
 
 update_main()
 {
9339a58a
    log_debug "::: update begin :::"
55a86360
 
    USAGE="fetch_usage"
    COMMAND="update"
    _common_main "$@"
 
9339a58a
    log_debug "::: update end :::"
55a86360
 }
 
 
8f951e19
 upgrade_main()
55a86360
 {
9339a58a
    log_debug "::: upgrade begin :::"
55a86360
 
    USAGE="fetch_usage"
8f951e19
    COMMAND="upgrade"
55a86360
    _common_main "$@"
22174806
 
9339a58a
    log_debug "::: upgrade end :::"
5de2fbd6
 }