From e5c5ec7c6bf8d0460b870b1dacc5c928326fb81b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 12 Nov 2012 18:56:53 -0500 Subject: librechroot: learn how to sync copies with root --- src/chroot-tools/librechroot | 119 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/chroot-tools/librechroot b/src/chroot-tools/librechroot index d53448a..1c9700c 100755 --- a/src/chroot-tools/librechroot +++ b/src/chroot-tools/librechroot @@ -27,35 +27,107 @@ cmd=${0##*/} -clean_chroot() { # Clean packages with pacman - msg "Cleaning chroot with pacman: ${chroot_path}" +lock_open_write() { + local fd=$1 + local path=$2 + local msg=$3 + + # Only reopen the FD if it wasn't handed to us + if [[ $(readlink -f /dev/fd/$fd) != "${path}.lock" ]]; then + exec $fd>"${path}.lock" + fi + + if ! flock -n $fd; then + stat_busy "$msg" + flock $fd + stat_done + fi +} + +lock_open_read() { + local fd=$1 + local path=$2 + local msg=$3 + + # Only reopen the FD if it wasn't handed to us + if [[ $(readlink -f /dev/fd/$fd) != "${path}.lock" ]]; then + exec $fd>"${path}.lock" + fi - cp -a "$(dirname $0)/chcleanup" "${chroot_path}/clean" - mkarchroot -r "cd /build; /clean" "${chroot_path}" + if ! flock -sn $fd; then + stat_busy "$msg" + flock -s $fd + stat_done + fi +} - #mkarchroot "${chroot_path}" base base-devel sudo "${CHROOTEXTRAPKG[@]}" +lock_close() { + local fd=$1 + exec $fd>&- +} + +clean_pacman() { + msg "Cleaning chroot with pacman: ${copydir}" + + cp -a "$(dirname $0)/chcleanup" "${copydir}/clean" + mkarchroot -r "cd /build; /clean" "${copydir}" + + #mkarchroot "${copydir}" base base-devel sudo "${CHROOTEXTRAPKG[@]}" } clean_repo() { - msg "Cleaning repo for chroot: ${chroot_path}" + msg "Cleaning repo for chroot: ${copydir}" + + if [ -d "${copydir}/repo" ]; then + find "${copydir}/repo/" -mindepth 1 -delete + else + mkdir -p "${copydir}/repo" + fi + bsdtar -czf "${copydir}/repo/repo.db.tar.gz" -T /dev/null + ln -s "repo.db.tar.gz" "${copydir}/repo/repo.db" +} + +## +# This function is almost verbatim from makechrootpkg +## +sync() { + if [[ $CHROOTCOPY = root ]]; then + error "Cannot sync the root copy with itself" + exit 1 + fi + + # Note that '9' is the same FD number as in mkarchroot + lock_open_write 9 "$copydir" "Locking chroot copy '$copy'" + lock_open_read 8 "$rootdir" "Locking clean chroot" - if [ -d "${chroot_path}/repo" ]; then - find "${chroot_path}/repo/" -mindepth 1 -delete + stat_busy 'Creating clean working copy' + local use_rsync=false + if type -P btrfs >/dev/null; then + [[ -d $copydir ]] && btrfs subvolume delete "$copydir" &>/dev/null + btrfs subvolume snapshot "$chrootdir/root" "$copydir" &>/dev/null || + use_rsync=true else - mkdir -p "${chroot_path}/repo" + use_rsync=true fi - bsdtar -czf "${chroot_path}/repo/repo.db.tar.gz" -T /dev/null - ln -s "repo.db.tar.gz" "${chroot_path}/repo/repo.db" + + if $use_rsync; then + mkdir -p "$copydir" + rsync -a --delete -q -W -x "$CHROOTDIR/$CHROOT/root/" "$copydir" + fi + stat_done + + lock_close 8 + lock_close 9 } update() { - msg "Updating chroot: ${chroot_path}" - mkarchroot -u "${chroot_path}" + msg "Updating chroot: ${copydir}" + mkarchroot -u "${copydir}" } enter() { - msg "Entering chroot: ${chroot_path}" - mkarchroot -r "bash" "${chroot_path}" + msg "Entering chroot: ${copydir}" + mkarchroot -r "bash" "${copydir}" } usage() { @@ -72,6 +144,7 @@ usage() { echo ' Modes:' echo ' -h Show this message' echo ' -c Clean the chroot using pacman' + echo " -C Clean the chroot by syncing it with 'root' copy" echo ' -r Clean /repo in the chroot' echo ' -u Update the chroot' } @@ -88,7 +161,8 @@ main() { d) CHROOTDIR=$OPTARG;; l) CHROOTCOPY=$OPTARG;; - c) mode=clean_chroot;; + c) mode=clean_pacman;; + C) mode=sync;; r) mode=clean_repo;; u) mode=update;; @@ -104,15 +178,24 @@ main() { esac # not local - chroot_path="${CHROOTDIR}/${CHROOT}/${CHROOTCOPY}" + rootdir="${CHROOTDIR}/${CHROOT}/root" + copydir="${CHROOTDIR}/${CHROOT}/${CHROOTCOPY}" if (( EUID )); then error "This script must be run as root." exit 1 fi + if [[ ! -d $rootdir ]]; then + libremkchroot -d "$CHROOTDIR" "$CHROOT" + fi + + if [[ ! -d $copydir ]] && [[ $mode != sync ]]; then + sync + fi + case "$mode" in - clean_chroot) clean_chroot; exit $?;; + clean_pacman) clean_pacman; exit $?;; clean_repo) clean_repo; exit $?;; update) update; exit $?;; enter) enter; exit $?;; -- cgit v1.2.2