| #!/bin/bash |
| # -*- tab-width : 4; indent-tabs-mode : nil -*- |
| # |
| # Copyright (C) 2015 Norbert Thiebaud |
| # License: GPLv3 |
| # |
| |
| # run debug=1 setup ... to debug |
| if [ -n "$debug" ] ; then |
| set -x |
| fi |
| |
| die() |
| { |
| echo "$@" 1>&2 |
| exit 1; |
| } |
| |
| usage() |
| { |
| cat <<EOF |
| |
| build_bibisect --epoch=<epoch_name> [ --count=<count> ] [ --move] [--fetch] |
| |
| the program will try to build all the commmit (max <count> if specified) |
| that are left to be build based on the current state of the bibisect |
| and either going to the head of the EPOCH_BRANCH or origin/master if the former |
| does not exist yet. |
| |
| --move indicate that we want to count 'fail' toward --count |
| and on restart we do not retry the last failure streak (in any) |
| |
| in ~/.bibisect/<epoch_name> there need to be: |
| |
| EPOCH_START_POINT=<tag of the start of the epoch> (libreoffice-4-4-branch-point i.e the branching point of the previous epoch) |
| EPOCH_BRANCH=<branch_name for the epoch> (libreoffice-5-0) |
| SOURCE_GIT_REPO=<path to the source git repo> |
| TARGET_GIT_REPO=<path to the bibisect repo (will be created if needed) |
| |
| EOF |
| } |
| |
| setup() |
| { |
| |
| if [ -z "$EPOCH_START_POINT" ] ; then |
| die "Missing EPOCH_START_POINT" |
| fi |
| |
| if [ -z "$EPOCH_BRANCH" ] ; then |
| die "Missing EPOCH_BRANCH" |
| fi |
| if [ -z "$SOURCE_GIT_REPO" ] ; then |
| die "Missing SOURCE_GIT_REPO" |
| fi |
| if [ ! -d "${SOURCE_GIT_REPO?}" -o ! -d "${SOURCE_GIT_REPO?}/.git" -o ! -d "${SOURCE_GIT_REPO?}/sal" ] ; then |
| die "The source ${SOURCE_GIT_REPO?} does not appear to be a LibreOffice core.git" |
| fi |
| if [ -z "$METADATA_DIR" ] ; then |
| METADATA_DIR=~/.bibisect/${bibisect_epoch?}.d |
| fi |
| if [ ! -d "${METADATA_DIR?}" ] ; then |
| mkdir -p "${METADATA_DIR?}" || die "Cannot create the metadata dir: ${METADATA_DIR?}" |
| fi |
| |
| if [ ! -d "${TARGET_GIT_REPO?}" ] ; then |
| mkdir -p "${TARGET_GIT_REPO?}" || die "Error creating the Target git repo location ${TARGET_GIT_REPO?}" |
| pushd "${TARGET_GIT_REPO?}" > /dev/null || die "Cannot cd to ${TARGET_GIT_REPO?}" |
| git init --quiet |
| popd > /dev/null |
| else |
| if [ ! -d "${TARGET_GIT_REPO?}/.git" ] ; then |
| die "The Target git repo ${TARGET_GIT_REPO?} does not appear to be a git repo" |
| fi |
| fi |
| } |
| |
| recover_resume_sha() |
| { |
| local master_sha |
| |
| pushd "${TARGET_GIT_REPO?}" > /dev/null || die "Cannot cd to the source repo ${TARGET_GIT_REPO?}" |
| master_sha=$(git rev-parse master 2> /dev/null) |
| if [ -z "$master_sha" -o "$master_sha" = "master" ] ; then |
| # empty bibibsect repo.. the resume is the sha just before the begin tag" |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null || die "Cannot cd to the source repo ${SOURCE_GIT_REPO?}" |
| resume_sha=$(git log -1 --format="%H" "${EPOCH_START_POINT}^" 2>/dev/null) |
| if [ -z "$resume_sha" ] ; then |
| die "Could not determine the resume point based one ${EPOCH_START_POINT?}" |
| fi |
| popd > /dev/null |
| else |
| resume_sha="$(git log -1 master | grep "source sha" | head -n 1 | sed -e "s/.*://")" |
| if [ -z "$resume_sha" ] ; then |
| die "Could not determine the resume point based bibisect current master" |
| fi |
| fi |
| popd > /dev/null |
| echo "$resume_sha" > "${METADATA_DIR?}/resume_sha" |
| } |
| |
| is_source_sha_exist() |
| { |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| if [ "$(git cat-file -t "$1" 2> /dev/null)" = "commit" ] ; then |
| echo "$1" |
| fi |
| popd > /dev/null |
| } |
| |
| determine_resume_sha() |
| { |
| # this set the variable resume_sha or die |
| # resume_sha is the source sha just prior to the next source to build |
| if [ ! -f "${METADATA_DIR?}/resume_sha" ] ; then |
| recover_resume_sha |
| else |
| resume_sha=$(cat "${METADATA_DIR?}/resume_sha") |
| resume_sha=$(is_source_sha_exist "$resume_sha") |
| if [ -z "$resume_sha" ] ; then |
| recover_resume_sha |
| fi |
| fi |
| } |
| |
| determine_last_build_sha() |
| { |
| # this set the variable resume_sha or die |
| # resume_sha is the source sha just prior to the next source to build |
| if [ ! -f "${METADATA_DIR?}/last_build_sha" ] ; then |
| last_build_sha=${resume_sha?} |
| else |
| last_build_sha=$(cat "${METADATA_DIR?}/last_build_sha") |
| last_build_sha=$(is_source_sha_exist "$last_build_sha") |
| if [ -z "$last_build_sha" ] ; then |
| last_build_sha=${resume_sha?} |
| fi |
| fi |
| } |
| |
| determine_todo_shas() |
| { |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| if [ -n "$fetch" ] ; then |
| git fetch |
| fi |
| end_sha=$(git rev-parse "origin/${EPOCH_BRANCH?}" 2> /dev/null) |
| if [ -z "$end_sha" -o "$end_sha" = "origin/${EPOCH_BRANCH?}" ] ; then |
| end_sha=$(git rev-parse origin/master 2> /dev/null) |
| fi |
| if [ -z "$end_sha" -o "$end_sha" = "master" ] ; then |
| die "cannot determine end sha" |
| fi |
| last_done_sha=${resume_sha} |
| todo_list=$(git log --first-parent --reverse --format="%H" ${last_build_sha}..${end_sha} | tail -n +$range_commits) |
| todo_n=$(echo "$todo_list" | wc -l) |
| echo "build to do:$todo_n" |
| popd > /dev/null |
| } |
| |
| build() |
| { |
| local stashed=0 |
| |
| echo -n "$n / $todo_n building $sha : " |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| # echo -n "stash " |
| # git stash > build.log 2>&1 || die "stashing" |
| echo -n "reset " |
| git reset --hard ${sha?} >> build.log 2>&1 || die "cannot reset to ${sha}" |
| # echo -n "pop " |
| # git stash pop >> build.log 2>&1 || "die stash poping" |
| |
| sleep 2 |
| if [ ! -e Makefile ] ; then |
| ./autogen.sh >> build.log 2>&1 |
| fi |
| if [ "$os" = "Cygwin" ] ; then |
| MAKE_CMD=/opt/lo/bin/make |
| else |
| MAKE_CMD=make |
| fi |
| ${MAKE_CMD} >> build.log 2>&1 |
| if [ $? -eq 0 ] ; then |
| echo "$sha good" >> "${METADATA_DIR?}/commit_list.done" |
| echo " Success." |
| echo "$sha" > "${METADATA_DIR?}/last_build_sha" |
| else |
| mv build.log "${METADATA_DIR?}/$sha.log.bad" |
| echo "$sha bad" >> "${METADATA_DIR?}/commit_list.done" |
| echo " Failed." |
| echo "$sha" > "${METADATA_DIR?}/last_build_sha" |
| sha= |
| fi |
| popd > /dev/null |
| } |
| |
| add_bibisect_Darwin() |
| { |
| echo -n "Adding $sha ..." |
| if [ -d ${SOURCE_GIT_REPO?}/workdir/installation/LibreOfficeDev/ ] ; then |
| dmg=$(ls -1 ${SOURCE_GIT_REPO?}/workdir/installation/LibreOfficeDev/dmg/install/en-US/*.dmg 2>/dev/null) |
| app=LibreOfficeDev |
| elif [ -d ${SOURCE_GIT_REPO?}/workdir/installation/LibreOffice/ ] ; then |
| dmg=$(ls -1 ${SOURCE_GIT_REPO?}/workdir/installation/LibreOffice/dmg/install/en-US/*.dmg 2>/dev/null) |
| app=LibreOffice |
| else |
| die "weird no dmg. Did you used --with-package-format=dmg?" |
| fi |
| if [ -z "$dmg" -o ! -f "$dmg" ] ; then |
| die "weird no dmg. Did you used --with-package-format=dmg?" |
| fi |
| |
| hdiutil attach -nobrowse "${dmg?}" > /dev/null || die "opening dmg $dmg" |
| pushd /Volumes/${app?} > /dev/null || die "can't cd to mounted volume" |
| rm -fr "${TARGET_GIT_REPO?}/LibreOffice.app" |
| if [ -d ${app?}.app ] ; then |
| cp -a ${app?}.app ${TARGET_GIT_REPO?}/LibreOffice.app |
| else |
| die "No LibreOffice.app found to copy" |
| fi |
| popd > /dev/null |
| sleep 1 |
| hdiutil detach /Volumes/${app?} > /dev/null 2>&1 || die "error detaching the volume" |
| |
| pushd "${TARGET_GIT_REPO?}" > /dev/null |
| git add -A LibreOffice.app |
| |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| cat << EOF > commit.msgs |
| source sha:${sha?} |
| |
| $(git log --pretty="format:source sha:%H" ${last_done_sha?}..${sha?}) |
| EOF |
| |
| popd > /dev/null |
| echo -n " committing" |
| git commit -q -F "${SOURCE_GIT_REPO?}/commit.msgs" || die "error committing $sha" |
| last_done_sha="${sha?}" |
| rm "${SOURCE_GIT_REPO?}/commit.msgs" |
| popd > /dev/null |
| echo "$sha good" >> "${METADATA_DIR}/commit_list.done.pushed" |
| echo "$sha" > "${METADATA_DIR?}/resume_sha" |
| |
| echo " Committed" |
| } |
| |
| add_bibisect_Cygwin() |
| { |
| echo -n "Adding $sha ..." |
| rm -fr "${TARGET_GIT_REPO?}/instdir" |
| cp -r "${SOURCE_GIT_REPO?}/instdir" "${TARGET_GIT_REPO?}/." |
| |
| pushd "${TARGET_GIT_REPO?}" > /dev/null |
| git add -A instdir |
| |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| cat << EOF > commit.msgs |
| source sha:${sha?} |
| |
| $(git log --pretty="format:source sha:%H" ${last_done_sha?}..${sha?}) |
| EOF |
| |
| popd > /dev/null |
| echo -n " committing" |
| git commit -q -F "${SOURCE_GIT_REPO?}/commit.msgs" || die "error committing $sha" |
| last_done_sha="${sha?}" |
| rm "${SOURCE_GIT_REPO?}/commit.msgs" |
| popd > /dev/null |
| echo "$sha good" >> "${METADATA_DIR}/commit_list.done.pushed" |
| echo "$sha" > "${METADATA_DIR?}/resume_sha" |
| |
| echo " Committed" |
| |
| } |
| |
| add_bibisect_Linux() |
| { |
| echo -n "Adding $sha ..." |
| rm -fr "${TARGET_GIT_REPO?}/instdir" |
| cp -r "${SOURCE_GIT_REPO?}/instdir" "${TARGET_GIT_REPO?}/." |
| |
| pushd "${TARGET_GIT_REPO?}" > /dev/null |
| git add -A instdir |
| |
| pushd "${SOURCE_GIT_REPO?}" > /dev/null |
| cat <<EOF > commit.msgs |
| source sha:${sha?} |
| |
| $(git log --pretty="format:source sha:%H" ${last_done_sha?}..${sha?}) |
| EOF |
| |
| popd > /dev/null |
| echo -n " committing" |
| git commit -q -F "${SOURCE_GIT_REPO?}/commit.msgs" || die "error committing $sha" |
| last_done_sha="${sha?}" |
| rm "${SOURCE_GIT_REPO?}/commit.msgs" |
| popd > /dev/null |
| echo "$sha good" >> "${METADATA_DIR}/commit_list.done.pushed" |
| echo "$sha" > "${METADATA_DIR?}/resume_sha" |
| |
| echo " Committed" |
| |
| } |
| |
| if [ -z "$LODE_HOME" ] ; then |
| die "LODE_HOME not set" |
| fi |
| |
| bibisect_epoch= |
| count= |
| move= |
| fetch= |
| range_commits=1 |
| |
| os=$(uname -s) |
| if [ "$os" != "Darwin" -a "$os" != "Linux" ] ; then |
| os=$(uname -o) |
| fi |
| |
| while [ "${1}" != "" ]; do |
| parm=${1%%=*} |
| arg=${1#*=} |
| has_arg= |
| if [ "${1}" != "${parm?}" ] ; then |
| has_arg=1 |
| else |
| arg="" |
| fi |
| |
| case "${parm}" in |
| --epoch) |
| bibisect_epoch="$arg" |
| ;; |
| --help|-h) |
| usage |
| exit 0 |
| ;; |
| --count) |
| count="$arg" |
| ;; |
| --fetch) |
| fetch=1 |
| ;; |
| --move) |
| move=1 |
| ;; |
| -*) |
| die "Invalid option $1" |
| ;; |
| *) |
| die "Invalid argument $1" |
| ;; |
| esac |
| shift |
| done |
| |
| if [ -z "$bibisect_epoch" ] ; then |
| die "missing parameter --epoch" |
| fi |
| |
| if [ ! -f ~/.bibisect/$bibisect_epoch ] ; then |
| die "missing ~/.bibisect/$bibisect_epoch" |
| fi |
| |
| source ~/.bibisect/$bibisect_epoch ] || die "Error sourcing epoch configuration" |
| |
| |
| setup |
| |
| # in the 'move' mode we do not retry to build the lastest failed |
| # build streak |
| # other we do |
| if [ -z "$move" ] ; then |
| rm -f "${METADATA_DIR?}/last_build_sha" |
| fi |
| |
| determine_resume_sha |
| |
| determine_last_build_sha |
| |
| determine_todo_shas |
| |
| n=$range_commits |
| has_error=0 |
| |
| todo_list_array=(${todo_list}) |
| |
| for ((i = 0; i < ${#todo_list_array[@]}; i = i + $range_commits)); do |
| sha=${todo_list_array[i]} |
| build "$sha" |
| if [ -n "$sha" ] ; then |
| add_bibisect_$os |
| else |
| has_error=1 |
| fi |
| if [ -n "$move" -o -n "$sha" ] ; then |
| if [ -n "$count" ] ; then |
| count="$(($count - 1))" |
| if [ $count -lt 1 ] ; then |
| echo "Quota Done." |
| rm -f "${METADATA_DIR?}/stop" |
| exit $has_error |
| fi |
| fi |
| fi |
| if [ -f "${METADATA_DIR?}/stop" ] ; then |
| rm "${METADATA_DIR?}/stop" |
| echo "Stopped." |
| exit $has_error |
| fi |
| n=$(($n + $range_commits)) |
| done |
| |
| echo "Done." |
| exit $has_error |