#! /usr/bin/env python

#   Copyright 2016 WebAssembly Community Group participants
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

import filecmp
import os
import shutil
import subprocess
import sys
import tempfile


def _open_archive(tarfile, tmp_dir):
  with tempfile.TemporaryFile(mode='w+') as f:
    try:
      subprocess.check_call(['tar', '-xvf', tarfile], cwd=tmp_dir, stdout=f)
    except:
      f.seek(0)
      sys.stderr.write(f.read())
      raise
  return os.listdir(tmp_dir)


def _files_same(dir1, dir2, basenames):
  diff = filecmp.cmpfiles(dir1, dir2, basenames)
  return 0 == len(diff[1] + diff[2])


def _dirs_same(dir1, dir2, basenames):
  for d in basenames:
    left = os.path.join(dir1, d)
    right = os.path.join(dir2, d)
    if not (os.path.isdir(left) and os.path.isdir(right)):
      return False
    diff = filecmp.dircmp(right, right)
    if 0 != len(diff.left_only + diff.right_only + diff.diff_files +
                diff.common_funny + diff.funny_files):
      return False
  return True


def _move_files(dirfrom, dirto, basenames):
  for f in basenames:
    from_file = os.path.join(dirfrom, f)
    to_file = os.path.join(dirto, f)
    if os.path.isfile(to_file):
      os.path.remove(to_file)
    shutil.move(from_file, to_file)


def _move_dirs(dirfrom, dirto, basenames):
    for d in basenames:
      from_dir = os.path.join(dirfrom, d)
      to_dir = os.path.join(dirto, d)
      if os.path.isdir(to_dir):
        shutil.rmtree(to_dir)
      shutil.move(from_dir, to_dir)


def untar(tarfile, outdir):
  """Returns True if untar content differs from pre-existing outdir content."""
  tmpdir = tempfile.mkdtemp()
  try:
    untared = _open_archive(tarfile, tmpdir)
    files = [f for f in untared if os.path.isfile(os.path.join(tmpdir, f))]
    dirs = [d for d in untared if os.path.isdir(os.path.join(tmpdir, d))]
    assert len(files) + len(dirs) == len(untared), 'Only files and directories'
    if _files_same(tmpdir, outdir, files) and _dirs_same(tmpdir, outdir, dirs):
      # Nothing new or different in the tarfile.
      return False
    # Some or all of the files / directories are new.
    _move_files(tmpdir, outdir, files)
    _move_dirs(tmpdir, outdir, dirs)
    return True
  finally:
    if os.path.isdir(tmpdir):
      shutil.rmtree(tmpdir)
