Branko ÄŒibej wrote:
> Martin Tomes wrote:
>>Branko ÄŒibej wrote:
>>>Jeff Lanzarotta wrote:
>>>>Hello,
>>>>
>>>>I have the subversion server (svnserve) setup on a linux machine and
>>>>our clients run on Windows 2000.
>>>>My question is, is there a way to protect against this? In this
>>>>scenario, the files DELETE.ICO and delete.ico are actually the same
>>>>file.
>>>
>>>What exactly would you like to protect against? I see two issues here:
>>>
>>> * Someone on a case-sensitive system checked in two files that
>>> differ only in case
>>
>>Not necessarily, if two people on Windows each add a file, one called
>>delete.ico and the other DELETE.ICO and both commit then one can end
>>up in the position described.
>
> Oh bother. You're right.
>>
>>I have a hook script on our CVS server which prevents this from
>>happening, when the second person tries to commit the new file it is
>>found to already exist with a different case and the commit is
>>rejected. My next challenge is to write a pre commit hook script
>>which does the same.
>
> In this case, I think a hook script is exactly the right way to go. Of
> course the fact that it has to support Unicode case folding isn't going
> to help a bit.
I have attached a pre commit hook which looks to see if a file already exists in the repository
whose name differs only in case. This is my first stab at this, it does work, but I would
appreciate comments as to whether it goes about this in the right way. It does rely on the perl
lc() function doing the right thing with unicode. I am afraid that I am no expert in UTF-8 and am
hoping that the :utf8 stuff on the open commands will do the job. Perhaps someone with utf-8 file
paths could try this script.
--
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
use strict;
my $svnlook = '/usr/local/bin/svnlook';
my $repos = $ARGV[0];
my $txn = $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 . ' --transaction ' . $txn;
open(SVNLOOK, '-|:utf8', $cmd) || die($cmd);
while (<SVNLOOK>) {
chomp;
if (/^A\s+(.*)/) {
push @added, $1;
}
}
close SVNLOOK;
# 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 . ' --transaction ' . $txn;
open(SVNLOOK, '-|:utf8', $cmd) || die($cmd);
my $shortest=999999;
my $changed;
while (<SVNLOOK>) {
chomp;
if (length($_) < $shortest) {
$changed = $_;
$shortest = length($_);
}
}
close SVNLOOK;
# Use the history of $changed path to find the revision of the previous commit.
$cmd = $svnlook . ' history ' . $repos . ' ' . $changed;
open(SVNLOOK, '-|:utf8', $cmd) || die($cmd);
my $lastrev;
while (<SVNLOOK>) {
chomp;
if (/(\d+)/) {
$lastrev = $1;
last;
}
}
# Get the file tree at the previous revision and turn the output into
# complete paths for each file.
my @path;
$cmd = $svnlook . ' tree ' . $repos . ' --revision ' . $lastrev;
open(SVNLOOK, '-|:utf8', $cmd) || die($cmd);
while (<SVNLOOK>) {
chomp;
next if (/^\/$/); # Ignore the root node.
if (/^(\s+)(.*)\/$/) { # Is a directory.
$#path = length($1)-2; # Number of spaces at start of line is nest level.
push @path, $2;
} elsif (/^\s+(.*)$/) { # This is a real file name, not a directory.
my $name = join('/', @path) . '/' . $1;
$tree{lc($name)} = $name; # Index the hash with case folded name.
}
}
close SVNLOOK;
my $failmsg;
foreach my $newfile (@added) {
if (exists($tree{lc($newfile)})) {
$failmsg .= "\n $newfile already exists as " . $tree{lc($newfile)};
}
}
if (defined($failmsg)) {
die "\nFile name case conflict found:\n" . $failmsg . "\n";
}
exit 0;
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Jun 1 17:50:11 2004