/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/bzrdir.py

  • Committer: Martin Pool
  • Date: 2007-09-14 06:31:28 UTC
  • mfrom: (2822 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2823.
  • Revision ID: mbp@sourcefrog.net-20070914063128-0p7mh6zfb4pzdg9p
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
from cStringIO import StringIO
27
27
import os
28
 
import textwrap
29
28
 
30
29
from bzrlib.lazy_import import lazy_import
31
30
lazy_import(globals(), """
32
31
from stat import S_ISDIR
 
32
import textwrap
 
33
from warnings import warn
33
34
 
34
35
import bzrlib
35
36
from bzrlib import (
36
37
    errors,
 
38
    graph,
37
39
    lockable_files,
38
40
    lockdir,
39
41
    registry,
48
50
    workingtree_4,
49
51
    )
50
52
from bzrlib.osutils import (
51
 
    safe_unicode,
52
53
    sha_strings,
53
54
    sha_string,
54
55
    )
70
71
    note,
71
72
    )
72
73
from bzrlib.transport.local import LocalTransport
 
74
from bzrlib.symbol_versioning import (
 
75
    deprecated_function,
 
76
    deprecated_method,
 
77
    zero_ninetyone,
 
78
    )
73
79
 
74
80
 
75
81
class BzrDir(object):
209
215
        t = get_transport(url)
210
216
        t.ensure_base()
211
217
 
212
 
    # TODO: Should take a Transport
213
218
    @classmethod
214
 
    def create(cls, base, format=None):
 
219
    def create(cls, base, format=None, possible_transports=None):
215
220
        """Create a new BzrDir at the url 'base'.
216
221
        
217
222
        This will call the current default formats initialize with base
219
224
 
220
225
        :param format: If supplied, the format of branch to create.  If not
221
226
            supplied, the default is used.
 
227
        :param possible_transports: If supplied, a list of transports that 
 
228
            can be reused to share a remote connection.
222
229
        """
223
230
        if cls is not BzrDir:
224
231
            raise AssertionError("BzrDir.create always creates the default"
225
232
                " format, not one of %r" % cls)
226
 
        t = get_transport(base)
 
233
        t = get_transport(base, possible_transports)
227
234
        t.ensure_base()
228
235
        if format is None:
229
236
            format = BzrDirFormat.get_default_format()
230
 
        return format.initialize(safe_unicode(base))
 
237
        return format.initialize(base, possible_transports)
231
238
 
232
239
    def create_branch(self):
233
240
        """Create a branch in this BzrDir.
266
273
        
267
274
    @staticmethod
268
275
    def create_branch_convenience(base, force_new_repo=False,
269
 
                                  force_new_tree=None, format=None):
 
276
                                  force_new_tree=None, format=None,
 
277
                                  possible_transports=None):
270
278
        """Create a new BzrDir, Branch and Repository at the url 'base'.
271
279
 
272
280
        This is a convenience function - it will use an existing repository
288
296
        :param force_new_repo: If True a new repository is always created.
289
297
        :param force_new_tree: If True or False force creation of a tree or 
290
298
                               prevent such creation respectively.
291
 
        :param format: Override for the for the bzrdir format to create
 
299
        :param format: Override for the for the bzrdir format to create.
 
300
        :param possible_transports: An optional reusable transports list.
292
301
        """
293
302
        if force_new_tree:
294
303
            # check for non local urls
295
 
            t = get_transport(safe_unicode(base))
 
304
            t = get_transport(base, possible_transports)
296
305
            if not isinstance(t, LocalTransport):
297
306
                raise errors.NotLocalUrl(base)
298
 
        bzrdir = BzrDir.create(base, format)
 
307
        bzrdir = BzrDir.create(base, format, possible_transports)
299
308
        repo = bzrdir._find_or_create_repository(force_new_repo)
300
309
        result = bzrdir.create_branch()
301
 
        if force_new_tree or (repo.make_working_trees() and 
 
310
        if force_new_tree or (repo.make_working_trees() and
302
311
                              force_new_tree is None):
303
312
            try:
304
313
                bzrdir.create_workingtree()
305
314
            except errors.NotLocalUrl:
306
315
                pass
307
316
        return result
308
 
        
 
317
 
309
318
    @staticmethod
 
319
    @deprecated_function(zero_ninetyone)
310
320
    def create_repository(base, shared=False, format=None):
311
321
        """Create a new BzrDir and Repository at the url 'base'.
312
322
 
321
331
        This must be overridden as an instance method in child classes, where
322
332
        it should take no parameters and construct whatever repository format
323
333
        that child class desires.
 
334
 
 
335
        This method is deprecated, please call create_repository on a bzrdir
 
336
        instance instead.
324
337
        """
325
338
        bzrdir = BzrDir.create(base, format)
326
339
        return bzrdir.create_repository(shared)
337
350
 
338
351
        :return: The WorkingTree object.
339
352
        """
340
 
        t = get_transport(safe_unicode(base))
 
353
        t = get_transport(base)
341
354
        if not isinstance(t, LocalTransport):
342
355
            raise errors.NotLocalUrl(base)
343
 
        bzrdir = BzrDir.create_branch_and_repo(safe_unicode(base),
 
356
        bzrdir = BzrDir.create_branch_and_repo(base,
344
357
                                               force_new_repo=True,
345
358
                                               format=format).bzrdir
346
359
        return bzrdir.create_workingtree()
520
533
        return BzrDir.open(base, _unsupported=True)
521
534
        
522
535
    @staticmethod
523
 
    def open(base, _unsupported=False):
 
536
    def open(base, _unsupported=False, possible_transports=None):
524
537
        """Open an existing bzrdir, rooted at 'base' (url)
525
538
        
526
539
        _unsupported is a private parameter to the BzrDir class.
527
540
        """
528
 
        t = get_transport(base)
 
541
        t = get_transport(base, possible_transports=possible_transports)
529
542
        return BzrDir.open_from_transport(t, _unsupported=_unsupported)
530
543
 
531
544
    @staticmethod
581
594
        raise NotImplementedError(self.open_branch)
582
595
 
583
596
    @staticmethod
584
 
    def open_containing(url):
 
597
    def open_containing(url, possible_transports=None):
585
598
        """Open an existing branch which contains url.
586
599
        
587
600
        :param url: url to search from.
588
601
        See open_containing_from_transport for more detail.
589
602
        """
590
 
        return BzrDir.open_containing_from_transport(get_transport(url))
 
603
        transport = get_transport(url, possible_transports)
 
604
        return BzrDir.open_containing_from_transport(transport)
591
605
    
592
606
    @staticmethod
593
607
    def open_containing_from_transport(a_transport):
743
757
        return self.cloning_metadir()
744
758
 
745
759
    def sprout(self, url, revision_id=None, force_new_repo=False,
746
 
               recurse='down'):
 
760
               recurse='down', possible_transports=None):
747
761
        """Create a copy of this bzrdir prepared for use as a new line of
748
762
        development.
749
763
 
757
771
        if revision_id is not None, then the clone operation may tune
758
772
            itself to download less data.
759
773
        """
760
 
        target_transport = get_transport(url)
 
774
        target_transport = get_transport(url, possible_transports)
761
775
        target_transport.ensure_base()
762
776
        cloning_format = self.cloning_metadir()
763
777
        result = cloning_format.initialize_on_transport(target_transport)
784
798
            result.create_repository()
785
799
        elif source_repository is not None and result_repo is None:
786
800
            # have source, and want to make a new target repo
787
 
            result_repo = source_repository.sprout(result, revision_id=revision_id)
 
801
            result_repo = source_repository.sprout(result,
 
802
                                                   revision_id=revision_id)
788
803
        else:
789
804
            # fetch needed content into target.
790
805
            if source_repository is not None:
791
806
                # would rather do 
792
 
                # source_repository.copy_content_into(result_repo, revision_id=revision_id)
 
807
                # source_repository.copy_content_into(result_repo,
 
808
                #                                     revision_id=revision_id)
793
809
                # so we can override the copy method
794
810
                result_repo.fetch(source_repository, revision_id=revision_id)
795
811
        if source_branch is not None:
796
812
            source_branch.sprout(result, revision_id=revision_id)
797
813
        else:
798
814
            result.create_branch()
799
 
        # TODO: jam 20060426 we probably need a test in here in the
800
 
        #       case that the newly sprouted branch is a remote one
801
 
        if result_repo is None or result_repo.make_working_trees():
 
815
        if isinstance(target_transport, LocalTransport) and (
 
816
            result_repo is None or result_repo.make_working_trees()):
802
817
            wt = result.create_workingtree()
803
818
            wt.lock_write()
804
819
            try:
958
973
        self._check_supported(format, unsupported)
959
974
        return format.open(self, _found=True)
960
975
 
961
 
    def sprout(self, url, revision_id=None, force_new_repo=False):
 
976
    def sprout(self, url, revision_id=None, force_new_repo=False,
 
977
               possible_transports=None):
962
978
        """See BzrDir.sprout()."""
963
979
        from bzrlib.workingtree import WorkingTreeFormat2
964
980
        self._make_tail(url)
1068
1084
        wt = self.open_workingtree(recommend_upgrade=False)
1069
1085
        repository = wt.branch.repository
1070
1086
        empty = repository.revision_tree(_mod_revision.NULL_REVISION)
1071
 
        wt.revert([], old_tree=empty)
 
1087
        wt.revert(old_tree=empty)
1072
1088
        self.destroy_workingtree_metadata()
1073
1089
 
1074
1090
    def destroy_workingtree_metadata(self):
1287
1303
        """
1288
1304
        raise NotImplementedError(self.get_converter)
1289
1305
 
1290
 
    def initialize(self, url):
 
1306
    def initialize(self, url, possible_transports=None):
1291
1307
        """Create a bzr control dir at this url and return an opened copy.
1292
1308
        
1293
1309
        Subclasses should typically override initialize_on_transport
1294
1310
        instead of this method.
1295
1311
        """
1296
 
        return self.initialize_on_transport(get_transport(url))
 
1312
        return self.initialize_on_transport(get_transport(url,
 
1313
                                                          possible_transports))
1297
1314
 
1298
1315
    def initialize_on_transport(self, transport):
1299
1316
        """Initialize a new bzrdir in the base directory of a Transport."""
1788
1805
    def _convert_working_inv(self):
1789
1806
        inv = xml4.serializer_v4.read_inventory(
1790
1807
                    self.branch.control_files.get('inventory'))
1791
 
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
 
1808
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv, working=True)
1792
1809
        # FIXME inventory is a working tree change.
1793
1810
        self.branch.control_files.put('inventory', StringIO(new_inv_xml))
1794
1811
 
1873
1890
        present_parents = [p for p in rev.parent_ids
1874
1891
                           if p not in self.absent_revisions]
1875
1892
        self._convert_revision_contents(rev, inv, present_parents)
1876
 
        self._store_new_weave(rev, inv, present_parents)
 
1893
        self._store_new_inv(rev, inv, present_parents)
1877
1894
        self.converted_revs.add(rev_id)
1878
1895
 
1879
 
    def _store_new_weave(self, rev, inv, present_parents):
 
1896
    def _store_new_inv(self, rev, inv, present_parents):
1880
1897
        # the XML is now updated with text versions
1881
1898
        if __debug__:
1882
1899
            entries = inv.iter_entries()
1887
1904
                    (file_id, rev.revision_id)
1888
1905
        new_inv_xml = xml5.serializer_v5.write_inventory_to_string(inv)
1889
1906
        new_inv_sha1 = sha_string(new_inv_xml)
1890
 
        self.inv_weave.add_lines(rev.revision_id, 
 
1907
        self.inv_weave.add_lines(rev.revision_id,
1891
1908
                                 present_parents,
1892
1909
                                 new_inv_xml.splitlines(True))
1893
1910
        rev.inventory_sha1 = new_inv_sha1
1918
1935
            w = Weave(file_id)
1919
1936
            self.text_weaves[file_id] = w
1920
1937
        text_changed = False
1921
 
        previous_entries = ie.find_previous_heads(parent_invs,
1922
 
                                                  None,
1923
 
                                                  None,
1924
 
                                                  entry_vf=w)
1925
 
        for old_revision in previous_entries:
1926
 
                # if this fails, its a ghost ?
1927
 
                assert old_revision in self.converted_revs, \
1928
 
                    "Revision {%s} not in converted_revs" % old_revision
 
1938
        parent_candiate_entries = ie.parent_candidates(parent_invs)
 
1939
        for old_revision in parent_candiate_entries.keys():
 
1940
            # if this fails, its a ghost ?
 
1941
            assert old_revision in self.converted_revs, \
 
1942
                "Revision {%s} not in converted_revs" % old_revision
 
1943
        heads = graph.Graph(self).heads(parent_candiate_entries.keys())
 
1944
        # XXX: Note that this is unordered - and this is tolerable because 
 
1945
        # the previous code was also unordered.
 
1946
        previous_entries = dict((head, parent_candiate_entries[head]) for head
 
1947
            in heads)
1929
1948
        self.snapshot_ie(previous_entries, ie, w, rev_id)
1930
1949
        del ie.text_id
1931
1950
        assert getattr(ie, 'revision', None) is not None
1932
1951
 
 
1952
    def get_parents(self, revision_ids):
 
1953
        for revision_id in revision_ids:
 
1954
            yield self.revisions[revision_id].parent_ids
 
1955
 
1933
1956
    def snapshot_ie(self, previous_revisions, ie, w, rev_id):
1934
1957
        # TODO: convert this logic, which is ~= snapshot to
1935
1958
        # a call to:. This needs the path figured out. rather than a work_tree
1944
1967
                ie.revision = previous_ie.revision
1945
1968
                return
1946
1969
        if ie.has_text():
1947
 
            text = self.branch.repository.text_store.get(ie.text_id)
 
1970
            text = self.branch.repository.weave_store.get(ie.text_id)
1948
1971
            file_lines = text.readlines()
1949
1972
            assert sha_strings(file_lines) == ie.text_sha1
1950
1973
            assert sum(map(len, file_lines)) == ie.text_size
2217
2240
    def initialize_on_transport(self, transport):
2218
2241
        try:
2219
2242
            # hand off the request to the smart server
2220
 
            medium = transport.get_smart_medium()
 
2243
            shared_medium = transport.get_shared_medium()
2221
2244
        except errors.NoSmartMedium:
2222
2245
            # TODO: lookup the local format from a server hint.
2223
2246
            local_dir_format = BzrDirMetaFormat1()
2224
2247
            return local_dir_format.initialize_on_transport(transport)
2225
 
        client = _SmartClient(medium)
 
2248
        client = _SmartClient(shared_medium)
2226
2249
        path = client.remote_path_from_transport(transport)
2227
 
        response = _SmartClient(medium).call('BzrDirFormat.initialize', path)
 
2250
        response = _SmartClient(shared_medium).call('BzrDirFormat.initialize',
 
2251
                                                    path)
2228
2252
        assert response[0] in ('ok', ), 'unexpected response code %s' % (response,)
2229
2253
        return remote.RemoteBzrDir(transport)
2230
2254
 
2342
2366
 
2343
2367
    def help_topic(self, topic):
2344
2368
        output = textwrap.dedent("""\
2345
 
            Bazaar directory formats
2346
 
            ------------------------
2347
 
 
2348
2369
            These formats can be used for creating branches, working trees, and
2349
2370
            repositories.
2350
2371
 
2351
2372
            """)
 
2373
        default_realkey = None
2352
2374
        default_help = self.get_help('default')
2353
2375
        help_pairs = []
2354
2376
        for key in self.keys():
2363
2385
        def wrapped(key, help, info):
2364
2386
            if info.native:
2365
2387
                help = '(native) ' + help
2366
 
            return '  %s:\n%s\n\n' % (key, 
 
2388
            return ':%s:\n%s\n\n' % (key, 
2367
2389
                    textwrap.fill(help, initial_indent='    ', 
2368
2390
                    subsequent_indent='    '))
2369
 
        output += wrapped('%s/default' % default_realkey, default_help,
2370
 
                          self.get_info('default'))
 
2391
        if default_realkey is not None:
 
2392
            output += wrapped(default_realkey, '(default) %s' % default_help,
 
2393
                              self.get_info('default'))
2371
2394
        deprecated_pairs = []
2372
2395
        for key, help in help_pairs:
2373
2396
            info = self.get_info(key)
2378
2401
            else:
2379
2402
                output += wrapped(key, help, info)
2380
2403
        if len(deprecated_pairs) > 0:
2381
 
            output += "Deprecated formats\n------------------\n\n"
 
2404
            output += "Deprecated formats are shown below.\n\n"
2382
2405
            for key, help in deprecated_pairs:
2383
2406
                info = self.get_info(key)
2384
2407
                output += wrapped(key, help, info)
2428
2451
    tree_format='bzrlib.workingtree.WorkingTreeFormat4',
2429
2452
    hidden=True,
2430
2453
    )
2431
 
format_registry.set_default('dirstate')
 
2454
format_registry.set_default('dirstate-tags')