Browse code

Make global config happening. Add missing files.

Nat! authored on 21-03-2017 17:17:58
Showing 12 changed files
... ...
@@ -1,7 +1,11 @@
1 1
 #! /bin/sh
2 2
 
3
+TAP="${1:-software}"
4
+[ $# -ne 0 ] && shift
5
+BRANCH="${1:-release}"
6
+[ $# -ne 0 ] && shift
3 7
 TAG="${1:-`./mulle-bootstrap version`}"
4
-
8
+[ $# -ne 0 ] && shift
5 9
 
6 10
 . src/mulle-bootstrap-logging.sh
7 11
 
... ...
@@ -19,34 +23,41 @@ git_must_be_clean()
19 23
    fi
20 24
 
21 25
    clean=`git status -s --untracked-files=no`
22
-   if [ "${clean}" != "" ]
26
+   if [ ! -z "${clean}" ]
23 27
    then
24 28
       fail "repository \"${name}\" is tainted"
25 29
    fi
26 30
 }
27 31
 
28 32
 
33
+[ -d "../homebrew-$TAP" ] || fail "tap $TAP is invalid"
34
+
29 35
 git_must_be_clean
30 36
 
31
-branch="`git rev-parse --abbrev-ref HEAD`"
37
+devbranch="`git rev-parse --abbrev-ref HEAD`"
38
+
39
+(
40
+   git checkout "${BRANCH}"    &&
41
+   git rebase "${devbranch}"   &&
42
+   git push public "${BRANCH}"
43
+) || exit 1
32 44
 
33
-git checkout release
34
-git rebase "${branch}"
35
-git push public release
36 45
 
37 46
 # seperate step, as it's tedious to remove tag when
38 47
 # previous push fails
39 48
 
40
-git tag "${TAG}"
41
-git push public release --tags
42
-git push github release --tags
49
+(
50
+   git tag "${TAG}"                    &&
51
+   git push public "${BRANCH}" --tags  &&
52
+   git push github "${BRANCH}" --tags
53
+) || exit 1
54
+
43 55
 
44
-./bin/generate-brew-formula.sh  > ../homebrew-software/mulle-bootstrap.rb
56
+./bin/generate-brew-formula.sh  > ../homebrew-$TAP/mulle-bootstrap.rb
45 57
 (
46
-	cd ../homebrew-software ; \
58
+	cd ../homebrew-$TAP ; \
47 59
  	git commit -m "${TAG} release of mulle-bootstrap" mulle-bootstrap.rb ; \
48 60
  	git push origin master
49 61
 )
50 62
 
51
-git checkout "${branch}"
52
-
63
+git checkout "${devbranch}"
53 64
new file mode 100755
... ...
@@ -0,0 +1,383 @@
1
+#! /bin/sh
2
+#
3
+#   Copyright (c) 2017 Nat! - Mulle kybernetiK
4
+#   All rights reserved.
5
+#
6
+#   Redistribution and use in source and binary forms, with or without
7
+#   modification, are permitted provided that the following conditions are met:
8
+#
9
+#   Redistributions of source code must retain the above copyright notice, this
10
+#   list of conditions and the following disclaimer.
11
+#
12
+#   Redistributions in binary form must reproduce the above copyright notice,
13
+#   this list of conditions and the following disclaimer in the documentation
14
+#   and/or other materials provided with the distribution.
15
+#
16
+#   Neither the name of Mulle kybernetiK nor the names of its contributors
17
+#   may be used to endorse or promote products derived from this software
18
+#   without specific prior written permission.
19
+#
20
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+#   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+#   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+#   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
+#   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+#   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+#   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+#   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+#   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+#   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+#   POSSIBILITY OF SUCH DAMAGE.
31
+MULLE_EXECUTABLE_VERSION_MAJOR=3
32
+MULLE_EXECUTABLE_VERSION_MINOR=0
33
+MULLE_EXECUTABLE_VERSION_PATCH=0
34
+
35
+MULLE_EXECUTABLE_VERSION="${MULLE_EXECUTABLE_VERSION_MAJOR}.${MULLE_EXECUTABLE_VERSION_MINOR}.${MULLE_EXECUTABLE_VERSION_PATCH}"
36
+
37
+#
38
+# This is the main user interface to mulle-bootstrap
39
+# sorta like git
40
+#
41
+
42
+trap_fail()
43
+{
44
+   exit 1
45
+}
46
+
47
+
48
+mulle_brew_usage()
49
+{
50
+   cat <<EOF
51
+usage: mulle-brew [flags] [command] [options]
52
+ Flags:
53
+   -n        : do nothing creative or destructive
54
+   -v        : -v to be more verbose (-vv or -vvv for more verbosity)
55
+EOF
56
+
57
+   bootstrap_technical_option_usage
58
+
59
+   cat <<EOF
60
+
61
+ Commands:
62
+   install   : fetches brews
63
+   update    : update brew
64
+   upgrade   : upgrade brew fomulae
65
+   init      : initializes a bootstrap project
66
+
67
+ Options are command specific. Use mulle-brew <command> -h for help.
68
+EOF
69
+
70
+   if [ "${UNAME}" = 'darwin' ]
71
+   then
72
+      cat <<EOF
73
+   xcode     : setup xcodeproj settings
74
+EOF
75
+   fi
76
+
77
+   exit 1
78
+}
79
+
80
+
81
+bootstrap_libexec_path()
82
+{
83
+   local exedir
84
+   local exedirpath
85
+   local prefix
86
+   local libexecpath
87
+
88
+   exedir="`dirname "$1"`"
89
+   exedirpath="`( cd "${exedir}" ; pwd -P )`" || fail "failed to get pwd"
90
+   prefix="`dirname "${exedirpath}"`"
91
+   libexecpath="${prefix}/libexec/mulle-bootstrap"
92
+
93
+   if [ ! -x "${libexecpath}/mulle-bootstrap-functions.sh" ]
94
+   then
95
+      libexecpath="${exedirpath}/src"
96
+   fi
97
+
98
+   if [ -x "${libexecpath}/mulle-bootstrap-functions.sh" ]
99
+   then
100
+      echo "${libexecpath}"
101
+   fi
102
+}
103
+
104
+
105
+bootstrap_init()
106
+{
107
+   local libexecpath
108
+
109
+   libexecpath="`bootstrap_libexec_path "$0"`"
110
+   if [ -z "${libexecpath}" ]
111
+   then
112
+      echo "could not find libexec for mulle-bootstrap" >&2
113
+      exit 1
114
+   fi
115
+
116
+   #
117
+   # shell export commands with minimal
118
+   # trap setup
119
+   #
120
+   case "${1}" in
121
+      library-path)
122
+         echo "${libexecpath}"
123
+         exit 0
124
+      ;;
125
+
126
+      version)
127
+         echo "${MULLE_EXECUTABLE_VERSION}"
128
+         exit 0
129
+      ;;
130
+   esac
131
+
132
+
133
+   PATH="${libexecpath}:$PATH"
134
+   export PATH
135
+
136
+   if [ ! -z "${MULLE_BOOTSTRAP_LIBEXEC_TRACE}" ]
137
+   then
138
+      echo "PATH=$PATH" >&2
139
+   fi
140
+
141
+   #  set -e # more pain then gain in the end
142
+   #  set -u # doesn't work with my style
143
+
144
+   # now include this first to get
145
+   # logging and UNAME
146
+
147
+   . mulle-bootstrap-logging.sh
148
+   . mulle-bootstrap-local-environment.sh || fail "not loaded"
149
+
150
+   trap trap_fail INT
151
+
152
+   # source_environment
153
+}
154
+
155
+
156
+brew_main()
157
+{
158
+   local command
159
+   local ps4string
160
+
161
+   # technical flags
162
+   local MULLE_FLAG_EXECUTOR_DRY_RUN="NO"
163
+   local MULLE_FLAG_LOG_CACHE="NO"
164
+   local MULLE_FLAG_LOG_DEBUG="NO"
165
+   local MULLE_FLAG_LOG_EXECUTOR="NO"
166
+   local MULLE_FLAG_LOG_EXECUTOR="NO"
167
+   local MULLE_FLAG_LOG_FLUFF="NO"
168
+   local MULLE_FLAG_LOG_SCRIPTS="NO"
169
+   local MULLE_FLAG_LOG_SETTINGS="NO"
170
+   local MULLE_FLAG_LOG_VERBOSE="NO"
171
+   local MULLE_FLAG_MERGE_LOG="NO"
172
+   local MULLE_TRACE_PATHS_FLIP_X="NO"
173
+   local MULLE_TRACE_POSTPONE="NO"
174
+   local MULLE_TRACE_RESOLVER_FLIP_X="NO"
175
+   local MULLE_TRACE_SETTINGS_FLIP_X="NO"
176
+
177
+   #
178
+   # simple option handling
179
+   #
180
+   while [ $# -ne 0 ]
181
+   do
182
+      if bootstrap_technical_flags "$1"
183
+      then
184
+         shift
185
+         continue
186
+      fi
187
+
188
+      case "$1" in
189
+         -h|--help)
190
+            mulle_brew_usage
191
+         ;;
192
+
193
+         -*)
194
+            log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown option \"$1\""
195
+            mulle_brew_usage
196
+         ;;
197
+
198
+         *)
199
+            break
200
+         ;;
201
+      esac
202
+
203
+      shift
204
+   done
205
+
206
+   bootstrap_setup_trace "${MULLE_TRACE}"
207
+
208
+   if [ "${MULLE_FLAG_EXECUTOR_DRY_RUN}" = "YES" ]
209
+   then
210
+      log_trace "Dry run is active."
211
+   fi
212
+
213
+   # source in environment now
214
+
215
+   local_environment_main
216
+
217
+   #
218
+   # some commands only run when we have a .bootstrap folder
219
+   #
220
+   command="${1:-install}"
221
+   [ $# -eq 0 ] || shift
222
+
223
+   if [ ! -d "${BOOTSTRAP_DIR}" -a ! -d "${BOOTSTRAP_DIR}.local" ]
224
+   then
225
+      case "$1" in
226
+         -h|--help)
227
+         ;;
228
+
229
+         *)
230
+            case "${command}" in
231
+               dist|clean|dist-clean|install|upgrade|update|setup-xcode|xcode)
232
+                  fail "There is no ${BOOTSTRAP_DIR} or ${BOOTSTRAP_DIR}.local folder here ($PWD), can't continue"
233
+               ;;
234
+            esac
235
+         ;;
236
+      esac
237
+   else
238
+      if bootstrap_should_defer_to_master "$@"
239
+      then
240
+         return 1
241
+      fi
242
+   fi
243
+
244
+   MULLE_EXECUTABLE_FAIL_PREFIX="${MULLE_EXECUTABLE} ${command}"
245
+   MULLE_EXECUTABLE_OPTIONS="$@"
246
+
247
+   case "${command}" in
248
+      build)
249
+         . mulle-bootstrap-build.sh
250
+
251
+         build_main "$@" || exit 1
252
+      ;;
253
+
254
+      clean)
255
+         . mulle-bootstrap-clean.sh
256
+
257
+         clean_main "$@" || exit 1
258
+      ;;
259
+
260
+      config)
261
+         . mulle-bootstrap-settings.sh
262
+
263
+         config_main "$@" || exit 1
264
+      ;;
265
+
266
+      dist)
267
+         . mulle-bootstrap-clean.sh
268
+
269
+         clean_main "dist" || exit 1
270
+      ;;
271
+
272
+      defer)
273
+         . mulle-bootstrap-defer.sh
274
+
275
+         defer_main "$@" || exit 1
276
+      ;;
277
+
278
+      emancipate)
279
+         . mulle-bootstrap-defer.sh
280
+
281
+         emancipate_main "$@" || exit 1
282
+      ;;
283
+
284
+      flags)
285
+         . mulle-bootstrap-flags.sh
286
+
287
+         flags_main "$@" || exit 1
288
+      ;;
289
+
290
+      help)
291
+         mulle_brew_usage "$@" || exit 1
292
+      ;;
293
+
294
+      init)
295
+         . mulle-bootstrap-init.sh
296
+
297
+         init_main "$@" || exit 1
298
+      ;;
299
+
300
+      install|fetch)
301
+         . mulle-bootstrap-brew.sh
302
+
303
+         brew_install_main "$@" || exit 1
304
+      ;;
305
+
306
+      library-path)
307
+         echo "$PATH" | tr ':' '\012' | head -1
308
+         return 0
309
+      ;;
310
+
311
+      setting)
312
+         . mulle-bootstrap-settings.sh
313
+
314
+         setting_main "$@" || exit 1
315
+      ;;
316
+
317
+      show)
318
+         . mulle-bootstrap-show.sh
319
+
320
+         show_main "$@" || exit 1
321
+      ;;
322
+
323
+      uname)
324
+         echo "${UNAME}"
325
+         exit 0
326
+      ;;
327
+
328
+      update)
329
+         . mulle-bootstrap-brew.sh
330
+
331
+         brew_update_main "$@" || exit 1
332
+      ;;
333
+
334
+      upgrade)
335
+         . mulle-bootstrap-brew.sh
336
+
337
+         brew_upgrade_main "$@" || exit 1
338
+      ;;
339
+
340
+      version)
341
+         echo "${MULLE_EXECUTABLE_VERSION}"
342
+         return 0
343
+      ;;
344
+
345
+      xcode|setup-xcode)
346
+         . mulle-bootstrap-xcode.sh
347
+
348
+         MULLE_EXECUTABLE_FAIL_PREFIX="mulle-bootstrap xcode"
349
+         xcode_main "$@" || exit 1
350
+      ;;
351
+
352
+      *)
353
+         log_error "${MULLE_EXECUTABLE_FAIL_PREFIX}: Unknown command \"${command}\""
354
+         mulle_bootstrap_usage
355
+      ;;
356
+   esac
357
+}
358
+
359
+#
360
+# service both names
361
+#
362
+MULLE_EXECUTABLE="`basename -- "$0"`"
363
+MULLE_ARGUMENTS="$@"
364
+MULLE_EXECUTABLE_FAIL_PREFIX="${MULLE_EXECUTABLE}"
365
+MULLE_EXECUTABLE_PID="$$"
366
+export MULLE_EXECUTABLE_PID
367
+
368
+
369
+bootstrap_init "$@" # needs params
370
+
371
+main()
372
+{
373
+   if ! brew_main "$@"
374
+   then
375
+      # just do it again, but cd has been set differently
376
+      main "$@" # is array
377
+      exit $?
378
+   fi
379
+}
380
+
381
+main "$@"
382
+
383
+trap - TERM EXIT
... ...
@@ -94,14 +94,14 @@ _bootstrap_auto_copy()
94 94
          ;;
