#!/bin/sh

# Copyright 2015-2021 Yury Gribov
# 
# Use of this source code is governed by MIT license that can be
# found in the LICENSE.txt file.

# Packs files to archive OUT. Format is determined from extension of OUT.
# For details run without arguments.

set -eu

error() {
  echo >&2 "$(basename $0): error: $@"
  exit 1
}

warn() {
  echo >&2 "$(basename $0): warning: $@"
}

check_prog() {
  for p in "$@"; do
    if ! which "$p" > /dev/null 2>&1; then
      error "your system is missing program '$p'" \
        "which is required to pack this type of file"
    fi
  done
}

isemptydir() {
  #test $(ls -A "$1" | wc -l) = 0
  test -d "$1" && test $(find "$1" -maxdepth 0 -empty)
}

strip_ext() {
  # Handle things like glibc-2.20.tar.bz2
  noext="${1%.*}"
  noext="${noext%.tar}"
  echo "$noext"
}

print_help_and_exit() {
  cat <<EOF
Syntax: $me OUT FILE..
Puts FILEs to archive OUT; type of archive is based on extension OUT
(e.g. tar+bzip2 for .tar.bz2 or .tbz2).

Supported archives: .tar*, .zip, .7z, .rar.

Example:
  $ pk my.tar.gz 1.txt 2.txt
  $ upk my.tar.gz
  $ ls my/
  1.txt 2.txt
EOF
  exit 1
}

me=$(basename $0)

curdir="$PWD"

case "${1:-h}" in
-h | --help)
  print_help_and_exit
  ;;
esac

TMP=$me.$$.tmp
mkdir -p $TMP
trap "rm -rf $TMP" EXIT INT TERM

if ! isemptydir $TMP; then
  error "cowardly refusing to clear original contents of $TMP"
fi

if test $# -lt 2; then
  error 'no inputs'
fi

dst="$1"
shift

base_dst=$(basename "$dst")
root=$(strip_ext "$base_dst")

# Detect situations where it makes sense to unnest subfolder
# e.g. glibc-2.20/glibc-2.20
if test $# -eq 1 -a $(basename "$1") = $root; then
  test -e $1 || error "File (or directory) $1 does not exist"
  cp -r "$1" "$TMP"
else
  mkdir -p "$TMP/$root"
  for src; do
    test -e $src || error "File (or directory) $src does not exist"
    cp -r "$src" "$TMP/$root"
  done
fi

cd $TMP

# Pack
case "$dst" in
  # We ignore archives with non-trivial meta-info
  # (.deb, .rpm, .jar, etc.).
  *.a)
    check_prog ar
    ar rcs "$base_dst" "$root"
    ;;
  *.ar)
    check_prog ar
    ar rc "$base_dst" "$root"
    ;;
  *.rar)
    check_prog rar
    rar a "$base_dst" "$root"
    ;;
  *.tar)
    check_prog tar
    tar cf "$base_dst" "$root"
    ;;
  *.tar.gz | *.tgz)
    check_prog tar gzip
    tar czf "$base_dst" "$root"
    ;;
  *.tar.bz2 | *.tbz2)
    check_prog tar bzip2
    tar cjf "$base_dst" "$root"
    ;;
  *.tar.lz | *.tlz)
    check_prog tar lzip
    tar --lzip cf "$base_dst" "$root"
    ;;
  *.tar.xz | *.txz)
    check_prog tar xz
    tar cJf "$base_dst" "$root"
    ;;
  *.zip)
    check_prog zip
    zip -r "$base_dst" "$root"
     ;;
  *.7z)
    check_prog 7zr
    7zr a "$base_dst" "$root"
    ;;
  *.lz | *.lzip | *.lzma)
    check_prog lzip
    lzip -o "$base_dst" "$root"
    ;;
  *)
    error "unsupported file format: $dst"
    ;;
esac

cd "$curdir"

mv "$TMP/$base_dst" "$dst"

