~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Aaron Bentley
  • Date: 2007-02-07 03:09:58 UTC
  • mfrom: (2268 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2269.
  • Revision ID: aaron.bentley@utoronto.ca-20070207030958-fx6ykp7rg7zma6xu
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
81
81
 
82
82
    base
83
83
        Base directory/url of the branch.
 
84
 
 
85
    hooks: An instance of BranchHooks.
84
86
    """
85
87
    # this is really an instance variable - FIXME move it there
86
88
    # - RBC 20060112
223
225
        try:
224
226
            if last_revision is None:
225
227
                pb.update('get source history')
226
 
                from_history = from_branch.revision_history()
227
 
                if from_history:
228
 
                    last_revision = from_history[-1]
229
 
                else:
230
 
                    # no history in the source branch
231
 
                    last_revision = _mod_revision.NULL_REVISION
 
228
                last_revision = from_branch.last_revision_info()[1]
232
229
            return self.repository.fetch(from_branch.repository,
233
230
                                         revision_id=last_revision,
234
231
                                         pb=nested_pb)
322
319
        else:
323
320
            return None
324
321
 
 
322
    def last_revision_info(self):
 
323
        """Return information about the last revision.
 
324
 
 
325
        :return: A tuple (revno, last_revision_id).
 
326
        """
 
327
        rh = self.revision_history()
 
328
        revno = len(rh)
 
329
        if revno:
 
330
            return (revno, rh[-1])
 
331
        else:
 
332
            return (0, _mod_revision.NULL_REVISION)
 
333
 
325
334
    def missing_revisions(self, other, stop_revision=None):
326
335
        """Return a list of new revisions that would perfectly fit.
327
336
        
375
384
        return history[revno - 1]
376
385
 
377
386
    def pull(self, source, overwrite=False, stop_revision=None):
 
387
        """Mirror source into this branch.
 
388
 
 
389
        This branch is considered to be 'local', having low latency.
 
390
        """
378
391
        raise NotImplementedError(self.pull)
379
392
 
 
393
    def push(self, target, overwrite=False, stop_revision=None):
 
394
        """Mirror this branch into target.
 
395
 
 
396
        This branch is considered to be 'local', having low latency.
 
397
        """
 
398
        raise NotImplementedError(self.push)
 
399
 
380
400
    def basis_tree(self):
381
401
        """Return `Tree` object for last revision."""
382
402
        return self.repository.revision_tree(self.last_revision())
599
619
            format = self.repository.bzrdir.cloning_metadir()
600
620
        return format
601
621
 
602
 
    def create_checkout(self, to_location, revision_id=None, 
 
622
    def create_checkout(self, to_location, revision_id=None,
603
623
                        lightweight=False):
604
624
        """Create a checkout of a branch.
605
625
        
676
696
 
677
697
    def get_format_description(self):
678
698
        """Return the short format description for this format."""
679
 
        raise NotImplementedError(self.get_format_string)
 
699
        raise NotImplementedError(self.get_format_description)
680
700
 
681
701
    def initialize(self, a_bzrdir):
682
702
        """Create a branch of this format in a_bzrdir."""
716
736
        return self.get_format_string().rstrip()
717
737
 
718
738
 
 
739
class BranchHooks(dict):
 
740
    """A dictionary mapping hook name to a list of callables for branch hooks.
 
741
    
 
742
    e.g. ['set_rh'] Is the list of items to be called when the
 
743
    set_revision_history function is invoked.
 
744
    """
 
745
 
 
746
    def __init__(self):
 
747
        """Create the default hooks.
 
748
 
 
749
        These are all empty initially, because by default nothing should get
 
750
        notified.
 
751
        """
 
752
        dict.__init__(self)
 
753
        # invoked whenever the revision history has been set
 
754
        # with set_revision_history. The api signature is
 
755
        # (branch, revision_history), and the branch will
 
756
        # be write-locked. Introduced in 0.15.
 
757
        self['set_rh'] = []
 
758
 
 
759
    def install_hook(self, hook_name, a_callable):
 
760
        """Install a_callable in to the hook hook_name.
 
761
 
 
762
        :param hook_name: A hook name. See the __init__ method of BranchHooks
 
763
            for the complete list of hooks.
 
764
        :param a_callable: The callable to be invoked when the hook triggers.
 
765
            The exact signature will depend on the hook - see the __init__ 
 
766
            method of BranchHooks for details on each hook.
 
767
        """
 
768
        try:
 
769
            self[hook_name].append(a_callable)
 
770
        except KeyError:
 
771
            raise errors.UnknownHook('branch', hook_name)
 
772
 
 
773
 
 
774
# install the default hooks into the Branch class.
 
775
Branch.hooks = BranchHooks()
 
776
 
 
777
 
719
778
class BzrBranchFormat4(BranchFormat):
720
779
    """Bzr branch format 4.
721
780
 
1077
1136
    def append_revision(self, *revision_ids):
1078
1137
        """See Branch.append_revision."""
1079
1138
        for revision_id in revision_ids:
 
1139
            _mod_revision.check_not_reserved_id(revision_id)
1080
1140
            mutter("add {%s} to revision-history" % revision_id)
1081
1141
        rev_history = self.revision_history()
1082
1142
        rev_history.extend(revision_ids)
1100
1160
            # this call is disabled because revision_history is 
1101
1161
            # not really an object yet, and the transaction is for objects.
1102
1162
            # transaction.register_clean(history)
 
1163
        for hook in Branch.hooks['set_rh']:
 
1164
            hook(self, rev_history)
1103
1165
 
1104
1166
    @needs_read_lock
1105
1167
    def revision_history(self):
1191
1253
        """See Branch.pull."""
1192
1254
        source.lock_read()
1193
1255
        try:
1194
 
            old_count = len(self.revision_history())
 
1256
            old_count = self.last_revision_info()[0]
1195
1257
            try:
1196
1258
                self.update_revisions(source, stop_revision)
1197
1259
            except DivergedBranches:
1199
1261
                    raise
1200
1262
            if overwrite:
1201
1263
                self.set_revision_history(source.revision_history())
1202
 
            new_count = len(self.revision_history())
 
1264
            new_count = self.last_revision_info()[0]
1203
1265
            return new_count - old_count
1204
1266
        finally:
1205
1267
            source.unlock()
1206
1268
 
 
1269
    @needs_read_lock
 
1270
    def push(self, target, overwrite=False, stop_revision=None):
 
1271
        """See Branch.push."""
 
1272
        target.lock_write()
 
1273
        try:
 
1274
            old_count = len(target.revision_history())
 
1275
            try:
 
1276
                target.update_revisions(self, stop_revision)
 
1277
            except DivergedBranches:
 
1278
                if not overwrite:
 
1279
                    raise
 
1280
            if overwrite:
 
1281
                target.set_revision_history(self.revision_history())
 
1282
            new_count = len(target.revision_history())
 
1283
            return new_count - old_count
 
1284
        finally:
 
1285
            target.unlock()
 
1286
 
1207
1287
    def get_parent(self):
1208
1288
        """See Branch.get_parent."""
1209
1289
 
1282
1362
        
1283
1363
    @needs_write_lock
1284
1364
    def pull(self, source, overwrite=False, stop_revision=None):
1285
 
        """Updates branch.pull to be bound branch aware."""
 
1365
        """Extends branch.pull to be bound branch aware."""
1286
1366
        bound_location = self.get_bound_location()
1287
1367
        if source.base != bound_location:
1288
1368
            # not pulling from master, so we need to update master.
1292
1372
                source = master_branch
1293
1373
        return super(BzrBranch5, self).pull(source, overwrite, stop_revision)
1294
1374
 
 
1375
    @needs_write_lock
 
1376
    def push(self, target, overwrite=False, stop_revision=None):
 
1377
        """Updates branch.push to be bound branch aware."""
 
1378
        bound_location = target.get_bound_location()
 
1379
        if target.base != bound_location:
 
1380
            # not pushing to master, so we need to update master.
 
1381
            master_branch = target.get_master_branch()
 
1382
            if master_branch:
 
1383
                # push into the master from this branch.
 
1384
                super(BzrBranch5, self).push(master_branch, overwrite,
 
1385
                    stop_revision)
 
1386
        # and push into the target branch from this. Note that we push from
 
1387
        # this branch again, because its considered the highest bandwidth
 
1388
        # repository.
 
1389
        return super(BzrBranch5, self).push(target, overwrite, stop_revision)
 
1390
 
1295
1391
    def get_bound_location(self):
1296
1392
        try:
1297
1393
            return self.control_files.get_utf8('bound').read()[:-1]