95 95
 
96 96
          repositories)
97
-            _bootstrap_merge_repository_files "${filepath}" "${dstfilepath}" "NO"
97
+            merge_repository_files "${filepath}" "${dstfilepath}" "NO"
98 98
          ;;
99 99
 
100 100
          embedded_repositories)
101 101
             (
102 102
                STASHES_DEFAULT_DIR=""
103 103
                STASHES_ROOT_DIR=""
104
-               _bootstrap_merge_repository_files "${filepath}" "${dstfilepath}" "NO"
104
+               merge_repository_files "${filepath}" "${dstfilepath}" "NO"
105 105
             )
106 106
          ;;
107 107
 
... ...
@@ -138,6 +138,21 @@ _bootstrap_auto_copy()
138 138
 }
139 139
 
140 140
 
141
+_bootstrap_create_required_if_needed()
142
+{
143
+   dst="$1"
144
+
145
+   #
146
+   # if there is no required file add all names from repositories
147
+   # which ought to have been expanded already
148
+   #
149
+   if [ ! -f "${dst}/required" -a -f "${dst}/repositories" ]
150
+   then
151
+      redirect_exekutor "${dst}/required" names_from_repository_file "${dst}/repositories"
152
+   fi
153
+}
154
+
155
+
141 156
 #
