#!/usr/bin/env bash
. ./wvtest-bup.sh

set -o pipefail

top="$(WVPASS pwd)" || exit $?
tmpdir="$(WVPASS wvmktempdir)" || exit $?

export BUP_DIR="$tmpdir/bup"
export GIT_DIR="$tmpdir/bup"

GC_OPTS=--unsafe

bup() { "$top/bup" "$@"; }
compare-trees() { "$top/dev/compare-trees" "$@"; }
data-size() { "$top/dev/data-size" "$@"; }

WVPASS cd "$tmpdir"
WVPASS bup init


WVSTART "gc (unchanged repo)"

WVPASS mkdir src-1
WVPASS bup random 1k > src-1/1
WVPASS bup index src-1
WVPASS bup save --strip -n src-1 src-1

WVPASS bup gc $GC_OPTS -v

WVPASS bup restore -C "$tmpdir/restore" /src-1/latest
WVPASS compare-trees src-1/ "$tmpdir/restore/latest/"


WVSTART "gc (unchanged, new branch)"

WVPASS mkdir src-2
WVPASS bup random 10M > src-2/1
WVPASS bup index src-2
WVPASS bup save --strip -n src-2 src-2

WVPASS bup gc $GC_OPTS -v

WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /src-1/latest
WVPASS compare-trees src-1/ "$tmpdir/restore/latest/"

WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /src-2/latest
WVPASS compare-trees src-2/ "$tmpdir/restore/latest/"


WVSTART "gc (removed branch)"

size_before=$(WVPASS data-size "$BUP_DIR") || exit $?
WVPASS rm "$BUP_DIR/refs/heads/src-2"
WVPASS bup gc $GC_OPTS -v
size_after=$(WVPASS data-size "$BUP_DIR") || exit $?

WVPASS [ "$size_before" -gt 5000000 ]
WVPASS [ "$size_after" -lt 50000 ]

WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /src-1/latest
WVPASS compare-trees src-1/ "$tmpdir/restore/latest/"

WVPASS rm -r "$tmpdir/restore"
WVFAIL bup restore -C "$tmpdir/restore" /src-2/latest
 

WVPASS mkdir src-ab-clean src-ab-clean/a src-ab-clean/b
WVPASS bup random 1k > src-ab-clean/a/1
WVPASS bup random 10M > src-ab-clean/b/1


WVSTART "gc (rewriting)"

WVPASS rm -rf "$BUP_DIR"
WVPASS bup init
WVPASS rm -rf src-ab
WVPASS cp -pPR src-ab-clean src-ab

WVPASS bup index src-ab
WVPASS bup save --strip -n src-ab src-ab
WVPASS bup index --clear
WVPASS bup index src-ab
WVPASS bup save -vvv --strip -n a src-ab/a

size_before=$(WVPASS data-size "$BUP_DIR") || exit $?
WVPASS rm "$BUP_DIR/refs/heads/src-ab"
WVPASS bup gc $GC_OPTS -v
size_after=$(WVPASS data-size "$BUP_DIR") || exit $?

WVPASS [ "$size_before" -gt 5000000 ]
WVPASS [ "$size_after" -lt 100000 ]

WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /a/latest
WVPASS compare-trees src-ab/a/ "$tmpdir/restore/latest/"

WVPASS rm -r "$tmpdir/restore"
WVFAIL bup restore -C "$tmpdir/restore" /src-ab/latest


WVSTART "gc (save -r after repo rewriting)"

WVPASS rm -rf "$BUP_DIR"
WVPASS bup init
WVPASS bup -d bup-remote init
WVPASS rm -rf src-ab
WVPASS cp -pPR src-ab-clean src-ab

WVPASS bup index src-ab
WVPASS bup save -r :bup-remote --strip -n src-ab src-ab
WVPASS bup index --clear
WVPASS bup index src-ab
WVPASS bup save -r :bup-remote -vvv --strip -n a src-ab/a

size_before=$(WVPASS data-size bup-remote) || exit $?
WVPASS rm bup-remote/refs/heads/src-ab
WVPASS bup -d bup-remote gc $GC_OPTS -v
size_after=$(WVPASS data-size bup-remote) || exit $?

WVPASS [ "$size_before" -gt 5000000 ]
WVPASS [ "$size_after" -lt 100000 ]

WVPASS rm -rf "$tmpdir/restore"
WVPASS bup -d bup-remote restore -C "$tmpdir/restore" /a/latest
WVPASS compare-trees src-ab/a/ "$tmpdir/restore/latest/"

WVPASS rm -r "$tmpdir/restore"
WVFAIL bup -d bup-remote restore -C "$tmpdir/restore" /src-ab/latest

