comparison mercurial/match.py @ 26000:9ac4e81b9659 stable

match: fix a caseonly rename + explicit path commit on icasefs (issue4768) The problem was that the former name and the new name are both normalized to the case in dirstate, so matcher._files would be ['ABC.txt', 'ABC.txt']. localrepo.commit() calls localrepo.status(), passing along the matcher. Inside dirstate.status(), _walkexplicit() simply grabs matcher.files() and processes those items. Since the old name isn't present, it is silently dropped. There's a fundamental tension here, because the status command should also accept files that don't match the filesystem, so we can't drop the normalization in status. The problem originated in baa11dde8c0e. Unfortunately with this change, the case of the old file must still be specified exactly, or the old file is again silently excluded. I went back to baa11dde8c0e^, and that had the same behavior, so we are no worse off. I'm open to ideas from a matcher or dirstate expert on how to fix that half.
author Matt Harbison <matt_harbison@yahoo.com>
date Thu, 06 Aug 2015 21:00:16 -0400
parents 511e1949d557
children a5f62af29517
comparison
equal deleted inserted replaced
25997:d4e1e947444b 26000:9ac4e81b9659
384 """ 384 """
385 385
386 def __init__(self, root, cwd, patterns, include, exclude, default, auditor, 386 def __init__(self, root, cwd, patterns, include, exclude, default, auditor,
387 ctx, listsubrepos=False, badfn=None): 387 ctx, listsubrepos=False, badfn=None):
388 init = super(icasefsmatcher, self).__init__ 388 init = super(icasefsmatcher, self).__init__
389 self._dsnormalize = ctx.repo().dirstate.normalize 389 self._dirstate = ctx.repo().dirstate
390 self._dsnormalize = self._dirstate.normalize
390 391
391 init(root, cwd, patterns, include, exclude, default, auditor=auditor, 392 init(root, cwd, patterns, include, exclude, default, auditor=auditor,
392 ctx=ctx, listsubrepos=listsubrepos, badfn=badfn) 393 ctx=ctx, listsubrepos=listsubrepos, badfn=badfn)
393 394
394 # m.exact(file) must be based off of the actual user input, otherwise 395 # m.exact(file) must be based off of the actual user input, otherwise
400 self._kp = super(icasefsmatcher, self)._normalize(patterns, default, 401 self._kp = super(icasefsmatcher, self)._normalize(patterns, default,
401 root, cwd, auditor) 402 root, cwd, auditor)
402 kindpats = [] 403 kindpats = []
403 for kind, pats, source in self._kp: 404 for kind, pats, source in self._kp:
404 if kind not in ('re', 'relre'): # regex can't be normalized 405 if kind not in ('re', 'relre'): # regex can't be normalized
406 p = pats
405 pats = self._dsnormalize(pats) 407 pats = self._dsnormalize(pats)
408
409 # Preserve the original to handle a case only rename.
410 if p != pats and p in self._dirstate:
411 kindpats.append((kind, p, source))
412
406 kindpats.append((kind, pats, source)) 413 kindpats.append((kind, pats, source))
407 return kindpats 414 return kindpats
408 415
409 def patkind(pattern, default=None): 416 def patkind(pattern, default=None):
410 '''If pattern is 'kind:pat' with a known kind, return kind.''' 417 '''If pattern is 'kind:pat' with a known kind, return kind.'''