Setting svn:keywords for specific files with Windows Powershell – Or grep with Powershell

In one of my current projects, all source files need to have a file-header looking like this:

// -------------------------------------------------------------
// <copyright company="..." file="Variance.cs">
//   ...
// </copyright>
// <remarks>
//   $HeadURL: https://svn....Api/Utils/Variance.cs $
//   $LastChangedRevision: 1951 $
//   $LastChangedDate: 2009-07-21 $
//   $LastChangedBy: corn_la $
// </remarks>
// <summary>
//   Safe co- and contra-variance for Interfaces in .NET FW 3.5.
// </summary>
// -------------------------------------------------------------

But all to often, the remarks part of the header is uncomplete:

// <remarks>
//   $HeadURL$
//   $LastChangedRevision$
//   $LastChangedDate$
//   $LastChangedBy$
// </remarks>

This means, someone (mostly me) checked in a file with out having configured the svn-keywords property properly.

Now, with “svn propset –R ….” you can reset the properties on all files in a directory recursively. But this is not smart enough to recognize if the properties really changed or not. So it would touch all files specified and boom, every header changes.

What I want to do is setting the properties only on those files that have no properties defined.

Good reason for learning Windows Power Shell! 🙂

Well, here is the command I used:

gci . -r -i *.cs | ? { (gc $_.fullname) -match '\$HeadURL\$$' } | % { svn ps svn:keywords "HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.fullname }

It uses a lot of aliases. The full version would look like this:

Get-ChildItem . -Recurse -Include *.cs 
    | Where-Object { 
        (Get-Content $_.FullName) -match '\$HeadURL\$$'
      } 
    | ForEach-Object { 
        svn propset svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.FullName 
      }

And here is, what it does:

  1. Getting FileInfos for all C#-files recursively in the current directory
  2. Selecting those FileInfos, where the content has a line ending on “$HeadURL$”, which means there was no property set for HeadURL. Getting and comparing the svn props was even slower 🙂
  3. Calling  “svn propset” on every FileInfo-Object using the FullName as command line argument

Issues:

  • It was very hard to find good documentation on PowerShell!!
  • Hard to find how to use regex with power shell. The problem was finding the dollar sign, because it is used for variable usage in double quoted strings. It only works properly in single-quoted strings.

    More on regex with powershell
  • It took me a while to find the aliases ?  and % for where-object and foreach-object. Again, hard to find documentation.

Many thanks to Johannes Rössel for helping me with PowerShell on a stackoverflow-Question.

Setting svn:keywords for specific files with Windows Powershell – Or grep with Powershell

In one of my current projects, all source files need to have a file-header looking like this:

// -------------------------------------------------------------
// <copyright company="..." file="Variance.cs">
//   ...
// </copyright>
// <remarks>
//   $HeadURL: https://svn....Api/Utils/Variance.cs $
//   $LastChangedRevision: 1951 $
//   $LastChangedDate: 2009-07-21 $
//   $LastChangedBy: corn_la $
// </remarks>
// <summary>
//   Safe co- and contra-variance for Interfaces in .NET FW 3.5.
// </summary>
// -------------------------------------------------------------

But all to often, the remarks part of the header is uncomplete:

// <remarks>
//   $HeadURL$
//   $LastChangedRevision$
//   $LastChangedDate$
//   $LastChangedBy$
// </remarks>

This means, someone (mostly me) checked in a file with out having configured the svn-keywords property properly.

Now, with “svn propset –R ….” you can reset the properties on all files in a directory recursively. But this is not smart enough to recognize if the properties really changed or not. So it would touch all files specified and boom, every header changes.

What I want to do is setting the properties only on those files that have no properties defined.

Good reason for learning Windows Power Shell! 🙂

Well, here is the command I used:

gci . -r -i *.cs | ? { (gc $_.fullname) -match '\$HeadURL\$$' } | % { svn ps svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.fullname }

It uses a lot of aliases. The full version would look like this:

Get-ChildItem . -Recurse -Include *.cs 
    | Where-Object { 
        (Get-Content $_.FullName) -match '\$HeadURL\$$'
      } 
    | ForEach-Object { 
        svn propset svn:keywords "
HeadURL Id LastChangedBy LastChangedRevision LastChangeDate" $_.FullName 
      }

And here is, what it does:

  1. Getting FileInfos for all C#-files recursively in the current directory
  2. Selecting those FileInfos, where the content has a line ending on “$HeadURL$”, which means there was no property set for HeadURL. Getting and comparing the svn props was even slower 🙂
  3. Calling  “svn propset” on every FileInfo-Object using the FullName as command line argument

Issues:

  • It was very hard to find good documentation on PowerShell!!
  • Hard to find how to use regex with power shell. The problem was finding the dollar sign, because it is used for variable usage in double quoted strings. It only works properly in single-quoted strings.

    More on regex with powershell
  • It took me a while to find the aliases ?  and % for where-object and foreach-object. Again, hard to find documentation.

Many thanks to Johannes Rössel for helping me with PowerShell on a stackoverflow-Question.