3185
3232
class GenericInterBranch(InterBranch):
3186
"""InterBranch implementation that uses public Branch functions.
3190
def _get_branch_formats_to_test():
3191
return BranchFormat._default_format, BranchFormat._default_format
3233
"""InterBranch implementation that uses public Branch functions."""
3236
def is_compatible(klass, source, target):
3237
# GenericBranch uses the public API, so always compatible
3241
def _get_branch_formats_to_test(klass):
3242
return [(BranchFormat._default_format, BranchFormat._default_format)]
3245
def unwrap_format(klass, format):
3246
if isinstance(format, remote.RemoteBranchFormat):
3247
format._ensure_real()
3248
return format._custom_format
3252
def copy_content_into(self, revision_id=None):
3253
"""Copy the content of source into target
3255
revision_id: if not None, the revision history in the new branch will
3256
be truncated to end with revision_id.
3258
self.source.update_references(self.target)
3259
self.source._synchronize_history(self.target, revision_id)
3261
parent = self.source.get_parent()
3262
except errors.InaccessibleParent, e:
3263
mutter('parent was not accessible to copy: %s', e)
3266
self.target.set_parent(parent)
3267
if self.source._push_should_merge_tags():
3268
self.source.tags.merge_to(self.target.tags)
3193
3271
def update_revisions(self, stop_revision=None, overwrite=False,
3195
3273
"""See InterBranch.update_revisions()."""
3196
self.source.lock_read()
3198
other_revno, other_last_revision = self.source.last_revision_info()
3199
stop_revno = None # unknown
3200
if stop_revision is None:
3201
stop_revision = other_last_revision
3202
if _mod_revision.is_null(stop_revision):
3203
# if there are no commits, we're done.
3205
stop_revno = other_revno
3207
# what's the current last revision, before we fetch [and change it
3209
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3210
# we fetch here so that we don't process data twice in the common
3211
# case of having something to pull, and so that the check for
3212
# already merged can operate on the just fetched graph, which will
3213
# be cached in memory.
3214
self.target.fetch(self.source, stop_revision)
3215
# Check to see if one is an ancestor of the other
3218
graph = self.target.repository.get_graph()
3219
if self.target._check_if_descendant_or_diverged(
3220
stop_revision, last_rev, graph, self.source):
3221
# stop_revision is a descendant of last_rev, but we aren't
3222
# overwriting, so we're done.
3224
if stop_revno is None:
3226
graph = self.target.repository.get_graph()
3227
this_revno, this_last_revision = \
3228
self.target.last_revision_info()
3229
stop_revno = graph.find_distance_to_null(stop_revision,
3230
[(other_last_revision, other_revno),
3231
(this_last_revision, this_revno)])
3232
self.target.set_last_revision_info(stop_revno, stop_revision)
3234
self.source.unlock()
3274
other_revno, other_last_revision = self.source.last_revision_info()
3275
stop_revno = None # unknown
3276
if stop_revision is None:
3277
stop_revision = other_last_revision
3278
if _mod_revision.is_null(stop_revision):
3279
# if there are no commits, we're done.
3281
stop_revno = other_revno
3283
# what's the current last revision, before we fetch [and change it
3285
last_rev = _mod_revision.ensure_null(self.target.last_revision())
3286
# we fetch here so that we don't process data twice in the common
3287
# case of having something to pull, and so that the check for
3288
# already merged can operate on the just fetched graph, which will
3289
# be cached in memory.
3290
self.target.fetch(self.source, stop_revision)
3291
# Check to see if one is an ancestor of the other
3294
graph = self.target.repository.get_graph()
3295
if self.target._check_if_descendant_or_diverged(
3296
stop_revision, last_rev, graph, self.source):
3297
# stop_revision is a descendant of last_rev, but we aren't
3298
# overwriting, so we're done.
3300
if stop_revno is None:
3302
graph = self.target.repository.get_graph()
3303
this_revno, this_last_revision = \
3304
self.target.last_revision_info()
3305
stop_revno = graph.find_distance_to_null(stop_revision,
3306
[(other_last_revision, other_revno),
3307
(this_last_revision, this_revno)])
3308
self.target.set_last_revision_info(stop_revno, stop_revision)
3236
3311
def pull(self, overwrite=False, stop_revision=None,
3237
possible_transports=None, _hook_master=None, run_hooks=True,
3312
possible_transports=None, run_hooks=True,
3238
3313
_override_hook_target=None, local=False):
3314
"""Pull from source into self, updating my master if any.
3241
:param _hook_master: Private parameter - set the branch to
3242
be supplied as the master to pull hooks.
3243
3316
:param run_hooks: Private parameter - if false, this branch
3244
3317
is being called because it's the master of the primary branch,
3245
3318
so it should not run its hooks.
3246
:param _override_hook_target: Private parameter - set the branch to be
3247
supplied as the target_branch to pull hooks.
3248
:param local: Only update the local branch, and not the bound branch.
3250
# This type of branch can't be bound.
3320
bound_location = self.target.get_bound_location()
3321
if local and not bound_location:
3252
3322
raise errors.LocalRequiresBoundBranch()
3253
result = PullResult()
3254
result.source_branch = self.source
3255
if _override_hook_target is None:
3256
result.target_branch = self.target
3258
result.target_branch = _override_hook_target
3259
self.source.lock_read()
3323
master_branch = None
3324
if not local and bound_location and self.source.user_url != bound_location:
3325
# not pulling from master, so we need to update master.
3326
master_branch = self.target.get_master_branch(possible_transports)
3327
master_branch.lock_write()
3261
# We assume that during 'pull' the target repository is closer than
3263
self.source.update_references(self.target)
3264
graph = self.target.repository.get_graph(self.source.repository)
3265
# TODO: Branch formats should have a flag that indicates
3266
# that revno's are expensive, and pull() should honor that flag.
3268
result.old_revno, result.old_revid = \
3269
self.target.last_revision_info()
3270
self.target.update_revisions(self.source, stop_revision,
3271
overwrite=overwrite, graph=graph)
3272
# TODO: The old revid should be specified when merging tags,
3273
# so a tags implementation that versions tags can only
3274
# pull in the most recent changes. -- JRV20090506
3275
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3277
result.new_revno, result.new_revid = self.target.last_revision_info()
3279
result.master_branch = _hook_master
3280
result.local_branch = result.target_branch
3282
result.master_branch = result.target_branch
3283
result.local_branch = None
3285
for hook in Branch.hooks['post_pull']:
3330
# pull from source into master.
3331
master_branch.pull(self.source, overwrite, stop_revision,
3333
return self._pull(overwrite,
3334
stop_revision, _hook_master=master_branch,
3335
run_hooks=run_hooks,
3336
_override_hook_target=_override_hook_target)
3288
self.source.unlock()
3339
master_branch.unlock()
3291
3341
def push(self, overwrite=False, stop_revision=None,
3292
3342
_override_hook_source_branch=None):
3358
def is_compatible(self, source, target):
3359
# GenericBranch uses the public API, so always compatible
3363
class InterToBranch5(GenericInterBranch):
3366
def _get_branch_formats_to_test():
3367
return BranchFormat._default_format, BzrBranchFormat5()
3369
def pull(self, overwrite=False, stop_revision=None,
3370
possible_transports=None, run_hooks=True,
3407
def _pull(self, overwrite=False, stop_revision=None,
3408
possible_transports=None, _hook_master=None, run_hooks=True,
3371
3409
_override_hook_target=None, local=False):
3372
"""Pull from source into self, updating my master if any.
3412
This function is the core worker, used by GenericInterBranch.pull to
3413
avoid duplication when pulling source->master and source->local.
3415
:param _hook_master: Private parameter - set the branch to
3416
be supplied as the master to pull hooks.
3374
3417
:param run_hooks: Private parameter - if false, this branch
3375
3418
is being called because it's the master of the primary branch,
3376
3419
so it should not run its hooks.
3420
:param _override_hook_target: Private parameter - set the branch to be
3421
supplied as the target_branch to pull hooks.
3422
:param local: Only update the local branch, and not the bound branch.
3378
bound_location = self.target.get_bound_location()
3379
if local and not bound_location:
3424
# This type of branch can't be bound.
3380
3426
raise errors.LocalRequiresBoundBranch()
3381
master_branch = None
3382
if not local and bound_location and self.source.user_url != bound_location:
3383
# not pulling from master, so we need to update master.
3384
master_branch = self.target.get_master_branch(possible_transports)
3385
master_branch.lock_write()
3427
result = PullResult()
3428
result.source_branch = self.source
3429
if _override_hook_target is None:
3430
result.target_branch = self.target
3432
result.target_branch = _override_hook_target
3433
self.source.lock_read()
3388
# pull from source into master.
3389
master_branch.pull(self.source, overwrite, stop_revision,
3391
return super(InterToBranch5, self).pull(overwrite,
3392
stop_revision, _hook_master=master_branch,
3393
run_hooks=run_hooks,
3394
_override_hook_target=_override_hook_target)
3435
# We assume that during 'pull' the target repository is closer than
3437
self.source.update_references(self.target)
3438
graph = self.target.repository.get_graph(self.source.repository)
3439
# TODO: Branch formats should have a flag that indicates
3440
# that revno's are expensive, and pull() should honor that flag.
3442
result.old_revno, result.old_revid = \
3443
self.target.last_revision_info()
3444
self.target.update_revisions(self.source, stop_revision,
3445
overwrite=overwrite, graph=graph)
3446
# TODO: The old revid should be specified when merging tags,
3447
# so a tags implementation that versions tags can only
3448
# pull in the most recent changes. -- JRV20090506
3449
result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
3451
result.new_revno, result.new_revid = self.target.last_revision_info()
3453
result.master_branch = _hook_master
3454
result.local_branch = result.target_branch
3456
result.master_branch = result.target_branch
3457
result.local_branch = None
3459
for hook in Branch.hooks['post_pull']:
3397
master_branch.unlock()
3462
self.source.unlock()
3400
3466
InterBranch.register_optimiser(GenericInterBranch)
3401
InterBranch.register_optimiser(InterToBranch5)