~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
 
from cStringIO import StringIO
19
 
 
20
18
from bzrlib.lazy_import import lazy_import
21
19
lazy_import(globals(), """
22
 
from warnings import warn
23
 
 
24
 
import bzrlib
25
20
from bzrlib import (
26
21
        bzrdir,
27
22
        cache_utf8,
30
25
        errors,
31
26
        lockdir,
32
27
        lockable_files,
33
 
        osutils,
34
28
        revision as _mod_revision,
35
29
        transport,
36
 
        tree,
37
30
        tsort,
38
31
        ui,
39
32
        urlutils,
40
33
        )
41
 
from bzrlib.config import BranchConfig, TreeConfig
42
 
from bzrlib.lockable_files import LockableFiles, TransportLock
 
34
from bzrlib.config import BranchConfig
43
35
from bzrlib.tag import (
44
36
    BasicTags,
45
37
    DisabledTags,
47
39
""")
48
40
 
49
41
from bzrlib.decorators import needs_read_lock, needs_write_lock
50
 
from bzrlib.errors import (BzrError, BzrCheckError, DivergedBranches,
51
 
                           HistoryMissing, InvalidRevisionId,
52
 
                           InvalidRevisionNumber, LockError, NoSuchFile,
53
 
                           NoSuchRevision, NotVersionedError,
54
 
                           NotBranchError, UninitializableFormat,
55
 
                           UnlistableStore, UnlistableBranch,
56
 
                           )
57
42
from bzrlib.hooks import Hooks
58
 
from bzrlib.symbol_versioning import (deprecated_function,
59
 
                                      deprecated_method,
60
 
                                      DEPRECATED_PARAMETER,
61
 
                                      deprecated_passed,
62
 
                                      zero_eight, zero_nine, zero_sixteen,
63
 
                                      zero_ninetyone,
 
43
from bzrlib.symbol_versioning import (deprecated_method,
 
44
                                      zero_sixteen,
64
45
                                      )
65
 
from bzrlib.trace import mutter, mutter_callsite, note
 
46
from bzrlib.trace import mutter, mutter_callsite, note, is_quiet
66
47
 
67
48
 
68
49
BZR_BRANCH_FORMAT_4 = "Bazaar-NG branch, format 0.0.4\n"
279
260
            if last_revision is None:
280
261
                pb.update('get source history')
281
262
                last_revision = from_branch.last_revision()
282
 
                if last_revision is None:
283
 
                    last_revision = _mod_revision.NULL_REVISION
 
263
                last_revision = _mod_revision.ensure_null(last_revision)
284
264
            return self.repository.fetch(from_branch.repository,
285
265
                                         revision_id=last_revision,
286
266
                                         pb=nested_pb)
338
318
        assert isinstance(revno, int)
339
319
        rh = self.revision_history()
340
320
        if not (1 <= revno <= len(rh)):
341
 
            raise InvalidRevisionNumber(revno)
 
321
            raise errors.InvalidRevisionNumber(revno)
342
322
        return self.repository.get_revision_delta(rh[revno-1])
343
323
 
344
324
    @deprecated_method(zero_sixteen)
436
416
        raise errors.UpgradeRequired(self.base)
437
417
 
438
418
    def last_revision(self):
439
 
        """Return last revision id, or None"""
440
 
        ph = self.revision_history()
441
 
        if ph:
442
 
            return ph[-1]
443
 
        else:
444
 
            return _mod_revision.NULL_REVISION
 
419
        """Return last revision id, or NULL_REVISION."""
 
420
        return self.last_revision_info()[1]
445
421
 
446
422
    def last_revision_info(self):
447
423
        """Return information about the last revision.
468
444
        common_index = min(self_len, other_len) -1
469
445
        if common_index >= 0 and \
470
446
            self_history[common_index] != other_history[common_index]:
471
 
            raise DivergedBranches(self, other)
 
447
            raise errors.DivergedBranches(self, other)
472
448
 
473
449
        if stop_revision is None:
474
450
            stop_revision = other_len
647
623
        Zero (the NULL revision) is considered invalid
648
624
        """
649
625
        if revno < 1 or revno > self.revno():
650
 
            raise InvalidRevisionNumber(revno)
 
626
            raise errors.InvalidRevisionNumber(revno)
651
627
 
652
628
    @needs_read_lock
653
629
    def clone(self, to_bzrdir, revision_id=None):
757
733
        return format
758
734
 
759
735
    def create_checkout(self, to_location, revision_id=None,
760
 
                        lightweight=False, accelerator_tree=None):
 
736
                        lightweight=False, accelerator_tree=None,
 
737
                        hardlink=False):
