view hg/hgsyncee @ 594:6fdcc066ec68

Fix spelling.
author Oleksandr Gavenko <gavenkoa@gmail.com>
date Sat, 21 Nov 2015 23:23:24 +0200
parents 242d4955e902
children e6675a7afbf1
line wrap: on
line source

#!/bin/sh
# -*- coding: cp1251-unix; sh-basic-offset: 4 -*-

# Copyright (C) 2008 by Oleksandr Gavenko <gavenkoa@gmail.com>

# set -x
# set -u

UTIL_NAME=$0
UTIL_NAME=${UTIL_NAME##*/}

LOG_FILE=$UTIL_NAME.log

Usage() {
    echo Sync external repo-set with master repo-set via intermediate repo-set.
    echo "Usage:"
    echo "$UTIL_NAME [--help]"
    echo "  --help    print this help"
}

PrintLog() {
    if [ x$1 = x ] ; then
        MSG_SIGN=ERROR
    else
        case $1 in
            INFO|PROCESSING)
                MSG_SIGN=$1
                MSG_SIGN_COLOR=$1
                ;;
            ADDED)
                MSG_SIGN=$1
                MSG_SIGN_COLOR="\033[32m"$1"\033[0m"
                ;;
            ERROR|WARNING)
                MSG_SIGN=$1
                MSG_SIGN_COLOR="\033[31m"$1"\033[0m"
                ;;
            *) exit 1 ;;
        esac
    fi
    printf "$MSG_SIGN_COLOR: $MSG\n"
    printf "$MSG_SIGN: $MSG\n" >>$LOG_FILE 2>&1
}

# For GNU ls.
export BLOCK_SIZE=1024
LOG_SIZE=20

# If log size larger then $LOG_SIZE KiB rotate log, log.1 and log.2.
RotateLog() {
    [ -e $LOG_FILE ] || return
    if [ `ls -s $LOG_FILE | sed 's_ *\([0-9]\) .*_\1_'` -ge $LOG_SIZE ]; then
        rm -f $LOG_FILE.2
        [ -e $LOG_FILE.1 ] && mv $LOG_FILE.1 $LOG_FILE.2
        mv $LOG_FILE $LOG_FILE.1
    fi
}

# Is hg utility present in system?
Check_HG_exist() {
    command -v hg && return 0 || return 1
}

Set_CFG() {
    # Если есть локальный файл конфигурации репозиториев (полезно для отладки).
    CFG=./hgsyncrc
    if [ -e $CFG ]; then
        return 0;
    fi
    # Иначе ищем по стандартному пути.
    if [ x$HOME = x ] ; then
        MSG="HOME is not set."
        return 1;
    fi
    CFG=$HOME/.hgsyncrc
    if [ -e $CFG ] ; then
        return 0;
    fi
    CFG=/etc/hgsyncrc
    if [ -e $CFG ]; then
        return 0;
    fi
    MSG="Config file '$CFG' is not found. See hgsyncrc(1)."
    return 1;
}

Check_CFG() {
    if [ x$MASTER_DIR = x ] ; then
        MSG="MASTER_DIR is not set in $CFG"
        return 1;
    fi
    if [ -d $MASTER_DIR ] ; then :
    else
        MSG="MASTER_DIR points to non-existing dir. See hgsyncrc(1) and '$CFG'."
        return 1;
    fi
    if [ x$MERGE_DIR = x ]; then
        MSG="MERGE_DIR is not set in $CFG"
        return 1;
        if [ -d $MERGE_DIR ]; then :
        else
            MSG="MERGE_DIR points to non existing dir. See hgsyncrc(1) and '$CFG'."
            return 1;
        fi
    fi
    return 0;
}

# Expect two args - path to compared repos.
CheckRepCompatibility() {
    REP1_ZERO_REV=`hg -R $1 log -r0 --template '{node}'`
    REP2_ZERO_REV=`hg -R $2 log -r0 --template '{node}'`

    [ "$REP1_ZERO_REV" = "$REP2_ZERO_REV" ] && return 0 || return 1
}

