#!/bin/bash
set -e
. tests/lib

t-dependencies DEBORIG mpack pristine-tar moreutils

p=example
t-worktree 1.0
cd $p

mkdir bizarre-names
perl -e '
    foreach my $x (0..15) {
        my $f = sprintf "bizarre-names/%x-", $x;
	my $o = "";
        foreach my $y (0..15) {
            my $c = ($x << 4) + $y;
	    next if $c == 0 || $c == ord "/";
	    $f .= sprintf "%x%c", $x, $c;
	    $o .= sprintf "%02x\n", $c;
        }
        $f .= ".txt";
        open F, ">", $f or die "$x $!";
        print F $o or die $!;
        close F or die $!;
    }
'
git add bizarre-names
git commit -m bizarre-names

ln -s /target-absolute symlink-absolute
ln -s target-relative symlink-relative
git add symlink-absolute symlink-relative
git commit -m symlinks

git checkout -B upstream
git rm -rf debian
git commit -m 'remove debian dir for fake upstream'
git archive -o ../base.tar --prefix=exa/ HEAD

: "add more exciting things to tarfile that don't survive though git"

mkdir hardlink{1,2}
touch hardlink1/1
ln hardlink1/1 hardlink2/2
ln symlink-relative hardlinked-symlink
git add hardlink[12]/[12] hardlinked-symlink
git commit -m hardlinks

dir-mode () {
    mkdir dir-mode-$1
    touch dir-mode-$1/file
    git add dir-mode-$1/file
    chmod $1 dir-mode-$1
}
dir-mode 2750
dir-mode 700

cd ..
rm -f exa
ln -s "$tmp/$p" exa
tar rf base.tar					\
    exa/hardlink[12]				\
    exa/hardlinked-symlink			\
    exa/dir-mode-{2750,700}
cd $tmp/$p
git commit -m 'dir-modes'

