Browse code

Fix svn checkout. Make cmake the default even on OS X. mulle_bootstrap can now checkout branches. Consistency check added, avoiding aborted fetches producing unpleasant results.

Nat! authored on 17-04-2016 14:44:15
Showing 11 changed files
... ...
@@ -133,6 +133,23 @@ echo "Finch Demo" > .bootstrap/Finch/targets
133 133
 Use `mulle-bootstrap -V` to get an extensive trace.
134 134
 
135 135
 
136
+### I want to only build with cmake
137
+
138
+Any setting can be overriden by the environment:
139
+
140
+```
141
+MULLE_BOOTSTRAP_BUILD_PREFERENCES=cmake mulle-bootstrap build
142
+```
143
+
144
+### Is the order of the repositories important ?
145
+
146
+Sometimes yes. Try to keep them in order of interdependency.
147
+
148
+f.e. mulle-aba is dependent on mulle-allocator and mulle-thread,
149
+but mulle-allocator is also dependent on mulle-thread, then put
150
+mulle-thread ahead of mulle-allocator in the `repositories` file.
151
+
152
+
136 153
 
137 154
 ### It's not working as I expect now what ?
138 155
 
... ...
@@ -1,3 +1,29 @@
1
+0.22
2
+===
3
+*  Fix repository order when merging. You should know, that the
4
+   repository order in `.bootstrap/repositories` needs to be in proper sorted
5
+   order. Only than can mulle-bootstrap figure out the recursive dependencies
6
+   correctly.
7
+*  Allow clone of specific branches by changing the repository spec line to
8
+   url;name;branch
9
+
10
+      ```
11
+      https://www.mulle-kybernetik.com/repositories/mulle-configuration;;MulleFoundation
12
+      ```
13
+      uses the default name, but fetches the MulleFoundation branch.
14
+*  Huge change:  CMake (and configure) are now the prefered build systems even
15
+   on OS X (if a `CMakeLists.txtà is available). xcodebuild becomes a fallback
16
+   preference. The reasons are:
17
+      1.  CMake + Make are seem faster than xcodebuild
18
+      2.  It forces me to keep up the CMakeLists.txt with the Xcode project
19
+   If you don't like it change the build setting 'build_preferences'.
20
+*  mulle-bootstrap recognizes that bare repositories need to be cloned more
21
+   often now, if not always.
22
+*  Make mulle-bootstrap more resilient against aborted fetches, added Dirty
23
+   Harry quote.
24
+*  Uses CMAKE_EXE_LINKER_FLAGS and DCMAKE_SHARED_LINKER_FLAGS instead of CMAKE_LD_FLAGS.
25
+*  Fix wrong --recursive for svn checkout.
26
+
1 27
 0.21
2 28
 ===
3 29
 
... ...
@@ -29,7 +29,7 @@
29 29
 #   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 30
 #   POSSIBILITY OF SUCH DAMAGE.
31 31
 
32
-VERSION=0.21
32
+VERSION=0.22
33 33
 
34 34
 #
35 35
 # This is the main user interface to mulle-bootstrap
... ...
@@ -366,7 +366,10 @@ build_fail()
366 366
       printf "${C_RESET}"
367 367
    fi
368 368
 
369
-   log_info "Check the build log: ${C_RESET_BOLD}${1}${C_INFO}"
369
+   if [ -z "$MULLE_BOOTSTRAP_TRACE" ]
370
+   then
371
+      log_info "Check the build log: ${C_RESET_BOLD}${1}${C_INFO}"
372
+   fi
370 373
    fail "$2 failed"
371 374
 }
372 375
 
... ...
@@ -454,6 +457,13 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO} in \"${builddir}\" ..."
454 457
    log_fluff "Build logs will be in \"${logfile1}\" and \"${logfile2}\""
455 458
 
456 459
    owd="${PWD}"
460
+
461
+#   cmake_keep_builddir="`read_build_setting "$name" "cmake_keep_builddir" "YES"`"
462
+#   if [ "${cmake_keep_builddir}" != "YES" ]
463
+#   then
464
+#      rmdir_safer "${builddir}"
465
+#   fi
466
+
457 467
    mkdir_if_missing "${builddir}"
458 468
    exekutor cd "${builddir}" || fail "failed to enter ${builddir}"
459 469
 
... ...
@@ -481,28 +491,31 @@ ${C_MAGENTA}${C_BOLD}${sdk}${C_INFO} in \"${builddir}\" ..."
481 491
 "-DDEPENDENCIES_DIR=${owd}/${REFERENCE_DEPENDENCY_SUBDIR}" \
482 492
 "-DCMAKE_INSTALL_PREFIX:PATH=${owd}/${BUILD_DEPENDENCY_SUBDIR}/usr/local"  \
483 493
 "-DCMAKE_C_FLAGS=\
484
--I${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${HEADER_DIR_NAME} \
485
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}${suffix} \
486
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}/${configuration} \
487
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME} \
494
+-I${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${HEADER_DIR_NAME} \
495
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}${suffix} \
496
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}/${configuration} \
497
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME} \
488 498
 ${other_cflags}" \
489 499
 "-DCMAKE_CXX_FLAGS=\
490
--I${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${HEADER_DIR_NAME} \
491
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}${suffix} \
492
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}/${configuration} \
493
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME} \
500
+-I${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${HEADER_DIR_NAME} \
501
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}${suffix} \
502
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}/${configuration} \
503
+-F${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME} \
494 504
 ${other_cppflags}" \
495
-"-DCMAKE_LD_FLAGS=\
496
--L${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}${suffix} \
497
--L${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}/${configuration} \
498
--L${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME} \
499
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}${suffix} \
500
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME}/${configuration} \
501
--F${relative}/${REFERENCE_DEPENDENCY_SUBDIR}/${FRAMEWORK_DIR_NAME} \
505
+"-DCMAKE_EXE_LINKER_FLAGS=\
506
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}${suffix} \
507
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}/${configuration} \
508
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME} \
502 509
 ${other_ldflags}" \
510
+"-DCMAKE_SHARED_LINKER_FLAGS=\
511
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}${suffix} \
512
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME}/${configuration} \
513
+-L${owd}/${REFERENCE_DEPENDENCY_SUBDIR}/${LIBRARY_DIR_NAME} \
514
+${other_ldflags}" \
515
+${CMAKE_FLAGS} \
503 516
 "${relative}/${srcdir}" > "${logfile1}" || build_fail "${logfile1}" "cmake"
504 517
 
505
-      logging_exekutor make VERBOSE=1 install > "${logfile2}" || build_fail "${logfile2}" "make"
518
+      logging_exekutor make ${MAKE_FLAGS} VERBOSE=1 install > "${logfile2}" || build_fail "${logfile2}" "make"
506 519
 
507 520
       set +f
508 521
 
... ...
@@ -1097,12 +1110,6 @@ build_xcodebuild_schemes_or_target()
1097 1110
    name="$5"
1098 1111
    project="$7"
1099 1112
 
1100
-   if [ -d "${builddir}" -a "${CLEAN_BEFORE_BUILD}" = "YES" ]
1101
-   then
1102
-      log_fluff "Cleaning build directory \"${builddir}\""
1103
-      rmdir_safer "${builddir}"
1104
-   fi
1105
-
1106 1113
    local scheme
1107 1114
    local schemes
1108 1115
 
... ...
@@ -1207,6 +1214,8 @@ build_script()
1207 1214
    logfile="${BUILDLOG_SUBDIR}/${name}-${configuration}-${sdk}.script.log"
1208 1215
    log_fluff "Build log will be in: ${C_RESET_BOLD}${logfile}${C_INFO}"
1209 1216
 
1217
+   mkdir_if_missing "${builddir}"
1218
+
1210 1219
    local owd
1211 1220
 
1212 1221
    owd=`pwd`
... ...
@@ -1269,9 +1278,9 @@ build()
1269 1278
       if [ "`uname`" = 'Darwin' ]
1270 1279
       then
1271 1280
          preferences="`read_config_setting "build_preferences" "script
1272
-xcodebuild
1273 1281
 cmake
1274
-configure"`"
1282
+configure
1283
+xcodebuild"`"
1275 1284
       else
1276 1285
          preferences="`read_config_setting "build_preferences" "script
1277 1286
 cmake
... ...
@@ -1326,6 +1335,12 @@ Release"`"
1326 1335
          builddir="${CLONESBUILD_SUBDIR}/${configuration}/${name}"
1327 1336
          relative="${CLONESBUILD_RELATIVE}/../.."
1328 1337
 
1338
+         if [ -d "${builddir}" -a "${CLEAN_BEFORE_BUILD}" = "YES" ]
1339
+         then
1340
+            log_fluff "Cleaning build directory \"${builddir}\""
1341
+            rmdir_safer "${builddir}"
1342
+         fi
1343
+
1329 1344
          hasbuilt=no
1330 1345
          for preference in ${preferences}
1331 1346
          do
... ...
@@ -1626,6 +1641,8 @@ main()
1626 1641
       return 0
1627 1642
    fi
1628 1643
 
1644
+   ensure_consistency
1645
+
1629 1646
    if [ $# -eq 0 ]
1630 1647
    then
1631 1648
       log_fluff "Setting up dependencies directory as \"${DEPENDENCY_SUBDIR}\""
... ...
@@ -52,7 +52,7 @@ embedded_repositories()
52 52
    then
53 53
       for clone in ${clones}
54 54
       do
55
-         name="`extension_less_basename "${clone}"`"
55
+         name="`canonical_name_from_clone "${clone}"`"
56 56
          dir="${name}"
57 57
          echo "${dir}"
58 58
       done
... ...
@@ -336,11 +336,8 @@ ask_symlink_it()
336 336
    #
337 337
    if [ -d "${clone}"/.git ]
338 338
    then
339
-      local is_bare
340
-
341 339
        # if bare repo, we can only clone anyway
342
-      is_bare=`( cd "${clone}"; git rev-parse --is-bare-repository )`
343
-      if [ "${is_bare}" = "true" ]
340
+      if git_is_bare_repository "${clone}"
344 341
       then
345 342
          log_info "${clone} is a bare git repository. So cloning"
346 343
          log_info "is the only way to go."
... ...
@@ -392,17 +389,56 @@ log_fetch_action()
392 389
 }
393 390
 
394 391
 
392
+search_git_repo_in_parent_directory()
393
+{
394
+   local name
395
+   local branch
396
+
397
+   name="$1"
398
+   branch="$2"
399
+
400
+   local found
401
+
402
+   if [ ! -z "${branch}" ]
403
+   then
404
+      found="../${name}.${branch}"
405
+      if [ -d "${found}" ]
406
+      then
407
+         echo "${found}"
408
+         return
409
+      fi
410
+   fi
411
+
412
+   found="../${name}"
413
+   if [ -d "${found}" ]
414
+   then
415
+      echo "${found}"
416
+      return
417
+   fi
418
+
419
+   found="../${name}.git"
420
+   if [ -d "${found}" ]
421
+   then
422
+      echo "${found}"
423
+      return
424
+   fi
425
+}
426
+
427
+
428
+
395 429
 checkout()
396 430
 {
397 431
    local url
398 432
    local name
399 433
    local dstdir
434
+   local branch
400 435
    local tag
401 436
 
402 437
    name="$1"
403 438
    url="$2"
404 439
    dstdir="$3"
405
-   tag="$4"
440
+   branch="$4"
441
+   tag="$5"
406 442
 
407 443
    [ ! -z "$name" ]   || internal_fail "name is empty"
408 444
    [ ! -z "$url" ]    || internal_fail "url is empty"
... ...
@@ -419,6 +455,8 @@ checkout()
419 455
    fi
420 456
    name2="`basename -- "${url}"`"  # only works for git really
421 457
 
458
+   local scmflagsdefault
459
+
422 460
    #
423 461
    # this implicitly ensures, that these folders are
424 462
    # movable and cleanable by mulle-bootstrap
... ...
@@ -443,6 +481,7 @@ checkout()
443 481
    case "${map}" in
444 482
       git|"" )
445 483
          operation="git_clone"
484
+         scmflagsdefault="--recursive"
446 485
          ;;
447 486
       svn)
