Interrupted initial push leads to branch reference

Bug #189757 reported by Aaron Bentley
This bug report is a duplicate of:  Bug #376274: push creating wrong format. Edit Remove
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Bazaar
Confirmed
High
canonical-bazaar

Bug Description

I interrupted a push from a checkout, apparently at a critical moment. Then I pushed again, and the result was a branch reference, which points at the branch on my machine.

Steps to reproduce:
$ bzr init foo
$ bzr commit -m unchanged --unchanged foo
Committing to: /home/abentley/foo/
Committed revision 1.
$ bzr checkout foo bar --lightweight
$ bzr init baz
$ rm baz/.bzr/branch -R
$ bzr push -d bar baz
Created new branch.
$ cd baz
$ cd .bzr/branch
$ ls
format location

Tags: push
Aaron Bentley (abentley)
Changed in bzr:
importance: Undecided → Critical
description: updated
Martin Pool (mbp)
Changed in bzr:
importance: Critical → High
Revision history for this message
John A Meinel (jameinel) wrote :

I can confirm that your steps do generate a branch reference in the target.

I'm guessing that this is happening because of the push fallback code.

Specifically, it used to be that doing "bzr push" would create the remote repository, but no branch. If you interrupted it, and tried to push again, it would fail, because it didn't have a branch, but it wasn't an empty directory, either.
I originally felt that push should create the remote branch, and then populate it, Robert felt that was a race condition. So now, it creates the repository, populates it, then the branch (as before). Except, if it finds a remote repo, it will then create a branch, and fetch into it (as I proposed, but only under extenuating circumstances, not as the default flow.)

The code in question is here:
elif br_to is None:
    # We have a repository but no branch, copy the revisions, and then
    # create a branch.
    if stacked_on is not None:
        warning("Ignoring request for a stacked branch as repository "
                "already exists at the destination location.")
    repository_to.fetch(br_from.repository, revision_id=revision_id)
    br_to = br_from.clone(dir_to, revision_id=revision_id)
    note('Created new branch.')
    if br_from.get_push_location() is None or remember:
        br_from.set_push_location(br_to.base)

So what is happening is that "br_from.clone()" on a BranchReference is creating a branch reference in the remote.
The problem may be as simple as using br_from.sprout() instead of .clone(), but sprout usually copies history, so I'm not sure how that works.

Also, we need to take some care because "br_from.sprout(to_bzrdir)" uses the 'to_bzrdir" as the one who decides the format. But as the target already existed, it probably isn't configured appropriately with the current branch format. (Normally, we do a sprout() after creating the bzrdir, and because we created the bzrdir we initialized it correctly, in this code path we *opened* the bzrdir, and have not set any of the format attributes.)

Changed in bzr:
status: New → Triaged
Martin Pool (mbp)
Changed in bzr:
status: Triaged → Confirmed
Jelmer Vernooij (jelmer)
tags: added: push
Martin Pool (mbp)
Changed in bzr:
assignee: nobody → canonical-bazaar (canonical-bazaar)
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.