5

Occasionally we commit a C# project file to SVN that references files we forgot to add to SVN. Are there any pre-commit hook scripts out there that parse the .csproj file and reject the commit if it references unversioned files?

nw.
  • 2,206
  • 5
  • 30
  • 40
  • I would also like something that does the opposite - spots you checking in .cs/.xaml files that aren't in the .csproj (it could output a warning, at least). – Alastair Maw Oct 17 '11 at 18:34
  • 2
    If you configure ignores properly, you can simply use `svn status` for that. Good clients show the status automatically before commit. – hamstergene Oct 17 '11 at 18:44

2 Answers2

1
#!/usr/bin/perl
# Checks for source files which have been added to a csproj in a commit
# but haven't themselves been committed.
use Modern::Perl;
use warnings FATAL => 'syntax';
use File::Basename qw(basename);
use XML::Simple;

die "usage: $0 repo transaction\n" if @ARGV != 2;
my $opt = "-t"; # -r for testing
my ($repos, $txn) = @ARGV;

# If you really, really want to add a file to the proj and
# not commit it, start your commit message with a !
my @info = `svnlook info $opt $txn "$repos"`;
exit 0 if ($info[3] =~ /\A!/);

my @lines = `svnlook changed $opt $txn "$repos"`;

my @projects = grep { /\AU/ }
               grep { /[.]csproj\z/ }
               map { chomp; $_ } @lines;

my @filelist = `svnlook tree $opt $txn "$repos" --full-paths`;
my %present;

foreach (@filelist) {
    chomp;
    $present{$_} = 1;
}

foreach (@projects) {
    m"\AU.\s\s([\w/.]+/)([\w]+\.csproj)\z" or die "bad line $_";
    my ($path, $proj) = ($1, $2);

    my $projfile = `svnlook cat $opt $txn "$repos" $path/$proj`;
    my $xml = XMLin($projfile);

    # Tested with VS 2012 project files
    my @includes = @{$xml->{ItemGroup}->[1]->{Compile}};
    # All the source files in the csproj
    my @filenames = map {$_->{Include}} @includes;

    foreach (@filenames) {
        # ignore "../etc", not below the project file in the tree
        next if /\A[.][.]/;
        # if you have files that are in the proj but shouldn't be committed
        # eg some generated files, add checks for them here
        # next if /MyGeneratedFile.cs\z/;

        my $file = $path . $_;
        # The csproj file speaks windows paths, but svn will output unix ones
        $file =~ tr|\\|/|;

        if (!defined $present{$file}) {
            die "The file $file is included in the project $path\\$proj, but is not present in the tree, did you forget to commit it?";
        }
    }
}
jwg
  • 5,547
  • 3
  • 43
  • 57
  • Maybe @gbjbaanb - lots of people use a Linux server for SVN even if they are developing for Windows. – jwg May 22 '14 at 12:45
  • Maybe, but just as likely a Windows shop will have SVN running on Windows (using the excellent VisualSVN Server for example). – gbjbaanb May 22 '14 at 15:38
0

If you are using a windows server, you can have a look at Subversion Notify for Windows -http://sourceforge.net/projects/svn-notify/

I use it to do a simple check on the commit message, to ensure users confirm with our in house rules. I have not gone into any of the other pre-commit uses, but it might be worth a shot!

I Quote from the Manual:

PRE-COMMIT CHECKS

 Ensure the integrity of your repository by enforcing commit message standards

 Restrict the types of files that can be committed (eliminate accidental commits of temporary or developer specific configuration files)

 Enforce file type checks - files that can be committed, but require a special commit tag to make sure it's being committed as per your rules

 Check against your task tracking/ bug tracking system to ensure it's a valid tracking item and your standards are enforced (no commits against closed bugs for example)

RooiWillie
  • 2,198
  • 1
  • 30
  • 36