# file      : tests/pkg-unpack.testscript
# license   : MIT; see accompanying LICENSE file

.include common.testscript \
         auth.testscript   \
         config.testscript \
         remote.testscript \
         remote-git.testscript

# Source repository:
#
# pkg-unpack
# |-- hello
# |   |-- libhello-1.0.0.tar.gz
# |   `-- repositories.manifest
# |-- libfoo-1.1.0
# |   |-- build
# |   |   `-- bootstrap.build
# |   |-- buildfile
# |   `-- manifest
# |-- t1
# |   |-- libfoo-1.0.0.tar.gz
# |   |-- libfoo-1.1.0.tar.gz
# |   `-- repositories.manifest
# |
# `-- git
#     `-- style-basic.git

# Prepare repositories used by tests if running in the local mode.
#
+if! $remote
{
  rep_create += 2>!

  # Create the signed 'hello' repository.
  #
  cp -r $src/hello $out/hello
  cat <<<$cert_manifest >+$out/hello/repositories.manifest

  $rep_create --key $key $out/hello &$out/hello/packages.manifest \
                                    &$out/hello/signature.manifest

  # Create the 't1' repository.
  #
  cp -r $src/t1 $out/t1
  $rep_create $out/t1 &$out/t1/packages.manifest &$out/t1/signature.manifest

  # Create git repositories.
  #
  $git_extract $src/git/style-basic.tar &$out_git/state0/***
}

pkg_fetch     += -d cfg 2>!
pkg_purge     += -d cfg
pkg_status    += -d cfg
rep_add       += -d cfg 2>!
rep_fetch     += -d cfg --auth all 2>!
pkg_configure += -d cfg
pkg_update    += -d cfg
pkg_disfigure += -d cfg

: replace-with-existing
:
$clone_cfg;
$* foo -r 2>>EOE != 0
  error: --replace|-r can only be specified with external package
  EOE

: no-dir
:
$clone_cfg;
$* -e 2>>EOE != 0
  error: package directory argument expected
    info: run 'bpkg help pkg-unpack' for more information
  EOE

: not-package-dir
:
$clone_cfg;
$* -e ./ 2>>/EOE != 0
  error: no manifest file in package directory ./
  EOE

: dir-not-exist
:
$clone_cfg;
$* -e ./no-such-dir 2>>/EOE != 0
  error: package directory ./no-such-dir/ does not exist
  EOE

: no-name
:
$clone_cfg;
$* 2>>EOE != 0
  error: package name argument expected
    info: run 'bpkg help pkg-unpack' for more information
  EOE

: fetched-rep
:
{{
  +$clone_cfg && $rep_add $rep/t1 && $rep_fetch --trust-yes

  : package-exists
  :
  {
    $clone_cfg && $pkg_fetch libfoo/1.0.0

    $* -e $src/libfoo-1.1.0 2>>/EOE != 0
      error: package libfoo already exists in configuration cfg/
        info: version: 1.0.0, state: fetched, substate: none
        info: use 'pkg-unpack --replace|-r' to replace
      EOE

    $pkg_purge  libfoo       2>'purged libfoo/1.0.0'
    $*  -e $src/libfoo-1.1.0 2>'using libfoo/1.1.0 (external)'
    $pkg_status libfoo/1.1.0 1>'libfoo unpacked 1.1.0'

    $pkg_configure libfoo  2>'configured libfoo/1.1.0'
    test    -d cfg/libfoo
    $pkg_disfigure libfoo  2>'disfigured libfoo/1.1.0'

    $pkg_purge libfoo 2>'purged libfoo/1.1.0'
  }

  : replace-fetched
  :
  {
    $clone_cfg && $pkg_fetch libfoo/1.0.0

    $* -e $src/libfoo-1.1.0 2>>/EOE != 0
      error: package libfoo already exists in configuration cfg/
        info: version: 1.0.0, state: fetched, substate: none
        info: use 'pkg-unpack --replace|-r' to replace
      EOE

    $* --replace --existing $src/libfoo-1.1.0 2>'using libfoo/1.1.0 (external)'
    $pkg_status libfoo/1.1.0 1>'libfoo unpacked 1.1.0'

    $pkg_purge libfoo 2>'purged libfoo/1.1.0'
  }

  : replace-unpacked
  :
  {
    $clone_cfg && $pkg_fetch libfoo/1.0.0

    $* libfoo 2>>EOE
      unpacking libfoo/1.0.0
      unpacked libfoo/1.0.0
      EOE

    $* -e $src/libfoo-1.1.0 2>>/EOE != 0
      error: package libfoo already exists in configuration cfg/
        info: version: 1.0.0, state: unpacked, substate: none
        info: use 'pkg-unpack --replace|-r' to replace
      EOE

    $* --replace --existing $src/libfoo-1.1.0 2>'using libfoo/1.1.0 (external)'
    $pkg_status libfoo/1.1.0 1>'libfoo unpacked 1.1.0'

    $pkg_purge libfoo 2>'purged libfoo/1.1.0'
  }

  : wrong-state
  :
  {
    $clone_cfg

    $* libfoo 2>>/EOE != 0
      error: package libfoo does not exist in configuration cfg/
      EOE

    $* -e $src/libfoo-1.1.0 2>'using libfoo/1.1.0 (external)'

    $* libfoo 2>>EOE != 0
      error: package libfoo is unpacked
        info: expected it to be fetched
      EOE

    $pkg_purge libfoo 2>'purged libfoo/1.1.0'
  }

  : right-state
  :
  {
    $clone_cfg && $pkg_fetch libfoo/1.0.0

    $pkg_status libfoo/1.0.0 1>'libfoo fetched 1.0.0'

    $* libfoo 2>>EOE
      unpacking libfoo/1.0.0
      unpacked libfoo/1.0.0
      EOE

    $pkg_status libfoo/1.0.0 1>'libfoo unpacked 1.0.0'

    $pkg_configure libfoo        2>'configured libfoo/1.0.0'
    test    -d cfg/libfoo-1.0.0
    $pkg_disfigure libfoo        2>'disfigured libfoo/1.0.0'

    $pkg_purge libfoo 2>'purged libfoo/1.0.0'
  }

  : purge-existing
  :
  {
    $clone_cfg
    cp --no-cleanup -r $src/libfoo-1.1.0 ./

    $* --purge --existing libfoo-1.1.0 2>'using libfoo/1.1.0 (external)'

    $pkg_purge libfoo 2>'purged libfoo/1.1.0'
  }
}}

: dir-rep
:
{{
  rep_add += --type dir

  : no-repos
  :
  {
    $clone_root_cfg

    $* libfoo/1.1.0 2>>/EOE != 0
      error: configuration cfg/ has no repositories
        info: use 'bpkg rep-add' to add a repository
      EOE
  }

  : unfetched
  :
  {
    $clone_root_cfg && $rep_add $src/libfoo-1.1.0

    $* libfoo/1.1.0 2>>/EOE != 0
      error: configuration cfg/ has no available packages
        info: use 'bpkg rep-fetch' to fetch available packages list
      EOE
  }

  : unavailable
  :
  {
    $clone_root_cfg && $rep_add $src/libfoo-1.1.0 && $rep_fetch

    $* libfoo/1.0.0 2>>EOE != 0
      error: package libfoo 1.0.0 is not available
      EOE
  }

  : unavailable-dir-based
  :
  {
    $clone_root_cfg && $rep_add $rep/t1 --type pkg && $rep_fetch --trust-yes

    $* libfoo/1.0.0 2>>EOE != 0
      error: package libfoo 1.0.0 is not available from a directory-based repository
      EOE
  }

  : available
  :
  {
    $clone_root_cfg && $rep_add $src/libfoo-1.1.0 && $rep_fetch

    $* libfoo/1.1.0 2>>EOE
      using libfoo/1.1.0 (external)
      EOE

    $pkg_status libfoo 1>'libfoo unpacked 1.1.0'

    $pkg_configure libfoo  2>'configured libfoo/1.1.0'
    test    -d cfg/libfoo
    $pkg_disfigure libfoo  2>'disfigured libfoo/1.1.0'
  }
}}

: existing
:
{{
  : version-fixup
  :
  : Test that the version is populated with the snapshot information for the
  : package directory that is under the version control.
  :
  if! $remote
  {
    $clone_root_cfg

    rep = $canonicalize([dir_path] $out_git/state0)

    $* -e $rep/style-basic.git 2>>~%EOE%
      %using style-basic/1\.1\.0-a\.0\.\d+\..+ \(external\)%
      EOE
  }
}}

: hello
:
{
  $clone_cfg
  $rep_add $rep/hello && $rep_fetch --trust $cert_fp &cfg/.bpkg/certs/**
  $pkg_fetch libhello/1.0.0

  $* libhello 2>>EOE
    unpacking libhello/1.0.0
    unpacked libhello/1.0.0
    EOE

  $pkg_purge libhello 2>'purged libhello/1.0.0'
}

: fetch-cache
:
{{
  # Enable the test-specific fetch caches.
  #
  options_guard = $~/.build2
  +mkdir $options_guard
  +echo '--no-default-options' >=$options_guard/bpkg.options
  +export BPKG_FETCH_CACHE=src
  +export BPKG_FETCH_CACHE_PATH=cache

  +$cfg_create -d cfg 2>! &cfg/***

  : basics
  :
  {
    $clone_cfg && $rep_add $rep/hello

    $rep_fetch --trust $cert_fp &cache/***
    $pkg_fetch libhello/1.0.0

    $* libhello 2>>EOE
      unpacking libhello/1.0.0 (cache, shared src)
      unpacked libhello/1.0.0
      EOE

    # Verify that the source directory is cached.
    #
    test -d cache/src/libhello-1.0.0
    test -d cfg/libhello-1.0.0 != 0

    # Verify that the unpacked package is buildable.
    #
    $pkg_configure libhello 2>'configured libhello/1.0.0'
    $pkg_update libhello 2>>~%EOE%
      %(mkdir|c\+\+|ar|ld|updated).+%{9}
      EOE

    test -d cfg/libhello-1.0.0

    rm -r cfg

    $clone_cfg && $rep_add $rep/hello

    $rep_fetch --trust $cert_fp &cache/***
    $pkg_fetch libhello/1.0.0

    $* libhello 2>>EOE
      unpacking libhello/1.0.0 (cache, shared src)
      unpacked libhello/1.0.0
      EOE

    # Verify that the source directory is cached.
    #
    test -d cache/src/libhello-1.0.0
    test -d cfg/libhello-1.0.0 != 0

    # Verify that the unpacked package is buildable.
    #
    $pkg_configure libhello 2>'configured libhello/1.0.0'
    $pkg_update libhello 2>>~%EOE%
      %(mkdir|c\+\+|ar|ld|updated).+%{9}
      EOE

    test -d cfg/libhello-1.0.0

    $pkg_disfigure libhello 2>'disfigured libhello/1.0.0'
    $pkg_purge     libhello 2>'purged libhello/1.0.0'
  }
}}