142 157
 # This function is called initially to setup .bootstrap.auto before
143 158
 # doing anything else. It is clear that .bootstrap.auto does not exist
... ...
@@ -175,6 +190,8 @@ _bootstrap_auto_create()
175 190
    then
176 191
       _bootstrap_auto_copy "${dst}" "${src}" "NO"
177 192
    fi
193
+
194
+   _bootstrap_create_required_if_needed "${dst}"
178 195
 }
179 196
 
180 197
 
... ...
@@ -211,25 +228,6 @@ _bootstrap_merge_expanded_settings_in_front()
211 228
 }
212 229
 
213 230
 
214
-_bootstrap_merge_repository_files()
215
-{
216
-   local srcfile="$1"
217
-   local dstfile="$2"
218
-   local delete_dstdir="${3:-NO}"
219
-
220
-   log_fluff "Copying expanded \"repositories\" from \"${srcfile}\""
221
-
222
-   local contents
223
-   local additions
224
-
225
-   contents="`cat "${dstfile}" 2> /dev/null || :`"
226
-   additions="`read_repository_file "${srcfile}" "${delete_dstdir}"`" || fail "read"
227
-   additions="`echo "${additions}"| sed 's/;*$//'`"
228
-   additions="`merge_repository_contents "${contents}" "${additions}"`"
229
-
230
-   redirect_exekutor "${dstfile}" echo "${additions}"
231
-}
232
-
233 231
 
234 232
 #
235 233
 # prepend new contents to old contents
... ...
@@ -280,7 +278,7 @@ _bootstrap_auto_merge_root_settings()
280 278
          ;;
281 279
 
282 280
          "repositories")
283
-            _bootstrap_merge_repository_files "${srcfile}" "${dstfile}" "YES"
281
+            merge_repository_files "${srcfile}" "${dstfile}" "YES"
284 282
             continue
285 283
          ;;
286 284
       esac
... ...
@@ -308,11 +306,10 @@ _bootstrap_auto_merge_root_settings()
308 306
       fi
309 307
    done
310 308
 
311
-   IFS="${DEFAULT_IFS}"
309
+   _bootstrap_create_required_if_needed "${dst}"
312 310
 }
313 311
 
314 312
 
315
-
316 313
 _bootstrap_auto_special_copy()
317 314
 {
318 315
    local key="$1"; shift
... ...
@@ -339,7 +336,7 @@ _bootstrap_auto_special_copy()
339 336
    (
340 337
       STASHES_DEFAULT_DIR=""
341 338
       STASHES_ROOT_DIR="${directory}"
342
-      _bootstrap_merge_repository_files "${filepath}" "${dstfilepath}" "NO"
339
+      merge_repository_files "${filepath}" "${dstfilepath}" "NO"
343 340
    )
344 341
 }
345 342
 
... ...
@@ -536,6 +533,7 @@ bootstrap_auto_final()
536 533
    fi
537 534
 
538 535
    order=""
536
+   missing="`read_setting "${REPOS_DIR}/.missing"`"
539 537
 
540 538
    IFS="
541 539
 "
... ...
@@ -544,7 +542,14 @@ bootstrap_auto_final()
544 542
       IFS="${DEFAULT_IFS}"
545 543
 
546 544
       parse_clone "${clone}"
547
-      order="`add_line "${order}" "${name}"`"
545
+
546
+      #
547
+      # don't build optional missing stuff
548
+      #
549
+      if ! echo "${missing}" | fgrep -s -x -q "${name}"
550
+      then
551
+         order="`add_line "${order}" "${name}"`"
552
+      fi
548 553
    done
549 554
 
550 555
    IFS="${DEFAULT_IFS}"
... ...
@@ -404,13 +404,11 @@ build_fail()
404 404
 
405 405
 build_log_name()
