kfogel@collab.net wrote:
> Time for version control, sounds like.
>
> When you guys get the "latest canonical version" of this script sorted
> out, can you post it here & clearly label it as such?
This is the version of this script which needs to be put in contrib. The confusion is mainly my
fault as I upgraded my Linux box and set up sendmail to masquerade domains too enthusiastically and
all my posts were not coming from the address I subscribed to the list with so they all ended up in
the moderators queue.
Pre-commit hook that stops case insensitive collisions.
This script can be called from a pre-commit hook on either Windows or a Unix
like operating system. It implements the checks required to ensure that the
repository acts in a way which is compatible with a case insensitive file
system.
When a file is added this script checks the file tree in the repository for
files which would be the same name on a case insensitive file system and
rejects the commit if there is a match.
* tools/hook-scripts/check-case-insensitive.pl
--
Martin Tomes
echo 'Martin x Tomes at controls x eurotherm x co x uk'\
| sed -e 's/ x /\./g' -e 's/ at /@/'
#!/usr/bin/perl
# ====================================================================
# Copyright (c) 2000-2004 Martin Tomes. All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals. For exact contribution history, see the revision
# history and logs, available at http://subversion.tigris.org/.
# ====================================================================
# This script can be called from a pre-commit hook on either Windows or a Unix
# like operating system. It implements the checks required to ensure that the
# repository acts in a way which is compatable with a case preserving but
# case insensitive file system.
#
# When a file is added this script checks the file tree in the repository for
# files which would be the same name on a case insensitive file system and
# rejects the commit.
#
# On a Unix system put this script in the hooks directory and add this to the
# pre-commit script:
#
# $REPOS/hooks/check-case-insensitive.pl "$REPOS" "$TXN" || exit 1
#
# On a windows machine add this to pre-commit.bat:
#
# perl <path-to-script>\check-case-insensitive.pl %1 %2
# if errorlevel 1 goto :ERROR
# exit 0
# :ERROR
# echo Error found in commit 1>&2
# exit 1
#
# You may need to change the setting of $svnlook to the path to the
# executable on your system.
#
# Turn on debug by adding up to three -debug options as the first options in
# the list. The more -debug options the more output. If you specify more
# than one the output goes into a file.
#
# If you have any problems with this script feel free to contact
# Martin Tomes <martin@tomes.org.uk>
# Bugfixes and some debug code added by Jeremy Bettis <jeremy@deadbeef.com>
use strict;
my $opSys = $^O;
my $svnlook;
my $openstr;
# Please check the path to svnlook is correct...
if ($opSys eq 'MSWin32') {
$svnlook = '"c:\Program Files\subversion\bin\svnlook.exe"';
$openstr = '-|';
} else {
$svnlook = '/usr/local/bin/svnlook';
$openstr = '-|:utf8';
}
# Shift off any debug options.
my $debug = 0;
while ($ARGV[0] eq '-debug') {
$debug++;
shift;
}
# If there is too much debug output to STDERR subversion doesn't like it, so,
# if a lot of output is expected send it to a file instead.
if ($debug > 1) {
if ($opSys eq 'MSWin32') {
open(STDERR, ">c:/svnlog.txt");
} else {
open(STDERR, ">/tmp/svnlog.txt");
}
}
# Fetch the command line arguments.
my $repos = $ARGV[0];
my $txn = $ARGV[1];
# Jeremy Bettis <jeremy@deadbeef.com> wrote the $flag code and has this to
# say about it:
#
# The reason I did that was so that I could test the hook without actually
# doing a commit. Whenever I had a commit that succeded in making a bad file
# or directory, or when a commit took too long I just did a sequence of
# operations like this:
#
# svnlook youngest path
# (it tells me that HEAD is 987 or whatever)
# check-case-insensitive.pl -debug path 987 -r
# and then the check-case-insensitiv.pl passes -r to svnlook instead of
# --transaction.
#
# Of course when it gets down to # Get the file tree at the previous revision,
# then it doesn't work, but most of my problems were found before that point.
my $flag = '--transaction';
$flag = $ARGV[2] if ($#ARGV > 1);
my @added; # Each added path put here.
my %tree; # The file tree as a hash, index lower cased name, value actual name.
my $cmd; # Command being executed.
# Get a list of added files.
local *SVNLOOK;
$cmd = $svnlook . ' changed "' . $repos . '" ' . $flag . ' ' . $txn;
print STDERR "$cmd\n" if ($debug);
open(SVNLOOK, $openstr, $cmd) || die($cmd);
while (<SVNLOOK>) {
chomp;
if (/^A\s+(\S.*)/) {
push @added, $1;
}
}
close SVNLOOK;
if ($debug) {
print STDERR "Added " . ($#added + 1) . " items:\n";
foreach my $itm (@added) {
print STDERR " $itm\n";
}
}
if ($#added < 0) {
print STDERR "No files added\n" if ($debug);
# No added files so no problem.
exit(0);
}
# Get the shortest directory name which has changed, this will be the path
# into the repository to use to get the history.
$cmd = $svnlook . ' dirs-changed "' . $repos . '" ' . $flag . ' ' . $txn;
print STDERR "$cmd\n" if ($debug);
open(SVNLOOK, $openstr, $cmd) || die($cmd);
my $shortest=999999;
my $changed;
while (<SVNLOOK>) {
chomp;
print STDERR " ", $_, "\n" if ($debug > 2);
if (length($_) < $shortest) {
$changed = $_;
$shortest = length($_);
}
}
close SVNLOOK;
# There isn't a leading slash on $changed but there is a trailing one. When
# it is the root of the repository the / is a pain, so always remove the
# trailing slash and put it back in where needed.
$changed =~ s/\/$//;
# Use the history of $changed path to find the revision of the previous commit.
$cmd = $svnlook . ' history "' . $repos . '" "' . $changed . '/"';
print STDERR "$cmd\n" if ($debug);
open(SVNLOOK, $openstr, $cmd) || die($cmd);
my $lastrev;
while (<SVNLOOK>) {
chomp;
if (/(\d+)/) {
$lastrev = $1;
last;
}
}
close SVNLOOK;
# Get the file tree at the previous revision and turn the output into
# complete paths for each file.
my @path;
$cmd = $svnlook . ' tree "' . $repos . '" "' . $changed . '/" --revision ' . $lastrev;
print STDERR "$cmd\n" if ($debug);
open(SVNLOOK, $openstr, $cmd) || die($cmd);
while (<SVNLOOK>) {
chomp;
print STDERR "tree: '", $_, "'\n" if ($debug > 2);
next if (/^\/{1,2}$/); # Ignore the root node. Two /'s at root of the repo.
if (/^(\s+)(.*)\/$/) { # Is a directory.
$#path = length($1)-2; # Number of spaces at start of line is nest level.
push @path, $2;
my $name = join('/', @path) . '/';
my $index;
if ($changed eq '') {
$index = $name;
} else {
$index = $changed . '/' . $name;
}
$tree{lc($index)} = $name; # Index the hash with case folded name.
print STDERR "\$tree{lc($index)}=$name (dir)\n" if ($debug > 1);
} elsif (/^(\s+)(.*)$/) { # This is a real file name, not a directory.
$#path = length($1)-2; # Number of spaces at start of line is nest level.
my $name;
if ($#path eq -1) {
$name = $2;
} else {
$name = join('/', @path) . '/' . $2;
}
my $index;
if ($changed eq '') {
$index = $name;
} else {
$index = $changed . '/' . $name;
}
$tree{lc($index)} = $name; # Index the hash with case folded name.
print STDERR "\$tree{lc($index)}=$name\n" if ($debug > 1);
}
}
close SVNLOOK;
my $failmsg;
foreach my $newfile (@added) {
print STDERR "Checking \$tree{lc($newfile)}\n" if ($debug > 1);
if (exists($tree{lc($newfile)})) {
$failmsg .= "\n $newfile already exists as " . $tree{lc($newfile)};
}
}
if (defined($failmsg)) {
print STDERR "\nFile name case conflict found:\n" . $failmsg . "\n";
exit 1;
}
exit 0;
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org
Received on Tue Jun 8 18:30:26 2004