mercurial/bundlerepo.py
changeset 1946 9fee186f7f0d
parent 1942 9da45de3118d
child 1971 915b81a35e46
equal deleted inserted replaced
1945:dec6d3c13dbf 1946:9fee186f7f0d
    13 from node import *
    13 from node import *
    14 from i18n import gettext as _
    14 from i18n import gettext as _
    15 from demandload import demandload
    15 from demandload import demandload
    16 demandload(globals(), "util os struct")
    16 demandload(globals(), "util os struct")
    17 
    17 
    18 from changelog import changelog
    18 import localrepo, changelog, manifest, filelog, revlog
    19 from manifest import manifest
       
    20 from filelog import filelog
       
    21 from localrepo import localrepository
       
    22 from revlog import *
       
    23 
    19 
    24 def getchunk(source):
    20 def getchunk(source):
    25     """get a chunk from a group"""
    21     """get a chunk from a group"""
    26     d = source.read(4)
    22     d = source.read(4)
    27     if not d:
    23     if not d:
    34         raise util.Abort(_("premature EOF reading chunk"
    30         raise util.Abort(_("premature EOF reading chunk"
    35                            " (got %d bytes, expected %d)")
    31                            " (got %d bytes, expected %d)")
    36                           % (len(d), l - 4))
    32                           % (len(d), l - 4))
    37     return d
    33     return d
    38 
    34 
    39 class bundlerevlog(revlog):
    35 class bundlerevlog(revlog.revlog):
    40     def __init__(self, opener, indexfile, datafile, bundlefile,
    36     def __init__(self, opener, indexfile, datafile, bundlefile,
    41                  linkmapper=None):
    37                  linkmapper=None):
    42         # How it works:
    38         # How it works:
    43         # to retrieve a revision, we need to know the offset of
    39         # to retrieve a revision, we need to know the offset of
    44         # the revision in the bundlefile (an opened file).
    40         # the revision in the bundlefile (an opened file).
    46         # We store this offset in the index (start), to differentiate a
    42         # We store this offset in the index (start), to differentiate a
    47         # rev in the bundle and from a rev in the revlog, we check
    43         # rev in the bundle and from a rev in the revlog, we check
    48         # len(index[r]). If the tuple is bigger than 7, it is a bundle
    44         # len(index[r]). If the tuple is bigger than 7, it is a bundle
    49         # (it is bigger since we store the node to which the delta is)
    45         # (it is bigger since we store the node to which the delta is)
    50         #
    46         #
    51         revlog.__init__(self, opener, indexfile, datafile)
    47         revlog.revlog.__init__(self, opener, indexfile, datafile)
    52         self.bundlefile = bundlefile
    48         self.bundlefile = bundlefile
    53         def genchunk():
    49         def genchunk():
    54             while 1:
    50             while 1:
    55                 pos = bundlefile.tell()
    51                 pos = bundlefile.tell()
    56                 chunk = getchunk(bundlefile)
    52                 chunk = getchunk(bundlefile)
    78                 link = linkmapper(cs)
    74                 link = linkmapper(cs)
    79 
    75 
    80             if not prev:
    76             if not prev:
    81                 prev = p1
    77                 prev = p1
    82             # start, size, base is not used, link, p1, p2, delta ref
    78             # start, size, base is not used, link, p1, p2, delta ref
    83             # warning: 
       
    84             e = (start, size, None, link, p1, p2, node, prev)
    79             e = (start, size, None, link, p1, p2, node, prev)
    85             self.index.append(e)
    80             self.index.append(e)
    86             self.nodemap[node] = n
    81             self.nodemap[node] = n
    87             prev = node
    82             prev = node
    88             n += 1
    83             n += 1
    96     def chunk(self, rev):
    91     def chunk(self, rev):
    97         # Warning: in case of bundle, the diff is against bundlebase,
    92         # Warning: in case of bundle, the diff is against bundlebase,
    98         # not against rev - 1
    93         # not against rev - 1
    99         # XXX: could use some caching
    94         # XXX: could use some caching
   100         if not self.bundle(rev):
    95         if not self.bundle(rev):
   101             return revlog.chunk(self, rev)
    96             return revlog.revlog.chunk(self, rev)
   102         self.bundlefile.seek(self.start(rev))
    97         self.bundlefile.seek(self.start(rev))
   103         return self.bundlefile.read(self.length(rev))
    98         return self.bundlefile.read(self.length(rev))
   104 
    99 
   105     def revdiff(self, rev1, rev2):
   100     def revdiff(self, rev1, rev2):
   106         """return or calculate a delta between two revisions"""
   101         """return or calculate a delta between two revisions"""
   108             # hot path for bundle
   103             # hot path for bundle
   109             revb = self.rev(self.bundlebase(rev2))
   104             revb = self.rev(self.bundlebase(rev2))
   110             if revb == rev1:
   105             if revb == rev1:
   111                 return self.chunk(rev2)
   106                 return self.chunk(rev2)
   112         elif not self.bundle(rev1) and not self.bundle(rev2):
   107         elif not self.bundle(rev1) and not self.bundle(rev2):
   113             return revlog.chunk(self, rev1, rev2)
   108             return revlog.revlog.chunk(self, rev1, rev2)
   114 
   109 
   115         return self.diff(self.revision(self.node(rev1)),
   110         return self.diff(self.revision(self.node(rev1)),
   116                          self.revision(self.node(rev2)))
   111                          self.revision(self.node(rev2)))
   117 
   112 
   118     def revision(self, node):
   113     def revision(self, node):
   130                 break
   125                 break
   131             chain.append(rev)
   126             chain.append(rev)
   132             iter_node = self.bundlebase(rev)
   127             iter_node = self.bundlebase(rev)
   133             rev = self.rev(iter_node)
   128             rev = self.rev(iter_node)
   134         if text is None:
   129         if text is None:
   135             text = revlog.revision(self, iter_node)
   130             text = revlog.revlog.revision(self, iter_node)
   136 
   131 
   137         while chain:
   132         while chain:
   138             delta = self.chunk(chain.pop())
   133             delta = self.chunk(chain.pop())
   139             text = self.patches(text, [delta])
   134             text = self.patches(text, [delta])
   140 
   135 
   141         p1, p2 = self.parents(node)
   136         p1, p2 = self.parents(node)
   142         if node != hash(text, p1, p2):
   137         if node != revlog.hash(text, p1, p2):
   143             raise RevlogError(_("integrity check failed on %s:%d")
   138             raise RevlogError(_("integrity check failed on %s:%d")
   144                           % (self.datafile, self.rev(node)))
   139                           % (self.datafile, self.rev(node)))
   145 
   140 
   146         self.cache = (node, rev, text)
   141         self.cache = (node, rev, text)
   147         return text
   142         return text
   153     def strip(self, rev, minlink):
   148     def strip(self, rev, minlink):
   154         raise NotImplementedError
   149         raise NotImplementedError
   155     def checksize(self):
   150     def checksize(self):
   156         raise NotImplementedError
   151         raise NotImplementedError
   157 
   152 
   158 class bundlechangelog(bundlerevlog, changelog):
   153 class bundlechangelog(bundlerevlog, changelog.changelog):
   159     def __init__(self, opener, bundlefile):
   154     def __init__(self, opener, bundlefile):
   160         changelog.__init__(self, opener)
   155         changelog.changelog.__init__(self, opener)
   161         bundlerevlog.__init__(self, opener, "00changelog.i", "00changelog.d",
   156         bundlerevlog.__init__(self, opener, "00changelog.i", "00changelog.d",
   162                               bundlefile)
   157                               bundlefile)
   163 
   158 
   164 class bundlemanifest(bundlerevlog, manifest):
   159 class bundlemanifest(bundlerevlog, manifest.manifest):
   165     def __init__(self, opener, bundlefile, linkmapper):
   160     def __init__(self, opener, bundlefile, linkmapper):
   166         manifest.__init__(self, opener)
   161         manifest.manifest.__init__(self, opener)
   167         bundlerevlog.__init__(self, opener, self.indexfile, self.datafile,
   162         bundlerevlog.__init__(self, opener, self.indexfile, self.datafile,
   168                               bundlefile, linkmapper)
   163                               bundlefile, linkmapper)
   169 
   164 
   170 class bundlefilelog(bundlerevlog, filelog):
   165 class bundlefilelog(bundlerevlog, filelog.filelog):
   171     def __init__(self, opener, path, bundlefile, linkmapper):
   166     def __init__(self, opener, path, bundlefile, linkmapper):
   172         filelog.__init__(self, opener, path)
   167         filelog.filelog.__init__(self, opener, path)
   173         bundlerevlog.__init__(self, opener, self.indexfile, self.datafile,
   168         bundlerevlog.__init__(self, opener, self.indexfile, self.datafile,
   174                               bundlefile, linkmapper)
   169                               bundlefile, linkmapper)
   175 
   170 
   176 class bundlerepository(localrepository):
   171 class bundlerepository(localrepo.localrepository):
   177     def __init__(self, ui, path, bundlename):
   172     def __init__(self, ui, path, bundlename):
   178         localrepository.__init__(self, ui, path)
   173         localrepo.localrepository.__init__(self, ui, path)
   179         f = open(bundlename, "rb")
   174         f = open(bundlename, "rb")
   180         s = os.fstat(f.fileno())
   175         s = os.fstat(f.fileno())
   181         self.bundlefile = f
   176         self.bundlefile = f
   182         header = self.bundlefile.read(4)
   177         header = self.bundlefile.read(4)
   183         if header == "HG10":
   178         if header == "HG10":
   207         if f in self.bundlefilespos:
   202         if f in self.bundlefilespos:
   208             self.bundlefile.seek(self.bundlefilespos[f])
   203             self.bundlefile.seek(self.bundlefilespos[f])
   209             return bundlefilelog(self.opener, f, self.bundlefile,
   204             return bundlefilelog(self.opener, f, self.bundlefile,
   210                                  self.changelog.rev)
   205                                  self.changelog.rev)
   211         else:
   206         else:
   212             return filelog(self.opener, f)
   207             return filelog.filelog(self.opener, f)
   213 
   208