blob: 061c5c501465d6f1ec2a3ac2a11832898ccadd08 [file] [log] [blame]
#!/usr/bin/env python
# To do:
# 1) Switch to using the Subversion Python bindings.
#
# $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 getopt
import fnmatch
import os
import re
import sys
# The default path to the Subversion configuration file.
SVN_CONFIG_FILENAME = os.path.expandvars('$HOME/.subversion/config')
# The name of Subversion's private directory in working copies.
SVN_WC_ADM_DIR_NAME = '.svn'
# The name this script was invoked as.
PROGNAME = os.path.basename(sys.argv[0])
def usage():
print("""This script reads the auto-properties defined in the file
'%s'
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.
Usage:
%s [options] [WC_PATH]
where WC_PATH is the path to a working copy.
If WC_PATH is not specified, '.' is assumed.
Valid options are:
--help, -h : Print this help text.
--config ARG : Read the Subversion config file at path ARG
instead of '%s'.
""" % (SVN_CONFIG_FILENAME, PROGNAME, SVN_CONFIG_FILENAME))
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 not descend into a .svn directory.
try:
filenames.remove(SVN_WC_ADM_DIR_NAME)
except ValueError:
pass
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))
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], 'h', ['help', 'config='])
except getopt.GetoptError as e:
usage()
return 1
config_filename = None
for (o, a) in opts:
if o == '-h' or o == '--help':
usage()
return 0
elif o == '--config':
config_filename = os.path.abspath(a)
if not config_filename:
config_filename = SVN_CONFIG_FILENAME
if len(args) == 0:
wc_path = '.'
elif len(args) == 1:
wc_path = args[0]
else:
usage()
print("Too many arguments: %s" % ' '.join(args))
return 1
try:
fd = file(config_filename)
except IOError:
print("Cannot open svn configuration file '%s' for reading: %s" \
% (config_filename, sys.exc_value.strerror))
return 1
autoprop_lines = get_autoprop_lines(fd)
fd.close()
autoprop_lines = process_autoprop_lines(autoprop_lines)
os.path.walk(wc_path, filter_walk, autoprop_lines)
if __name__ == '__main__':
sys.exit(main())