~svn/ubuntu/raring/subversion/ppa

« back to all changes in this revision

Viewing changes to contrib/hook-scripts/check-case-insensitive.pl

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-12-05 01:26:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051205012614-qom4xfypgtsqc2xq
Tags: 1.2.3dfsg1-3ubuntu1
Merge with the final Debian release of 1.2.3dfsg1-3, bringing in
fixes to the clean target, better documentation of the libdb4.3
upgrade and build fixes to work with swig1.3_1.3.27.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl -w
 
2
# ====================================================================
 
3
# Copyright (c) 2000-2004 Collab Net.  All rights reserved.
 
4
#
 
5
# This software is licensed as described in the file COPYING, which
 
6
# you should have received as part of this distribution.  The terms
 
7
# are also available at http://subversion.tigris.org/license-1.html.
 
8
# If newer versions of this license are posted there, you may use a
 
9
# newer version instead, at your option.
 
10
#
 
11
# This software consists of voluntary contributions made by many
 
12
# individuals.  For exact contribution history, see the revision
 
13
# history and logs, available at http://subversion.tigris.org/.
 
14
# ====================================================================
 
15
 
 
16
use strict;
 
17
require 5.004; # This is when locale support was added.
 
18
# This 'use encoding' and setting the LANG environment variable has the
 
19
# desired effect of handling the comparison of extended characters and
 
20
# preventing a commit.  However, if any of the files in conflict have
 
21
# extended characters in them this is the error displayed by the client:
 
22
#
 
23
#   Commit failed (details follow):
 
24
#   svn: MERGE request failed on '/svn/play/martinto/trunk'
 
25
#   svn: General svn error from server
 
26
#
 
27
# It should list the file names which are in conflict.  But it does stop the
 
28
# commit. 
 
29
use encoding "utf8";
 
30
$ENV{'LANG'} = 'en_GB.UTF-8';
 
31
 
 
32
# Please check the path to svnlook is correct...
 
33
my $svnlook;
 
34
if ($^O eq 'MSWin32') {
 
35
  $svnlook = '"c:\Program Files\subversion\bin\svnlook.exe"';
 
36
} else {
 
37
  $svnlook = '/usr/local/bin/svnlook';
 
38
}
 
39
 
 
40
# This script can be called from a pre-commit hook on either Windows or a Unix
 
41
# like operating system.  It implements the checks required to ensure that the
 
42
# repository acts in a way which is compatible with a case preserving but
 
43
# case insensitive file system.
 
44
#
 
45
# When a file is added this script checks the file tree in the repository for
 
46
# files which would be the same name on a case insensitive file system and
 
47
# rejects the commit.
 
48
#
 
49
# On a Unix system put this script in the hooks directory and add this to the
 
50
# pre-commit script:
 
51
#
 
52
#  $REPOS/hooks/check-case-insensitive.pl "$REPOS" "$TXN" || exit 1
 
53
#
 
54
# On a windows machine add this to pre-commit.bat:
 
55
#
 
56
#  perl <path-to-script>\check-case-insensitive.pl %1 %2
 
57
#  if errorlevel 1 goto :ERROR
 
58
#  exit 0
 
59
#  :ERROR
 
60
#  echo Error found in commit 1>&2
 
61
#  exit 1
 
62
#
 
63
# You may need to change the setting of $svnlook to the path to the
 
64
# executable on your system.
 
65
#
 
66
# Turn on debug by adding up to three -debug options as the first options in
 
67
# the list.  The more -debug options the more output.  If you specify more
 
68
# than one the output goes into a file.
 
69
#
 
70
# If you have any problems with this script feel free to contact
 
71
# Martin Tomes <martin@tomes.org.uk>
 
72
 
 
73
# Bugfixes and some debug code added by Jeremy Bettis <jeremy@deadbeef.com>
 
74
 
 
75
my $openstr = '-|';
 
76
# Shift off any debug options.
 
77
my $debug = 0;
 