448 487
          operation="svn_checkout"
... ...
@@ -466,43 +505,40 @@ checkout()
466 505
    else
467 506
       case "${url}" in
468 507
          /*)
469
-            ask_symlink_it "${src}"
470
-            if [ $? -eq 0 ]
508
+            if git_is_bare_repository "${url}"
471 509
             then
472
-               operation=link_command
510
+               :
511
+            else
512
+               ask_symlink_it "${src}"
513
+               if [ $? -eq 0 ]
514
+               then
515
+                  operation=link_command
516
+               fi
473 517
             fi
474 518
          ;;
475 519
 
476 520
          ../*|./*)
477
-            src="${url}"
478
-            ask_symlink_it "${src}"
479
-            if [ $? -eq 0 ]
521
+            if git_is_bare_repository "${url}"
480 522
             then
481
-               operation=link_command
482
-               src="${relative}${url}"
523
+               :
524
+            else
525
+               ask_symlink_it "${src}"
526
+               if [ $? -eq 0 ]
527
+               then
528
+                  operation=link_command
529
+                  src="${relative}${url}"
530
+               fi
483 531
             fi
484 532
          ;;
485 533
 
486 534
          *)
487
-            found="../${name}.${tag}"
488
-            if [ ! -d "${found}" ]
535
+            found="`search_git_repo_in_parent_directory "${name}" "${branch}"`"
536
+            if [ -z "${found}" ]
489 537
             then
490
-               found="../${name}"
491
-               if [ ! -d "${found}" ]
492
-               then
493
-                  found="../${name2}.${tag}"
494
-                  if [ ! -d "${found}" ]
495
-                  then
496
-                     found="../${name2}"
497
-                     if [ ! -d "${found}" ]
498
-                     then
499
-                        found=""
500
-                     fi
501
-                  fi
502
-               fi
538
+               found="`search_git_repo_in_parent_directory "${name2}" "${branch}"`"
503 539
             fi
504 540
 
505
-            if [ "${found}" != ""  ]
541
+            if [ ! -z "${found}" ]
506 542
             then
507 543
                user_say_yes "There is a ${found} folder in the parent
508 544
 directory of this project.
... ...
@@ -510,26 +546,57 @@ Use it ?"
510 546
                if [ $? -eq 0 ]
511 547
                then
512 548
                   src="${found}"
513
-                  ask_symlink_it "${src}"
514
-                  if [ $? -eq 0 ]
549
+
550
+                  if git_is_bare_repository "${src}"
515 551
                   then
516
-                     operation=link_command
517
-                     src="${relative}${found}"
552
+                     :
553
+                  else
554
+                     ask_symlink_it "${src}"
555
+                     if [ $? -eq 0 ]
556
+                     then
557
+                        operation=link_command
558
+                        src="${relative}${found}"
559
+                     fi
518 560
                   fi
519 561
                fi
520 562
             fi
563
+
521 564
          ;;
522 565
       esac
523 566
 
524 567
       local scmflags
525 568
 
526
-      scmflags="`read_repo_setting "${name}" "checkout" "--recursive"`"
527
-      "${operation}" "${src}" "${dstdir}" "${tag}" "${scmflags}"
569
+      scmflags="`read_repo_setting "${name}" "checkout" "${scmflagsdefault}"`"
570
+      "${operation}" "${src}" "${dstdir}" "${branch}" "${tag}" "${scmflags}"
528 571
       mulle-bootstrap-warn-scripts.sh "${dstdir}/.bootstrap" "${dstdir}" || fail "Ok, aborted"  #sic
529 572
    fi
530 573
 }
531 574
 
532 575
 
576
+ensure_clone_branch_is_correct()
577
+{
578
+   local dstdir
579
+   local branch
580
+
581
+   dstdir="${1}"
582
+   branch="${2}"
583
+
584
+   local actual
585
+
586
+   if [ ! -z "${branch}" ]
587
+   then
588
+      actual="`git_get_branch "${dstdir}"`"
589
+      if [ "${actual}" != "${branch}" ]
590
+      then
591
+         fail "Repository \"${dstdir}\" checked-out branch is \"${actual}\".
592
+But \"${branch}\" is specified.
593
+Suggested fix:
594
+   mulle-bootstrap clean dist
595
+   mulle-bootstrap"
596
+      fi
597
+   fi
598
+}
599
+
533 600
 #
534 601
 # Use git clones for stuff that gets tagged
535 602
 # if you specify ../ it will assume you have
... ...
@@ -544,10 +611,14 @@ checkout_repository()
544 611
    local name
545 612
    local flag
546 613
    local url
614
+   local branch
615
+   local tag
547 616
 
548 617
    name="$1"
549 618
    url="$2"
550 619
    dstdir="$3"
620
+   branch="$4"
621
+   tag="$5"
551 622
 
552 623
    if [ ! -e "${dstdir}" ]
553 624
    then
... ...
@@ -575,8 +646,9 @@ checkout_repository()
575 646
       then
576 647
          return 1
577 648
       fi
578
-
579 649
    else
650
+      ensure_clone_branch_is_correct "${dstdir}" "${branch}"
651
+
580 652
       log_fluff "Repository \"${dstdir}\" already exists"
581 653
    fi
582 654
    return 0
... ...
@@ -587,9 +659,11 @@ clone_repository()
587 659
 {
588 660
    local name
589 661
    local url
662
+   local branch
590 663
 
591 664
    name="$1"
592 665
    url="$2"
666
+   branch="$3"
593 667
 
594 668
    local tag
595 669
    local dstdir
... ...
@@ -599,7 +673,10 @@ clone_repository()
599 673
    dstdir="${CLONESFETCH_SUBDIR}/${name}"
600 674
    log_fetch_action "${name}" "${dstdir}"
601 675
 
602
-   checkout_repository "${name}" "${url}" "${dstdir}" "${tag}"
676
+   # mark the checkout progress, so that we don't do incomplete fetches and
677
+   # later on happily build
678
+
679
+   checkout_repository "${name}" "${url}" "${dstdir}" "${branch}" "${tag}"
603 680
    flag=$?
604 681
 
605 682
    return $flag
... ...
@@ -610,9 +687,11 @@ did_clone_repository()
610 687
 {
611 688
    local name
612 689
    local url
690
+   local branch
613 691
 
614 692
    name="$1"
615 693
    url="$2"
694
+   branch="$3"
616 695
 
617 696
    local dstdir
618 697
 
... ...
@@ -631,6 +710,7 @@ clone_repositories()
631 710
    local url
632 711
    local fetched
633 712
    local match
713
+   local branch
634 714
 
635 715
    old="${IFS:-" "}"
636 716
 
... ...
@@ -663,7 +743,9 @@ ${clone}"
663 743
 
664 744
                name="`canonical_name_from_clone "${clone}"`"
665 745
                url="`url_from_clone "${clone}"`"
666
-               clone_repository "${name}" "${url}"
746
+               branch="`branch_from_clone "${clone}"`"
747
+
748
+               clone_repository "${name}" "${url}" "${branch}"
667 749
 
668 750
                if [ $? -eq 1 ]
669 751
                then
... ...
@@ -682,7 +764,7 @@ ${clone}"
682 764
       IFS="${old}"
683 765
       name="`canonical_name_from_clone "${clone}"`"
684 766
       url="`url_from_clone "${clone}"`"
685
-      did_clone_repository "${name}" "${url}"
767
+      did_clone_repository "${name}" "${url}" "${branch}"
686 768
    done
687 769
 
688 770
    IFS="${old}"
... ...
@@ -701,6 +783,7 @@ install_embedded_repositories()
701 783
    local name
702 784
    local url
703 785
    local dstdir
786
+   local branch
704 787
 
705 788
    old="${IFS:-" "}"
706 789
 
... ...
@@ -717,6 +800,7 @@ install_embedded_repositories()
717 800
          IFS="${old}"
718 801
          name="`canonical_name_from_clone "${clone}"`"
719 802
          url="`url_from_clone "${clone}"`"
803
+         branch="`branch_from_clone "${clone}"`"
720 804
 
721 805
          tag="`read_repo_setting "${name}" "tag"`" #repo (sic)
722 806
          dstdir="${dstprefix}${name}"
... ...
@@ -732,7 +816,7 @@ install_embedded_repositories()
732 816
             old="${SYMLINK_FORBIDDEN}"
733 817
 
734 818
             SYMLINK_FORBIDDEN="YES"
735
-            checkout "${name}" "${url}" "${dstdir}" "${tag}"
819
+            checkout "${name}" "${url}" "${dstdir}" "${branch}" "${tag}"
736 820
             SYMLINK_FORBIDDEN="$old"
737 821
 
738 822
             if read_yes_no_config_setting "update_gitignore" "YES"
... ...
@@ -759,7 +843,9 @@ install_embedded_repositories()
759 843
 
760 844
             run_build_settings_script "${name}" "${url}" "${dstdir}" "post-${COMMAND}" "$@"
761 845
          else
762
-            log_fluff "\"${dstdir}\" already exists"
846
+            ensure_clone_branch_is_correct "${dstdir}" "${branch}"
847
+
848
+           log_fluff "Repository \"${dstdir}\" already exists"
763 849
          fi
764 850
       done
765 851
    fi
... ...
@@ -774,13 +860,15 @@ update()
774 860
 {
775 861
    local name
776 862
    local url
863
+   local branch
777 864
    local tag
778 865
    local dstdir
779 866
 
780 867
    name="$1"
781 868
    url="$2"
782 869
    dstdir="$3"
783
-   tag="$4"
870
+   branch="$4"
871
+   tag="$5"
784 872
 
785 873
    [ ! -z "$url" ]           || internal_fail "url is empty"
786 874
    exekutor [ -d "$dstdir" ] || internal_fail "dstdir \"${dstdir}\" is wrong ($PWD)"
... ...
@@ -814,11 +902,12 @@ update()
814 902
       then
815 903
          run_script "${script}" "$@"
816 904
       else
817
-         "${operation}" "${dstdir}" "${tag}"
905
+         "${operation}" "${dstdir}" "${branch}" "${tag}"
818 906
       fi
819 907
 
820 908
       run_repo_settings_script "${name}" "${dstdir}" "post-update" "$@"
821 909
    else
910
+      ensure_clone_branch_is_correct "${dstdir}" "${branch}"
822 911
       log_fluff "Repository \"${name}\" exists, so not updated."
823 912
       return 1
824 913
    fi
... ...
@@ -829,9 +918,11 @@ update_repository()
829 918
 {
830 919
    local name
831 920
    local url
921
+   local branch
832 922
 
833 923
    name="$1"
834 924
    url="$2"
925
+   branch="$3"
835 926
 
836 927
    local name
837 928
    local tag
... ...
@@ -845,7 +936,7 @@ update_repository()
845 936
 
846 937
    log_fetch_action "${url}" "${dstdir}"
847 938
 
848
-   update "${name}" "${url}" "${dstdir}" "${tag}"
939
+   update "${name}" "${url}" "${dstdir}" "${branch}" "${tag}"
849 940
 
850 941
    #update will return 1 if repo is symlinked
851 942
 
... ...
@@ -865,6 +956,8 @@ update_repository()
865 956
       BOOTSTRAP_SUBDIR="${old}"
866 957
 #      CLONESFETCH_SUBDIR="${oldfetch}"
867 958
    fi
959
+
960
+   ensure_clone_branch_is_correct "${dstdir}" "${branch}"
868 961
 }
869 962
 
870 963
 
... ...
@@ -930,7 +1023,9 @@ update_repositories()
930 1023
             IFS="${old}"
931 1024
             name="`canonical_name_from_clone "${clone}"`"
932 1025
             url="`url_from_clone "${clone}"`"
933
-            update_repository "${name}" "${url}"
1026
+            branch="`branch_from_clone "${clone}"`"
1027
+
1028
+            update_repository "${name}" "${url}" "${branch}"
934 1029
          done
935 1030
 
936 1031
          # reread because of auto
... ...
@@ -942,7 +1037,9 @@ update_repositories()
942 1037
             IFS="${old}"
943 1038
             name="`canonical_name_from_clone "${clone}"`"
944 1039
             url="`url_from_clone "${clone}"`"
945
-            did_update_repository "${name}" "${url}"
1040
+            branch="`branch_from_clone "${clone}"`"
1041
+
1042
+            did_update_repository "${name}" "${url}" "${branch}"
946 1043
          done
947 1044
       fi
948 1045
    fi
... ...
@@ -962,6 +1059,7 @@ update_embedded_repositories()
962 1059
    local old
963 1060
    local name
964 1061
    local url
1062
+   local branch
965 1063
 
966 1064
    MULLE_BOOTSTRAP_SETTINGS_NO_AUTO="YES"
967 1065
    export MULLE_BOOTSTRAP_SETTINGS_NO_AUTO
... ...
@@ -978,12 +1076,13 @@ update_embedded_repositories()
978 1076
          IFS="${old}"
979 1077
          name="`canonical_name_from_clone "${clone}"`"
980 1078
          url="`url_from_clone "${clone}"`"
1079
+         branch="`branch_from_clone "${clone}"`"
981 1080
 
982 1081
          tag="`read_repo_setting "${name}" "tag"`" #repo (sic)
983 1082
          dstdir="${dstprefix}${name}"
984 1083
          log_fetch_action "${name}" "${dstdir}"
985 1084
 
986
-         update "${name}" "${url}" "${dstdir}" "${tag}"
1085
+         update "${name}" "${url}" "${dstdir}" "${branch}" "${tag}"
987 1086
       done
988 1087
    fi
989 1088
 
... ...
@@ -1010,10 +1109,6 @@ main()
1010 1109
    SYMLINK_FORBIDDEN="`read_config_setting "symlink_forbidden"`"
1011 1110
    export SYMLINK_FORBIDDEN
1012 1111
 
1013
-
1014
-   #
1015
-   # Run prepare scripts if present
1016
-   #
1017 1112
    if [ "${COMMAND}" = "install" ]
1018 1113
    then
1019 1114
       if [ $# -ne 0 ]
... ...
@@ -1022,6 +1117,16 @@ main()
1022 1117
          usage >&2
1023 1118
          exit 1
1024 1119
       fi
1120
+   fi
1121
+
1122
+   ensure_consistency
1123
+   create_file_if_missing "${CLONESFETCH_SUBDIR}/.fetch_update_started"
1124
+
1125
+   #
1126
+   # Run prepare scripts if present
1127
+   #
1128
+   if [ "${COMMAND}" = "install" ]
1129
+   then
1025 1130
 
1026 1131
       clone_repositories
1027 1132
 
... ...
@@ -1030,6 +1135,7 @@ main()
1030 1135
       install_gems
1031 1136
       install_pips
1032 1137
       check_tars
1138
+
1033 1139
    else
1034 1140
       update_repositories "$@"
1035 1141
 
... ...
@@ -1041,6 +1147,8 @@ main()
1041 1147
    #
1042 1148
    run_fetch_settings_script "post-${COMMAND}" "$@"
1043 1149
 
1150
+   remove_file_if_present "${CLONESFETCH_SUBDIR}/.fetch_update_started"
1151
+
1044 1152
    if read_yes_no_config_setting "update_gitignore" "YES"
1045 1153
    then
1046 1154
       if [ -d .git ]
... ...
@@ -391,6 +391,27 @@ mkdir_if_missing()
391 391
 }
392 392
 
393 393
 
394
+create_file_if_missing()
395
+{
396
+   if [ ! -f "${1}" ]
397
+   then
398
+      log_fluff "Creating \"$1\" (`pwd -P`)"
399
+      exekutor touch "$1" || fail "failed to create \"$1\""
400
+   fi
401
+}
402
+
403
+
404
+remove_file_if_present()
405
+{
406
+   if [ -f "${1}" ]
407
+   then
408
+      log_fluff "Removing \"$1\" (`pwd -P`)"
409
+      exekutor rm -f "$1" || fail "failed to remove \"$1\""
410
+   fi
411
+}
412
+
413
+
414
+
394 415
 #
395 416
 # consider . .. ~ or absolute paths as unsafe
396 417
 # anything starting with a $ is probably also bad
... ...
@@ -525,22 +546,50 @@ find_xcodeproj()
525 546
 }
526 547
 
527 548
 
549
+# deal with stuff like
550
+# foo
551
+# https://www./foo.git
552
+# host:foo
553
+#
528 554
 canonical_clone_name()
529 555
 {
530
-   extension_less_basename "${1}"
556
+   local  url
557
+
558
+   url="$1"
559
+
560
+   # cut off scheme part
561
+
562
+   case "$url" in
563
+      *:*)
564
+         url="`echo "$@" | sed 's/^\(.*\):\(.*\)/\2/'`"
565
+         ;;
566
+   esac
567
+
568
+   extension_less_basename "$url"
531 569
 }
532 570
 
533 571
 
572
+count_clone_components()
573
+{
574
+  echo "$@" | tr ';' '\012' | wc -l | awk '{ print $1 }'
575
+}
576
+
534 577
 
535 578
 url_from_clone()
536 579
 {
537
-   echo "$@" | sed 's/^\(.*\);\(.*\)/\1/'
580
+   echo "$@" | tr ';' '\012' | head -1
538 581
 }
539 582
 
540 583
 
541 584
 _name_part_from_clone()
542 585
 {
543
-   echo "$@" | sed 's/^\(.*\);\(.*\)/\2/'
586
+   echo "$@" | tr ';' '\012' | head -2 | tail -1
587
+}
588
+
589
+
590
+_branch_part_from_clone()
591
+{
592
+   echo "$@" | tr ';' '\012' | head -3 | tail -1
544 593
 }
545 594
 
546 595
 
... ...
@@ -548,11 +597,12 @@ canonical_name_from_clone()
548 597
 {
549 598
    local url
550 599
    local name
600
+   local branch
551 601
 
552 602
    url="`url_from_clone "$@"`"
553 603
    name="`_name_part_from_clone "$@"`"
554 604
 
555
-   if [ "${name}" != "${url}" ]
605
+   if [ ! -z "${name}" -a "${name}" != "${url}" ]
556 606
    then
557 607
       canonical_clone_name "${name}"
558 608
       return
... ...
@@ -562,6 +612,19 @@ canonical_name_from_clone()
562 612
 }
563 613
 
564 614
 
615
+branch_from_clone()
616
+{
617
+   local count
618
+
619
+   count="`count_clone_components "$@"`"
620
+   if [ "$count" -ge 3 ]
621
+   then
622
+      _branch_part_from_clone "$@"
623
+   fi
624
+}
625
+
626
+
627
+
565 628
 # http://askubuntu.com/questions/152001/how-can-i-get-octal-file-permissions-from-command-line
566 629
 lso()
567 630
 {
... ...
@@ -614,3 +677,19 @@ ensure_clones_directory()
614 677
    fi
615 678
 }
616 679
 
680
+
681
+ensure_consistency()
682
+{
683
+   if [ -f "${CLONESFETCH_SUBDIR}/.fetch_update_started" ]
684
+   then
685
+      log_error "A previous fetch or update was incomplete.
686
+Suggested resolution:
687
+    ${C_RESET_BOLD}mulle-bootstrap clean dist${C_ERROR}
688
+    ${C_RESET_BOLD}mulle-bootstrap${C_ERROR}
689
+
690
+Or do you feel lucky ? ${C_RESET_BOLD}rm ${CLONESFETCH_SUBDIR}/.fetch_update_started${C_ERROR}
691
+and try again. But you've gotta ask yourself one question: Do I feel lucky ?
692
+Well, do ya, punk? "
693
+      exit 1
694
+   fi
695
+}
... ...
@@ -178,6 +178,8 @@ mark_all_repositories_zombies()
178 178
             exekutor touch "${CLONESFETCH_SUBDIR}/.zombies/${name}"
179 179
          fi
180 180
       done
181
+   else
182
+      log_fluff "No projects found in \"${CLONESFETCH_SUBDIR}\""
181 183
    fi
182 184
 }
183 185
 
... ...
@@ -263,7 +265,7 @@ bury_zombies()
263 265
             dstdir="${CLONESFETCH_SUBDIR}/${name}"
264 266
             if [ -d "${dstdir}" ]
265 267
             then
266
-               log_info "Removing unused repository ${C_MAGENTA_BOLD}${name}${C_INFO}"
268
+               log_info "Removing unused repository ${C_MAGENTA}${C_BOLD}${name}${C_INFO}"
267 269
 
268 270
                if [ -e "${gravepath}/${name}" ]
269 271
                then
... ...
@@ -298,7 +300,7 @@ mark_all_embedded_repositories_zombies()
298 300
    local path
299 301
    local zombiepath
300 302
 
301
-      # first mark all repos as stale
303
+   # first mark all repos as stale
302 304
    path="${CLONESFETCH_SUBDIR}/.embedded"
303 305
    if dir_has_files "${CLONESFETCH_SUBDIR}/.embedded"
304 306
    then
... ...
@@ -313,6 +315,8 @@ mark_all_embedded_repositories_zombies()
313 315
          name="`basename "$i"`"
314 316
          exekutor touch "${zombiepath}/${name}"
315 317
       done
318
+   else
319
+      log_fluff "No files in \"${CLONESFETCH_SUBDIR}/.embedded\", hmm"
316 320
    fi
317 321
 }
318 322
 
... ...
@@ -358,7 +362,6 @@ bury_embedded_zombies()
358 362
          then
359 363
             name="`basename -- "${i}"`"
360 364
             dstdir="${name}"
361
-            log_info "Removing unused embedded repository ${C_MAGENTA_BOLD}${name}${C_INFO}"
362 365
 
363 366
             if [ -d "${dstdir}" ]
364 367
             then
... ...
@@ -370,6 +373,7 @@ bury_embedded_zombies()
370 373
                exekutor mv "${dstdir}" "${gravepath}"
371 374
                exekutor rm "${i}"
372 375
                exekutor rm "${CLONESFETCH_SUBDIR}/.embedded/${name}"
376
+               log_info "Removed unused embedded repository ${C_MAGENTA}${C_BOLD}${name}${C_INFO} from \"${dstdir}\""
373 377
             else
374 378
                log_fluff "\"${dstdir}\" embedded zombie vanished or never existed"
375 379
             fi
... ...
@@ -493,15 +497,20 @@ refresh_deeply_embedded_repositories()
493 497
          name="`canonical_name_from_clone "${clone}"`"
494 498
          dstprefix="${CLONESFETCH_SUBDIR}/${name}/"
495 499
 
496
-         previous_bootstrap="${BOOTSTRAP_SUBDIR}"
497
-         previous_clones="${CLONESFETCH_SUBDIR}"
498
-         BOOTSTRAP_SUBDIR="${dstprefix}.bootstrap"
499
-         CLONESFETCH_SUBDIR="${dstprefix}${CLONESFETCH_SUBDIR}"
500
+         if [ ! -L "${CLONESFETCH_SUBDIR}/${name}" ]
501
+         then
502
+            previous_bootstrap="${BOOTSTRAP_SUBDIR}"
503
+            previous_clones="${CLONESFETCH_SUBDIR}"
504
+            BOOTSTRAP_SUBDIR="${dstprefix}.bootstrap"
505
+            CLONESFETCH_SUBDIR="${dstprefix}${CLONESFETCH_SUBDIR}"
500 506
 
501
-         refresh_embedded_repositories "${dstprefix}"
507
+            refresh_embedded_repositories "${dstprefix}"
502 508
 
503
-         BOOTSTRAP_SUBDIR="${previous_bootstrap}"
504
-         CLONESFETCH_SUBDIR="${previous_clones}"
509
+            BOOTSTRAP_SUBDIR="${previous_bootstrap}"
510
+            CLONESFETCH_SUBDIR="${previous_clones}"
511
+         else
512
+            log_fluff  "Don't refresh embedded repositories of symlinked \"${name}\""
513
+         fi
505 514
       done
506 515
    fi
507 516
 
... ...
@@ -28,6 +28,22 @@
28 28
 #   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 29
 #   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 30
 #
31
+git_is_bare_repository()
32
+{
33
+   local is_bare
34
+
35
+       # if bare repo, we can only clone anyway
36
+    is_bare=`( cd "${1}"; git rev-parse --is-bare-repository )`
37
+    [ "${is_bare}" = "true" ]
38
+}
39
+
40
+
41
+git_get_branch()
42
+{
43
+   ( cd "$1" ; git rev-parse --abbrev-ref HEAD )
44
+}
45
+
46
+
31 47
 
32 48
 git_checkout_tag()
33 49
 {
... ...
@@ -48,7 +64,7 @@ git_checkout_tag()
48 64
 
49 65
    local branch
50 66
 
51
-   branch="`( cd "$dst" ; git rev-parse --abbrev-ref HEAD )`"
67
+   branch="`git_get_branch "${dst}"`"
52 68
 
53 69
    if [ "${branch}" != "${tag}" ]
54 70
    then
... ...
@@ -75,18 +91,27 @@ git_clone()
75 91
 {
76 92
    local src
77 93
    local dst
94
+   local branch
78 95
    local tag
79 96
    local flags
80 97
 
81 98
    src="$1"
82 99
    dst="$2"
83
-   tag="$3"
84
-   flags="$4"
100
+   branch="$3"
101
+   tag="$4"
102
+   flags="$5"
85 103
 
86
-   [ ! -z "$src" ] || internal_fail "src is empty"
87
-   [ ! -z "$dst" ] || internal_fail "dst is empty"
104
+   [ ! -z "${src}" ] || internal_fail "src is empty"
105
+   [ ! -z "${dst}" ] || internal_fail "dst is empty"
106
+
107
+   if [ ! -z "${branch}" ]
108
+   then
109
+      log_info "Cloning branch ${C_RESET_BOLD}$branch${C_INFO} of ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
110
+      flags="${flags} -b ${branch}"
111
+   else
112
+      log_info "Cloning ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
113
+   fi
88 114
 
89
-   log_info "Cloning ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
90 115
    exekutor git clone ${flags} ${GITFLAGS} "${src}" "${dst}" || fail "git clone of \"${src}\" into \"${dst}\" failed"
91 116
 
92 117
    if [ "${tag}" != "" ]
... ...
@@ -99,14 +124,19 @@ git_clone()
99 124
 git_pull()
100 125
 {
101 126
    local dst
127
+   local branch
102 128
    local tag
129
+   local flags
103 130
 
104 131
    dst="$1"
105
-   tag="$2"
132
+   branch="$2"
133
+   tag="$3"
134
+   tag="$4"
106 135
 
107 136
    [ ! -z "$dst" ] || internal_fail "dst is empty"
108 137
 
109 138
    log_info "Updating ${C_MAGENTA}${C_BOLD}${dst}${C_INFO} ..."
139
+
110 140
    ( exekutor cd "${dst}" ; exekutor git pull ${GITFLAGS} ) || fail "git pull of \"${dst}\" failed"
111 141
 
112 142
    if [ "${tag}" != "" ]
... ...
@@ -122,46 +152,64 @@ svn_checkout()
122 152
    local src
123 153
    local dst
124 154
    local tag
155
+   local branch
156
+   local flags
125 157
 
126 158
    src="$1"
127 159
    dst="$2"
128
-   tag="$3"
160
+   branch="$3"
161
+   tag="$4"
162
+   flags="$5"
129 163
 
130 164
    [ ! -z "$src" ] || internal_fail "src is empty"
131 165
    [ ! -z "$dst" ] || internal_fail "dst is empty"
132 166
 
133
-   log_info "SVN checkout ${C_MAGENTA}${src}${C_INFO} ..."
134 167
 
135
-   local flags
136
-
137
-   flags="${SVNFLAGS}"
138
-   if [ ! -z "${tag}" ]
168
+   if [ ! -z "${branch}" ]
139 169
    then
140
-      flags="-r ${tag} ${flags}"
170
+      log_info "SVN checkout ${C_RESET_BOLD}${branch}${C_INFO} of ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
171
+      flags="${flags} -r ${branch}"
172
+   else
173
+      if [ ! -z "${tag}" ]
174
+      then
175
+         log_info "SVN checkout ${C_RESET_BOLD}${tag}${C_INFO} of ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
176
+         flags="${flags} -r ${tag}"
177
+      else
178
+         log_info "SVN checkout ${C_MAGENTA}${C_BOLD}${src}${C_INFO} ..."
179
+      fi
141 180
    fi
142
-   exekutor svn checkout ${flags} "${src}" "${dst}" || fail "svn clone of \"${src}\" into \"${dst}\" failed"
181
+
182
+
183
+   exekutor svn checkout ${flags} ${SVNFLAGS} "${src}" "${dst}" || fail "svn clone of \"${src}\" into \"${dst}\" failed"
143 184
 }
144 185
 
145 186
 
146 187
 svn_update()
147 188
 {
148 189
    local dst
190
+   local branch
149 191
    local tag
192
+   local flags
150 193
 
151 194
    dst="$1"
152
-   tag="$2"
195
+   branch="$2"
196
+   tag="$3"
197
+   flags="$4"
153 198
 
154 199
    [ ! -z "$dst" ] || internal_fail "dst is empty"
155 200
 
156 201
    log_info "SVN updating ${C_MAGENTA}${C_BOLD}${dst}${C_INFO} ..."
157 202
 
158
-   local flags
159 203
 
160
-   flags="${SVNFLAGS}"
161
-   if [ ! -z "$tag" ]
204
+   if [ ! -z "$branch" ]
162 205
    then
163
-      flags="-r ${tag} ${flags}"
206
+      flags="-r ${branch} ${flags}"
207
+   else
208
+      if [ ! -z "$tag" ]
209
+      then
210
+         flags="-r ${tag} ${flags}"
211
+      fi
164 212
    fi
165 213
 
166
-   ( exekutor cd "${dst}" ; exekutor svn update ${flags} ) || fail "svn update of \"${dst}\" failed"
214
+   ( exekutor cd "${dst}" ; exekutor svn update ${flags} ${SVNFLAGS} ) || fail "svn update of \"${dst}\" failed"
167 215
 }
... ...
@@ -112,7 +112,7 @@ _read_setting()
112 112
       then
113 113
          local os
114 114
          os="`uname`"
115
-         log_fluff "${C_MAGENTA_BOLD}`basename -- "${file}" ".${os}"`${C_FLUFF} found as \"${file}\""
115
+         log_fluff "${C_MAGENTA}${C_BOLD}`basename -- "${file}" ".${os}"`${C_FLUFF} found as \"${file}\""
116 116
       fi
117 117
    else
118 118
       value=`egrep -v '^#|^[ ]*$' "${file}"`
... ...
@@ -120,7 +120,7 @@ _read_setting()
120 120
       then
121 121
          local os
122 122
          os="`uname`"
123
-         log_fluff "Setting ${C_MAGENTA_BOLD}`basename -- "${file}" ".${os}"`${C_FLUFF} found in \"${file}\" as ${C_MAGENTA_BOLD}${value}${C_FLUFF}"
123
+         log_fluff "Setting ${C_MAGENTA}${C_BOLD}`basename -- "${file}" ".${os}"`${C_FLUFF} found in \"${file}\" as ${C_MAGENTA}${C_BOLD}${value}${C_FLUFF}"
124 124
       fi
125 125
    fi
126 126
 
... ...
@@ -165,7 +165,7 @@ _read_environment_setting()
165 165
 
166 166
    if [ "${MULLE_BOOTSTRAP_VERBOSE}" = "YES" ]
167 167
    then
168
-      log_trace "Setting ${C_MAGENTA_BOLD}${name}${C_TRACE} found in environment variable \"${envname}\" as ${C_MAGENTA_BOLD}${value}${C_TRACE}"
168
+      log_trace "Setting ${C_MAGENTA}${C_BOLD}${name}${C_TRACE} found in environment variable \"${envname}\" as ${C_MAGENTA}${C_BOLD}${value}${C_TRACE}"
169 169
    fi
170 170
 
171 171
    warn_environment_setting "${envname}"
... ...
@@ -200,7 +200,7 @@ _read_local_setting()
200 200
 
201 201
    if [ "${MULLE_BOOTSTRAP_VERBOSE}" = "YES" ]
202 202
    then
203
-      log_trace "Setting ${C_MAGENTA_BOLD}${name}${C_TRACE} found in \"~/.mulle-bootstrap\" as ${C_MAGENTA_BOLD}${value}${C_TRACE}"
203
+      log_trace "Setting ${C_MAGENTA}${C_BOLD}${name}${C_TRACE} found in \"~/.mulle-bootstrap\" as ${C_MAGENTA}${C_BOLD}${value}${C_TRACE}"
204 204
    fi
205 205
    warn_user_setting "${HOME}/.mulle-bootstrap/${name}"
206 206
 
... ...
@@ -492,7 +492,6 @@ read_yes_no_config_setting()
492 492
 }
493 493
 
494 494
 
495
-
496 495
 read_sane_config_path_setting()
497 496
 {
498 497
    local name
... ...
@@ -520,8 +519,6 @@ read_sane_config_path_setting()
520 519
 }
521 520
 
522 521
 
523
-
524
-
525 522
 merge_settings_in_front()
526 523
 {
527 524
    local settings1
... ...
@@ -536,10 +533,12 @@ merge_settings_in_front()
536 533
    local old
537 534
    local line1
538 535
 
536
+   # https://stackoverflow.com/questions/742466/how-can-i-reverse-the-order-of-lines-in-a-file/744093#744093
537
+
539 538
    old="${IFS:-" "}"
540 539
    IFS="
541 540
 "
542
-   for line in $settings1
541
+   for line in `echo "${settings1}" | sed -n '1!G;h;$p'`
543 542
    do
544 543
       result="`echo "${result}" | grep -v -x "${line}"`"
545 544
       result="${line}
... ...
@@ -256,6 +256,7 @@ main()
256 256
 {
257 257
    log_fluff "::: tag :::"
258 258
 
259
+   ensure_consistency
259 260
    ensure_tags_unknown "${TAG}" "${VENDOR_TAG}"
260 261
    ensure_repos_clean
261 262