I have noticed in particular with Subversion that in an environment with different operating systems, you often end up with mixed line endings in files unless some measures are taken to combat this. This is a particular issue with using an svn master with git mirrors as you may see problems with git-svn.
Subversion allows metadata to be stored and versioned against any file or directory in the repository using properties. Subversion has its own namespace for properties that extend its capabilities to manage the items under source control. Some of the key properties are:
svn:mime-type- value is returned as the Content-type HTTP header on GET requests (useful when browsing the repository)svn:keywords- provides keyword expansion such as Author, Date, Id and Revision, and ensuring that changes to these values do not cause differencessvn:eol-style- handles CR+LF issues in heterogeneous operating system environmentssvn:executable- will set execution mask correctly on operating systems that support it
A key part of this is ensuring that properties are set effectively. Subversion provides a mechanism called autoprops to set default properties on files and directory based on pattern matching the filename. Autoprops does not modify existing files as you may need to deviate from the defaults in rare cases, so addition is chosen as a suitable point to consider what these values should be.
Configuring autoprops
All subversion clients support autoprops and this is usually configured in the runtime configuration area. This file is usually located at ~/.subversion/config although this may vary depending on the subversion client and the operating system.
Modify the subversion configuration file (config), making the following changes:
- Ensure
enable-auto-props = yesis present and not commented out - Ensure the
[auto-props]section at the end of the file contains at least the following entries:
*.bat = svn:mime-type=text/plain;svn:eol-style=native;svn:executable=on
*.c = svn:mime-type=text/plain;svn:eol-style=native
*.cmd = svn:mime-type=text/plain;svn:eol-style=native;svn:executable=on
*.cpp = svn:mime-type=text/plain;svn:eol-style=native
*.css = svn:mime-type=text/css;svn:eol-style=native
*.doc = svn:mime-type=application/msword
*.dtd = svn:mime-type=text/plain;svn:eol-style=native
*.erb = svn:mime-type=text/plain;svn:eol-style=native
*.gif = svn:mime-type=image/gif
*.h = svn:mime-type=text/plain;svn:keywords=Author Date Id Revision;svn:eol-style=native
*.html = svn:mime-type=text/html;svn:eol-style=native
*.java = svn:mime-type=text/plain;svn:eol-style=native;svn:keywords=Author Date Id Revision
*.jpg = svn:mime-type=image/jpeg
*.js = svn:mime-type=text/plain;svn:eol-style=native
*.jsp = svn:mime-type=text/plain;svn:eol-style=native
*.png = svn:mime-type=image/png
*.properties = svn:mime-type=text/plain;svn:eol-style=native
*.rb = svn:mime-type=text/plain;svn:eol-style=native;svn:executable=on
*.sh = svn:mime-type=text/plain;svn:eol-style=native;svn:executable=on
*.sql = svn:mime-type=text/plain;svn:eol-style=native
*.tld = svn:mime-type=text/xml;svn:eol-style=native
*.txt = svn:mime-type=text/plain;svn:eol-style=native
*.xls = svn:mime-type=application/msexcel
*.xml = svn:mime-type=text/xml;svn:eol-style=native
*.xsd = svn:mime-type=text/xml;svn:eol-style=native
*.xsl = svn:mime-type=text/xml;svn:eol-style=native
*.yml = svn:mime-type=text/plain;svn:eol-style=native
.checkstyle = svn:mime-type=text/plain;svn:eol-style=native
.classpath = svn:mime-type=text/plain;svn:eol-style=native
.project = svn:mime-type=text/plain;svn:eol-style=native
Makefile = svn:eol-style=native
The above list is not definitive, so add any file types common to your development process.
Fixing existing autoprops
The following script is designed to run in a bash shell and requires ruby. It reads the subversion config file from ~/.subversion/config and applies the rules to files already added to subversion in the current directory and its children - effectively applying autoprops to the file as if it were a new addition.
In particular, note that:
- the modification will be to the working copy and will therefore need to be committed as required
- the use of dos2unix and unix2dos gives EOL consistency. Subversion may complain if you try to change the eol-style on a file with inconsistent line endings.
- this can generate a lot of changes and cause some major conflicts if people have uncommitted local modifications. It is advised to do this during a quiet period.
#!/usr/bin/env ruby
require 'optparse'
require 'fileutils'
options = { :dryrun => false }
opts = OptionParser.new do |opts|
opts.banner = "fix_svn_autoprops"
opts.on("-n", "--dry-run", "Show what would happen but don't actually do anything") do |tf|
options[:dryrun] = tf
end
opts.on("--fix-eols-windows", "Fix eol for windows if eol-style property is set") do |tf|
options[:fixeols] = :windows
end
opts.on("--fix-eols-linux", "Fix eol for linux (and mac) if eol-style property is set") do |tf|
options[:fixeols] = :linux
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end
opts.parse!
autoprops = Hash.new {|h,k| h[k] = {}}
File.open(File.expand_path("~/.subversion/config"), "r") do |file|
section = nil
while line = file.gets
line.chomp!.strip!
next if line =~ /^$/
next if line =~ /^#.*$/
if line =~ /^\[[\w-]*\]$/
section = line
next
end
next unless section == "[auto-props]"
# parse auto props line
m, filename_pattern, props = *line.match(/([^\s=]+)\s*=\s*(.+)$/)
props.split(';').each do |prop|
propname, value = prop.split('=')
autoprops[filename_pattern][propname] = value
end
end
end
autoprops.each do |filename_pattern, props|
puts "Fixing #{filename_pattern} with #{props.inspect}"
command = %Q{find . -name .svn -prune -o -name target -prune -o -name test-output -prune -o -name "#{filename_pattern}" -print0}
props.each do |propname, value|
if propname == 'svn:eol-style'
case options[:fixeols]
when :windows
command << %Q{ -exec dos2unix '{}' \\;}
command << %Q{ -exec unix2dos '{}' \\;}
when :linux
command << %Q{ -exec unix2dos '{}' \\;}
command << %Q{ -exec dos2unix '{}' \\;}
end
end
command << %Q{ -exec svn ps "#{propname}" "#{value}" '{}' \\;}
end
puts command
system command unless options[:dryrun]
end
Comments
blog comments powered by Disqus