You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-1/install/cl-builder

207 lines
6.6 KiB

#!/bin/bash
#------------------------------------------------------------------------------
# cl-builder
# Copyright ©2009 Calculate Ltd.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#------------------------------------------------------------------------------
# выбор строки перемонтирования разделов в зависимости от используемого модуля
BUILDER=/mnt/builder
if [[ -n `mount | grep " / type aufs"` ]];
then
REMOUNT="mount -t aufs -o remount,br:/ none /"
REMOUNTBUILDER="mount -t aufs -o remount,br:/ none $BUILDER"
else
REMOUNT="mount -t unionfs -o remount,dirs=/ unionfs /"
REMOUNTBUILDER=":"
fi
TIMERUN=`date +%s`
EMERGELOG=${BUILDER}/var/log/emerge.log
TAILEMERGELOG="tail -f ${EMERGELOG}"
#------------------------------------------------------------------------------
# Обновление Unionfs в течение сборки пакетов
#------------------------------------------------------------------------------
watching() {
$TAILEMERGELOG |
while read line;
do
if [ `echo "$line" | awk -F: '{print $1;}'` -ge $TIMERUN ] &&
[ "`echo "$line" | grep -e "unemerge success" -e "completed emerge"`" ]
then
$REMOUNT &>/dev/null
fi
done
}
#------------------------------------------------------------------------------
# Монтируем ресурсы
#------------------------------------------------------------------------------
mountres() {
mount -o bind /var/calculate/remote ${BUILDER}/var/calculate/remote
mount -t proc none ${BUILDER}/proc && mount -o bind /dev ${BUILDER}/dev &&
mount -t sysfs none ${BUILDER}/sys &&
mount -o bind /dev/pts ${BUILDER}/dev/pts && return 0
return 1
}
#------------------------------------------------------------------------------
# Выполним emerge
#------------------------------------------------------------------------------
runchroot() {
touch $EMERGELOG
watching & 2>/dev/null
chroot $BUILDER /bin/bash --rcfile /usr/calculate/install/config/chroot.rc
WATCHINGPID=`ps axo pid,cmd | sed -nr "s|^\s*([0-9]+)\s+${TAILEMERGELOG}.*|\1|p"`
[ "${WATCHINGPID}" ] && kill -9 $WATCHINGPID &>/dev/null
$REMOUNT &>/dev/null
}
#------------------------------------------------------------------------------
# Отмонтируем ресурсы
#------------------------------------------------------------------------------
umountres() {
# перебираем строку в обратном порядке
MOUNTDIRS=`mount | grep -Po "${BUILDER}/[^ ]+" | sed "{N;s/\n/ /}"`
for MOUNTDIR in $( echo $MOUNTDIRS | rev )
do
umount $(echo $MOUNTDIR | rev) || exit
done
}
#------------------------------------------------------------------------------
# Выполним проверки
#------------------------------------------------------------------------------
checkrun() {
if [[ `/usr/bin/id -u` -ne 0 ]]
then
echo "Only root can perform system building."
exit;
fi
#не запустим если загрузка не в Scrach режиме
if ! mount | grep /mnt/scratch &>/dev/null
then
echo "This program only works in the system, installed by Calculate with the option '--build'."
exit;
fi
#не запустим второй раз
if mount | grep "/dev/pts on /mnt/builder/dev/pts " &>/dev/null
then
if [ `ps ax | grep -v grep | grep -c "/bin/bash /usr/bin/cl-builder"` -gt 3 ];
then
echo "This program is already run."
exit;
else
umountres
fi
fi
#не запустим из chroot
if [ `mount | grep -c "devpts on /dev/pts "` -ne 1 ];
then
echo "This program can't be run from Scratch layer."
exit;
fi
}
#------------------------------------------------------------------------------
# Выполним предварительные настройки
#------------------------------------------------------------------------------
configure() {
# Перенесем resolv.conf
if [ -f /etc/resolv.conf ]
then
mkdir -p ${BUILDER}/etc
cp /etc/resolv.conf ${BUILDER}/etc/
fi
}
checkrun
configure
$REMOUNTBUILDER &>/dev/null
mountres && runchroot
umountres
ROOTDIR=/
UPDATE_DIRS="/boot /lib/modules /lib/firmware"
#------------------------------------------------------------------------------
# Ask: whether to replace the old file
#------------------------------------------------------------------------------
ask_replace() {
[[ $REPLACE_ANSWER == "yes" ]] && return 0
[[ $REPLACE_ANSWER == "no" ]] && return 1
local destfile=$1
echo "File '$destfile' in builder is newer than in workspace"
local line
while true
do
echo -n "Do you want replace old file (Yes/No/All/None):"
read line <&1
case $line in
All|all) REPLACE_ANSWER=yes;return 0;;
None|none) REPLACE_ANSWER=no;return 1;;
Y*|y*) return 0 ;;
N*|n*) return 1 ;;
esac
done
}
#------------------------------------------------------------------------------
# Compare modify time of the first and second file
#------------------------------------------------------------------------------
test_newer() {
# [[ file1 -nt file2 ]] not correct work with symbolic link, because
# get modify time of target file
if [[ -L $1 || -L $2 ]]
then
[[ `stat -c %Y $1` -gt `stat -c %Y $2` ]]
else
[[ $1 -nt $2 ]]
fi
}
#------------------------------------------------------------------------------
# Compare modify time, ask user for update and update file
#------------------------------------------------------------------------------
try_update_file() {
[[ -e $2 || -L $2 ]] && test_newer $1 $2 &&
ask_replace $2 && cp -P $1 $2
}
#------------------------------------------------------------------------------
# Find in first directory files and symbolic links with modify time great than
# same files in the second directory
#------------------------------------------------------------------------------
update_from_builder() {
basesrc=${1%/}
basedest=${2%/}
shift 2
for place in $*
do
src=$basesrc/${place#/}
dest=$basedest/${place#/}
find $src -type f -o -type l |
while read srcfile;
do
dstfile=${dest}/${srcfile#${src}/}
try_update_file $srcfile $dstfile
done
done
}
update_from_builder $BUILDER $ROOTDIR $UPDATE_DIRS