761
738
        """Create a checkout of a branch.
762
739
        
763
740
        :param to_location: The url to produce the checkout at
768
745
            contents more quickly than the revision tree, i.e. a workingtree.
769
746
            The revision tree will be used for cases where accelerator_tree's
770
747
            content is different.
 
748
        :param hardlink: If true, hard-link files from accelerator_tree,
 
749
            where possible.
771
750
        :return: The tree of the created checkout
772
751
        """
773
752
        t = transport.get_transport(to_location)
788
767
            from_branch=None
789
768
        tree = checkout.create_workingtree(revision_id,
790
769
                                           from_branch=from_branch,
791
 
                                           accelerator_tree=accelerator_tree)
 
770
                                           accelerator_tree=accelerator_tree,
 
771
                                           hardlink=hardlink)
792
772
        basis_tree = tree.basis_tree()
793
773
        basis_tree.lock_read()
794
774
        try:
851
831
            transport = a_bzrdir.get_branch_transport(None)
852
832
            format_string = transport.get("format").read()
853
833
            return klass._formats[format_string]
854
 
        except NoSuchFile:
855
 
            raise NotBranchError(path=transport.base)
 
834
        except errors.NoSuchFile:
 
835
            raise errors.NotBranchError(path=transport.base)
856
836
        except KeyError:
857
 
            raise errors.UnknownFormatError(format=format_string)
 
837
            raise errors.UnknownFormatError(format=format_string, kind='branch')
858
838
 
859
839
    @classmethod
860
840
    def get_default_format(klass):
1140
1120
                              _control_files=control_files,
1141
1121
                              a_bzrdir=a_bzrdir,
1142
1122
                              _repository=a_bzrdir.find_repository())
1143
 
        except NoSuchFile:
1144
 
            raise NotBranchError(path=transport.base)
 
1123
        except errors.NoSuchFile:
 
1124
            raise errors.NotBranchError(path=transport.base)
1145
1125
 
1146
1126
 
1147
1127
class BzrBranchFormat6(BzrBranchFormat5):
1413
1393
        configured to check constraints on history, in which case this may not
1414
1394
        be permitted.
1415
1395
        """
 
1396
        revision_id = _mod_revision.ensure_null(revision_id)
1416
1397
        history = self._lefthand_history(revision_id)
1417
1398
        assert len(history) == revno, '%d != %d' % (len(history), revno)
1418
1399
        self.set_revision_history(history)
1429
1410
        if 'evil' in debug.debug_flags:
1430
1411
            mutter_callsite(4, "_lefthand_history scales with history.")
1431
1412
        # stop_revision must be a descendant of last_revision
1432
 
        stop_graph = self.repository.get_revision_graph(revision_id)
1433
 
        if (last_rev is not None and last_rev != _mod_revision.NULL_REVISION
1434
 
            and last_rev not in stop_graph):
1435
 
            # our previous tip is not merged into stop_revision
1436
 
            raise errors.DivergedBranches(self, other_branch)
 
1413
        graph = self.repository.get_graph()
 
1414
        if last_rev is not None:
 
1415
            if not graph.is_ancestor(last_rev, revision_id):
 
1416
                # our previous tip is not merged into stop_revision
 
1417
                raise errors.DivergedBranches(self, other_branch)
1437
1418
        # make a new revision history from the graph
 
1419
        parents_map = graph.get_parent_map([revision_id])
 
1420
        if revision_id not in parents_map:
 
1421
            raise errors.NoSuchRevision(self, revision_id)
1438
1422
        current_rev_id = revision_id
1439
1423
        new_history = []
1440
 
        while current_rev_id not in (None, _mod_revision.NULL_REVISION):
 
1424
        # Do not include ghosts or graph origin in revision_history
 
1425
        while (current_rev_id in parents_map and
 
1426
               len(parents_map[current_rev_id]) > 0):
1441
1427
            new_history.append(current_rev_id)
1442
 
            current_rev_id_parents = stop_graph[current_rev_id]
1443
 
            try:
1444
 
                current_rev_id = current_rev_id_parents[0]
1445
 
            except IndexError:
1446
 
                current_rev_id = None
 
1428
            current_rev_id = parents_map[current_rev_id][0]
 
1429
            parents_map = graph.get_parent_map([current_rev_id])
1447
1430
        new_history.reverse()
1448
1431
        return new_history
1449
1432
 
1548
1531
        for l in _locs:
1549
1532
            try:
1550
1533
                return self.control_files.get(l).read().strip('\n')
1551
 
            except NoSuchFile:
 
1534
            except errors.NoSuchFile:
1552
1535
                pass
1553
1536
        return None
1554
1537
 
1632
1615
        result.old_revno, result.old_revid = target.last_revision_info()
1633
1616
        try:
1634
1617
            target.update_revisions(self, stop_revision)
1635
 
        except DivergedBranches:
 
1618
        except errors.DivergedBranches:
1636
1619
            if not overwrite:
1637
1620
                raise
1638
1621
        if overwrite:
1771
1754
        else:
1772
1755
            try:
1773
1756
                self.control_files._transport.delete('bound')
1774
 
            except NoSuchFile:
 
1757
            except errors.NoSuchFile:
1775
1758
                return False
1776
1759
            return True
1777
1760
 
1824
1807
        return None
1825
1808
 
1826
1809
 
1827
 
class BzrBranchExperimental(BzrBranch5):
1828
 
    """Bzr experimental branch format