78
while (@ARGV and $ARGV[0] =~ /^-d(ebug)?$/) {
 
79
  $debug++;
 
80
  shift;
 
81
}
 
82
 
 
83
# If there is too much debug output to STDERR subversion doesn't like it, so,
 
84
# if a lot of output is expected send it to a file instead.
 
85
if ($debug > 0) {
 
86
  if ($^O eq 'MSWin32') {
 
87
    open(STDERR, ">c:/svnlog.txt")
 
88
      or die "$0: cannot open 'c:/svnlog.txt' for writing: $!\n";
 
89
  } else {
 
90
    open(STDERR, ">/tmp/svnlog.txt")
 
91
      or die "$0: cannot open '/tmp/svnlog.txt' for writing: $!\n";
 
92
  }
 
93
}
 
94
 
 
95
# Fetch the command line arguments.
 
96
unless (@ARGV > 1) {
 
97
  die "usage: $0 [-d [-d [-d]]] repos txn [--revision]\n";
 
98
}
 
99
 
 
100
my $repos = shift;
 
101
my $txn = shift;
 
102
 
 
103
# Jeremy Bettis <jeremy@deadbeef.com> wrote the $flag code and has this to
 
104
# say about it:
 
105
#
 
106
# The reason I did that was so that I could test the hook without actually
 
107
# doing a commit.  Whenever I had a commit that succeeded in making a bad file
 
108
# or directory, or when a commit took too long I just did a sequence of
 
109
# operations like this:
 
110
#
 
111
# svnlook youngest path
 
112
# (it tells me that HEAD is 987 or whatever)
 
113
# check-case-insensitive.pl -debug path 987 -r
 
114
# and then the check-case-insensitive.pl passes -r to svnlook instead of
 
115
# --transaction.
 
116
#
 
117
# Of course when it gets down to # Get the file tree at the previous revision,
 
118
# then it doesn't work, but most of my problems were found before that point.
 
119
my $flag = '--transaction';
 
120
$flag = shift if @ARGV;
 
121
 
 
122
# Each added path put here.
 
123
my @added;
 
124
 
 
125
# The file tree as a hash, index lower cased name, value actual name.
 
126
my %tree;
 
127
 
 
128
# Command being executed.
 
129
my $cmd;
 
130
 
 
131
print STDERR "LANG=", $ENV{'LANG'}, "\n" if ($debug and defined($ENV{'LANG'}));
 
132
# Get a list of added files.
 
133
local *SVNLOOK;
 
134
$cmd = "$svnlook changed \"$repos\" $flag $txn";
 
135
print STDERR "$cmd\n" if ($debug);
 
136
open(SVNLOOK, $openstr, $cmd)
 
137
  or die("$0: cannot open '$cmd' pipe for reading: $!\n");
 
138
while (<SVNLOOK>) {
 
139
  chomp;
 
140
  if (/^A\s+(\S.*)/) {
 
141
    push @added, $1;
 
142
  }
 
143
}
 
144
close SVNLOOK;
 
