* subversion/svn/main.c
[svn.git] / contrib / client-side / svn_apply_autoprops.py
blob29befaaa979a4df8da3e42073321cc643aef96df
1 #!/usr/bin/env python
3 # This script reads the auto-properties defined in the
4 # $HOME/.subversion/config file and applies them recursively to all
5 # the files and directories in the current working copy. It may
6 # behave differently than the Subversion command line; where the
7 # subversion command line may only apply a single matching
8 # auto-property to a single pathname, this script will apply all
9 # matching lines to a single pathname.
11 # To do:
12 # 1) Switch to using the Subversion Python bindings.
13 # 2) Allow a command line option to specify the configuration file to
14 # load the auto-properties from.
16 # $HeadURL$
17 # $LastChangedRevision$
18 # $LastChangedDate$
19 # $LastChangedBy$
21 # Copyright (C) 2005,2006 Blair Zajac <blair@orcaware.com>
23 # This script is free software; you can redistribute it and/or modify
24 # it under the terms of the GNU General Public License as published by
25 # the Free Software Foundation; either version 2 of the License, or
26 # (at your option) any later version.
28 # This script is distributed in the hope that it will be useful, but
29 # WITHOUT ANY WARRANTY; without even the implied warranty of
30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
31 # General Public License for more details.
33 # A copy of the GNU General Public License can be obtained by writing
34 # to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
35 # Boston, MA 02111-1307 USA.
37 import fnmatch
38 import os
39 import re
40 import sys
42 # The path to the Subversion configuration file.
43 SVN_CONFIG_FILENAME = '$HOME/.subversion/config'
45 # The name of Subversion's private directory in working copies.
46 SVN_WC_ADM_DIR_NAME = '.svn'
48 def get_autoprop_lines(fd):
49 lines = []
50 reading_autoprops = 0
52 re_start_autoprops = re.compile('^\s*\[auto-props\]\s*')
53 re_end_autoprops = re.compile('^\s*\[\w+\]\s*')
55 for line in fd.xreadlines():
56 if reading_autoprops:
57 if re_end_autoprops.match(line):
58 reading_autoprops = 0
59 continue
60 else:
61 if re_start_autoprops.match(line):
62 reading_autoprops = 1
63 continue
65 if reading_autoprops:
66 lines += [line]
68 return lines
70 def process_autoprop_lines(lines):
71 result = []
73 for line in lines:
74 # Split the line on the = separating the fnmatch string from the
75 # properties.
76 try:
77 (fnmatch, props) = line.split('=', 1)
78 except ValueError:
79 continue
81 # Remove leading and trailing whitespace from the fnmatch and
82 # properties.
83 fnmatch = fnmatch.strip()
84 props = props.strip()
86 # Create a list of property name and property values. Remove all
87 # leading and trailing whitespce from the propery names and
88 # values.
89 props_list = []
90 for prop in props.split(';'):
91 prop = prop.strip()
92 if not len(prop):
93 continue
94 try:
95 (prop_name, prop_value) = prop.split('=', 1)
96 prop_name = prop_name.strip()
97 prop_value = prop_value.strip()
98 except ValueError:
99 prop_name = prop
100 prop_value = '*'
101 if len(prop_name):
102 props_list += [(prop_name, prop_value)]
104 result += [(fnmatch, props_list)]
106 return result
108 def filter_walk(autoprop_lines, dirname, filenames):
109 # Do no descend into directories that do not have a .svn directory.
110 try:
111 filenames.remove(SVN_WC_ADM_DIR_NAME)
112 except ValueError:
113 filenames = []
114 print "Will not process files in '%s' because it does not have a '%s' " \
115 "directory." \
116 % (dirname, SVN_WC_ADM_DIR_NAME)
117 return
119 filenames.sort()
121 # Find those filenames that match each fnmatch.
122 for autoprops_line in autoprop_lines:
123 fnmatch_str = autoprops_line[0]
124 prop_list = autoprops_line[1]
126 matching_filenames = fnmatch.filter(filenames, fnmatch_str)
127 if not matching_filenames:
128 continue
130 for prop in prop_list:
131 command = ['svn', 'propset', prop[0], prop[1]]
132 for f in matching_filenames:
133 command += ["%s/%s" % (dirname, f)]
135 status = os.spawnvp(os.P_WAIT, 'svn', command)
136 if status:
137 print 'Command "%s" failed with exit status %s' \
138 % (command, status)
139 sys.exit(1)
141 def main():
142 config_filename = os.path.expandvars(SVN_CONFIG_FILENAME)
143 try:
144 fd = file(config_filename)
145 except IOError:
146 print "Cannot open svn configuration file '%s' for reading: %s" \
147 % (config_filename, sys.exc_value.strerror)
149 autoprop_lines = get_autoprop_lines(fd)
151 fd.close()
153 autoprop_lines = process_autoprop_lines(autoprop_lines)
155 os.path.walk('.', filter_walk, autoprop_lines)
157 if __name__ == '__main__':
158 sys.exit(main())