Using PowerShell Scripts as SVN Hooks

§ December 2, 2008 18:18 by beefarino |

You can tell from my recent blog posts that I'm spending a good deal of time in my SCM role at work.  I've recently been looking at using powershell scripts to replace some binary hooks that have become dated, and to expand our repository's integration with our bug tracking system.  All in all it was pretty simple, but a few gotchas held me up:

First, SVN hooks have to be directly executable (e.g., .exe, .bat., .com, .cmd, or windows script files); powershell scripts are not directly executable for security reasons, so I had to use a batch script as a proxy.  

Second, SVN invokes the hooks with an empty environment (again for security purposes); without an active PATH variable specified, the batch and powershell scripts need to specify full paths to all files.

Finally, some hooks, such as the post-revprop-change hook, read data from STDIN, but the proxy batch file will not forward its STDIN to the powershell process without some intervention.  

Here is the batch proxy for the post-revprop-change hook:

rem   =====================================================================
rem    %  Argument     Description
rem   --- ------------ ----------------------------------------------------
rem   [1] REPOS-PATH   (the path to this repository)
rem   [2] REV          (the revision that was tweaked)
rem   [3] USER         (the username of the person tweaking the property)
rem   [4] PROPNAME     (the property that was changed)
rem   [5] ACTION       (the property was 'A'dded, 'M'odified, or 'D'eleted)
rem   [STDIN] PROPVAL  ** the old property value is passed via STDIN.
rem   ---------------------------------------------------------------------

c:\windows\system32\windowspowershell\v1.0\powershell.exe -command "$input | d:\repository\hooks\postrevprop.ps1" -args "%1" "%2" "%3" "%4" "%5"

A few things to note:

  • I'm using full paths to the powershell executable and the powershell script; this is necessary because the batch file will be run with an empty environment and no PATH to search.
  • I'm not really executing the powershell script, I'm executing a command string that passes the implicit $input variable to the powershell script.  This $input variable resolves to the STDIN for the batch proxy, and enables the powershell script to read it.
  • Because my command string invokes a script file, I need to make sure that the powershell execution policy is set to RemoteSigned or Unrestricted on the SVN server.    

Here is the powershell script invoked by the batch file proxy:

param( $repo, $rev, $user, $propname, $action );
@($repo, $rev, $user, $propname, $action) + $input
    | out-file "d:\repository\hooks\log.txt" -append

The script doesn't do much at the moment - just logs the hook parameters and input to a file so I can verify that the script is executing correctly.  Now that I have ironed out the major wrinkles, I can start porting our hooks to powershell!

SVN Log Parsing with Powershell

§ June 20, 2008 07:47 by beefarino |

I absolutely love powershell.  I would estimate that over the past 6 months, powershell has saved me about two work weeks of time.

Case in point: next week we're entering a rather bulky merge phase across - count 'em now - four branches of the same project.  I needed a list of all of my commits for each branch to use as a cross-reference.  I thought about seeking out or coding up a SVN log parser, until I saw my powershell console and realized I didn't need to.  After a half-minute of hacking, I came up with this little diddy:

( [xml] ( svn log --xml | join-string -sep "" ) ).log.logentry |
 ? { $ -eq "jim christopher" } |

In a nutshell, this one-liner requests the SVN log, filters log entries with my SVN username as the author, and formats them as a very readible list.

And that's the "power" in "powershell:" when I need a quick hack, powershell is there for me; but when I need the reliability and safety of objects, it's there for me too.