#!/bin/sh
#  marten : Manager of image archives and temporary-containers 

set -e -u
MINC=`dirname $0`/minc
LIBEXEC=/usr/libexec/mincs
MINCFARM=$LIBEXEC/minc-farm
MINCSMGL=$LIBEXEC/minc-smuggler

usage() { # [error messages]
  test $# -ne 0 && echo "$*"
  echo "$0 - Manager of image archives and temporary-containers"
  echo "Usage: $0 [action] <command> [argument...]"
  echo " commands:"
  echo "    lc or list          List containers"
  echo "    li or images        List images"
  echo "    rm UUID             Remove specified container"
  echo "    rmi UUID            Remove specified image"
  echo "    pull [USER/]NAME[:TAG] Import a docker image from Dockerhub"
  echo "    import DIR|IMAGE    Import DIR or Dokcer IMAGE as an image"
  echo "    commit UUID         Commit specified container to image"
  echo "    rename UUID NAME    Rename given UUID container to NAME"
  echo "    renamei UUID NAME   Rename given UUID image to NAME"
  echo "    tag UUID NAME       Alias of renamei"
  echo " options:"
  echo "    -h or --help        Show this help"
  echo "    --long              Show long ID with li/lc commands"

  exit $#
}

do_list() { # command [opts..]
  cmd=$1
  shift 1
  export MINC_LONG_ID=
  while [ $# -ne 0 ]; do
    case $1 in
      --long|-l)
      export MINC_LONG_ID=1
      ;;
    esac
    shift 1
  done
  $MINCFARM $cmd
}

import_docker() {
  FILE=$1
  OPT=
  case $FILE in
  *tar.gz) OPT="-z" ;;
  *tar.bz) OPT="-j" ;;
  esac
  NAME=`tar $OPT -xf $FILE repositories -O | jq -r "keys[0]" `
  IMAGE=`tar $OPT -xf $FILE repositories -O | jq -r ".[] | .[]" `
  if [ -z "$NAME" -o -z "$IMAGE" ]; then
    usage "$FILE is not a docker image"
  fi
  echo "Importing image: $NAME"

  IDS=
  ID=$IMAGE
  while [ "$ID" -a "$ID" != "null" ]; do
    IDS="$ID $IDS"
    ID=`tar $OPT -xf $FILE $ID/json -O | jq -r ".parent"`
  done
  for id in $IDS; do
    tmproot=`mktemp -d`
    tar $OPT -xf $FILE $id/layer.tar -O | tar -x -C $tmproot
    export MINC_IMPORT_UUID=$id
    if [ $id = $IMAGE ]; then
      export MINC_IMPORT_NAME=$NAME
    fi
    $MINCFARM import $tmproot
    export MINC_BASE_UUID=$id
    rm -rf $tmproot
  done
  exit 0
}

pull_docker() {
  TAG=${1##*:}
  NAME=${1%%:*}
  USER=${NAME%%/*}
  test -z "$NAME" && usage
  test -z "$TAG" -o "$TAG" = "$NAME" && TAG=latest
  test -z "$USER" -o "$USER" = "$NAME" && NAME="library/$NAME"
  echo "Trying to pull $NAME:$TAG"
  TMPDIR=`mktemp -d backyard-XXXXXX`
  $MINCSMGL $NAME $TAG $TMPDIR
  echo "Pulled. Importing image: $NAME"
  LASTID=`cat $TMPDIR/manifest.json | jq -r .layers[].digest | tail -n 1`
  LASTID=${LASTID##*:}
  if [ "$SQUASH" = "true" ] ; then
    tmproot=`mktemp -d $TMPDIR/layer-root-XXXXXX`
    cat $TMPDIR/manifest.json | jq -r .layers[].digest | while read d; do
      ID=${d##*:}
      tar --force-local -xf $TMPDIR/$d -C $tmproot
      cd $tmproot
      for whiteout in `find . -name '*.wh.*'` ; do
        deletedFile=`echo $whiteout | sed -e "s|\.wh\.||"`
        rm -rf $whiteout
        rm -rf $deletedFile
      done
      cd ../..
      export MINC_IMPORT_UUID=$ID
    done
    export MINC_IMPORT_NAME=${NAME##*/}
    $MINCFARM import $tmproot
  else
    cat $TMPDIR/manifest.json | jq -r .layers[].digest | while read d; do
      tmproot=`mktemp -d $TMPDIR/layer-root-XXXXXX`
      ID=${d##*:}
      tar --force-local -xf $TMPDIR/$d -C $tmproot
      export MINC_IMPORT_UUID=$ID
      test "$ID" = "$LASTID" && export MINC_IMPORT_NAME=${NAME##*/}
      $MINCFARM import $tmproot
      export MINC_BASE_UUID=$ID
      rm -rf $tmproot
    done
  fi

  rm -rf $TMPDIR
  exit 0
}


test $# -eq 0 && usage
if [ "$1" = "--debug" ] ; then
  export MINC_DEBUG=1
  set -x
  shift 1
fi
test $# -eq 0 && usage
cmd=$1
shift 1
case $cmd in
  lc|list|li|images)
  do_list $cmd $*
  ;;
  pull)
  if [ "$1" = "--squash" ] ; then SQUASH=true ; shift ; else SQUASH=false ; fi
  pull_docker $1
  ;;
  import)
  test -d $1 || import_docker $1
  $MINCFARM import $1
  ;;
  commit)
  $MINCFARM commit $1
  ;;
  rm|rmi)
  $MINCFARM $cmd $1
  ;;
  rename|renamei|tag)
  test $cmd = "rename" && cmd="dir" || cmd="idir"
  UUID=$1
  NAME=$2
  test -z "$UUID" -o -z "$NAME" && usage "No uuid/name was given."
  DIR=`$MINCFARM $cmd $UUID`
  if [ -d "$DIR" ]; then
    $MINCFARM $cmd $NAME > /dev/null && usage "$NAME is already used."
    test $cmd = "idir" && ( echo "$NAME" > $DIR/name ) || \
        ( echo "$NAME" > $DIR/utsname)
  else
    usage "$UUID is not found."
  fi
  ;;
  *)
  usage
esac