406 406
 {
407
-   local tool
408
-   local name
407
+   local tool="$1"; shift
408
+   local name="$1"; shift
409 409
 
410
-   tool="$1"
411
-   [ $# -eq 0 ] || shift
412
-   name="$1"
413
-   [ $# -eq 0 ] || shift
410
+   [ -z "${tool}" ] && internal_fail "tool missing"
411
+   [ -z "${name}" ] && internal_fail "name missing"
414 412
 
415 413
    local logfile
416 414
 
... ...
@@ -1032,7 +1030,7 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO} in \"${builddir}\" ..."
1032 1030
 
1033 1031
       logging_redirect_eval_exekutor "${logfile1}" "'${CMAKE}'" \
1034 1032
 -G "'${CMAKE_GENERATOR}'" \
1035
-"-DMULLE_EXECUTABLE_VERSION=${MULLE_EXECUTABLE_VERSION}" \
1033
+"-DMULLE_BOOTSTRAP_VERSION=${MULLE_EXECUTABLE_VERSION}" \
1036 1034
 "-DCMAKE_BUILD_TYPE='${mapped}'" \
1037 1035
 "-DCMAKE_INSTALL_PREFIX:PATH='${prefixbuild}'"  \
1038 1036
 "${sdkparameter}" \
... ...
@@ -1405,7 +1403,9 @@ build_xcodebuild()
1405 1403
 
1406 1404
    enforce_build_sanity "${builddir}"
1407 1405
 
1408
-   toolname=`read_config_setting "xcodebuild" "xcodebuild"`
1406
+   local toolname
1407
+
1408
+   toolname="`read_config_setting "xcodebuild" "xcodebuild"`"
1409 1409
 
1410 1410
    local info
1411 1411
 
... ...
@@ -1473,8 +1473,6 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO}${info} in \
1473 1473
       skip_install="SKIP_INSTALL=NO"
1474 1474
    fi
1475 1475
 
1476
-   local toolname
1477
-
1478 1476
    #
1479 1477
    # xctool needs schemes, these are often autocreated, which xctool cant do
1480 1478
    # xcodebuild can just use a target
... ...
@@ -1482,7 +1480,7 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO}${info} in \
1482 1480
    #
1483 1481
    if [ "${toolname}" = "xctool"  -a "${schemename}" = ""  ]
1484 1482
    then
1485
-      if [ "$targetname" != "" ]
1483
+      if [ ! -z "$targetname" ]
1486 1484
       then
1487 1485
          schemename="${targetname}"
1488 1486
          targetname=
... ...
@@ -1511,7 +1509,7 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO}${info} in \
1511 1509
    local owd
1512 1510
    local command
1513 1511
 
1514
-   if [ "$MULLE_FLAG_EXECUTOR_DRY_RUN" != "" ]
1512
+   if [ "${MULLE_FLAG_EXECUTOR_DRY_RUN}" = "YES" ]
1515 1513
    then
1516 1514
       command=-showBuildSettings
1517 1515
    else
... ...
@@ -1910,18 +1908,21 @@ build_with_configuration_sdk_preferences()
1910 1908
                return 0
1911 1909
             else
1912 1910
                [ ! -e "${script}" ] || fail "script ${script} is not executable"
1911
+               log_fluff "There is no build script in \"`build_setting_path "${name}" "bin/build.sh"`\""
1913 1912
             fi
1914 1913
          ;;
1915 1914
 
1916 1915
          xcodebuild)
1917 1916
             if [ ! -z "${XCODEBUILD}" ]
1918 1917
             then
1919
-               project=`(cd "${srcdir}" ; find_xcodeproj "${name}")`
1918
+               project="`(cd "${srcdir}" ; find_xcodeproj "${name}")`"
1920 1919
 
1921
-               if [ ! -z "$project" ]
1920
+               if [ ! -z "${project}" ]
1922 1921
                then
1923 1922
                   build_xcodebuild_schemes_or_target "${configuration}" "${srcdir}" "${builddir}" "${name}" "${sdk}" "${project}"  || exit 1
1924 1923
                   return 0
1924
+               else
1925
+                  log_fluff "There is no Xcode project in \"${srcdir}\""
1925 1926
                fi
1926 1927
             fi
1927 1928
          ;;
... ...
@@ -1941,6 +1942,8 @@ build_with_configuration_sdk_preferences()
1941 1942
                   build_configure "${configuration}" "${srcdir}" "${builddir}" "${name}" "${sdk}"  || exit 1
1942 1943
                   return 0
1943 1944
                fi
1945
+            else
1946
+               log_fluff "There is no configure script in \"${srcdir}\""
1944 1947
             fi
1945 1948
          ;;
1946 1949
 
... ...
@@ -1954,6 +1957,8 @@ build_with_configuration_sdk_preferences()
1954 1957
                   build_cmake "${configuration}" "${srcdir}" "${builddir}" "${name}" "${sdk}"  || exit 1
1955 1958
                   return 0
1956 1959
                fi
1960
+            else
1961
+               log_fluff "There is no CMakeLists.txt file in \"${srcdir}\""
1957 1962
             fi
1958 1963
          ;;
1959 1964
 
... ...
@@ -2125,7 +2130,7 @@ build_if_alive()
2125 2130
          build_wrapper "${name}" "${stashdir}"
2126 2131
 
2127 2132
          # memorize what we build
2128
-         redirect_append_exekutor "${REPOS_DIR}/.build_done" echo "${name}"
2133
+         merge_line_into_file "${REPOS_DIR}/.build_done" "${name}"
2129 2134
 
2130 2135
          BUILT="${name}
2131 2136
 ${BUILT}"
... ...
@@ -2223,7 +2228,7 @@ build_stashes()
2223 2228
 have_tars()
2224 2229
 {
2225 2230
    tarballs=`read_root_setting "tarballs"`
2226
-   [ "${tarballs}" != "" ]
2231
+   [ ! -z "${tarballs}" ]
2227 2232
 }
2228 2233
 
2229 2234
 
... ...
@@ -114,7 +114,7 @@ check_tars()
114 114
    log_fluff "Looking for tarballs"
115 115
 
116 116
    tarballs="`read_root_setting "tarballs" | sort | sort -u`"
117
-   if [ "${tarballs}" != "" ]
117
+   if [ ! -z "${tarballs}" ]
118 118
    then
119 119
       [ -z "${DEFAULT_IFS}" ] && internal_fail "IFS fail"
120 120
       IFS="
... ...
@@ -182,7 +182,10 @@ link_command()
182 182
    local absolute
183 183
 
184 184
    absolute="`read_config_setting "absolute_symlinks" "NO"`"
185
-   exekutor create_symlink "${url}" "${stashdir}" "${absolute}"
185
+   if ! exekutor create_symlink "${url}" "${stashdir}" "${absolute}"
186
+   then
187
+      return 1
188
+   fi
186 189
 
187 190
    local branchlabel
188 191
 
... ...
@@ -496,7 +499,7 @@ clone_or_symlink()
496 499
    # and check that the archive is correct
497 500
    #
498 501
    extra="`echo "${scm}" | sed -n 's/^[^?]*\?\(.*\)/\1/p'`"
499
-   if [ ! -z "{extra}" ]
502
+   if [ ! -z "${extra}" ]
500 503
    then
501 504
       log_fluff "Parsed SCM_OPTIONS as \"${extra}\""
502 505
       SCM_OPTIONS="${extra}"
... ...
@@ -567,13 +570,38 @@ clone_or_symlink()
567 570
       ;;
