#!/usr/bin/env python
#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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 sys
import os
import getpass
from svn import client, ra, core

def printer(segment, pool):
  path = segment.path is not None and segment.path or "(null)"
  print("r%d-r%d: %s" % (segment.range_start, segment.range_end, path))


def parse_args(args):
  argc = len(sys.argv)

  # parse the target URL and optional peg revision
  path_pieces = args[0].split('@')
  if len(path_pieces) > 1:
    peg_revision = int(path_pieces[-1])
    assert peg_revision >= 0
    url = '@'.join(path_pieces[:-1])
  else:
    peg_revision = core.SVN_INVALID_REVNUM
    url = path_pieces[0]
  url = core.svn_path_canonicalize(url)

  # parse the revision range, if any
  if argc > 2:
    rev_pieces = args[1].split(':')
    num_revs = len(rev_pieces)
    assert num_revs < 3
    if num_revs == 2:
      start_revision = int(rev_pieces[0])
      end_revision = int(rev_pieces[1])
    else:
      start_revision = end_revision = int(rev_pieces[0])
    assert(start_revision >= 0)
    assert(end_revision >= 0)
  else:
    start_revision = peg_revision
    end_revision = 0

  # validate
  if start_revision >= 0 \
     and end_revision >= 0 \
     and end_revision > start_revision:
    raise Exception("End revision must not be younger than start revision")
  if peg_revision >= 0 \
     and start_revision >= 0 \
     and start_revision > peg_revision:
    raise Exception("Start revision must not be younger than peg revision")

  return url, peg_revision, start_revision, end_revision


def prompt_func_ssl_unknown_cert(realm, failures, cert_info, may_save, pool):
  print( "The certificate details are as follows:")
  print("--------------------------------------")
  print("Issuer     : " + str(cert_info.issuer_dname))
  print("Hostname   : " + str(cert_info.hostname))
  print("ValidFrom  : " + str(cert_info.valid_from))
  print("ValidUpto  : " + str(cert_info.valid_until))
  print("Fingerprint: " + str(cert_info.fingerprint))
  print("")
  ssl_trust = core.svn_auth_cred_ssl_server_trust_t()
  if may_save:
    choice = raw_input( "accept (t)temporarily   (p)permanently: ")
  else:
    choice = raw_input( "(r)Reject or accept (t)temporarily: ")
  if choice[0] == "t" or choice[0] == "T":
    ssl_trust.may_save = False
    ssl_trust.accepted_failures = failures
  elif choice[0] == "p" or choice[0] == "P":
    ssl_trust.may_save = True
    ssl_trust.accepted_failures = failures
  else:
    ssl_trust = None
  return ssl_trust

def prompt_func_simple_prompt(realm, username, may_save, pool):
  username = raw_input("username: ")
  password = getpass.getpass(prompt="password: ")
  simple_cred = core.svn_auth_cred_simple_t()
  simple_cred.username = username
  simple_cred.password = password
  simple_cred.may_save = False
  return simple_cred

def prompt_func_gnome_keyring_prompt(keyring, pool):
  return getpass.getpass(prompt="Password for '%s' GNOME keyring: " % keyring)

def main():
  try:
    url, peg_revision, start_revision, end_revision = parse_args(sys.argv[1:])
  except Exception as e:
    sys.stderr.write("""Usage: %s URL[@PEG-REV] [START-REV[:END-REV]]

Trace the history of URL@PEG-REV, printing the location(s) of its
existence between START-REV and END-REV.  If START-REV is not
provided, the entire history of URL@PEG-REV back to its origin will be
displayed.  If provided, START-REV must not be younger than PEG-REV.
If END-REV is provided, it must not be younger than START-REV.

(This is a wrapper around Subversion's svn_ra_get_location_segments() API.)

ERROR: %s
""" % (os.path.basename(sys.argv[0]), str(e)))
    sys.exit(1)

  core.svn_config_ensure(None)
  ctx = client.svn_client_create_context()
  ctx.config = core.svn_config_get_config(None)

  # Make sure that these are at the start of the list, so passwords from
  # gnome-keyring / kwallet are checked before asking for new passwords.
  providers = core.svn_auth_get_platform_specific_client_providers(ctx.config['config'], None)
  providers.extend([
    client.get_simple_provider(),
    core.svn_auth_get_ssl_server_trust_file_provider(),
    core.svn_auth_get_simple_prompt_provider(prompt_func_simple_prompt, 2),
    core.svn_auth_get_ssl_server_trust_prompt_provider(prompt_func_ssl_unknown_cert),
    client.get_username_provider(),
    client.get_ssl_server_trust_file_provider(),
    client.get_ssl_client_cert_file_provider(),
    client.get_ssl_client_cert_pw_file_provider(),
  ])

  ctx.auth_baton = core.svn_auth_open(providers)

  if hasattr(core, 'svn_auth_set_gnome_keyring_unlock_prompt_func'):
    core.svn_auth_set_gnome_keyring_unlock_prompt_func(ctx.auth_baton, prompt_func_gnome_keyring_prompt)

  ra_callbacks = ra.callbacks_t()
  ra_callbacks.auth_baton = ctx.auth_baton
  ra_session = ra.open(url, ra_callbacks, None, ctx.config)
  ra.get_location_segments(ra_session, "", peg_revision,
                           start_revision, end_revision, printer)

if __name__ == "__main__":
  main()
