~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/remote.py

  • Committer: Patch Queue Manager
  • Date: 2011-12-14 21:50:54 UTC
  • mfrom: (6282.6.43 hpss-get-inventories)
  • Revision ID: pqm@pqm.ubuntu.com-20111214215054-kbzhlka9gtbd4zd7
(jelmer) Add HPSS call for retrieving inventories. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
    errors,
28
28
    gpg,
29
29
    graph,
 
30
    inventory_delta,
30
31
    lock,
31
32
    lockdir,
32
33
    osutils,
1830
1831
    def get_inventory(self, revision_id):
1831
1832
        return list(self.iter_inventories([revision_id]))[0]
1832
1833
 
 
1834
    def _iter_inventories_rpc(self, revision_ids, ordering):
 
1835
        if ordering is None:
 
1836
            ordering = 'unordered'
 
1837
        path = self.bzrdir._path_for_remote_call(self._client)
 
1838
        body = "\n".join(revision_ids)
 
1839
        response_tuple, response_handler = (
 
1840
            self._call_with_body_bytes_expecting_body(
 
1841
                "VersionedFileRepository.get_inventories",
 
1842
                (path, ordering), body))
 
1843
        if response_tuple[0] != "ok":
 
1844
            raise errors.UnexpectedSmartServerResponse(response_tuple)
 
1845
        deserializer = inventory_delta.InventoryDeltaDeserializer()
 
1846
        byte_stream = response_handler.read_streamed_body()
 
1847
        decoded = smart_repo._byte_stream_to_stream(byte_stream)
 
1848
        if decoded is None:
 
1849
            # no results whatsoever
 
1850
            return
 
1851
        src_format, stream = decoded
 
1852
        if src_format.network_name() != self._format.network_name():
 
1853
            raise AssertionError(
 
1854
                "Mismatched RemoteRepository and stream src %r, %r" % (
 
1855
                src_format.network_name(), self._format.network_name()))
 
1856
        # ignore the src format, it's not really relevant
 
1857
        prev_inv = Inventory(root_id=None,
 
1858
            revision_id=_mod_revision.NULL_REVISION)
 
1859
        # there should be just one substream, with inventory deltas
 
1860
        substream_kind, substream = stream.next()
 
1861
        if substream_kind != "inventory-deltas":
 
1862
            raise AssertionError(
 
1863
                 "Unexpected stream %r received" % substream_kind)
 
1864
        for record in substream:
 
1865
            (parent_id, new_id, versioned_root, tree_references, invdelta) = (
 
1866
                deserializer.parse_text_bytes(record.get_bytes_as("fulltext")))
 
1867
            if parent_id != prev_inv.revision_id:
 
1868
                raise AssertionError("invalid base %r != %r" % (parent_id,
 
1869
                    prev_inv.revision_id))
 
1870
            inv = prev_inv.create_by_apply_delta(invdelta, new_id)
 
1871
            yield inv, inv.revision_id
 
1872
            prev_inv = inv
 
1873
 
 
1874
    def _iter_inventories_vfs(self, revision_ids, ordering=None):
 
1875
        self._ensure_real()
 
1876
        return self._real_repository._iter_inventories(revision_ids, ordering)
 
1877
 
1833
1878
    def iter_inventories(self, revision_ids, ordering=None):
1834
 
        self._ensure_real()
1835
 
        return self._real_repository.iter_inventories(revision_ids, ordering)
 
1879
        """Get many inventories by revision_ids.
 
1880
 
 
1881
        This will buffer some or all of the texts used in constructing the
 
1882
        inventories in memory, but will only parse a single inventory at a
 
1883
        time.
 
1884
 
 
1885
        :param revision_ids: The expected revision ids of the inventories.
 
1886
        :param ordering: optional ordering, e.g. 'topological'.  If not
 
1887
            specified, the order of revision_ids will be preserved (by
 
1888
            buffering if necessary).
 
1889
        :return: An iterator of inventories.
 
1890
        """
 
1891
        if ((None in revision_ids)
 
1892
            or (_mod_revision.NULL_REVISION in revision_ids)):
 
1893
            raise ValueError('cannot get null revision inventory')
 
1894
        for inv, revid in self._iter_inventories(revision_ids, ordering):
 
1895
            if inv is None:
 
1896
                raise errors.NoSuchRevision(self, revid)
 
1897
            yield inv
 
1898
 
 
1899
    def _iter_inventories(self, revision_ids, ordering=None):
 
1900
        if len(revision_ids) == 0:
 
1901
            return
 
1902
        missing = set(revision_ids)
 
1903
        if ordering is None:
 
1904
            order_as_requested = True
 
1905
            invs = {}
 
1906
            order = list(revision_ids)
 
1907
            order.reverse()
 
1908
            next_revid = order.pop()
 
1909
        else:
 
1910
            order_as_requested = False
 
1911
            if ordering != 'unordered' and self._fallback_repositories:
 
1912
                raise ValueError('unsupported ordering %r' % ordering)
 
1913
        iter_inv_fns = [self._iter_inventories_rpc] + [
 
1914
            fallback._iter_inventories for fallback in
 
1915
            self._fallback_repositories]
 