568 571
    esac
569 572
 
570
-   "${operation}" "${reposdir}" \
571
-                  "${name}" \
572
-                  "${url}" \
573
-                  "${branch}" \
574
-                  "${scm}" \
575
-                  "${tag}" \
576
-                  "${stashdir}" || exit 1
573
+   local rval
574
+
575
+   if ! "${operation}" "${reposdir}" \
576
+                       "${name}" \
577
+                       "${url}" \
578
+                       "${branch}" \
579
+                       "${scm}" \
580
+                       "${tag}" \
581
+                       "${stashdir}"
582
+   then
583
+      #
584
+      # check if clone is an optional install component
585
+      # it is if it doesn't show up in "required"
586
+      # required is built by mulle-bootstrap usually
587
+      # you specify optionals, by specifying the required
588
+      # clones and leaving the optional out
589
+      #
590
+      local required
591
+
592
+      required="`read_root_setting "required"`"
593
+      [ -z "${required}" ] && internal_fail "required missing"
594
+
595
+      if ! echo "${required}" | fgrep -s -q -x "${name}" > /dev/null
596
+      then
597
+         log_info "${C_MAGENTA}${C_BOLD}${name}${C_INFO} is missing, but it's not required."
598
+
599
+         merge_line_into_file "${REPOS_DIR}/.missing" "${name}"
600
+         return 1  # means just skip
601
+      fi
602
+
603
+      return  # means exit
604
+   fi
577 605
 
578 606
    if [ "${DONT_WARN_SCRIPTS}" != "YES" ]
579 607
    then
... ...
@@ -1186,6 +1214,10 @@ work_clones()
1186 1214
                         # if we used a symlink, we want to memorize that
1187 1215
                         scm="symlink"
1188 1216
                      ;;
1217
+
1218
+                     3)
1219
+                        exit 1
1220
+                     ;;
1189 1221
                   esac
1190 1222
                ;;
1191 1223
 
... ...
@@ -50,6 +50,8 @@ eval_trace()
50 50
    then
51 51
       local arrow
52 52
 
53
+      [ -z "${MULLE_EXECUTABLE_PID}" ] && internal_fail "MULLE_EXECUTABLE_PID not set"
54
+
53 55
       if [ "${PPID}" -ne "${MULLE_EXECUTABLE_PID}" ]
54 56
       then
55 57
          arrow="=[${PPID}]=>"
... ...
@@ -75,6 +77,8 @@ eval_trace_output()
75 77
    then
76 78
       local arrow
77 79
 
80
+      [ -z "${MULLE_EXECUTABLE_PID}" ] && internal_fail "MULLE_EXECUTABLE_PID not set"
81
+
78 82
       if [ "${PPID}" -ne "${MULLE_EXECUTABLE_PID}" ]
79 83
       then
80 84
          arrow="=[${PPID}]=>"
... ...
@@ -1172,6 +1176,19 @@ _create_file_if_missing()
1172 1176
 }
1173 1177
 
1174 1178
 
1179
+merge_line_into_file()
1180
+{
1181
+  local path="$1"
1182
+  local line="$2"
1183
+
1184
+  if fgrep -s -q -x "${name}" "${path}" 2> /dev/null
1185
+  then
1186
+     return
1187
+  fi
1188
+  redirect_append_exekutor "${path}" echo "${line}"
1189
+}
1190
+
1191
+
1175 1192
 create_file_if_missing()
1176 1193
 {
1177 1194
   _create_file_if_missing "$1" "# intentionally blank file"
... ...
@@ -1301,7 +1318,7 @@ find_xcodeproj()
1301 1318
    #
1302 1319
    # don't go too deep in search
1303 1320
    #
1304
-   for i in `find . -depth 2 -name "*.xcodeproj" -print`
1321
+   for i in `find . -maxdepth 2 -name "*.xcodeproj" -print`
1305 1322
    do
1306 1323
       match=`basename -- "${i}" .xcodeproj`
1307 1324
       if [ "$match" = "$expect" ]
... ...
@@ -1318,7 +1335,7 @@ find_xcodeproj()
1318 1335
       fi
1319 1336
    done
1320 1337
 
1321
-   if [ "$found" != "" ]
1338
+   if [ ! -z "$found" ]
1322 1339
    then
1323 1340
       echo "${found}"
1324 1341
       return 0
... ...
@@ -399,7 +399,7 @@ user_say_yes()
399 399
 
400 400
       if [ -z "${x}" ]
401 401
       then
402
-         x="${MULLE_FLAG_ANSWER}"
402
+         x="NO"
403 403
       fi
404 404
    done
405 405
 }
... ...
@@ -518,9 +518,12 @@ build_needed()
518 518
 
519 519
    [ -z "${REPOS_DIR}" ] && internal_fail "REPOS_DIR undefined"
520 520
 
521
-   if [ ! -f "${REPOS_DIR}/build_done" ]
521
+   local build_done
522
+
523
+   build_done="${REPOS_DIR}/.build_done"
524
+   if [ ! -f "${build_done}" ]
522 525
    then
523
-      log_verbose "Need build because \"${REPOS_DIR}/.build_done\" does not exist."
526
+      log_verbose "Need build because \"${build_done}\" does not exist."
524 527
       return 0
525 528
    fi
526 529
 
... ...
@@ -531,12 +534,12 @@ build_needed()
531 534
    # sort  and unique, because people can redo builds manually
532 535
    # which will add duplicate lines
533 536
    #
534
-   progress="`read_setting "${REPOS_DIR}/.build_done" | sort | sort -u`"
537
+   progress="`read_setting "${build_done}" | sort`"
535 538
    complete="`read_root_setting "build_order" | sort`"
536 539
 
537 540
    if [ "${progress}" != "${complete}" ]
538 541
    then
539
-      log_verbose "Need build because \"${REPOS_DIR}/build_done\" is different to \"build_order\""
542
+      log_verbose "Need build because \"${build_done}\" is different to \"build_order\""
540 543
       return 0
541 544
    fi
542 545
 
... ...
@@ -591,6 +594,23 @@ fetch_needed()
591 594
       fi
592 595
    done
593 596
 
597
+   local minions
598
+
599
+   minions="`read_root_setting "minions"`"
600
+
601
+   IFS="
602
+"
603
+   for stashdir in ${minions}
604
+   do
605
+      IFS="${DEFAULT_IFS}"
606
+
607
+      if [ "${referencefile}" -ot "${stashdir}/${BOOTSTRAP_DIR}" ]
608
+      then
609
+         log_verbose "Need fetch because \"${stashdir}/${BOOTSTRAP_DIR}\" is modified"
610
+         return 0
611
+      fi
612
+   done
613
+
594 614
    IFS="${DEFAULT_IFS}"
595 615
 
596 616
    return 1
... ...
@@ -780,6 +780,8 @@ parse_raw_clone()
780 780
 }