cd ..
rm exa
mkdir exa
cd exa
mkfifo -m600 fifo
$troot/t2u-fake-manager --expect-oracled-crash socket --- false
cd ..
tar rf base.tar exa/*

cd $p
git checkout --orphan empty
git rm --quiet -rf .
touch NOTHING
git add NOTHING
git commit -m 'do regen in empty tree, proving no working file use'

git checkout -b base/master master
git branch -f base/upstream upstream

mkdir ../imported ../success
orig_stem=${p}_1.0.orig
orig=${orig_stem}.tar.gz

next-test () {
    : "$@"
    cd "$tmp"
    rm -rf exa
    cd $p
    cp ../base.tar ../this.tar
    git checkout -B master base/master
    git branch -f upstream base/upstream
    git branch -D pristine-tar ||:
    git tag -d upstream/1.0 ||:
    rm -f ../$orig
}

gz-and-gbp-import-tarball () {
    cd "$tmp/$p"
    gzip -1 <../this.tar >../$orig
    gbp import-orig --pristine-tar --upstream-version=1.0 ../$orig </dev/null
    mv ../$orig ../imported/.
}
gz-and-raw-import-tarball () {
    cd "$tmp/$p"
    gzip -1 <../this.tar >../$orig
    pristine-tar commit ../$orig upstream
    mv ../$orig ../imported/.
}

regenerate-tarball () {
    DGIT_DRS_DGIT='perl -e exit(4) --'				\
    ${DGIT_T2U_OBTAIN_ORIGS_TEST-tag2upload-obtain-origs}	\
        p=$p v=1.0-1 bpd=..					\
        u=$(git rev-parse upstream)				\
	pristine_tar=$(git rev-parse pristine-tar)
}

next-test "-------------------- success --------------------"
gz-and-gbp-import-tarball
git checkout pristine-tar
touch example_1.1.orig.tar.gz.{id,delta}
git add example_1.1.orig.tar.gz.{id,delta}
git commit -m 'irrelevancies'
regenerate-tarball
cp ../$orig ../success/.
git branch -f success/upstream upstream
git branch -f success/pristine-tar pristine-tar

next-test "-------------------- bizarre pristine-tar --------------------"
git checkout -b pristine-tar success/pristine-tar
touch $orig_stem.tar.=
git add $orig_stem.tar.=
git commit -m sabotage
t-expect-fail E:'apparently-relevant .* with byte 0x3d in its name' \
regenerate-tarball

next-test "-------------------- bizarre pristine-tar 2 --------------------"
git checkout -b pristine-tar success/pristine-tar
chmod +x $orig.id
git commit -m sabotage $orig.id
t-expect-fail E:'apparently-relevant .* not a non-excutable file' \
regenerate-tarball

next-test "-------------------- bizarre pristine-tar 3 --------------------"
git checkout -b pristine-tar success/pristine-tar
touch $orig_stem-_wrong.tar.gz.id
git add $orig_stem-_wrong.tar.gz.id
git commit -m sabotage
t-expect-fail E:'apparently-relevant .* info .* with unsupported filename' \
regenerate-tarball

next-test "-------------------- multiple tarballs --------------------"
git checkout -b pristine-tar success/pristine-tar
touch $orig_stem.tar.xz.{id,delta}
git add $orig_stem.tar.xz.{id,delta}
git commit -m sabotage $orig_stem.tar.xz.{id,delta}
t-expect-fail E:'conflicting example_1.0.orig\*.tar\* for .* '\''\.'\''' \
regenerate-tarball

next-test "-------------------- missing .id --------------------"
git checkout -b pristine-tar success/pristine-tar
git rm $orig.id
git commit -m sabotage
t-expect-fail E:' example_1\.0\.orig\.tar\.gz\.id missing' \
regenerate-tarball

next-test "-------------------- missing .delta --------------------"
git checkout -b pristine-tar success/pristine-tar
git rm $orig.delta
git commit -m sabotage
t-expect-fail E:' example_1\.0\.orig\.tar\.gz\.delta missing' \
regenerate-tarball

next-test "-------------------- bad data in .id --------------------"
git checkout -b pristine-tar success/pristine-tar
echo @ >>$orig.id
git commit -m sabotage $orig.id
t-expect-fail E:'unexpected data in pristine-tar .*\.id' \
regenerate-tarball

next-test "-------------------- tarbomb, extra file --------------------"
tar rf ../this.tar example
git checkout -B upstream success/upstream
gz-and-raw-import-tarball
t-expect-fail E:'top-level object not a directory, might be a tarbomb' \
regenerate-tarball

next-test "-------------------- tarbomb, extra dir --------------------"
tar rf ../this.tar debian
git checkout -B upstream success/upstream
gz-and-raw-import-tarball
t-expect-fail E:'first directory part varies - tarfile is a tarbomb' \
regenerate-tarball

next-test "-------------------- device file --------------------"
cd ..
ln -s /dev exa
tar rf this.tar exa/null
cd $p
git checkout -B upstream success/upstream
gz-and-raw-import-tarball
t-expect-fail E:'forbidden object type: c' \
regenerate-tarball

next-test "-------------------- set-id file --------------------"
cd ..
mkdir exa
touch exa/setuid
tar --mode=u+s -rf this.tar exa/setuid
gz-and-gbp-import-tarball
t-expect-fail E:'forbidden file permissions' \
regenerate-tarball

next-test "-------------------- same file twice --------------------"
cd ..
ln -s example exa
tar rf this.tar exa/example
gz-and-gbp-import-tarball
t-expect-fail E:'file list in tarball does not match file list in git' \
regenerate-tarball
grep -P '^\+100755 blob\texample$' ../t.output

next-test "-------------------- same symlink twice --------------------"
cd ..
ln -s example exa
tar rf this.tar exa/symlink-relative
gz-and-gbp-import-tarball
t-expect-fail E:'file list in tarball does not match file list in git' \
regenerate-tarball
grep -P '^\+120000 blob\tsymlink-relative$' ../t.output

next-test "-------------------- absolute paths --------------------"
tar --transform='s/^/\//' -cf ../this.tar example
gz-and-raw-import-tarball
t-expect-fail E:'path in tarball may not start with .* /' \
regenerate-tarball

next-test "-------------------- ./ paths --------------------"
tar -cf ../this.tar ./example
gz-and-raw-import-tarball
t-expect-fail E:'path in tarball may not start with \. ' \
regenerate-tarball

next-test "-------------------- .. in middle of path --------------------"
tar --transform='s/^/exa\/..\/example\//' -cf ../this.tar example
gz-and-raw-import-tarball
t-expect-fail E:'fatal.*is outside repository' \
regenerate-tarball

next-test "-------------------- mismatch vs id --------------------"
git checkout upstream
echo discrepancy >>example
git commit -m discrepancy example
git branch -f discrepancy/upstream
gz-and-raw-import-tarball
t-expect-fail E:'pristine-tar .* and .*\.tar\.gz disagree about example' \
regenerate-tarball

next-test "-------------------- symlink mismatch vs id --------------------"
git checkout upstream
rm symlink-relative
ln -s discrepancy symlink-relative
git commit -m discrepancy symlink-relative
gz-and-raw-import-tarball
t-expect-fail E:'symlink-relative: link target differs between tar and git' \
regenerate-tarball

next-test "-------------------- hardlink mismatch vs id --------------------"
git checkout upstream
rm hardlink2/2
echo discrepancy >hardlink2/2
git commit -m discrepancy hardlink2/2
gz-and-raw-import-tarball
t-expect-fail E:'exa/hardlink2/2: hardlink target has different contents' \
regenerate-tarball

: "can't test 'hardlink, missing' since tar won't generate such a thing"

next-test "-------------------- top-level mismatch --------------------"
git branch -f upstream discrepancy/upstream
git branch -f pristine-tar success/pristine-tar
t-expect-fail E:'tarball contents are not treesame to upstream commit' \
regenerate-tarball

t-ok
