mercurial/repository.py
changeset 37320 39f7d4ee8bcd
parent 37316 836867586b83
child 37351 fdd22bf6398f
equal deleted inserted replaced
37319:36d17f37db91 37320:39f7d4ee8bcd
     4 #
     4 #
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 
     7 
     8 from __future__ import absolute_import
     8 from __future__ import absolute_import
     9 
       
    10 import abc
       
    11 
     9 
    12 from .i18n import _
    10 from .i18n import _
    13 from .thirdparty.zope import (
    11 from .thirdparty.zope import (
    14     interface as zi,
    12     interface as zi,
    15 )
    13 )
    16 from . import (
    14 from . import (
    17     error,
    15     error,
    18 )
    16 )
    19 
    17 
    20 class _basepeer(object):
    18 class ipeerconnection(zi.Interface):
    21     """Represents a "connection" to a repository.
    19     """Represents a "connection" to a repository.
    22 
    20 
    23     This is the base interface for representing a connection to a repository.
    21     This is the base interface for representing a connection to a repository.
    24     It holds basic properties and methods applicable to all peer types.
    22     It holds basic properties and methods applicable to all peer types.
    25 
    23 
    26     This is not a complete interface definition and should not be used
    24     This is not a complete interface definition and should not be used
    27     outside of this module.
    25     outside of this module.
    28     """
    26     """
    29     __metaclass__ = abc.ABCMeta
    27     ui = zi.Attribute("""ui.ui instance""")
    30 
    28 
    31     @abc.abstractproperty
    29     def url():
    32     def ui(self):
       
    33         """ui.ui instance."""
       
    34 
       
    35     @abc.abstractmethod
       
    36     def url(self):
       
    37         """Returns a URL string representing this peer.
    30         """Returns a URL string representing this peer.
    38 
    31 
    39         Currently, implementations expose the raw URL used to construct the
    32         Currently, implementations expose the raw URL used to construct the
    40         instance. It may contain credentials as part of the URL. The
    33         instance. It may contain credentials as part of the URL. The
    41         expectations of the value aren't well-defined and this could lead to
    34         expectations of the value aren't well-defined and this could lead to
    43 
    36 
    44         TODO audit/clean consumers and more clearly define the contents of this
    37         TODO audit/clean consumers and more clearly define the contents of this
    45         value.
    38         value.
    46         """
    39         """
    47 
    40 
    48     @abc.abstractmethod
    41     def local():
    49     def local(self):
       
    50         """Returns a local repository instance.
    42         """Returns a local repository instance.
    51 
    43 
    52         If the peer represents a local repository, returns an object that
    44         If the peer represents a local repository, returns an object that
    53         can be used to interface with it. Otherwise returns ``None``.
    45         can be used to interface with it. Otherwise returns ``None``.
    54         """
    46         """
    55 
    47 
    56     @abc.abstractmethod
    48     def peer():
    57     def peer(self):
       
    58         """Returns an object conforming to this interface.
    49         """Returns an object conforming to this interface.
    59 
    50 
    60         Most implementations will ``return self``.
    51         Most implementations will ``return self``.
    61         """
    52         """
    62 
    53 
    63     @abc.abstractmethod
    54     def canpush():
    64     def canpush(self):
       
    65         """Returns a boolean indicating if this peer can be pushed to."""
    55         """Returns a boolean indicating if this peer can be pushed to."""
    66 
    56 
    67     @abc.abstractmethod
    57     def close():
    68     def close(self):
       
    69         """Close the connection to this peer.
    58         """Close the connection to this peer.
    70 
    59 
    71         This is called when the peer will no longer be used. Resources
    60         This is called when the peer will no longer be used. Resources
    72         associated with the peer should be cleaned up.
    61         associated with the peer should be cleaned up.
    73         """
    62         """
    74 
    63 
    75 class _basewirecommands(object):
    64 class ipeercommands(zi.Interface):
    76     """Client-side interface for communicating over the wire protocol.
    65     """Client-side interface for communicating over the wire protocol.
    77 
    66 
    78     This interface is used as a gateway to the Mercurial wire protocol.
    67     This interface is used as a gateway to the Mercurial wire protocol.
    79     methods commonly call wire protocol commands of the same name.
    68     methods commonly call wire protocol commands of the same name.
    80     """
    69     """
    81     __metaclass__ = abc.ABCMeta
    70 
    82 
    71     def branchmap():
    83     @abc.abstractmethod
       
    84     def branchmap(self):
       
    85         """Obtain heads in named branches.
    72         """Obtain heads in named branches.
    86 
    73 
    87         Returns a dict mapping branch name to an iterable of nodes that are
    74         Returns a dict mapping branch name to an iterable of nodes that are
    88         heads on that branch.
    75         heads on that branch.
    89         """
    76         """
    90 
    77 
    91     @abc.abstractmethod
    78     def capabilities():
    92     def capabilities(self):
       
    93         """Obtain capabilities of the peer.
    79         """Obtain capabilities of the peer.
    94 
    80 
    95         Returns a set of string capabilities.
    81         Returns a set of string capabilities.
    96         """
    82         """
    97 
    83 
    98     @abc.abstractmethod
    84     def debugwireargs(one, two, three=None, four=None, five=None):
    99     def debugwireargs(self, one, two, three=None, four=None, five=None):
       
   100         """Used to facilitate debugging of arguments passed over the wire."""
    85         """Used to facilitate debugging of arguments passed over the wire."""
   101 
    86 
   102     @abc.abstractmethod
    87     def getbundle(source, **kwargs):
   103     def getbundle(self, source, **kwargs):
       
   104         """Obtain remote repository data as a bundle.
    88         """Obtain remote repository data as a bundle.
   105 
    89 
   106         This command is how the bulk of repository data is transferred from
    90         This command is how the bulk of repository data is transferred from
   107         the peer to the local repository
    91         the peer to the local repository
   108 
    92 
   109         Returns a generator of bundle data.
    93         Returns a generator of bundle data.
   110         """
    94         """
   111 
    95 
   112     @abc.abstractmethod
    96     def heads():
   113     def heads(self):
       
   114         """Determine all known head revisions in the peer.
    97         """Determine all known head revisions in the peer.
   115 
    98 
   116         Returns an iterable of binary nodes.
    99         Returns an iterable of binary nodes.
   117         """
   100         """
   118 
   101 
   119     @abc.abstractmethod
   102     def known(nodes):
   120     def known(self, nodes):
       
   121         """Determine whether multiple nodes are known.
   103         """Determine whether multiple nodes are known.
   122 
   104 
   123         Accepts an iterable of nodes whose presence to check for.
   105         Accepts an iterable of nodes whose presence to check for.
   124 
   106 
   125         Returns an iterable of booleans indicating of the corresponding node
   107         Returns an iterable of booleans indicating of the corresponding node
   126         at that index is known to the peer.
   108         at that index is known to the peer.
   127         """
   109         """
   128 
   110 
   129     @abc.abstractmethod
   111     def listkeys(namespace):
   130     def listkeys(self, namespace):
       
   131         """Obtain all keys in a pushkey namespace.
   112         """Obtain all keys in a pushkey namespace.
   132 
   113 
   133         Returns an iterable of key names.
   114         Returns an iterable of key names.
   134         """
   115         """
   135 
   116 
   136     @abc.abstractmethod
   117     def lookup(key):
   137     def lookup(self, key):
       
   138         """Resolve a value to a known revision.
   118         """Resolve a value to a known revision.
   139 
   119 
   140         Returns a binary node of the resolved revision on success.
   120         Returns a binary node of the resolved revision on success.
   141         """
   121         """
   142 
   122 
   143     @abc.abstractmethod
   123     def pushkey(namespace, key, old, new):
   144     def pushkey(self, namespace, key, old, new):
       
   145         """Set a value using the ``pushkey`` protocol.
   124         """Set a value using the ``pushkey`` protocol.
   146 
   125 
   147         Arguments correspond to the pushkey namespace and key to operate on and
   126         Arguments correspond to the pushkey namespace and key to operate on and
   148         the old and new values for that key.
   127         the old and new values for that key.
   149 
   128 
   150         Returns a string with the peer result. The value inside varies by the
   129         Returns a string with the peer result. The value inside varies by the
   151         namespace.
   130         namespace.
   152         """
   131         """
   153 
   132 
   154     @abc.abstractmethod
   133     def stream_out():
   155     def stream_out(self):
       
   156         """Obtain streaming clone data.
   134         """Obtain streaming clone data.
   157 
   135 
   158         Successful result should be a generator of data chunks.
   136         Successful result should be a generator of data chunks.
   159         """
   137         """
   160 
   138 
   161     @abc.abstractmethod
   139     def unbundle(bundle, heads, url):
   162     def unbundle(self, bundle, heads, url):
       
   163         """Transfer repository data to the peer.
   140         """Transfer repository data to the peer.
   164 
   141 
   165         This is how the bulk of data during a push is transferred.
   142         This is how the bulk of data during a push is transferred.
   166 
   143 
   167         Returns the integer number of heads added to the peer.
   144         Returns the integer number of heads added to the peer.
   168         """
   145         """
   169 
   146 
   170 class _baselegacywirecommands(object):
   147 class ipeerlegacycommands(zi.Interface):
   171     """Interface for implementing support for legacy wire protocol commands.
   148     """Interface for implementing support for legacy wire protocol commands.
   172 
   149 
   173     Wire protocol commands transition to legacy status when they are no longer
   150     Wire protocol commands transition to legacy status when they are no longer
   174     used by modern clients. To facilitate identifying which commands are
   151     used by modern clients. To facilitate identifying which commands are
   175     legacy, the interfaces are split.
   152     legacy, the interfaces are split.
   176     """
   153     """
   177     __metaclass__ = abc.ABCMeta
   154 
   178 
   155     def between(pairs):
   179     @abc.abstractmethod
       
   180     def between(self, pairs):
       
   181         """Obtain nodes between pairs of nodes.
   156         """Obtain nodes between pairs of nodes.
   182 
   157 
   183         ``pairs`` is an iterable of node pairs.
   158         ``pairs`` is an iterable of node pairs.
   184 
   159 
   185         Returns an iterable of iterables of nodes corresponding to each
   160         Returns an iterable of iterables of nodes corresponding to each
   186         requested pair.
   161         requested pair.
   187         """
   162         """
   188 
   163 
   189     @abc.abstractmethod
   164     def branches(nodes):
   190     def branches(self, nodes):
       
   191         """Obtain ancestor changesets of specific nodes back to a branch point.
   165         """Obtain ancestor changesets of specific nodes back to a branch point.
   192 
   166 
   193         For each requested node, the peer finds the first ancestor node that is
   167         For each requested node, the peer finds the first ancestor node that is
   194         a DAG root or is a merge.
   168         a DAG root or is a merge.
   195 
   169 
   196         Returns an iterable of iterables with the resolved values for each node.
   170         Returns an iterable of iterables with the resolved values for each node.
   197         """
   171         """
   198 
   172 
   199     @abc.abstractmethod
   173     def changegroup(nodes, kind):
   200     def changegroup(self, nodes, kind):
       
   201         """Obtain a changegroup with data for descendants of specified nodes."""
   174         """Obtain a changegroup with data for descendants of specified nodes."""
   202 
   175 
   203     @abc.abstractmethod
   176     def changegroupsubset(bases, heads, kind):
   204     def changegroupsubset(self, bases, heads, kind):
   177         pass
   205         pass
   178 
   206 
   179 class ipeerbase(ipeerconnection, ipeercommands):
   207 class peer(_basepeer, _basewirecommands):
   180     """Unified interface for peer repositories.
   208     """Unified interface and base class for peer repositories.
   181 
   209 
   182     All peer instances must conform to this interface.
   210     All peer instances must inherit from this class and conform to its
       
   211     interface.
       
   212     """
   183     """
   213 
   184     def iterbatch():
   214     @abc.abstractmethod
       
   215     def iterbatch(self):
       
   216         """Obtain an object to be used for multiple method calls.
   185         """Obtain an object to be used for multiple method calls.
   217 
   186 
   218         Various operations call several methods on peer instances. If each
   187         Various operations call several methods on peer instances. If each
   219         method call were performed immediately and serially, this would
   188         method call were performed immediately and serially, this would
   220         require round trips to remote peers and/or would slow down execution.
   189         require round trips to remote peers and/or would slow down execution.
   234 
   203 
   235         Not all peers or wire protocol implementations may actually batch method
   204         Not all peers or wire protocol implementations may actually batch method
   236         calls. However, they must all support this API.
   205         calls. However, they must all support this API.
   237         """
   206         """
   238 
   207 
   239     def capable(self, name):
   208     def capable(name):
   240         """Determine support for a named capability.
   209         """Determine support for a named capability.
   241 
   210 
   242         Returns ``False`` if capability not supported.
   211         Returns ``False`` if capability not supported.
   243 
   212 
   244         Returns ``True`` if boolean capability is supported. Returns a string
   213         Returns ``True`` if boolean capability is supported. Returns a string
   245         if capability support is non-boolean.
   214         if capability support is non-boolean.
   246         """
   215         """
       
   216 
       
   217     def requirecap(name, purpose):
       
   218         """Require a capability to be present.
       
   219 
       
   220         Raises a ``CapabilityError`` if the capability isn't present.
       
   221         """
       
   222 
       
   223 class ipeerbaselegacycommands(ipeerbase, ipeerlegacycommands):
       
   224     """Unified peer interface that supports legacy commands."""
       
   225 
       
   226 @zi.implementer(ipeerbase)
       
   227 class peer(object):
       
   228     """Base class for peer repositories."""
       
   229 
       
   230     def capable(self, name):
   247         caps = self.capabilities()
   231         caps = self.capabilities()
   248         if name in caps:
   232         if name in caps:
   249             return True
   233             return True
   250 
   234 
   251         name = '%s=' % name
   235         name = '%s=' % name
   254                 return cap[len(name):]
   238                 return cap[len(name):]
   255 
   239 
   256         return False
   240         return False
   257 
   241 
   258     def requirecap(self, name, purpose):
   242     def requirecap(self, name, purpose):
   259         """Require a capability to be present.
       
   260 
       
   261         Raises a ``CapabilityError`` if the capability isn't present.
       
   262         """
       
   263         if self.capable(name):
   243         if self.capable(name):
   264             return
   244             return
   265 
   245 
   266         raise error.CapabilityError(
   246         raise error.CapabilityError(
   267             _('cannot %s; remote repository does not support the %r '
   247             _('cannot %s; remote repository does not support the %r '
   268               'capability') % (purpose, name))
   248               'capability') % (purpose, name))
   269 
   249 
   270 class legacypeer(peer, _baselegacywirecommands):
   250 @zi.implementer(ipeerbaselegacycommands)
       
   251 class legacypeer(peer):
   271     """peer but with support for legacy wire protocol commands."""
   252     """peer but with support for legacy wire protocol commands."""
   272 
   253 
   273 class completelocalrepository(zi.Interface):
   254 class completelocalrepository(zi.Interface):
   274     """Monolithic interface for local repositories.
   255     """Monolithic interface for local repositories.
   275 
   256