781 781
 
782 782
 
783
+#   # process_raw_clone
784
+#   local name        # name of clone
783 785
 process_raw_clone()
784 786
 {
785 787
    name="`_canonical_clone_name "${url}"`"
... ...
@@ -831,6 +833,40 @@ parse_clone()
831 833
 }
832 834
 
833 835
 
836
+names_from_repository_file()
837
+{
838
+   local filename="$1"
839
+
840
+   local clones
841
+
842
+   local url        # url of clone
843
+   local dstdir
844
+   local name
845
+   local branch
846
+   local scm
847
+   local tag
848
+
849
+   clones="`read_setting "${dst}/repositories"`"
850
+
851
+   IFS="
852
+"
853
+   for clone in ${clones}
854
+   do
855
+      IFS="${DEFAULT_IFS}"
856
+
857
+      parse_raw_clone "${clone}"
858
+      process_raw_clone
859
+
860
+      if [ ! -z "${name}" ]
861
+      then
862
+         echo "${name}"
863
+      fi
864
+   done
865
+
866
+   IFS="${DEFAULT_IFS}"
867
+}
868
+
869
+
834 870
 #
835 871
 # read repository file, properly do expansions
836 872
 # replace branch with override if needed
... ...
@@ -980,6 +1016,29 @@ merge_repository_contents()
980 1016
 }
981 1017
 
982 1018
 
1019
+merge_repository_files()
1020
+{
1021
+   local srcfile="$1"
1022
+   local dstfile="$2"
1023
+   local delete_dstdir="${3:-NO}"
1024
+
1025
+   [ -z "${srcfile}" ] && internal_fail "srcfile is empty"
1026
+   [ -z "${dstfile}" ] && internal_fail "dstfile is empty"
1027
+
1028
+   log_fluff "Copying expanded \"repositories\" from \"${srcfile}\""
1029
+
1030
+   local contents
1031
+   local additions
1032
+
1033
+   contents="`cat "${dstfile}" 2> /dev/null || :`"
1034
+   additions="`read_repository_file "${srcfile}" "${delete_dstdir}"`" || fail "read"
1035
+   additions="`echo "${additions}"| sed 's/;*$//'`"
1036
+   additions="`merge_repository_contents "${contents}" "${additions}"`"
1037
+
1038
+   redirect_exekutor "${dstfile}" echo "${additions}"
1039
+}
1040
+
1041
+
983 1042
 #
984 1043
 # take a list of repositories
985 1044
 # unique them with another list of repositories by url
... ...
@@ -234,14 +234,20 @@ _git_clone()
234 234
 
235 235
    if [ ! -d "${dstdir}" ]
236 236
    then
237
-      exekutor git ${GITFLAGS} clone ${options} ${GITOPTIONS} -- "${url}" "${dstdir}"  >&2 \
238
-         || fail "git clone of \"${url}\" into \"${dstdir}\" failed"
237
+      if ! exekutor git ${GITFLAGS} clone ${options} ${GITOPTIONS} -- "${url}" "${dstdir}" >&2
238
+      then
239
+         log_error "git clone of \"${url}\" into \"${dstdir}\" failed"
240
+         return 1
241
+      fi
239 242
    fi
240 243
 
241 244
    if [ ! -z "${CLONE_CACHE}" -a "${stashdir}" != "${CLONE_CACHE}" ]
242 245
    then
243
-      exekutor git ${GITFLAGS} clone ${options} ${GITOPTIONS} -- "${dstdir}" "${stashdir}"  >&2 \
244
-      || fail "git clone of \"${dstdir}\" into \"${stashdir}\" failed"
246
+      if ! exekutor git ${GITFLAGS} clone ${options} ${GITOPTIONS} -- "${dstdir}" "${stashdir}"  >&2
247
+      then
248
+         log_error "git clone of \"${dstdir}\" into \"${stashdir}\" failed"
249
+         return 1
250
+      fi
245 251
    fi
246 252
 
247 253
    if [ ! -z "${tag}" ]
... ...
@@ -365,8 +371,11 @@ svn_checkout()
365 371
       fi
366 372
    fi
367 373
 
368
-   exekutor svn checkout ${options} ${SVNOPTIONS} "${url}" "${stashdir}"  >&2 \
369
-     || fail "svn clone of \"${url}\" into \"${stashdir}\" failed"
374
+   if ! exekutor svn checkout ${options} ${SVNOPTIONS} "${url}" "${stashdir}"  >&2
375
+   then
376
+      log_error "svn clone of \"${url}\" into \"${stashdir}\" failed"
377
+      return 1
378
+   fi
370 379
 }
371 380
 
372 381
 
... ...
@@ -721,17 +730,17 @@ tar_unpack()
721 730
    esac
722 731
 
723 732
    rmdir_safer "${name}.tmp"
724
-   tmpdir="`exekutor mktemp -d "${name}.tmp"`" || exit 1
733
+   tmpdir="`exekutor mktemp -d "${name}.tmp"`" || return 1
725 734
    (
726
-      exekutor cd "${tmpdir}" || exit 1
735
+      exekutor cd "${tmpdir}" || return 1
727 736
 
728
-      _tar_download "${download}" || exit 1
737
+      _tar_download "${download}" || return 1
729 738
 
730 739
       case "${url}" in
731 740
          *.zip)
732
-            exekutor unzip "${download}" || exit 1
741
+            exekutor unzip "${download}" || return 1
733 742
             archive="`basename "${download}" .zip`"
734
-            exekutor rm "${download}" || exit 1
743
+            exekutor rm "${download}" || return 1
735 744
          ;;
736 745
       esac
737 746
 
... ...
@@ -758,9 +767,9 @@ tar_unpack()
758 767
 
759 768
       log_verbose "Extracting ${C_MAGENTA}${C_BOLD}${archive}${C_INFO} ..."
760 769
 
761
-      exekutor tar xf ${TAROPTIONS} ${options} "${archive}" || exit 1
762
-      exekutor rm "${archive}" || exit 1
763
-   ) || exit 1
770
+      exekutor tar xf ${TAROPTIONS} ${options} "${archive}" || return 1
771
+      exekutor rm "${archive}"
772
+   ) || return 1
764 773
 
765 774
    _move_stuff "${tmpdir}" "${stashdir}" "${archivename}" "${name}"
766 775
 }
... ...
@@ -788,18 +797,18 @@ zip_unpack()
788 797
    rmdir_safer "${name}.tmp"
789 798
    tmpdir="`exekutor mktemp -d "${name}.tmp"`" || exit 1