1829
 
 
1830
 
    This format has:
1831
 
     - a revision-history file.
1832
 
     - a format string
1833
 
     - a lock dir guarding the branch itself
1834
 
     - all of this stored in a branch/ subdirectory
1835
 
     - works with shared repositories.
1836
 
     - a tag dictionary in the branch
1837
 
 
1838
 
    This format is new in bzr 0.15, but shouldn't be used for real data, 
1839
 
    only for testing.
1840
 
 
1841
 
    This class acts as it's own BranchFormat.
1842
 
    """
1843
 
 
1844
 
    _matchingbzrdir = bzrdir.BzrDirMetaFormat1()
1845
 
 
1846
 
    @classmethod
1847
 
    def get_format_string(cls):
1848
 
        """See BranchFormat.get_format_string()."""
1849
 
        return "Bazaar-NG branch format experimental\n"
1850
 
 
1851
 
    @classmethod
1852
 
    def get_format_description(cls):
1853
 
        """See BranchFormat.get_format_description()."""
1854
 
        return "Experimental branch format"
1855
 
 
1856
 
    @classmethod
1857
 
    def get_reference(cls, a_bzrdir):
1858
 
        """Get the target reference of the branch in a_bzrdir.
1859
 
 
1860
 
        format probing must have been completed before calling
1861
 
        this method - it is assumed that the format of the branch
1862
 
        in a_bzrdir is correct.
1863
 
 
1864
 
        :param a_bzrdir: The bzrdir to get the branch data from.
1865
 
        :return: None if the branch is not a reference branch.
1866
 
        """
1867
 
        return None
1868
 
 
1869
 
    @classmethod
1870
 
    def set_reference(self, a_bzrdir, to_branch):
1871
 
        """Set the target reference of the branch in a_bzrdir.
1872
 
 
1873
 
        format probing must have been completed before calling
1874
 
        this method - it is assumed that the format of the branch
1875
 
        in a_bzrdir is correct.
1876
 
 
1877
 
        :param a_bzrdir: The bzrdir to set the branch reference for.
1878
 
        :param to_branch: branch that the checkout is to reference
1879
 
        """
1880
 
        raise NotImplementedError(self.set_reference)
1881
 
 
1882
 
    @classmethod
1883
 
    def _initialize_control_files(cls, a_bzrdir, utf8_files, lock_filename,
1884
 
            lock_class):
1885
 
        branch_transport = a_bzrdir.get_branch_transport(cls)
1886
 
        control_files = lockable_files.LockableFiles(branch_transport,
1887
 
            lock_filename, lock_class)
1888
 
        control_files.create_lock()
1889
 
        control_files.lock_write()
1890
 
        try:
1891
 
            for filename, content in utf8_files:
1892
 
                control_files.put_utf8(filename, content)
1893
 
        finally:
1894
 
            control_files.unlock()
1895
 
        
1896
 
    @classmethod
1897
 
    def initialize(cls, a_bzrdir):
1898
 
        """Create a branch of this format in a_bzrdir."""
1899
 
        utf8_files = [('format', cls.get_format_string()),
1900
 
                      ('revision-history', ''),
1901
 
                      ('branch-name', ''),
1902
 
                      ('tags', ''),
1903
 
                      ]
1904
 
        cls._initialize_control_files(a_bzrdir, utf8_files,
1905
 
            'lock', lockdir.LockDir)
1906
 
        return cls.open(a_bzrdir, _found=True)
1907
 
 
1908
 
    @classmethod
1909
 
    def open(cls, a_bzrdir, _found=False):
1910
 
        """Return the branch object for a_bzrdir