145
 
 
146
if ($debug) {
 
147
  print STDERR "Added " . ($#added + 1) . " items:\n";
 
148
  foreach my $itm (@added) {
 
149
    print STDERR " $itm\n";
 
150
  }
 
151
}
 
152
 
 
153
unless (@added) {
 
154
  print STDERR "No files added\n" if ($debug);
 
155
  # No added files so no problem.
 
156
  exit(0);
 
157
}
 
158
 
 
159
# Get the shortest directory name which has changed, this will be the path
 
160
# into the repository to use to get the history.
 
161
$cmd = "$svnlook dirs-changed \"$repos\" $flag $txn";
 
162
print STDERR "$cmd\n" if ($debug);
 
163
open(SVNLOOK, $openstr, $cmd)
 
164
  or die("$0: cannot open '$cmd' pipe for reading: $!\n");
 
165
my $shortest=999999;
 
166
my $changed;
 
167
while (<SVNLOOK>) {
 
168
  chomp;
 
169
  print STDERR "  ", $_, "\n" if ($debug > 2);
 
170
  if (length($_) < $shortest) {
 
171
    $changed = $_;
 
172
    $shortest = length($_);
 
173
  }
 
174
}
 
175
close SVNLOOK;
 
176
# There isn't a leading slash on $changed but there is a trailing one.  When
 
177
# it is the root of the repository the / is a pain, so always remove the
 
178
# trailing slash and put it back in where needed.
 
179
$changed =~ s/\/$//;
 
180
 
 
181
# Use the history of $changed path to find the revision of the previous commit.
 
182
$cmd = "$svnlook history \"$repos\" \"$changed/\"";
 
183
print STDERR "$cmd\n" if ($debug);
 
184
open(SVNLOOK, $openstr, $cmd)
 
185
  or die("$0: cannot open '$cmd' pipe for reading: $!\n");
 
186
my $lastrev;
 
187
while (<SVNLOOK>) {
 
188
  chomp;
 
189
  if (/(\d+)/) {
 
190
    $lastrev = $1;
 
191
    last;
 
192
  }
 
193
}
 
194
close SVNLOOK;
 
195
 
 
196
# Get the file tree at the previous revision and turn the output into
 
197
# complete paths for each file.
 
198
my @path;
 
199
$cmd = "$svnlook tree \"$repos\" \"$changed/\" --revision $lastrev";
 
200
print STDERR "$cmd\n" if ($debug);
 
201
open(SVNLOOK, $openstr, $cmd)
 
202
  or die("$0: cannot open '$cmd' pipe for reading: $!\n");
 
203
while (<SVNLOOK>) {
 
204
  chomp;
 
205
  print STDERR "tree: '", $_, "'\n" if ($debug > 2);
 
206
  next if (/^\/{1,2}$/); # Ignore the root node.  Two /'s at root of the repos.
 
207
  if (/^(\s+)(.*)\/$/) { # Is a directory.
 
208
    $#path = length($1)-2; # Number of spaces at start of line is nest level.
 
209
    push @path, $2;
 
210
    my $name = join('/', @path) . '/';
 
211
    my $index;
 
212
    if ($changed eq '') {
 
213
      $index = $name;
 
214
    } else {
 
215
      $index = $changed . '/' . $name;
 
216
    }
 
217
    $tree{lc($index)} = $name; # Index the hash with case folded name.
 
218
    print STDERR "\$tree{lc($index)}=$name (dir)\n" if ($debug > 1);
 
219
  } elsif (/^(\s+)(.*)$/) {  # This is a real file name, not a directory.
 
220
    $#path = length($1)-2; # Number of spaces at start of line is nest level.
 
221
    my $name;
 
222
    if ($#path eq -1) {
 
223
      $name = $2;
 
224
    } else {
 
225
      $name = join('/', @path) . '/' . $2;
 
226
    }
 
227
    my $index;
 
228
    if ($changed eq '') {
 
229
      $index = $name;
 
230
    } else {
 
231
      $index = $changed . '/' . $name;
 
232
    }
 
233
    $tree{lc($index)} = $name; # Index the hash with case folded name.
 
234
    print STDERR "\$tree{lc($index)}=$name\n" if ($debug > 1);
 
235
  }
 
236
}
 
237
close SVNLOOK;
 
238
 
 
239
my $failmsg;
 
240
 
 
241
foreach my $newfile (@added) {
 
242
  print STDERR "Checking \$tree{lc($newfile)}\n" if ($debug > 1);
 
243
  # Without the following line it gets the lc() wrong.
 
244
  my $junk = "x$newfile";
 
245
  if (exists($tree{lc($newfile)})) {
 
246
    $failmsg .= "\n  $newfile already exists as " . $tree{lc($newfile)};
 
247
  }
 
248
}
 
249
if (defined($failmsg)) {
 
250
  print STDERR "\nFile name case conflict found:\n" . $failmsg . "\n";
 
251
  exit 1;
 
252
}
 
253
 
 
254
exit 0;