hgext3rd/evolve/legacy.py
changeset 1810 ce4018f03520
parent 1757 86e71a0b3319
child 2025 d286222293c8
equal deleted inserted replaced
1809:7edd4ceefce0 1810:ce4018f03520
       
     1 # Copyright 2011 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
       
     2 #                Logilab SA        <contact@logilab.fr>
       
     3 #
       
     4 # This software may be used and distributed according to the terms of the
       
     5 # GNU General Public License version 2 or any later version.
       
     6 """Deprecated extension that formerly introduced "Changeset Obsolescence".
       
     7 
       
     8 This concept is now partially in Mercurial core (starting with Mercurial 2.3).
       
     9 The remaining logic has been grouped with the evolve extension.
       
    10 
       
    11 Some code remains in this extensions to detect and convert prehistoric format
       
    12 of obsolete marker than early user may have create. Keep it enabled if you
       
    13 were such user.
       
    14 """
       
    15 
       
    16 from mercurial import error
       
    17 
       
    18 try:
       
    19     from mercurial import obsolete
       
    20 except ImportError:
       
    21     raise error.Abort('Obsolete extension requires Mercurial 2.3 (or later)')
       
    22 
       
    23 import sys
       
    24 import json
       
    25 
       
    26 from mercurial import cmdutil
       
    27 from mercurial.i18n import _
       
    28 from mercurial.node import bin, nullid
       
    29 from mercurial import util
       
    30 
       
    31 
       
    32 #####################################################################
       
    33 ### Older format management                                       ###
       
    34 #####################################################################
       
    35 
       
    36 # Code related to detection and management of older legacy format never
       
    37 # handled by core
       
    38 
       
    39 
       
    40 def reposetup(ui, repo):
       
    41     """Detect that a repo still contains some old obsolete format
       
    42     """
       
    43     if not repo.local():
       
    44         return
       
    45     evolveopts = ui.configlist('experimental', 'evolution')
       
    46     if not evolveopts:
       
    47         evolveopts = 'all'
       
    48         ui.setconfig('experimental', 'evolution', evolveopts)
       
    49     for arg in sys.argv:
       
    50         if 'debugc' in arg:
       
    51             break
       
    52     else:
       
    53         data = repo.opener.tryread('obsolete-relations')
       
    54         if not data:
       
    55             data = repo.svfs.tryread('obsoletemarkers')
       
    56         if data:
       
    57             raise error.Abort('old format of obsolete marker detected!\n'
       
    58                               'run `hg debugconvertobsolete` once.')
       
    59 
       
    60 def _obsdeserialize(flike):
       
    61     """read a file like object serialized with _obsserialize
       
    62 
       
    63     this deserialize into a {subject -> objects} mapping
       
    64 
       
    65     this was the very first format ever."""
       
    66     rels = {}
       
    67     for line in flike:
       
    68         subhex, objhex = line.split()
       
    69         subnode = bin(subhex)
       
    70         if subnode == nullid:
       
    71             subnode = None
       
    72         rels.setdefault(subnode, set()).add(bin(objhex))
       
    73     return rels
       
    74 
       
    75 cmdtable = {}
       
    76 command = cmdutil.command(cmdtable)
       
    77 @command('debugconvertobsolete', [], '')
       
    78 def cmddebugconvertobsolete(ui, repo):
       
    79     """import markers from an .hg/obsolete-relations file"""
       
    80     cnt = 0
       
    81     err = 0
       
    82     l = repo.lock()
       
    83     some = False
       
    84     try:
       
    85         unlink = []
       
    86         tr = repo.transaction('convert-obsolete')
       
    87         try:
       
    88             repo._importoldobsolete = True
       
    89             store = repo.obsstore
       
    90             ### very first format
       
    91             try:
       
    92                 f = repo.opener('obsolete-relations')
       
    93                 try:
       
    94                     some = True
       
    95                     for line in f:
       
    96                         subhex, objhex = line.split()
       
    97                         suc = bin(subhex)
       
    98                         prec = bin(objhex)
       
    99                         sucs = (suc==nullid) and [] or [suc]
       
   100                         meta = {
       
   101                             'date':  '%i %i' % util.makedate(),
       
   102                             'user': ui.username(),
       
   103                             }
       
   104                         try:
       
   105                             store.create(tr, prec, sucs, 0, metadata=meta)
       
   106                             cnt += 1
       
   107                         except ValueError:
       
   108                             repo.ui.write_err("invalid old marker line: %s"
       
   109                                               % (line))
       
   110                             err += 1
       
   111                 finally:
       
   112                     f.close()
       
   113                 unlink.append(repo.join('obsolete-relations'))
       
   114             except IOError:
       
   115                 pass
       
   116             ### second (json) format
       
   117             data = repo.svfs.tryread('obsoletemarkers')
       
   118             if data:
       
   119                 some = True
       
   120                 for oldmark in json.loads(data):
       
   121                     del oldmark['id']  # dropped for now
       
   122                     del oldmark['reason']  # unused until then
       
   123                     oldobject = str(oldmark.pop('object'))
       
   124                     oldsubjects = [str(s) for s in oldmark.pop('subjects', [])]
       
   125                     LOOKUP_ERRORS = (error.RepoLookupError, error.LookupError)
       
   126                     if len(oldobject) != 40:
       
   127                         try:
       
   128                             oldobject = repo[oldobject].node()
       
   129                         except LOOKUP_ERRORS:
       
   130                             pass
       
   131                     if any(len(s) != 40 for s in oldsubjects):
       
   132                         try:
       
   133                             oldsubjects = [repo[s].node() for s in oldsubjects]
       
   134                         except LOOKUP_ERRORS:
       
   135                             pass
       
   136 
       
   137                     oldmark['date'] = '%i %i' % tuple(oldmark['date'])
       
   138                     meta = dict((k.encode('utf-8'), v.encode('utf-8'))
       
   139                                  for k, v in oldmark.iteritems())
       
   140                     try:
       
   141                         succs = [bin(n) for n in oldsubjects]
       
   142                         succs = [n for n in succs if n != nullid]
       
   143                         store.create(tr, bin(oldobject), succs,
       
   144                                      0, metadata=meta)
       
   145                         cnt += 1
       
   146                     except ValueError:
       
   147                         repo.ui.write_err("invalid marker %s -> %s\n"
       
   148                                      % (oldobject, oldsubjects))
       
   149                         err += 1
       
   150                 unlink.append(repo.sjoin('obsoletemarkers'))
       
   151             tr.close()
       
   152             for path in unlink:
       
   153                 util.unlink(path)
       
   154         finally:
       
   155             tr.release()
       
   156     finally:
       
   157         del repo._importoldobsolete
       
   158         l.release()
       
   159     if not some:
       
   160         ui.warn(_('nothing to do\n'))
       
   161     ui.status('%i obsolete marker converted\n' % cnt)
       
   162     if err:
       
   163         ui.write_err('%i conversion failed. check you graph!\n' % err)