#!/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: http://svn.collab.net/repos/svn/branches/1.6.x/contrib/client-side/svn_apply_autoprops.py $ # $LastChangedRevision: 20787 $ # $LastChangedDate: 2006-07-20 03:41:28 +0000 (Thu, 20 Jul 2006) $ # $LastChangedBy: blair $ # # Copyright (C) 2005,2006 Blair Zajac # # 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) 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())