3189
3285
class GenericInterBranch(InterBranch):
3190
"""InterBranch implementation that uses public Branch functions.
3194
def _get_branch_formats_to_test():
3195
return BranchFormat._default_format, BranchFormat._default_format
3286
"""InterBranch implementation that uses public Branch functions."""
3289
def is_compatible(klass, source, target):
3290
# GenericBranch uses the public API, so always compatible
3294
def _get_branch_formats_to_test(klass):
3295
return [(BranchFormat._default_format, BranchFormat._default_format)]
3298
def unwrap_format(klass, format):
3299
if isinstance(format, remote.RemoteBranchFormat):
3300
format._ensure_real()
3301
return format._custom_format
3305
def copy_content_into(self, revision_id=None):
3306
"""Copy the content of source into target
3308
revision_id: if not None, the revision history in the new branch will
3309
be truncated to end with revision_id.
3311
self.source.update_references(self.target)
3312
self.source._synchronize_history(self.target, revision_id)
3314
parent = self.source.get_parent()
3315
except errors.InaccessibleParent, e:
3316
mutter('parent was not accessible to copy: %s', e)
3319
self.target.set_parent(parent)
3320
if self.source._push_should_merge_tags():
3321
self.source.tags.merge_to(self.target.tags)
3197
3324
def update_revisions(self, stop_revision=None, overwrite=False,
3199
3326
"""See InterBranch.update_revisions()."""
3200
self.source.lock_read()
3202
other_revno, other_last_revision = self.source.last_revision_info()
3203
stop_revno = None # unknown
3204
if stop_revision is None:
3205
stop_revision = other_last_revision
3206
if _mod_revision.is_null(stop_revision):
3207
# if there are no commits, we're done.
3209
stop_revno = other_revno
3211
# what's the current last revision, before we fetch [and change it
3213
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3214
# we fetch here so that we don't process data twice in the common
3215
# case of having something to pull, and so that the check for
3216
# already merged can operate on the just fetched graph, which will
3217
# be cached in memory.
3218
self.target.fetch(self.source, stop_revision)
3219
# Check to see if one is an ancestor of the other
3222
graph = self.target.repository.get_graph()
3223
if self.target._check_if_descendant_or_diverged(
3224
stop_revision, last_rev, graph, self.source):
3225
# stop_revision is a descendant of last_rev, but we aren't
3226
# overwriting, so we're done.
3228
if stop_revno is None:
3230
graph = self.target.repository.get_graph()
3231
this_revno, this_last_revision = \
3232
self.target.last_revision_info()
3233
stop_revno = graph.find_distance_to_null(stop_revision,
3234
[(other_last_revision, other_revno),
3235
(this_last_revision, this_revno)])
3236
self.target.set_last_revision_info(stop_revno, stop_revision)
3238
self.source.unlock()
3327
other_revno, other_last_revision = self.source.last_revision_info()
3328
stop_revno = None # unknown
3329
if stop_revision is None:
3330
stop_revision = other_last_revision
3331
if _mod_revision.is_null(stop_revision):
3332
# if there are no commits, we're done.
3334
stop_revno = other_revno
3336
# what's the current last revision, before we fetch [and change it
3338
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3339
# we fetch here so that we don't process data twice in the common
3340
# case of having something to pull, and so that the check for
3341
# already merged can operate on the just fetched graph, which will
3342
# be cached in memory.
3343
self.target.fetch(self.source, stop_revision)
3344
# Check to see if one is an ancestor of the other
3347
graph = self.target.repository.get_graph()
3348
if self.target._check_if_descendant_or_diverged(
3349
stop_revision, last_rev, graph, self.source):
3350
# stop_revision is a descendant of last_rev, but we aren't
3351
# overwriting, so we're done.
3353
if stop_revno is None:
3355
graph = self.target.repository.get_graph()
3356
this_revno, this_last_revision = \
3357
self.target.last_revision_info()
3358
stop_revno = graph.find_distance_to_null(stop_revision,
3359
[(other_last_revision, other_revno),
3360
(this_last_revision, this_revno)])
3361
self.target.set_last_revision_info(stop_revno, stop_revision)
3240
3364
def pull(self, overwrite=False, stop_revision=None,
3241
possible_transports=None, _hook_master=None, run_hooks=True,
3365
possible_transports=None, run_hooks=True,
3242
3366
_override_hook_target=None, local=False):
3367
"""Pull from source into self, updating my master if any.
3245
:param _hook_master: Private parameter - set the branch to
3246
be supplied as the master to pull hooks.
3247
3369
:param run_hooks: Private parameter - if false, this branch
3248
3370
is being called because it's the master of the primary branch,
3249
3371
so it should not run its hooks.
3250
:param _override_hook_target: Private parameter - set the branch to be
3251
supplied as the target_branch to pull hooks.
3252
:param local: Only update the local branch, and not the bound branch.
3254
# This type of branch can't be bound.
3373
bound_location = self.target.get_bound_location()
3374
if local and not bound_location:
3256
3375
raise errors.LocalRequiresBoundBranch()
3257
result = PullResult()
3258
result.source_branch = self.source
3259
if _override_hook_target is None:
3260
result.target_branch = self.target
3262
result.target_branch = _override_hook_target
3263
self.source.lock_read()
3376
master_branch = None
3377
if not local and bound_location and self.source.user_url != bound_location:
3378
# not pulling from master, so we need to update master.
3379
master_branch = self.target.get_master_branch(possible_transports)
3380
master_branch.lock_write()
3265
# We assume that during 'pull' the target repository is closer than
3267
self.source.update_references(self.target)
3268
graph = self.target.repository.get_graph(self.source.repository)
3269
# TODO: Branch formats should have a flag that indicates
3270
# that revno's are expensive, and pull() should honor that flag.
3272
result.old_revno, result.old_revid = \
3273
self.target.last_revision_info()
3274
self.target.update_revisions(self.source, stop_revision,
3275
overwrite=overwrite, graph=graph)
3276
# TODO: The old revid should be specified when merging tags,
3277
# so a tags implementation that versions tags can only
3278
# pull in the most recent changes. -- JRV20090506
3279
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3281
result.new_revno, result.new_revid = self.target.last_revision_info()
3283
result.master_branch = _hook_master
3284
result.local_branch = result.target_branch
3286
result.master_branch = result.target_branch
3287
result.local_branch = None
3289
for hook in Branch.hooks['post_pull']:
3383
# pull from source into master.
3384
master_branch.pull(self.source, overwrite, stop_revision,
3386
return self._pull(overwrite,
3387
stop_revision, _hook_master=master_branch,
3388
run_hooks=run_hooks,
3389
_override_hook_target=_override_hook_target)
3292
self.source.unlock()
3392
master_branch.unlock()
3295
3394
def push(self, overwrite=False, stop_revision=None,
3296
3395
_override_hook_source_branch=None):
3362
def is_compatible(self, source, target):
3363
# GenericBranch uses the public API, so always compatible
3367
class InterToBranch5(GenericInterBranch):
3370
def _get_branch_formats_to_test():
3371
return BranchFormat._default_format, BzrBranchFormat5()
3373
def pull(self, overwrite=False, stop_revision=None,
3374
possible_transports=None, run_hooks=True,
3460
def _pull(self, overwrite=False, stop_revision=None,
3461
possible_transports=None, _hook_master=None, run_hooks=True,
3375
3462
_override_hook_target=None, local=False):
3376
"""Pull from source into self, updating my master if any.
3465
This function is the core worker, used by GenericInterBranch.pull to
3466
avoid duplication when pulling source->master and source->local.
3468
:param _hook_master: Private parameter - set the branch to
3469
be supplied as the master to pull hooks.
3378
3470
:param run_hooks: Private parameter - if false, this branch
3379
3471
is being called because it's the master of the primary branch,
3380
3472
so it should not run its hooks.
3473
:param _override_hook_target: Private parameter - set the branch to be
3474
supplied as the target_branch to pull hooks.
3475
:param local: Only update the local branch, and not the bound branch.
3382
bound_location = self.target.get_bound_location()
3383
if local and not bound_location:
3477
# This type of branch can't be bound.
3384
3479
raise errors.LocalRequiresBoundBranch()
3385
master_branch = None
3386
if not local and bound_location and self.source.user_url != bound_location:
3387
# not pulling from master, so we need to update master.
3388
master_branch = self.target.get_master_branch(possible_transports)
3389
master_branch.lock_write()
3480
result = PullResult()
3481
result.source_branch = self.source
3482
if _override_hook_target is None:
3483
result.target_branch = self.target
3485
result.target_branch = _override_hook_target
3486
self.source.lock_read()
3392
# pull from source into master.
3393
master_branch.pull(self.source, overwrite, stop_revision,
3395
return super(InterToBranch5, self).pull(overwrite,
3396
stop_revision, _hook_master=master_branch,
3397
run_hooks=run_hooks,
3398
_override_hook_target=_override_hook_target)
3488
# We assume that during 'pull' the target repository is closer than
3490
self.source.update_references(self.target)
3491
graph = self.target.repository.get_graph(self.source.repository)
3492
# TODO: Branch formats should have a flag that indicates
3493
# that revno's are expensive, and pull() should honor that flag.
3495
result.old_revno, result.old_revid = \
3496
self.target.last_revision_info()
3497
self.target.update_revisions(self.source, stop_revision,
3498
overwrite=overwrite, graph=graph)
3499
# TODO: The old revid should be specified when merging tags,
3500
# so a tags implementation that versions tags can only
3501
# pull in the most recent changes. -- JRV20090506
3502
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3504
result.new_revno, result.new_revid = self.target.last_revision_info()
3506
result.master_branch = _hook_master
3507
result.local_branch = result.target_branch
3509
result.master_branch = result.target_branch
3510
result.local_branch = None
3512
for hook in Branch.hooks['post_pull']:
3401
master_branch.unlock()
3515
self.source.unlock()
3404
3519
InterBranch.register_optimiser(GenericInterBranch)
3405
InterBranch.register_optimiser(InterToBranch5)