1911
 
 
1912
 
        _found is a private parameter, do not use it. It is used to indicate
1913
 
               if format probing has already be done.
1914
 
        """
1915
 
        if not _found:
1916
 
            format = BranchFormat.find_format(a_bzrdir)
1917
 
            assert format.__class__ == cls
1918
 
        transport = a_bzrdir.get_branch_transport(None)
1919
 
        control_files = lockable_files.LockableFiles(transport, 'lock',
1920
 
                                                     lockdir.LockDir)
1921
 
        return cls(_format=cls,
1922
 
            _control_files=control_files,
1923
 
            a_bzrdir=a_bzrdir,
1924
 
            _repository=a_bzrdir.find_repository())
1925
 
 
1926
 
    @classmethod
1927
 
    def is_supported(cls):
1928
 
        return True
1929
 
 
1930
 
    def _make_tags(self):
1931
 
        return BasicTags(self)
1932
 
 
1933
 
    @classmethod
1934
 
    def supports_tags(cls):
1935
 
        return True
1936
 
 
1937
 
 
1938
 
BranchFormat.register_format(BzrBranchExperimental)
1939
 
 
1940
 
 
1941
1810
class BzrBranch6(BzrBranch5):
1942
1811
 
1943
1812
    @needs_read_lock
1948
1817
        revno = int(revno)
1949
1818
        return revno, revision_id
1950
1819
 
1951
 
    def last_revision(self):
1952
 
        """Return last revision id, or None"""
1953
 
        revision_id = self.last_revision_info()[1]
1954
 
        return revision_id
1955
 
 
1956
1820
    def _write_last_revision_info(self, revno, revision_id):
1957
1821
        """Simply write out the revision id, with no checks.
1958
1822
 
1962
1826
        Intended to be called by set_last_revision_info and
1963
1827
        _write_revision_history.
1964
1828
        """
1965
 
        if revision_id is None:
1966
 
            revision_id = 'null:'
 
1829
        assert revision_id is not None, "Use NULL_REVISION, not None"
1967
1830
        out_string = '%d %s\n' % (revno, revision_id)
1968
1831
        self.control_files.put_bytes('last-revision', out_string)
1969
1832
 
1970
1833
    @needs_write_lock
1971
1834
    def set_last_revision_info(self, revno, revision_id):
 
1835
        revision_id = _mod_revision.ensure_null(revision_id)
1972
1836
        if self._get_append_revisions_only():
1973
1837
            self._check_history_violation(revision_id)
1974
1838
        self._write_last_revision_info(revno, revision_id)
2097
1961
    def _make_tags(self):
2098
1962
        return BasicTags(self)
2099
1963
 
 
1964
    @needs_write_lock
 
1965
    def generate_revision_history(self, revision_id, last_rev=None,
 
1966
                                  other_branch=None):
 
1967
        """See BzrBranch5.generate_revision_history"""
 
1968
        history = self._lefthand_history(revision_id, last_rev, other_branch)
 
1969
        revno = len(history)
 
1970
        self.set_last_revision_info(revno, revision_id)
 
1971
 
2100
1972
 
2101
1973
######################################################################
2102
1974
# results of operations
2129
2001
        return self.new_revno - self.old_revno
2130
2002
 
2131
2003
    def report(self, to_file):
2132
 
        if self.old_revid == self.new_revid:
2133
 
            to_file.write('No revisions to pull.\n')
2134
 
        else:
2135
 
            to_file.write('Now on revision %d.\n' % self.new_revno)
 
2004
        if not is_quiet():
 
2005
            if self.old_revid == self.new_revid:
 
2006
                to_file.write('No revisions to pull.\n')
 
2007
            else:
 
2008
                to_file.write('Now on revision %d.\n' % self.new_revno)
2136
2009
        self._show_tag_conficts(to_file)
2137
2010
 
2138
2011
 
2206
2079
        new_branch.control_files._transport.delete('revision-history')
2207
2080
        try:
2208
2081
            branch.set_parent(None)
2209
 
        except NoSuchFile:
 
2082
        except errors.NoSuchFile:
2210
2083
            pass
2211
2084
        branch.set_bound_location(None)