# ##########
# Main work.
# ##########

case "${1-}" in
    -h|--help)
        Usage
        exit 0;
        ;;
esac

RotateLog

echo >>$LOG_FILE 2>&1
echo ========================= >>$LOG_FILE 2>&1
date +"%F %T" >>$LOG_FILE 2>&1

if Check_HG_exist; then :
else
    MSG="'hg' utility is not in the PATH."
    PrintLog ERROR
    exit 1;
fi

if Set_CFG; then
    . $CFG
else
    PrintLog ERROR
    exit 1;
fi

if Check_CFG; then :
else
    PrintLog ERROR
    exit 1;
fi

if [ -d "$MERGE_DIR" ] || mkdir "$MERGE_DIR"; then
    :
else
    MSG="Can not create $MERGE_DIR."
    PrintLog ERROR
    exit 1;
fi

MSG="master dir: $MASTER_DIR"
PrintLog INFO
MSG="external dir: $MERGE_DIR"
PrintLog INFO

echo

for dir in */.hg/. .*/.hg/.; do
    dir=${dir%/.hg/.}
    [ -d "$dir" ] || continue

    MSG="'$dir' repo."
    PrintLog PROCESSING

    if [ -d $MASTER_DIR/$dir/.hg ]; then
        if [ -d $MERGE_DIR/$dir/.hg ]; then
            if CheckRepCompatibility $MERGE_DIR/$dir $MASTER_DIR/$dir; then :
            else
                MSG="'$MERGE_DIR/$dir' and '$MASTER_DIR/$dir' are not compatable."
                PrintLog ERROR
                exit 1;
            fi
            hg -R $MERGE_DIR/$dir pull $MASTER_DIR/$dir >>$LOG_FILE 2>&1
        else
            hg clone $MASTER_DIR/$dir $MERGE_DIR/$dir >>$LOG_FILE 2>&1
        fi
        if CheckRepCompatibility $MERGE_DIR/$dir ./$dir; then :
        else
            MSG="'$dir' and master are not compatable."
            PrintLog ERROR
            exit 1;
        fi
        hg -R $MERGE_DIR/$dir pull ./$dir >>$LOG_FILE 2>&1
    else
        MSG="'$dir' is skipped. It absents in master repo-set."
        PrintLog INFO
        continue
    fi

    HEAD_CNT=`hg -R $MERGE_DIR/$dir head | grep "changeset:" | wc -l`
    case $HEAD_CNT in
        # Если нет необходимости мержить - изменения "правильные"
        # и должны быть возвращены как в промежуточный репозиторий,
        # так и в эталонный репозиторий.
        1)
            CHANGESET_CNT=`hg --config defaults.outgoing="" --quiet -R $MERGE_DIR/$dir out \
                --template '{node}\n' $MASTER_DIR/$dir | wc -l`
            case $CHANGESET_CNT in
                0) ;;
                *)
                    hg -R $MERGE_DIR/$dir push $MASTER_DIR/$dir >>$LOG_FILE 2>&1
                    MSG="==> master"
                    PrintLog ADDED
                    ;;
            esac
            CHANGESET_CNT=`hg --config defaults.outgoing="" --quiet -R $MERGE_DIR/$dir out \
                --template '{node}\n' ./$dir | wc -l`
            case $CHANGESET_CNT in
                0) ;;
                *)
                    hg -R $MERGE_DIR/$dir push ./$dir >>$LOG_FILE 2>&1
                    MSG="==> work"
                    PrintLog ADDED
                    ;;
            esac
            ;;
        # Иначе переносим только "правильные" делты в промежуточный репозиторый
        # для их доступности из промежуточного репозитория на другом рабочем месте.
        *)
            MSG="You must manually merge '$dir' proj and re-run $UTIL_NAME."
            PrintLog WARNING
            MSG="Go to $MERGE_DIR/$dir dir."
            PrintLog WARNING
            hg -R $MASTER_DIR/$dir push -f ./$dir >>$LOG_FILE 2>&1
            ;;
    esac
done

command -v sync >/dev/null && sync