#!/usr/bin/env bash

source "$(dirname $0)/../dokku_common"

dokku_restore_timestamps() {
  perl - "$1" <<"EOF"
my $commit = $ARGV[0];

$commit = 'HEAD' unless $commit;

# git a list of access times and files
my @logbook = `git whatchanged --pretty=%at $commit`;

my %seen;
my $timestamp;
my $filename;
foreach (@logbook) {
    next if /^$/; # skip emtpy lines
    if (/^:/) {
        chomp ($filename = (split /\t/)[1]);
        next if $seen{$filename};
        utime($timestamp, $timestamp, $filename);
        $seen{$filename} = 1;
    } else {
        chomp ($timestamp = $_);
    }
}
EOF
}

dokku_build_app_from_git() {
    verify_app_name "$1"
    verify_max_args "2" "$@"
    REV="$2"

    # delete directory on return
    TMP_WORK_DIR="$(mktemp -d)"
    trap "rm -rf \"$TMP_WORK_DIR\"" RETURN

    # clone git repository
    chmod 755 "$TMP_WORK_DIR"
    unset GIT_DIR GIT_WORK_TREE
    pushd "$TMP_WORK_DIR" > /dev/null
    git clone "$DOKKU_ROOT/$APP" "$TMP_WORK_DIR" > /dev/null
    git config advice.detachedHead false
    git checkout "$REV" > /dev/null
    git submodule update --init --recursive > /dev/null

    # Build using either Dockerfile
    if [[ -f "Dockerfile" ]]; then
      info "Building $APP using Dockerfile..."
      dokku_restore_timestamps "$REV"
      find -name .git -prune -exec rm -rf {} \; > /dev/null
      docker build -t "$IMAGE_GENERIC:build" .
      pluginhook pre-build "$APP" "$REV" "dockerfile"
      pluginhook post-build "$APP" "$REV" "dockerfile"
    else
      # or buildstep (heroku-style)
      info "Building $APP using buildstep..."

      find -name .git -prune -exec rm -rf {} \; > /dev/null
      tar c . | docker run -i -a stdin "$BUILDSTEP_IMAGE" /bin/bash \
                        -c "mkdir -p /app && tar -xC /app" | commit_image "$IMAGE_GENERIC:build"

      pluginhook pre-build "$APP" "$REV" "buildstep"
      DOCKER_ARGS="$(: | pluginhook docker-args "$APP" build)"
      # start data container for cache
      docker run -d -v "/cache" --name="$APP_CACHE_NAME" \
                busybox "exit 0" 1>/dev/null 2>/dev/null || true
      # link volumes from data container
      docker run -i -a stdin --volumes-from="$APP_CACHE_NAME" \
                  $DOCKER_ARGS \
                  "$IMAGE_GENERIC:build" \
                  /build/builder | attach_and_commit_image "$IMAGE_GENERIC:build"

      pluginhook post-build "$APP" "$REV" "buildstep"
    fi

    dokku release "$APP"
    dokku deploy "$APP"

    # Do cleanup only if everything finished!
    flock -n "$DOKKU_ROOT/cleanup.lock" dokku cleanup
}

case "$1" in
  rebuild)
    verify_app_name "$2"
    verify_max_args 3 "$@"

    if [[ $# -ge 3 ]]; then
      REF="$3"
    elif [[ -f "$APP_DIR/refs/heads/master" ]]; then
      REF="$(cat "$APP_DIR/refs/heads/master")"
    else
      fail "$APP: No refs/heads/master found"
    fi
    
    dokku_build_app_from_git "$APP" "$REF" | sed -u "s/^/"$'\e[1G'"/"
    ;;

  rebuild:all)
    verify_max_args 1 "$@"

    for app in $(ls -d $DOKKU_ROOT/*/ 2>/dev/null); do
      if [[ -f "$app/refs/heads/master" ]]; then
        dokku rebuild "$(basename "$app")"
      fi
    done
    ;;

  help)
    cat && cat<<EOF
    rebuild <app>                                   Rebuild an app
    rebuild:all                                     Rebuild all apps
EOF
  ;;

esac