790 799
    (
791
-      exekutor cd "${tmpdir}" || exit 1
800
+      exekutor cd "${tmpdir}" || return 1
792 801
 
793 802
       log_info "Downloading ${C_MAGENTA}${C_BOLD}${url}${C_INFO} ..."
794 803
 
795
-      exekutor curl -O -L ${CURLOPTIONS} "${url}" || exit 1
796
-      _validate_download "${download}" "${SCM_OPTIONS}" || exit 1
804
+      exekutor curl -O -L ${CURLOPTIONS} "${url}" || return 1
805
+      _validate_download "${download}" "${SCM_OPTIONS}" || return 1
797 806
 
798 807
       log_verbose "Extracting ${C_MAGENTA}${C_BOLD}${download}${C_INFO} ..."
799 808
 
800
-      exekutor unzip "${download}" || exit 1
801
-      exekutor rm "${download}" || exit 1
802
-   ) || exit 1
809
+      exekutor unzip "${download}" || return 1
810
+      exekutor rm "${download}"
811
+   ) || return 1
803 812
 
804 813
    _move_stuff "${tmpdir}" "${stashdir}" "${archivename}" "${name}"
805 814
 }
... ...
@@ -39,6 +39,7 @@ usage:
39 39
 
40 40
    Options:
41 41
       -d   : delete config setting
42
+      -g   : use ~/.mulle-bootstrap folder instead of .bootstrap-local
42 43
       -l   : list config values
43 44
 
44 45
    Use:
... ...
@@ -231,7 +232,7 @@ _read_setting()
231 232
 {
232 233
    local apath="$1"
233 234
 
234
-   [ ! -z "${apath}" ] || fail "no path given to read_setting"
235
+   [ ! -z "${apath}" ] || internal_fail "no path given to read_setting"
235 236
 
236 237
    local value
237 238
 
... ...
@@ -314,7 +315,7 @@ read_raw_setting()
314 315
 {
315 316
    local key="$1"
316 317
 
317
-   [ $# -ne 1 ]     && internal_fail "parameterization error"
318
+   [ $# -ne 1 ]    && internal_fail "parameterization error"
318 319
    [ -z "${key}" ] && internal_fail "empty key in read_raw_setting"
319 320
 
320 321
    if _read_setting "${BOOTSTRAP_DIR}.local/${key}"
... ...
@@ -324,6 +325,25 @@ read_raw_setting()
324 325
    _read_setting "${BOOTSTRAP_DIR}/${key}"
325 326
 }
326 327
 
328
+
329
+_bootstrap_setting_path()
330
+{
331
+   local key="$1"
332
+
333
+   #
334
+   # to access unmerged data (needed for embedded repos)
335
+   #
336
+   if [ "${MULLE_BOOTSTRAP_SETTINGS_NO_AUTO}" = "YES" ]
337
+   then
338
+      suffix=""
339
+   else
340
+      suffix=".auto"
341
+   fi
342
+
343
+   echo "${BOOTSTRAP_DIR}${suffix}/${key}"
344
+}
345
+
346
+
327 347
 #
328 348
 # this has to be flexible, because fetch and build settings read differently
329 349
 #
... ...
@@ -331,7 +351,7 @@ _read_bootstrap_setting()
331 351
 {
332 352
    local key="$1"
333 353
 
334
-   [ $# -ne 1 ]     && internal_fail "parameterization error"
354
+   [ $# -ne 1 ]    && internal_fail "parameterization error"
335 355
    [ -z "${key}" ] && internal_fail "empty key in _read_bootstrap_setting"
336 356
 
337 357
    local value
... ...
@@ -530,6 +550,15 @@ read_config_setting()
530 550
 }
531 551
 
532 552
 
553
+build_setting_path()
554
+{
555
+   local package="$1"
556
+   local key="$2"
557
+
558
+   _bootstrap_setting_path "${package}.build/${key}"
559
+}
560
+
561
+
533 562
 #
534 563
 # values in "overrides" override those inherited by repositories
535 564
 # values in "settings" are overriden by those inherited by repositories
... ...
@@ -541,15 +570,11 @@ read_build_setting()
541 570
       set +x
542 571
    fi
543 572
 
544
-   local key
545
-   local default
546
-   local package
547
-
548 573
    [ $# -lt 2 -o $# -gt 3 ] && internal_fail "parameterization error"
549 574
 
550
-   package="$1"
551
-   key="$2"
552
-   default="$3"
575
+   local package="$1"
576
+   local key="$2"
577
+   local default="$3"
553 578
 
554 579
    [ -z "${key}" ] && internal_fail "empty parameter in read_config_setting"
555 580
 
... ...
@@ -634,6 +659,8 @@ find_build_setting_file()
634 659
 }
635 660
 
636 661
 
662
+
663
+
637 664
 ####
638 665
 # Functions building on read_ functions
639 666
 #
... ...
@@ -709,6 +736,46 @@ read_expanded_setting()
709 736
 }
710 737
 
711 738
 
739
+# sti
740
+_combine_settings_in_front()
741
+{
742
+   local settings1="$1"
743
+   local settings2="$2"
744
+   local key="$3"
745
+
746
+   local result
747
+
748
+   result="${settings2}"
749
+
750
+   local line
751
+
752
+   # https://stackoverflow.com/questions/742466/how-can-i-reverse-the-order-of-lines-in-a-file/744093#744093
753
+
754
+   IFS="
755
+"
756
+   for line in `echo "${settings1}" | sed -n '1!G;h;$p'`
757
+   do
758
+      result="`echo "${result}" | grep -v -x "${line}"`"
759
+      result="${line}
760
+${result}"
761
+   done
762
+
763
+   IFS="${DEFAULT_IFS}"
764
+
765
+   if [ "$MULLE_FLAG_LOG_SETTINGS" = "YES" -o \
766
+        "$MULLE_FLAG_MERGE_LOG" = "YES"  ]
767
+   then
768
+      log_trace2 "----------------------"
769
+      log_trace2 "Merged settings:      "
770
+      log_trace2 "----------------------"
771
+      log_trace2 "${result}"
772
+      log_trace2 "----------------------"
773
+   fi
774
+   echo "${result}"
775
+}
776
+
777
+
778
+
712 779
 _merge_settings_in_front()
713 780
 {
714 781
    local settings1="$1"
... ...
@@ -908,9 +975,12 @@ _setting_append()
908 975
    filename="${directory}/${key}"
909 976
    before="`_read_setting "${filename}"`"
910 977
 
978
+   # ugliness needed for
979
+   [ -z "${MULLE_BOOTSTRAP_REPOSITORIES_SH}" ] && . mulle-bootstrap-repositories.sh
980
+
911 981
    case "${key}" in
912 982
       embedded_repositories|repositories)
913
-         redirect_exekutor "${filename}" merge_repository_file "${before}" "${value}"
983
+         redirect_exekutor "${filename}" merge_repository_contents "${before}" "${value}"
914 984
       ;;
915 985
 
916 986
       brews|tarballs)
... ...
@@ -960,32 +1030,54 @@ _config_list()
960 1030
 
961 1031
 _config_read()
962 1032
 {
963
-   local key="$1"
964
-
965 1033
    read_config_setting "${key}"
966 1034
 }
967 1035
 
968 1036
 
969 1037
 _config_append()
970 1038
 {
971
-   fail "Not yet implemented"
1039
+   internal_fail "Not yet implemented"
972 1040
 }
973 1041
 
974 1042
 
975 1043
 _config_write()
976 1044
 {
977
-   mkdir_if_missing "${BOOTSTRAP_DIR}.local/config"
1045
+   local key="$1"
1046
+   local value="$2"
1047
+
1048
+   local configdir
1049
+
1050
+   configdir="${BOOTSTRAP_DIR}.local/config"
1051
+
1052
+   if [ "${OPTION_GLOBAL}" = "YES" ]
1053
+   then
1054
+      configdir="${HOME}/.mulle-bootstrap"
1055
+   fi
1056
+
1057
+   mkdir_if_missing "${configdir}"
1058
+   exekutor echo "${value}" > "${configdir}/${key}"
978 1059
 
979
-   exekutor echo "$2" > "${BOOTSTRAP_DIR}.local/config/$1"
980 1060
    exekutor touch "${BOOTSTRAP_DIR}.local"
981 1061
 }
982 1062
 
983 1063
 
984 1064
 _config_delete()
985 1065
 {
986
-   if [ -f "${BOOTSTRAP_DIR}.local/config/$1" ]
1066
+   local key="$1"
1067
+   local value="$2"
1068
+
1069
+   local configdir
1070
+
1071
+   configdir="${BOOTSTRAP_DIR}.local/config"
1072
+
1073
+   if [ "${OPTION_GLOBAL}" = "YES" ]
987 1074
    then
988
-      exekutor rm "${BOOTSTRAP_DIR}.local/config/$1"  >&2
1075
+      configdir="${HOME}/.mulle-bootstrap"
1076
+   fi
1077
+
1078
+   if [ -f "${configdir}/$1" ]
1079
+   then
1080
+      exekutor rm "${configdir}/$1"  >&2
989 1081
       exekutor touch "${BOOTSTRAP_DIR}.local"  >&2
990 1082
    fi
991 1083
 }
... ...
@@ -1026,7 +1118,7 @@ _expansion_write()
1026 1118
 
1027 1119
 _expansion_append()
1028 1120
 {
1029
-   fail "Not yet implemented"
1121
+   internal_fail "Not yet implemented"
1030 1122
 }
1031 1123
 
1032 1124
 
... ...
@@ -1043,7 +1135,7 @@ _expansion_delete()
1043 1135
 
1044 1136
 _expansion_list()
1045 1137
 {
1046
-   fail "Not yet implemented"
1138
+   internal_fail "Not yet implemented"
1047 1139
 }
1048 1140
 
1049 1141
 
... ...
@@ -88,7 +88,7 @@ git_must_be_clean()
88 88
    local clean
89 89
 
90 90
    clean=`git status -s`
91
-   if [ "${clean}" != "" ]
91
+   if [ ! -z "${clean}" ]
92 92
    then
93 93
       log_error "Repository \"$name\" is not ready to be tagged yet."
94 94
       if [ "${MULLE_FLAG_LOG_TERSE}" != "YES" ]
95 95
new file mode 100755
... ...
@@ -0,0 +1,136 @@
1
+#! /bin/sh
2
+
3
+clear_test_dirs()
4
+{
5
+   local i
6
+
7
+   for i in "$@"
8
+   do
9
+      if [ -d "$i" ]
10
+      then
11
+         rm -rf "$i"
12
+      fi
13
+   done
14
+}
15
+
16
+
17
+fail()
18
+{
19
+   echo "failed" "$@" >&2
20
+   exit 1
21
+}
22
+
23
+
24
+run_mulle_bootstrap()
25
+{
26
+   echo "####################################" >&2
27
+   echo mulle-bootstrap "$@"  >&2
28
+   echo "####################################" >&2
29
+
30
+   mulle-bootstrap "$@" || fail "mulle-bootstrap failed"
31
+}
32
+
33
+
34
+#
35
+#
36
+#
37
+setup()
38
+{
39
+   [ -d a ] && rm -rf a
40
+   [ -d b ] && rm -rf b
41
+   [ -d c ] && rm -rf c
42
+
43
+   mkdir a
44
+   mkdir b
45
+   mkdir c
46
+
47
+   (
48
+      cd a
49
+
50
+      mkdir -p .bootstrap
51
+      echo "b" > .bootstrap/repositories
52
+
53
+      mkdir -p .bootstrap/b.build/bin
54
+      echo "echo a/.bootstrap/b.build/bin/pre-build.sh >&2" > .bootstrap/b.build/bin/pre-build.sh
55
+      chmod 755 .bootstrap/b.build/bin/pre-build.sh
56
+      # echo "echo a/.bootstrap/b.build/bin/post-build.sh >&2" > .bootstrap/b.build/bin/post-build.sh
57
+      # chmod 755 .bootstrap/b.build/bin/post-build.sh
58
+
59
+      mkdir -p .bootstrap/bin
60
+      echo "echo a/.bootstrap/bin/pre-build.sh >&2" > .bootstrap/bin/pre-build.sh
61
+      chmod 755 .bootstrap/bin/pre-build.sh
62
+      echo "echo a/.bootstrap/bin/post-build.sh >&2" > .bootstrap/bin/post-build.sh
63
+      chmod 755 .bootstrap/bin/post-build.sh
64
+      echo "echo a/.bootstrap/bin/build.sh >&2" > .bootstrap/bin/build.sh
65
+      chmod 755 .bootstrap/bin/build.sh
66
+   )
67
+
68
+   (
69
+      cd b
70
+
71
+      mkdir -p .bootstrap
72
+      echo "c" > .bootstrap/repositories
73
+
74
+      mkdir -p .bootstrap/c.build/bin
75
+      echo "echo b/.bootstrap/c.build/bin/pre-build.sh >&2" > .bootstrap/c.build/bin/pre-build.sh
76
+      chmod 755 .bootstrap/c.build/bin/pre-build.sh
77
+      echo "echo b/.bootstrap/c.build/bin/post-build.sh >&2" > .bootstrap/c.build/bin/post-build.sh
78
+      chmod 755 .bootstrap/c.build/bin/post-build.sh
79
+
80
+      mkdir -p .bootstrap/bin
81
+      echo "echo b/.bootstrap/bin/pre-build.sh >&2" > .bootstrap/bin/pre-build.sh
82
+      chmod 755 .bootstrap/bin/pre-build.sh
83
+      echo "echo b/.bootstrap/bin/post-build.sh >&2" > .bootstrap/bin/post-build.sh
84
+      chmod 755 .bootstrap/bin/post-build.sh
85
+      echo "echo b/.bootstrap/bin/build.sh >&2" > .bootstrap/bin/build.sh