# Make sure a post-gc index/save that includes gc-ed data works
WVPASS bup index src-ab
WVPASS bup save -r :bup-remote --strip -n src-ab src-ab
WVPASS rm -r "$tmpdir/restore"
WVPASS bup -d bup-remote restore -C "$tmpdir/restore" /src-ab/latest
WVPASS compare-trees src-ab/ "$tmpdir/restore/latest/"


WVSTART "gc (bup on after repo rewriting)"

WVPASS rm -rf "$BUP_DIR"
WVPASS bup init
WVPASS rm -rf src-ab
WVPASS cp -pPR src-ab-clean src-ab

WVPASS bup on - index src-ab
WVPASS bup on - save --strip -n src-ab src-ab
WVPASS bup index --clear
WVPASS bup on - index src-ab
WVPASS bup on - save -vvv --strip -n a src-ab/a

size_before=$(WVPASS data-size "$BUP_DIR") || exit $?
WVPASS rm "$BUP_DIR/refs/heads/src-ab"
WVPASS bup gc $GC_OPTS -v
size_after=$(WVPASS data-size "$BUP_DIR") || exit $?

WVPASS [ "$size_before" -gt 5000000 ]
WVPASS [ "$size_after" -lt 100000 ]

WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /a/latest
WVPASS compare-trees src-ab/a/ "$tmpdir/restore/latest/"

WVPASS rm -r "$tmpdir/restore"
WVFAIL bup restore -C "$tmpdir/restore" /src-ab/latest

# Make sure a post-gc index/save that includes gc-ed data works
WVPASS bup on - index src-ab
WVPASS bup on - save --strip -n src-ab src-ab
WVPASS rm -r "$tmpdir/restore"
WVPASS bup restore -C "$tmpdir/restore" /src-ab/latest
WVPASS compare-trees src-ab/ "$tmpdir/restore/latest/"


WVSTART "gc (threshold 0)"

WVPASS rm -rf "$BUP_DIR"
WVPASS bup init
WVPASS rm -rf src && mkdir src
WVPASS echo 0 > src/0
WVPASS echo 1 > src/1

WVPASS bup index src
WVPASS bup save -n src-1 src

pack_contents_before="$(git show-index < "$BUP_DIR/objects/pack/"*.idx | cut -d' ' -f2- | sort)" || exit $?
WVPASS bup gc -v $GC_OPTS --threshold 0 2>&1 | tee gc.log
pack_contents_after="$(git show-index < "$BUP_DIR/objects/pack/"*.idx | cut -d' ' -f2- | sort)" || exit $?
# Check that the pack was rewritten or a new pack written, but
# with the same objects. Note that the name of the pack will
# likely change as the *order* of objects is different. The
# "git show-index | cut | sort" ignores the offsets but checks
# the object and their crc.
WVPASSEQ 1 "$(grep -cE '^rewriting ' gc.log)"
WVPASSEQ "$pack_contents_before" "$pack_contents_after"


WVSTART "gc (--ignore-missing)"

WVPASS rm -rf "$BUP_DIR"
WVPASS bup init
WVPASS rm -rf src && mkdir src
WVPASS echo 0 > src/0
WVPASS echo 1 > src/1
WVPASS mkdir src/victim
WVPASS echo 2 > src/victim/2
WVPASS bup index src
WVPASS bup save -n src --strip src

root_bupm="$(WVPASS git cat-file -t "$(git rev-parse src:.bupm)")" || exit $?

WVPASS echo 3 > src/3
WVPASS bup index src
WVPASS bup save -n src --strip src

last_save="$(WVPASS bup ls -s src | tail -n -2 | head -n 1 | cut -d ' ' -f 2)" || exit $?
WVPASS bup rm --unsafe src/"$last_save"

# Drop the victim tree
WVPASS git ls-tree src | grep victim | WVPASS cut -d' ' -f 3 \
    | WVPASS cut -b -40 > victim-oid
WVPASS test -n "$(<victim-oid)"
WVPASS "$top/dev/perforate-repo" --drop-oids "$BUP_DIR" < victim-oid

WVFAIL bup gc -v $GC_OPTS --threshold 0 --ignore-missing 2>&1 | tee gc.log
WVPASSEQ 1 "$(WVPASS grep -cE '^rewriting ' gc.log)"
WVPASSEQ 1 "$(WVPASS grep -cE '^missing ' gc.log)"

obj_n_after="$(WVPASS git cat-file --batch-all-objects --batch-check='%(objectname)' | wc -l)" || exit $?
if test "$root_bupm" = blob; then
    WVPASSEQ 5 $obj_n_after
else
    WVPASSEQ 7 $obj_n_after
fi

WVPASS rm -rf "$tmpdir"
