Repository Dictated Configuration Via Inheritable Properties
Many software development shops of non-trivial size desire to have (and to the extent possible, to enforce) a uniform configuration environment among the various clients which commit to their repositories. Although these shops may have some ability to control the environment on the client machines (dictating software versions, etc), expecting humans to consistently set and maintain various runtime configuration parameters in accordance with corporate policy and on every repository-accessing client computer is both error-prone and unscalable.
Subversion already provides the means of enforcing much (but not all) of this configuration through the hook script mechanism, but at best this can only punish non-compliant client behavior and clumsily recommend configuration changes (which, again, a human must implement on their client computer). An administrator could save a good deal of time and frustration if they could set a special configuration property on the root 1 of their repository which well-behaved clients (treating the special configuration property as inheritable) would use to override the user's local config file settings.
"Wait, this sounds familiar..."
This effort started life as an alternative approach to the server dictated configuration ideas described in http://wiki.apache.org/subversion/ServerDictatedConfiguration and as such a quick read of that original design is suggested. If you've already read that a lot of this will sound familiar since the goals are essentially the same.
Two new Subversion reserved properties, "svn:auto-props" and "svn:global-ignores", will provide additional configuration information that overrides/extends the settings found in the user's run-time configuration.
This "svn:auto-props" property will (no surprise!) override/extend the auto-props configuration settings which dictate the properties which are automatically set on newly added or imported files. Unlike traditional auto-props, which can be disabled in the run-time config (i.e. "enable-auto-props = no") or via the --config-option option, svn:auto-props are active even when configuration auto-props are not. The exception to this is the --no-auto-props option, which disregards all auto-props.
The "svn:global-ignores" property will extend the global-ignores configuration settings and the existing svn:ignore property, both of which define file patterns that are ignored by the svn status, import, and add subcommands. The new ignore patterns provided by this property can be disregarded with the --no-ignore option.
This Really isn't "Dictated"
The configuration dictated by the "svn:auto-props" and "svn:global-ignores" properties can at best be only a suggestion to the client. Older clients will obviously not understand the meaning of these properties and users can disregard the properties with the --no-ignore and --no-auto-props options. Given this reality, server-side enforcement of desired behaviors (where possible, and often via hook scripts) is still strongly recommended.
The new "ephemeral transaction properties" feature (see http://subversion.tigris.org/issues/show_bug.cgi?id=4124) provide a simple way for servers to disallow commits from clients which don't claim to understand svn:auto-props. Thus there is no new capability string required for this feature.
The values of the svn:auto-props property are as per the existing run-time configuration auto-props, they contain "any number of key-value pairs in the format PATTERN = PROPNAME=VALUE[;PROPNAME=VALUE...], where PATTERN is a file pattern that matches one or more filenames and the rest of the line is a semicolon-delimited set of property assignments. (If you need to use a semicolon in your property's name or value, you can escape it by doubling it.)")2
Like the svn:ignore property it only makes sense to set svn:auto-props on directories, so attempts to propset the latter on a file will fail.
The values for the svn:global-ignores property are in the same format as the svn:ignore property: a newline-delimited collection of file patterns.3 Like svn:auto-props, the svn:global-ignores property can only be set on directories.
Auto-Props Hierarchy and Precedence
Any path added to the working copy or imported to the repository must have a previously versioned parent. Both the svn:auto-props explicitly set on that parent and the properties inherited by that parent, in addition to the run-time configuration auto-props, will determine the auto-props for the added/imported files under the versioned parent. Where the auto-prop values for the same file pattern conflict there are a few simple rules:
- svn:auto-props override the run-time configuration auto-props.
- svn:auto-props inherited from a nearer parent override those from a more distant parent.
- Explicit svn:auto-props override inherited auto-props.
Auto-props are overridden by individual file pattern. This means the if a run-time config defines auto-props for several different file patterns (say *.c, *.h, and *.py) and a single pattern (*.c) is defined in a svn:auto-props property at the root of the repository, then only the *.h and *.py auto-props from the run-time config still apply, only the *.c value is overridden.
For example if we have this run-time config:
[miscellany] enable-auto-props = yes [auto-props] *.c = svn:eol-style=native *.h = svn:eol-style=native *.py = svn:eol-style=native
And a repository with this hierarchy and svn:auto-props set as shown:
/ svn:auto-props = '*.bat = svn:executable' /ProjX svn:auto-props = '*.c = svn:eol-style=CRLF' '*.h = svn:eol-style=CRLF' /ProjY /ProjZ
If we check out ^/ProjX and add the files 'bar.py', 'baz.c', and 'foo.bat':
>svn pg svn:auto-props -vR --show-inherited-props Properties inherited from '%ROOT-URL%': svn:auto-props *.bat = svn:executable Properties on '.': svn:auto-props *.c = svn:eol-style=CRLF *.h = svn:eol-style=CRLF >svn st ? bar.py ? baz.c ? foo.bat >svn add bar.py baz.c foo.bat A bar.py A baz.c A foo.bat
Thee file 'bar.py' has its automatic svn:eol-style dictated by the auto-props for *.py which exist soley in the run-time configuration. While bar.py has parents with the svn:auto-props property, none of them have a matching pattern, so there is no override.
The file 'baz.c' gets its auto-props from the svn:auto-props set on '.', which override those set for the same pattern in the run-time config.
Lastly the file 'foo.bat' gets its auto-props from the svn:auto-props property set on the root of the repository. Even though svn:auto-props is set on foo.bat's nearest parent '.', there is no matching pattern, so the no override occurs and the next nearest parent with svn:auto-props applies.
>svn pl -v bar.py baz.c foo.bat Properties on 'bar.py': svn:eol-style native Properties on 'baz.c': svn:eol-style CRLF Properties on 'foo.bat': svn:executable *
If multiple patterns, defined at different levels (i.e. the run-time config and multiple parent's svn:auto-props) all match a given file, then, like multiple matching patterns within the run-time config, there is no guarantee that auto-props will be applied in any particular order. One rule only overrides another rule if they have the exact same pattern.
The cumulative set of ignores patterns in effect for a given path are the sum of the patterns found in:
- The global-ignores section of the runtime configuration.
- Any svn:global-ignores properties explicitly set on, or inherited by, the path.
- The svn:ignore property, if any, set on the path's immediate parent.
There is no actual hierarchy among these ignore sources, the patterns found in each are simply combined, they do do not override each other.
Remember that users can only inherit properties from paths which they have read access to -- see http://wiki.apache.org/subversion/InheritedProperties#Authentication. So make sure all users have read access to the path(s) on which you set "svn:auto-props" or "svn:global-ignores" properties.
Of course the property need not be set on the root of repository. It might be set on the root of some project folder, e.g. ^/subversion in our own repos, or some other root. The point is that the property doesn't need to be set on every directory to affect the whole repository (or some large subtree) the way that svn:ignore currently requires (1)
Thank you 'Version Control with Subversion' book, http://svnbook.red-bean.com/en/1.7/svn-book.html#svn.advanced.confarea (2)
At the time when 1.8 was released, the release notes and this page incorrectly said the format was the same as configuration defined global-ignores: that is, whitespace-delimited. (3)