#!/bin/sh
# packages copied to a --fetch directory or a --destination repository

. ./sh/lib/setup
. ./sh/lib/repo-setup

ORIGREPO=

setUp() {
    [ -z "$ORIGREPO" ] && ORIGREPO=$REPO
    [ -z "$ORIGREPO" ] && fail "empty REPO env variable"
    rm -rf $ORIGREPO/* $CACHEDIR/*

    REPO="$ORIGREPO/src"
    DESTINATION_REPO="$ORIGREPO/dest"
    FETCHDIR="$ORIGREPO/fetched"
    mkdir -p $REPO $DESTINATION_REPO $FETCHDIR || fail "mkdir failed"

    build_package $REPO a
    # provide /bin/sh auto requirement
    build_package $DESTINATION_REPO sh -p /bin/sh
    POLDEK_INSTALL="$POLDEK_NOCONF --st dir -s $REPO --dt dir --destination $DESTINATION_REPO"
}

# cp refuses to write through a dangling symlink
block_copy_to() {
    ln -s $ORIGREPO/nothing-here $1/a-1-1.noarch.rpm || fail "ln failed"
}

testFetch() {
    $POLDEK_INSTALL -i --fetch=$FETCHDIR a
    assertEquals "fetch failed" "0" "$?"
    assertTrue "a not fetched" "[ -f $FETCHDIR/a-1-1.noarch.rpm ]"
}

testFetchCopyFails() {
    block_copy_to $FETCHDIR
    $POLDEK_INSTALL -i --fetch=$FETCHDIR a
    rc=$?
    assertTrue "a failed copy ended with exit code 0" "[ $rc -ne 0 ]"
}

# change a payload byte: the header still loads, the digest no longer matches
corrupt_package() {
    local off byte

    off=$(($(stat -c %s $1) - 100))
    byte=$(dd if=$1 bs=1 skip=$off count=1 2>/dev/null | od -An -tx1 | tr -d ' ')
    [ "$byte" = 58 ] && byte=Y || byte=X
    printf $byte | dd of=$1 bs=1 seek=$off conv=notrunc 2>/dev/null || fail "dd failed"
}

# damage a, then run the given install with --fetch and the rpm backend,
# which checks package digests (--dt dir does not)
fetch_damaged() {
    local root=$ORIGREPO/root out

    corrupt_package $REPO/a-1-1.noarch.rpm
    mkdir -p $root && rpm --root $root --initdb || fail "initdb failed"
    out=$("$@" --root $root --fetch=$FETCHDIR 2>&1)
    rc=$?
    echo "$out"
    echo "$out" | grep -q "a-1-1.noarch.rpm: MD5 signature verification failed" ||
        fail "a was not refused by the digest check"
    assertTrue "a damaged package ended with exit code 0" "[ $rc -ne 0 ]"
    assertFalse "a damaged package left in the fetch directory" "[ -e $FETCHDIR/a-1-1.noarch.rpm ]"
}

testFetchDigestFails() {
    fetch_damaged $POLDEK_NOCONF --st dir -s $REPO --nodeps -i a
}

testFetchRemoteDigestFails() {
    $POLDEK_NOCONF -s $REPO --mkidx --mt pndir || fail "mkidx failed"
    fetch_damaged $POLDEK_UP -Osource="src,type=pndir test://$REPO/" --nodeps -i a
}

# b needs a, so both are downloaded at once; b is gone from the repository
testFetchRemoteDigestFailsWithFailedDownload() {
    build_package $REPO b -r "a"
    build_package $REPO sh -p /bin/sh
    $POLDEK_NOCONF -s $REPO --mkidx --mt pndir || fail "mkidx failed"
    rm -f $REPO/b-1-1.noarch.rpm
    fetch_damaged $POLDEK_UP -Osource="src,type=pndir test://$REPO/" -i b
}

testDestination() {
    $POLDEK_INSTALL -i a
    assertEquals "install failed" "0" "$?"
    assertTrue "a not copied" "[ -f $DESTINATION_REPO/a-1-1.noarch.rpm ]"
}

testDestinationCopyFails() {
    block_copy_to $DESTINATION_REPO
    $POLDEK_INSTALL -i a
    rc=$?
    assertTrue "a failed copy ended with exit code 0" "[ $rc -ne 0 ]"
}

# of two packages that differ only in arch, the one for this machine is
# copied; it comes from the first source, and without rpm's scores the
# arch poldek sees last would win
testDestinationPrefersMachineArch() {
    local arch=$(uname -m) foreign=$ORIGREPO/foreign out

    mkdir -p $foreign || fail "mkdir failed"
    build_package $REPO b 1-1 -a $arch -f /b.$arch
    build_package $foreign b 1-1 -a xtensa -f /b.xtensa
    # outside test mode, so nothing test-only can set rpm up instead
    out=$(env -u POLDEK_TESTING $POLDEK_INSTALL --st dir -s $foreign -i b 2>&1)
    assertEquals "install failed: $out" "0" "$?"
    assertTrue "b for $arch not copied: $out" "[ -f $DESTINATION_REPO/b-1-1.$arch.rpm ]"
    assertFalse "b for xtensa copied" "[ -e $DESTINATION_REPO/b-1-1.xtensa.rpm ]"
}

testDestinationWithoutRpmConfig() {
    local out rc

    out=$(RPM_CONFIGDIR=$ORIGREPO/no-rpm-config $POLDEK_INSTALL -i a 2>&1)
    rc=$?
    assertTrue "exit code 0 without rpm configuration: $out" "[ $rc -ne 0 ]"
    assertFalse "a copied" "[ -e $DESTINATION_REPO/a-1-1.noarch.rpm ]"
}

. ./sh/lib/shunit2
