mercurial/remotenames.py
changeset 35347 a29fe459fc49
parent 35346 9eb19b13e92a
child 35348 576ba8194fa8
equal deleted inserted replaced
35346:9eb19b13e92a 35347:a29fe459fc49
     1 # remotenames.py
       
     2 #
       
     3 # Copyright 2017 Augie Fackler <raf@durin42.com>
       
     4 # Copyright 2017 Sean Farley <sean@farley.io>
       
     5 #
       
     6 # This software may be used and distributed according to the terms of the
       
     7 # GNU General Public License version 2 or any later version.
       
     8 
       
     9 from __future__ import absolute_import
       
    10 
       
    11 from .node import hex
       
    12 
       
    13 from . import (
       
    14     vfs as vfsmod,
       
    15 )
       
    16 
       
    17 # directory name in .hg/ in which remotenames files will be present
       
    18 remotenamedir = 'remotenames'
       
    19 
       
    20 def readremotenamefile(repo, filename):
       
    21     """
       
    22     reads a file from .hg/remotenames/ directory and yields it's content
       
    23     filename: the file to be read
       
    24     yield a tuple (node, remotepath, name)
       
    25     """
       
    26 
       
    27     vfs = vfsmod.vfs(repo.vfs.join(remotenamedir))
       
    28     if not vfs.exists(filename):
       
    29         return
       
    30     f = vfs(filename)
       
    31     lineno = 0
       
    32     for line in f:
       
    33         line = line.strip()
       
    34         if not line:
       
    35             continue
       
    36         # contains the version number
       
    37         if lineno == 0:
       
    38             lineno += 1
       
    39         try:
       
    40             node, remote, rname = line.split('\0')
       
    41             yield node, remote, rname
       
    42         except ValueError:
       
    43             pass
       
    44 
       
    45     f.close()
       
    46 
       
    47 def readremotenames(repo):
       
    48     """
       
    49     read the details about the remotenames stored in .hg/remotenames/ and
       
    50     yields a tuple (node, remotepath, name). It does not yields information
       
    51     about whether an entry yielded is branch or bookmark. To get that
       
    52     information, call the respective functions.
       
    53     """
       
    54 
       
    55     for bmentry in readremotenamefile(repo, 'bookmarks'):
       
    56         yield bmentry
       
    57     for branchentry in readremotenamefile(repo, 'branches'):
       
    58         yield branchentry
       
    59 
       
    60 def writeremotenamefile(repo, remotepath, names, nametype):
       
    61     vfs = vfsmod.vfs(repo.vfs.join(remotenamedir))
       
    62     f = vfs(nametype, 'w', atomictemp=True)
       
    63     # write the storage version info on top of file
       
    64     # version '0' represents the very initial version of the storage format
       
    65     f.write('0\n\n')
       
    66 
       
    67     olddata = set(readremotenamefile(repo, nametype))
       
    68     # re-save the data from a different remote than this one.
       
    69     for node, oldpath, rname in sorted(olddata):
       
    70         if oldpath != remotepath:
       
    71             f.write('%s\0%s\0%s\n' % (node, oldpath, rname))
       
    72 
       
    73     for name, node in sorted(names.iteritems()):
       
    74         if nametype == "branches":
       
    75             for n in node:
       
    76                 f.write('%s\0%s\0%s\n' % (n, remotepath, name))
       
    77         elif nametype == "bookmarks":
       
    78             if node:
       
    79                 f.write('%s\0%s\0%s\n' % (node, remotepath, name))
       
    80 
       
    81     f.close()
       
    82 
       
    83 def saveremotenames(repo, remotepath, branches=None, bookmarks=None):
       
    84     """
       
    85     save remotenames i.e. remotebookmarks and remotebranches in their
       
    86     respective files under ".hg/remotenames/" directory.
       
    87     """
       
    88     wlock = repo.wlock()
       
    89     try:
       
    90         if bookmarks:
       
    91             writeremotenamefile(repo, remotepath, bookmarks, 'bookmarks')
       
    92         if branches:
       
    93             writeremotenamefile(repo, remotepath, branches, 'branches')
       
    94     finally:
       
    95         wlock.release()
       
    96 
       
    97 def pullremotenames(localrepo, remoterepo):
       
    98     """
       
    99     pulls bookmarks and branches information of the remote repo during a
       
   100     pull or clone operation.
       
   101     localrepo is our local repository
       
   102     remoterepo is the peer instance
       
   103     """
       
   104     remotepath = remoterepo.url()
       
   105     bookmarks = remoterepo.listkeys('bookmarks')
       
   106     # on a push, we don't want to keep obsolete heads since
       
   107     # they won't show up as heads on the next pull, so we
       
   108     # remove them here otherwise we would require the user
       
   109     # to issue a pull to refresh the storage
       
   110     bmap = {}
       
   111     repo = localrepo.unfiltered()
       
   112     for branch, nodes in remoterepo.branchmap().iteritems():
       
   113         bmap[branch] = []
       
   114         for node in nodes:
       
   115             if node in repo and not repo[node].obsolete():
       
   116                 bmap[branch].append(hex(node))
       
   117 
       
   118     saveremotenames(localrepo, remotepath, bmap, bookmarks)