mercurial/changelog.py
changeset 43147 54e943b28101
parent 43146 0171483b082f
child 43230 e51f5d06a99c
equal deleted inserted replaced
43146:0171483b082f 43147:54e943b28101
    14     nullid,
    14     nullid,
    15 )
    15 )
    16 from .thirdparty import attr
    16 from .thirdparty import attr
    17 
    17 
    18 from . import (
    18 from . import (
       
    19     copies,
    19     encoding,
    20     encoding,
    20     error,
    21     error,
    21     pycompat,
    22     pycompat,
    22     revlog,
    23     revlog,
    23     util,
    24     util,
    87         for k in sorted(d)
    88         for k in sorted(d)
    88     ]
    89     ]
    89     return b"\0".join(items)
    90     return b"\0".join(items)
    90 
    91 
    91 
    92 
    92 def encodecopies(files, copies):
       
    93     items = []
       
    94     for i, dst in enumerate(files):
       
    95         if dst in copies:
       
    96             items.append(b'%d\0%s' % (i, copies[dst]))
       
    97     if len(items) != len(copies):
       
    98         raise error.ProgrammingError(
       
    99             b'some copy targets missing from file list'
       
   100         )
       
   101     return b"\n".join(items)
       
   102 
       
   103 
       
   104 def decodecopies(files, data):
       
   105     try:
       
   106         copies = {}
       
   107         if not data:
       
   108             return copies
       
   109         for l in data.split(b'\n'):
       
   110             strindex, src = l.split(b'\0')
       
   111             i = int(strindex)
       
   112             dst = files[i]
       
   113             copies[dst] = src
       
   114         return copies
       
   115     except (ValueError, IndexError):
       
   116         # Perhaps someone had chosen the same key name (e.g. "p1copies") and
       
   117         # used different syntax for the value.
       
   118         return None
       
   119 
       
   120 
       
   121 def encodefileindices(files, subset):
       
   122     subset = set(subset)
       
   123     indices = []
       
   124     for i, f in enumerate(files):
       
   125         if f in subset:
       
   126             indices.append(b'%d' % i)
       
   127     return b'\n'.join(indices)
       
   128 
       
   129 
       
   130 def decodefileindices(files, data):
       
   131     try:
       
   132         subset = []
       
   133         if not data:
       
   134             return subset
       
   135         for strindex in data.split(b'\n'):
       
   136             i = int(strindex)
       
   137             if i < 0 or i >= len(files):
       
   138                 return None
       
   139             subset.append(files[i])
       
   140         return subset
       
   141     except (ValueError, IndexError):
       
   142         # Perhaps someone had chosen the same key name (e.g. "added") and
       
   143         # used different syntax for the value.
       
   144         return None
       
   145 
       
   146 
       
   147 def stripdesc(desc):
    93 def stripdesc(desc):
   148     """strip trailing whitespace and leading and trailing empty lines"""
    94     """strip trailing whitespace and leading and trailing empty lines"""
   149     return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n')
    95     return b'\n'.join([l.rstrip() for l in desc.splitlines()]).strip(b'\n')
   150 
    96 
   151 
    97 
   366             rawindices = self._sidedata.get(sidedatamod.SD_FILESADDED)
   312             rawindices = self._sidedata.get(sidedatamod.SD_FILESADDED)
   367         else:
   313         else:
   368             rawindices = self.extra.get(b'filesadded')
   314             rawindices = self.extra.get(b'filesadded')
   369         if rawindices is None:
   315         if rawindices is None:
   370             return None
   316             return None
   371         return decodefileindices(self.files, rawindices)
   317         return copies.decodefileindices(self.files, rawindices)
   372 
   318 
   373     @property
   319     @property
   374     def filesremoved(self):
   320     def filesremoved(self):
   375         if sidedatamod.SD_FILESREMOVED in self._sidedata:
   321         if sidedatamod.SD_FILESREMOVED in self._sidedata:
   376             rawindices = self._sidedata.get(sidedatamod.SD_FILESREMOVED)
   322             rawindices = self._sidedata.get(sidedatamod.SD_FILESREMOVED)
   377         else:
   323         else:
   378             rawindices = self.extra.get(b'filesremoved')
   324             rawindices = self.extra.get(b'filesremoved')
   379         if rawindices is None:
   325         if rawindices is None:
   380             return None
   326             return None
   381         return decodefileindices(self.files, rawindices)
   327         return copies.decodefileindices(self.files, rawindices)
   382 
   328 
   383     @property
   329     @property
   384     def p1copies(self):
   330     def p1copies(self):
   385         if sidedatamod.SD_P1COPIES in self._sidedata:
   331         if sidedatamod.SD_P1COPIES in self._sidedata:
   386             rawcopies = self._sidedata.get(sidedatamod.SD_P1COPIES)
   332             rawcopies = self._sidedata.get(sidedatamod.SD_P1COPIES)
   387         else:
   333         else:
   388             rawcopies = self.extra.get(b'p1copies')
   334             rawcopies = self.extra.get(b'p1copies')
   389         if rawcopies is None:
   335         if rawcopies is None:
   390             return None
   336             return None
   391         return decodecopies(self.files, rawcopies)
   337         return copies.decodecopies(self.files, rawcopies)
   392 
   338 
   393     @property
   339     @property
   394     def p2copies(self):
   340     def p2copies(self):
   395         if sidedatamod.SD_P2COPIES in self._sidedata:
   341         if sidedatamod.SD_P2COPIES in self._sidedata:
   396             rawcopies = self._sidedata.get(sidedatamod.SD_P2COPIES)
   342             rawcopies = self._sidedata.get(sidedatamod.SD_P2COPIES)
   397         else:
   343         else:
   398             rawcopies = self.extra.get(b'p2copies')
   344             rawcopies = self.extra.get(b'p2copies')
   399         if rawcopies is None:
   345         if rawcopies is None:
   400             return None
   346             return None
   401         return decodecopies(self.files, rawcopies)
   347         return copies.decodecopies(self.files, rawcopies)
   402 
   348 
   403     @property
   349     @property
   404     def description(self):
   350     def description(self):
   405         return encoding.tolocal(self._text[self._offsets[3] + 2 :])
   351         return encoding.tolocal(self._text[self._offsets[3] + 2 :])
   406 
   352 
   709                 b'filesadded',
   655                 b'filesadded',
   710                 b'filesremoved',
   656                 b'filesremoved',
   711             ):
   657             ):
   712                 extra.pop(name, None)
   658                 extra.pop(name, None)
   713         if p1copies is not None:
   659         if p1copies is not None:
   714             p1copies = encodecopies(sortedfiles, p1copies)
   660             p1copies = copies.encodecopies(sortedfiles, p1copies)
   715         if p2copies is not None:
   661         if p2copies is not None:
   716             p2copies = encodecopies(sortedfiles, p2copies)
   662             p2copies = copies.encodecopies(sortedfiles, p2copies)
   717         if filesadded is not None:
   663         if filesadded is not None:
   718             filesadded = encodefileindices(sortedfiles, filesadded)
   664             filesadded = copies.encodefileindices(sortedfiles, filesadded)
   719         if filesremoved is not None:
   665         if filesremoved is not None:
   720             filesremoved = encodefileindices(sortedfiles, filesremoved)
   666             filesremoved = copies.encodefileindices(sortedfiles, filesremoved)
   721         if self._copiesstorage == b'extra':
   667         if self._copiesstorage == b'extra':
   722             extrasentries = p1copies, p2copies, filesadded, filesremoved
   668             extrasentries = p1copies, p2copies, filesadded, filesremoved
   723             if extra is None and any(x is not None for x in extrasentries):
   669             if extra is None and any(x is not None for x in extrasentries):
   724                 extra = {}
   670                 extra = {}
   725             if p1copies is not None:
   671             if p1copies is not None: