slice of twisted lime

A New Twist to Dealing with Line Endings

by Tony Apuzzo, Director of Engineering

At FDI, we make heavy use of Virtualized environments to streamline our software development. Using Vagrant to script the build and configuration of development environments improves our staff’s elasticity by enabling everyone to use up-to-date and properly configured tools without needing to maintain a huge set of pre-configured virtual machine images.

An important goal with DevOps tools like Vagrant is avoiding the dreaded “works on my machine” response to problems. By using scripted environments, we minimize the potential for small variations in an environment to lead to inconsistent results with associated product quality impacts.

Recently we encountered a new variation on a long-standing environmental concern regarding file line endings. As most developers will know, Windows software uses two characters to indicate the end of a line in a text file (CRLF) while Unix and Linux systems use only a single character (LF). Many tools over the years have been updated to handle the difference between CRLF and LF in text files, but in some situations these differences can still cause problems.

In our case, Vagrant exacerbates these line ending problems more than usual. We use git to manage our Vagrantfile machine configurations. By default git automatically determines which files are text or binary and converts the line-endings based on its internal configuration. When git clone is performed on a Windows host, text files are created by default with CRLF line endings. As part of the virtual machine production, that cloned working directory is mounted into /vagrant in the guest. If the guest is running Linux then any text files provided to it by the host will have potentially incorrect line endings.

The specific situation we encountered recently was that shell scripts hosted in the Vagrant host folder were created with CRLF line endings that are interpreted as syntax errors when the guest tries to run those shell scripts.

There are a few different approaches to fixing this that I’ve tried. None are perfect, but here are some alternative approaches to dealing with this issue:

git configuration

Ask everyone who uses Windows to update the local configuration for each Vagrant project to have LF line endings by default for all text files.

PS> cd some-working-folder
PS> git config core.eol lf
PS> git config core.autocrlf input

…then commit everything and have a clean working dir…

PS> git checkout-index --force --all # Rebuild working dir with all text files corrected

This option is risky because people tend to forget to this instruction until it is too late. Then they will ask you again about it and then you can remind them to re-read the instructions.

git installation

You can set core.eol and core.autocrlf globally. Or during git-for-windows installation, do not chose the default (recommended) line-ending settings. Unfortunately this has the same problem as the prior option in that it is unlikely for people to consistently change this setting.

git attributes

You can override these determinations with an attributes file .gitattributes to force specific files to have LF and others to have CRLF. This is safer than the other options because it causes git to do the work for you regardless of how people have set up their git configuration.

.gitattributes

*.sh      text eol=lf 
*.bash    text eol=lf 
*.cmd     text eol=crlf
*.ps1     text eol=crlf

For an extreme example of this, see the Drupal source code: http://cgit.drupalcode.org/drupal/tree/.gitattributes

Don’t mount or rsync the files at all

When using Vagrant in some situations it may not necessary to mount the host working folder into /vagrant on the guest at all.

In the future I hope to create a Vagrant plugin that will independently synchronize /vagrant using a separate git clone on the guest. This plugin will solve several other inter-operability issues with vagrant, windows and linux virtual environments, but that is a topic for another blog.

Conclusion

As a best practice, I recommend that you indicate the files that must have CRLF and LF line endings in the .gitattributes file.

About the Author

Tony Apuzzo is Director of Engineering for Flatirons Digital Innovations. As a content solutions consultant, he’s helped educational publishers provide services that enable thousands of teachers to reach students more effectively and worked with numerous organizations to improve the productivity of authors and production managers as well as comply with documentation standards. When he’s not solving complex content problems, Tony builds bicycles for kids and rides his bike in the mountains near Boulder, Colorado.

Follow Tony on LinkedIn.