~ubuntu-branches/ubuntu/trusty/subversion/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/hook-scripts/case-insensitive.py

  • Committer: Package Import Robot
  • Author(s): Andy Whitcroft
  • Date: 2012-06-21 15:36:36 UTC
  • mfrom: (0.4.13 sid)
  • Revision ID: package-import@ubuntu.com-20120621153636-amqqmuidgwgxz1ly
Tags: 1.7.5-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Create pot file on build.
  - Build a python-subversion-dbg package.
  - Build-depend on python-dbg.
  - Build-depend on default-jre-headless/-jdk.
  - Do not apply java-build patch.
  - debian/rules: Manually create the doxygen output directory, otherwise
    we get weird build failures when running parallel builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
 
3
 
# Licensed under the same terms as Subversion.
4
 
 
5
 
# A pre-commit hook to detect case-insensitive filename clashes.
6
 
#
7
 
# What this script does:
8
 
#  - Detects new paths that 'clash' with existing, or other new, paths.
9
 
#  - Ignores existings paths that already 'clash'
10
 
#  - Exits with an error code, and a diagnostic on stderr, if 'clashes'
11
 
#    are detected.
12
 
#
13
 
# How it does it:
14
 
#  - Get a list of changed paths.
15
 
#  - From that list extract the new paths that represent adds or replaces.
16
 
#  - For each new path:
17
 
#    - Split the path into a directory and a name.
18
 
#    - Get the names of all the entries in the version of the directory
19
 
#      within the txn.
20
 
#    - Compare the canonical new name with each canonical entry name.
21
 
#    - If the canonical names match and the pristine names do not match
22
 
#      then we have a 'clash'.
23
 
#
24
 
# Notes:
25
 
#  - All the paths from the Subversion filesystem bindings are encoded
26
 
#    in UTF-8 and the separator is '/' on all OS's.
27
 
#  - The canonical form determines what constitutes a 'clash', at present
28
 
#    a simple 'lower case' is used.  That's probably not identical to the
29
 
#    behaviour of Windows or OSX, but it might be good enough.
30
 
#  - Hooks get invoked with an empty environment so this script explicitly
31
 
#    sets a locale; make sure it is a sensible value.
32
 
#  - If used with Apache the 'clash' diagnostic must be ASCII irrespective
33
 
#    of the locale, see the 'Force' comment near the end of the script for
34
 
#    one way to achieve this.
35
 
#
36
 
# How to call it:
37
 
#
38
 
#   On a Unix system put this script in the hooks directory and add this to
39
 
#   the pre-commit script:
40
 
#
41
 
#     $REPOS/hooks/case-insensitive.py "$REPOS" "$TXN" || exit 1
42
 
#
43
 
#   On a windows machine add this to pre-commit.bat:
44
 
#
45
 
#     python <path-to-script>\case-insensitive.py %1 %2
46
 
#     if errorlevel 1 goto :ERROR
47
 
#     exit 0
48
 
#     :ERROR
49
 
#     echo Error found in commit 1>&2
50
 
#     exit 1
51
 
#
52
 
#   Make sure the python bindings are installed and working on Windows.  The
53
 
#   zip file can be downloaded from the Subversion site.  The bindings depend
54
 
#   on dll's shipped as part of the Subversion binaries, if the script cannot
55
 
#   load the _fs dll it is because it cannot find the other Subversion dll's.
56
 
#
57
 
# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.6.x/contrib/hook-scripts/case-insensitive.py $
58
 
# $LastChangedRevision: 867334 $
59
 
# $LastChangedDate: 2007-10-17 22:04:06 +0000 (Wed, 17 Oct 2007) $
60
 
# $LastChangedBy: philip $
61
 
 
62
 
import sys, locale
63
 
sys.path.append('/usr/local/subversion/lib/svn-python')
64
 
from svn import repos, fs
65
 
locale.setlocale(locale.LC_ALL, 'en_GB')
66
 
 
67
 
def canonicalize(path):
68
 
  return path.decode('utf-8').lower().encode('utf-8')
69
 
 
70
 
def get_new_paths(txn_root):
71
 
  new_paths = []
72
 
  for path, change in fs.paths_changed(txn_root).iteritems():
73
 
    if (change.change_kind == fs.path_change_add
74
 
        or change.change_kind == fs.path_change_replace):
75
 
      new_paths.append(path)
76
 
  return new_paths
77
 
 
78
 
def split_path(path):
79
 
  slash = path.rindex('/')
80
 
  if (slash == 0):
81
 
    return '/', path[1:]
82
 
  return path[:slash], path[slash+1:]
83
 
 
84
 
def join_path(dir, name):
85
 
  if (dir == '/'):
86
 
    return '/' + name
87
 
  return dir + '/' + name
88
 
 
89
 
def ensure_names(path, names, txn_root):
90
 
  if (not names.has_key(path)):
91
 
     names[path] = []
92
 
     for name, dirent in fs.dir_entries(txn_root, path).iteritems():
93
 
       names[path].append([canonicalize(name), name])
94
 
 
95
 
names = {}   # map of: key - path, value - list of two element lists of names
96
 
clashes = {} # map of: key - path, value - map of: key - path, value - dummy
97
 
 
98
 
native = locale.getlocale()[1]
99
 
if not native: native = 'ascii'
100
 
repos_handle = repos.open(sys.argv[1].decode(native).encode('utf-8'))
101
 
fs_handle = repos.fs(repos_handle)
102
 
txn_handle = fs.open_txn(fs_handle, sys.argv[2].decode(native).encode('utf-8'))
103
 
txn_root = fs.txn_root(txn_handle)
104
 
 
105
 
new_paths = get_new_paths(txn_root)
106
 
for path in new_paths:
107
 
  dir, name = split_path(path)
108
 
  canonical = canonicalize(name)
109
 
  ensure_names(dir, names, txn_root)
110
 
  for name_pair in names[dir]:
111
 
    if (name_pair[0] == canonical and name_pair[1] != name):
112
 
      canonical_path = join_path(dir, canonical)
113
 
      if (not clashes.has_key(canonical_path)):
114
 
        clashes[canonical_path] = {}
115
 
      clashes[canonical_path][join_path(dir, name)] = True
116
 
      clashes[canonical_path][join_path(dir, name_pair[1])] = True
117
 
 
118
 
if (clashes):
119
 
  # native = 'ascii' # Force ASCII output for Apache
120
 
  for canonical_path in clashes.iterkeys():
121
 
    sys.stderr.write(u'Clash:'.encode(native))
122
 
    for path in clashes[canonical_path].iterkeys():
123
 
      sys.stderr.write(u' \''.encode(native) +
124
 
                       str(path).decode('utf-8').encode(native, 'replace') +
125
 
                       u'\''.encode(native))
126
 
    sys.stderr.write(u'\n'.encode(native))
127
 
  sys.exit(1)