#!/usr/bin/env bash

set -eu -o pipefail
shopt -s dotglob nullglob

failwith() { echo "error: $*" 1>&2; exit 1; }

if [[ "$#" -ne 1 ]]; then failwith "Usage: $0 <other-dir>"; fi
OTHER="$1"; shift
if [[ ! -d "$OTHER" ]]; then failwith "$OTHER is not a directory"; fi
other="$(cd "$OTHER"; pwd)"
if [[ "$(pwd)" = "$other" ]]; then failwith "Cannot compare with itself!"; fi

show() { printf "%q: %s\n" "$1" "$2"; }

run() ( # relative-dir filename
  o="$other/$1"
  if [[ ! -e "$o" && ! -L "$o" ]]; then
    show "$1" "missing in $OTHER"
  elif [[ -L "$1" ]]; then
    if [[ ! -L "$o" ]]; then
      show "$1" "symlink here, but not in $OTHER"
    elif [[ "$(readlink "$1")" = "$(readlink "$o")" ]]; then
      show "$1" "equal symlinks => removing!"
      rm -f -- "$1"
    else
      show "$1" "different symlinks"
    fi
  elif [[ -f "$1" ]]; then
    if [[ -L "$o" ]]; then
      show "$1" "file here, but symlink in $OTHER"
    elif [[ ! -f "$o" ]]; then
      show "$1" "file here, but not in $OTHER"
    elif [[ ! -r "$o" ]]; then
      show "$1" "not readable in $OTHER"
    elif cmp -s -- "$1" "$o"; then
      show "$1" "equal => removing!"
      rm -f -- "$1"
    else
      show "$1" "different"
    fi
  elif [[ -d "$1" ]]; then
    for f in "$1/"*; do run "$f"; done
    if rmdir -- "$1" > /dev/null 2>&1; then
      show "$1" "empty => removing!"
    fi
  else
    show "$1" "missing/unknown file"
  fi
)

for f in *; do run "$f"; done
