#!/usr/bin/env python3
# Copyright (C) 2013 The Android Open Source Project
#
# 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.

from __future__ import print_function

from hashlib import sha1
from optparse import OptionParser
from os import environ, link, makedirs, path, remove
import shutil
from subprocess import check_call, CalledProcessError
from sys import stderr
from util import hash_file, resolve_url
from zipfile import ZipFile, BadZipfile, LargeZipFile

GERRIT_HOME = path.expanduser('~/.gerritcodereview')
CACHE_DIR = environ.get(
    'GERRIT_CACHE_HOME',
    path.join(GERRIT_HOME, 'bazel-cache', 'downloaded-artifacts'))

LOCAL_PROPERTIES = 'local.properties'


def safe_mkdirs(d):
  if path.isdir(d):
    return
  try:
    makedirs(d)
  except OSError as err:
    if not path.isdir(d):
      raise err


def download_properties(root_dir):
  """ Get the download properties.

  First tries to find the properties file in the given root directory,
  and if not found there, tries in the Gerrit settings folder in the
  user's home directory.

  Returns a set of download properties, which may be empty.

  """
  p = {}
  local_prop = path.join(root_dir, LOCAL_PROPERTIES)
  if not path.isfile(local_prop):
    local_prop = path.join(GERRIT_HOME, LOCAL_PROPERTIES)
  if path.isfile(local_prop):
    try:
      with open(local_prop) as fd:
        for line in fd:
          if line.startswith('download.'):
            d = [e.strip() for e in line.split('=', 1)]
            name, url = d[0], d[1]
            p[name[len('download.'):]] = url
    except OSError:
      pass
  return p


def cache_entry(args):
  if args.v:
    h = args.v
  else:
    h = sha1(args.u.encode('utf-8')).hexdigest()
  name = '%s-%s' % (path.basename(args.o), h)
  return path.join(CACHE_DIR, name)

opts = OptionParser()
opts.add_option('-o', help='local output file')
opts.add_option('-u', help='URL to download')
opts.add_option('-v', help='expected content SHA-1')
opts.add_option('-x', action='append', help='file to delete from ZIP')
opts.add_option('--exclude_java_sources', action='store_true')
args, _ = opts.parse_args()

root_dir = args.o
while root_dir and path.dirname(root_dir) != root_dir:
  root_dir, n = path.split(root_dir)
  if n == 'WORKSPACE':
    break

redirects = download_properties(root_dir)
cache_ent = cache_entry(args)
src_url = resolve_url(args.u, redirects)

if not path.exists(cache_ent):
  try:
    safe_mkdirs(path.dirname(cache_ent))
  except OSError as err:
    print('error creating directory %s: %s' %
          (path.dirname(cache_ent), err), file=stderr)
    exit(1)

  print('Download %s' % src_url, file=stderr)
  try:
    check_call(['curl', '--proxy-anyauth', '-ksSfLo', cache_ent, src_url])
  except OSError as err:
    print('could not invoke curl: %s\nis curl installed?' % err, file=stderr)
    exit(1)
  except CalledProcessError as err:
    print('error using curl: %s' % err, file=stderr)
    exit(1)

if args.v:
  have = hash_file(sha1(), cache_ent).hexdigest()
  if args.v != have:
    print((
      '%s:\n' +
      'expected %s\n' +
      'received %s\n') % (src_url, args.v, have), file=stderr)
    try:
      remove(cache_ent)
    except OSError as err:
      if path.exists(cache_ent):
        print('error removing %s: %s' % (cache_ent, err), file=stderr)
    exit(1)

exclude = []
if args.x:
  exclude = exclude + args.x
if args.exclude_java_sources:
  try:
    with ZipFile(cache_ent, 'r') as zf:
      for n in zf.namelist():
        if n.endswith('.java'):
          exclude.append(n)
  except (BadZipfile, LargeZipFile) as err:
    print('error opening %s: %s' % (cache_ent, err), file=stderr)
    exit(1)

safe_mkdirs(path.dirname(args.o))
if exclude:
  try:
    shutil.copyfile(cache_ent, args.o)
  except (shutil.Error, IOError) as err:
    print('error copying to %s: %s' % (args.o, err), file=stderr)
    exit(1)
  try:
    check_call(['zip', '-d', args.o] + exclude)
  except CalledProcessError as err:
    print('error removing files from zip: %s' % err, file=stderr)
    exit(1)
else:
  try:
    link(cache_ent, args.o)
  except OSError as err:
    try:
      shutil.copyfile(cache_ent, args.o)
    except (shutil.Error, IOError) as err:
      print('error copying to %s: %s' % (args.o, err), file=stderr)
      exit(1)
