#!/usr/bin/env python

# This script reads the auto-properties defined in the
# $HOME/.subversion/config file and applies them recursively to all
# the files and directories in the current working copy.  It may
# behave differently than the Subversion command line; where the
# subversion command line may only apply a single matching
# auto-property to a single pathname, this script will apply all
# matching lines to a single pathname.
#
# To do:
# 1) Switch to using the Subversion Python bindings.
# 2) Allow a command line option to specify the configuration file to
#    load the auto-properties from.
#
# $HeadURL$
# $LastChangedRevision$
# $LastChangedDate$
# $LastChangedBy$
#
# Copyright (C) 2005,2006 Blair Zajac <blair@orcaware.com>
#
# This script is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This script is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# A copy of the GNU General Public License can be obtained by writing
# to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307 USA.

import fnmatch
import os
import re
import sys

# The path to the Subversion configuration file.
SVN_CONFIG_FILENAME = '$HOME/.subversion/config'

# The name of Subversion's private directory in working copies.
SVN_WC_ADM_DIR_NAME = '.svn'

def get_autoprop_lines(fd):
  lines = []
  reading_autoprops = 0

  re_start_autoprops = re.compile('^\s*\[auto-props\]\s*')
  re_end_autoprops = re.compile('^\s*\[\w+\]\s*')

  for line in fd.xreadlines():
    if reading_autoprops:
      if re_end_autoprops.match(line):
        reading_autoprops = 0
        continue
    else:
      if re_start_autoprops.match(line):
        reading_autoprops = 1
        continue

    if reading_autoprops:
      lines += [line]

  return lines

def process_autoprop_lines(lines):
  result = []

  for line in lines:
    # Split the line on the = separating the fnmatch string from the
    # properties.
    try:
      (fnmatch, props) = line.split('=', 1)
    except ValueError:
      continue

    # Remove leading and trailing whitespace from the fnmatch and
    # properties.
    fnmatch = fnmatch.strip()
    props = props.strip()

    # Create a list of property name and property values.  Remove all
    # leading and trailing whitespce from the propery names and
    # values.
    props_list = []
    for prop in props.split(';'):
      prop = prop.strip()
      if not len(prop):
        continue
      try:
        (prop_name, prop_value) = prop.split('=', 1)
        prop_name = prop_name.strip()
        prop_value = prop_value.strip()
      except ValueError:
        prop_name = prop
        prop_value = '*'
      if len(prop_name):
        props_list += [(prop_name, prop_value)]

    result += [(fnmatch, props_list)]

  return result

def filter_walk(autoprop_lines, dirname, filenames):
  # Do no descend into directories that do not have a .svn directory.
  try:
    filenames.remove(SVN_WC_ADM_DIR_NAME)
  except ValueError:
    filenames = []
    print "Will not process files in '%s' because it does not have a '%s' " \
          "directory." \
          % (dirname, SVN_WC_ADM_DIR_NAME)
    return

  filenames.sort()

  # Find those filenames that match each fnmatch.
  for autoprops_line in autoprop_lines:
    fnmatch_str = autoprops_line[0]
    prop_list = autoprops_line[1]

    matching_filenames = fnmatch.filter(filenames, fnmatch_str)
    matching_filenames = [f for f in matching_filenames \
      if not os.path.islink(os.path.join(dirname, f))]
    if not matching_filenames:
      continue

    for prop in prop_list:
      command = ['svn', 'propset', prop[0], prop[1]]
      for f in matching_filenames:
        command += ["%s/%s" % (dirname, f)]

      status = os.spawnvp(os.P_WAIT, 'svn', command)
      if status:
        print 'Command "%s" failed with exit status %s' \
              % (command, status)
        sys.exit(1)

def main():
  config_filename = os.path.expandvars(SVN_CONFIG_FILENAME)
  try:
    fd = file(config_filename)
  except IOError:
    print "Cannot open svn configuration file '%s' for reading: %s" \
          % (config_filename, sys.exc_value.strerror)

  autoprop_lines = get_autoprop_lines(fd)

  fd.close()

  autoprop_lines = process_autoprop_lines(autoprop_lines)

  os.path.walk('.', filter_walk, autoprop_lines)

if __name__ == '__main__':
  sys.exit(main())
