# Copyright (c) 2011 elego Software Solutions GmbH <info@elego.de>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

# Python module helpful for writing hook scripts.
#
# This is mostly an example for calling 'svnlook' and 'svn' from Python hooks
# and for reading simple configuration files. While it's an example, this may
# also be useful in a production environment as is.
#
# To use this, place this file next to your python hook scripts (e.g. in
# 'repos/hooks/'). To be able use these functions, you may simply write:
#   from hook_toolbox import *

# NOTE: Adjust the BIN_PATH according to your operating system, to get valid
# paths to your binaries (e.g. '/usr/bin/svnlook'):
BIN_PATH = '/usr/bin'


import sys, os, subprocess, shlex


def get_log_message(*args):
  '''Synopsis:
       get_log_message(repos, '-t', transaction)   (from pre-commit hook)
       get_log_message(repos, '-r', revision)      (from post-commit hook)
     Returns the log message as a string.
  '''
  cmd = [os.path.join(BIN_PATH, 'svnlook'), 'propget', '--revprop']
  cmd.extend(args)
  cmd.append('svn:log')
  return run(*cmd)


def get_changed_paths(*args):
  '''Synopsis:
       get_changed_paths(repos, '-t', transaction)   (from pre-commit hook)
       get_changed_paths(repos, '-r', revision)      (from post-commit hook)
     Returns the list of changed paths, relative to the repository root.
  '''
  cmd = [os.path.join(BIN_PATH, 'svnlook'), 'changed']
  cmd.extend(args)
  changes = run(*cmd)
  #print changes

  # First four chars of each svnlook output line show the kind of change.
  # The rest of the line is the complete repository path. See:
  # https://svnbook.red-bean.com/nightly/en/svn.ref.svnlook.c.changed.html
  changed_paths = [ line[4:] for line in changes.split('\n') if len(line) > 4 ]

  #print '%s:\n '%(' '.join(args)), '\n  '.join(changed_paths)
  return changed_paths


def has_path_changed(path, changed_paths):
  '''Returns True if any changed path begins with the given path.
     path: A path relative to the repos root, without leading slash.
     changed_paths: A list obtained from the function get_changed_paths().'''

  for changed_path in changed_paths:
    if changed_path.startswith(path):
      return True
  return False


def read_config(repos, filename, expected_tokens_per_line=-1):
  '''Reads the file <repos>/conf/<filename> line wise and tokenizes each
  line according to shell syntax rules. For example, a file like

   # comments & blank lines ignored

   aaa bb
   cccc "d d d" ee
   ff

  would return a list

   [ ['aaa', 'bb'],
     ['cccc', 'd d d', 'ee'],
     ['ff']                   ]

  If expected_tokens_per_line is > 0, then only the lines matching the
  given number of tokens are returned. In above example, passing
  expected_tokens_per_line=2 would yield just:

   [ ['aaa', 'bb'] ]

  Returns an empty list if no such config file exists.
  '''
  path = os.path.join(repos, 'conf', filename)
  if not os.path.exists(path):
    print('Not present:', path)
    return []

  config_lines = open(path).readlines()

  tokenized_lines = [ shlex.split(line, True) for line in config_lines ]
  tokenized_lines = [ tokens for tokens in tokenized_lines if tokens ]

  if expected_tokens_per_line < 1:
    return tokenized_lines

  matching_lines = [ tokens for tokens in tokenized_lines
                     if len(tokens) == expected_tokens_per_line ]

  if len(matching_lines) < len(tokenized_lines):
    print('*** %d syntax errors in %s' % (
             len(tokenized_lines) - len(matching_lines),
             path))

  return matching_lines


def update_working_copy(wc_path):
  if not os.path.exists(wc_path):
    print('--> *** Cannot find working copy', wc_path)
    return None
  return run(os.path.join(BIN_PATH, 'svn'), 'update', wc_path)


def run(*cmd):
  '''Call the given command & args and return what it printed to stdout.
     e.g. result = run('/usr/bin/svn', 'info', wc_dir_path) '''
  print('-->', ' '.join(cmd))
  stdout = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
  print(stdout.strip())
  return stdout

