47 raise error.ConfigError( |
47 raise error.ConfigError( |
48 _("ui.portablefilenames value is invalid ('%s')") % val) |
48 _("ui.portablefilenames value is invalid ('%s')") % val) |
49 return abort, warn |
49 return abort, warn |
50 |
50 |
51 class casecollisionauditor(object): |
51 class casecollisionauditor(object): |
52 def __init__(self, ui, abort, existingiter): |
52 def __init__(self, ui, abort, dirstate): |
53 self._ui = ui |
53 self._ui = ui |
54 self._abort = abort |
54 self._abort = abort |
55 self._map = {} |
55 allfiles = '\0'.join(dirstate._map) |
56 for f in existingiter: |
56 self._loweredfiles = set(encoding.lower(allfiles).split('\0')) |
57 self._map[encoding.lower(f)] = f |
57 self._dirstate = dirstate |
|
58 # The purpose of _newfiles is so that we don't complain about |
|
59 # case collisions if someone were to call this object with the |
|
60 # same filename twice. |
|
61 self._newfiles = set() |
58 |
62 |
59 def __call__(self, f): |
63 def __call__(self, f): |
60 fl = encoding.lower(f) |
64 fl = encoding.lower(f) |
61 map = self._map |
65 if (fl in self._loweredfiles and f not in self._dirstate and |
62 if fl in map and map[fl] != f: |
66 f not in self._newfiles): |
63 msg = _('possible case-folding collision for %s') % f |
67 msg = _('possible case-folding collision for %s') % f |
64 if self._abort: |
68 if self._abort: |
65 raise util.Abort(msg) |
69 raise util.Abort(msg) |
66 self._ui.warn(_("warning: %s\n") % msg) |
70 self._ui.warn(_("warning: %s\n") % msg) |
67 map[fl] = f |
71 self._loweredfiles.add(fl) |
|
72 self._newfiles.add(f) |
68 |
73 |
69 class pathauditor(object): |
74 class pathauditor(object): |
70 '''ensure that a filesystem path contains no banned components. |
75 '''ensure that a filesystem path contains no banned components. |
71 the following properties of a path are checked: |
76 the following properties of a path are checked: |
72 |
77 |