1916
        try:
 
1917
            for iter_inv in iter_inv_fns:
 
1918
                request = [revid for revid in revision_ids if revid in missing]
 
1919
                for inv, revid in iter_inv(request, ordering):
 
1920
                    if inv is None:
 
1921
                        continue
 
1922
                    missing.remove(inv.revision_id)
 
1923
                    if ordering != 'unordered':
 
1924
                        invs[revid] = inv
 
1925
                    else:
 
1926
                        yield inv, revid
 
1927
                if order_as_requested:
 
1928
                    # Yield as many results as we can while preserving order.
 
1929
                    while next_revid in invs:
 
1930
                        inv = invs.pop(next_revid)
 
1931
                        yield inv, inv.revision_id
 
1932
                        try:
 
1933
                            next_revid = order.pop()
 
1934
                        except IndexError:
 
1935
                            # We still want to fully consume the stream, just
 
1936
                            # in case it is not actually finished at this point
 
1937
                            next_revid = None
 
1938
                            break
 
1939
        except errors.UnknownSmartMethod:
 
1940
            for inv, revid in self._iter_inventories_vfs(revision_ids, ordering):
 
1941
                yield inv, revid
 
1942
            return
 
1943
        # Report missing
 
1944
        if order_as_requested:
 
1945
            if next_revid is not None:
 
1946
                yield None, next_revid
 
1947
            while order:
 
1948
                revid = order.pop()
 
1949
                yield invs.get(revid), revid
 
1950
        else:
 
1951
            while missing:
 
1952
                yield None, missing.pop()
1836
1953
 
1837
1954
    @needs_read_lock
1838
1955
    def get_revision(self, revision_id):
2191
2308
 
2192
2309
    @needs_read_lock
2193
2310
    def _get_inventory_xml(self, revision_id):
 
2311
        # This call is used by older working tree formats,
 
2312
        # which stored a serialized basis inventory.
2194
2313
        self._ensure_real()
2195
2314
        return self._real_repository._get_inventory_xml(revision_id)
2196
2315
 
2235
2354
            revids.update(set(fallback.all_revision_ids()))
2236
2355
        return list(revids)
2237
2356
 
 
2357
    def _filtered_revision_trees(self, revision_ids, file_ids):
 
2358
        """Return Tree for a revision on this branch with only some files.
 
2359
 
 
2360
        :param revision_ids: a sequence of revision-ids;
 
2361
          a revision-id may not be None or 'null:'
 
2362
        :param file_ids: if not None, the result is filtered
 
2363
          so that only those file-ids, their parents and their
 
2364
          children are included.
 
2365
        """
 
2366
        inventories = self.iter_inventories(revision_ids)
 
2367
        for inv in inventories:
 
2368
            # Should we introduce a FilteredRevisionTree class rather
 
2369
            # than pre-filter the inventory here?
 
2370
            filtered_inv = inv.filter(file_ids)
 
2371
            yield InventoryRevisionTree(self, filtered_inv, filtered_inv.revision_id)
 
2372
 
2238
2373
    @needs_read_lock
2239
2374
    def get_deltas_for_revisions(self, revisions, specific_fileids=None):
2240
 
        self._ensure_real()
2241
 
        return self._real_repository.get_deltas_for_revisions(revisions,
2242
 
            specific_fileids=specific_fileids)
 
2375
        medium = self._client._medium
 
2376
        if medium._is_remote_before((1, 2)):
 
2377
            self._ensure_real()
 
2378
            for delta in self._real_repository.get_deltas_for_revisions(
 
2379
                    revisions, specific_fileids):
 
2380
                yield delta
 
2381
            return
 
2382
        # Get the revision-ids of interest
 
2383
        required_trees = set()
 
2384
        for revision in revisions:
 
2385
            required_trees.add(revision.revision_id)
 
2386
            required_trees.update(revision.parent_ids[:1])
 
2387
 
 
2388
        # Get the matching filtered trees. Note that it's more
 
2389
        # efficient to pass filtered trees to changes_from() rather
 
2390
        # than doing the filtering afterwards. changes_from() could
 
2391
        # arguably do the filtering itself but it's path-based, not
 
2392
        # file-id based, so filtering before or afterwards is
 
2393
        # currently easier.
 
2394
        if specific_fileids is None:
 
2395
            trees = dict((t.get_revision_id(), t) for
 
2396
                t in self.revision_trees(required_trees))
 
2397
        else:
 
2398
            trees = dict((t.get_revision_id(), t) for
 
2399
                t in self._filtered_revision_trees(required_trees,
 
2400
                specific_fileids))
 
2401
 
 
2402
        # Calculate the deltas
 
2403
        for revision in revisions:
 
2404
            if not revision.parent_ids:
 
2405
                old_tree = self.revision_tree(_mod_revision.NULL_REVISION)
 
2406
            else:
 
2407
                old_tree = trees[revision.parent_ids[0]]
 
2408
            yield trees[revision.revision_id].changes_from(old_tree)
2243
2409
 
2244
2410
    @needs_read_lock
2245
2411
    def get_revision_delta(self, revision_id, specific_fileids=None):