~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branchbuilder.py

  • Committer: Martin Pool
  • Date: 2010-07-16 15:20:17 UTC
  • mfrom: (5346.3.1 pathnotchild)
  • mto: This revision was merged to the branch mainline in revision 5351.
  • Revision ID: mbp@canonical.com-20100716152017-t4c73h9y1uoih7fb
PathNotChild should not give a traceback.

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
        a series in progress, it should be None.
57
57
    """
58
58
 
59
 
    def __init__(self, transport, format=None):
 
59
    def __init__(self, transport=None, format=None, branch=None):
60
60
        """Construct a BranchBuilder on transport.
61
61
 
62
62
        :param transport: The transport the branch should be created on.
64
64
            it will be created.
65
65
        :param format: Either a BzrDirFormat, or the name of a format in the
66
66
            bzrdir format registry for the branch to be built.
 
67
        :param branch: An already constructed branch to use.  This param is
 
68
            mutually exclusive with the transport and format params.
67
69
        """
68
 
        if not transport.has('.'):
69
 
            transport.mkdir('.')
70
 
        if format is None:
71
 
            format = 'default'
72
 
        if isinstance(format, str):
73
 
            format = bzrdir.format_registry.make_bzrdir(format)
74
 
        self._branch = bzrdir.BzrDir.create_branch_convenience(transport.base,
75
 
            format=format, force_new_tree=False)
 
70
        if branch is not None:
 
71
            if format is not None:
 
72
                raise AssertionError(
 
73
                    "branch and format kwargs are mutually exclusive")
 
74
            if transport is not None:
 
75
                raise AssertionError(
 
76
                    "branch and transport kwargs are mutually exclusive")
 
77
            self._branch = branch
 
78
        else:
 
79
            if not transport.has('.'):
 
80
                transport.mkdir('.')
 
81
            if format is None:
 
82
                format = 'default'
 
83
            if isinstance(format, str):
 
84
                format = bzrdir.format_registry.make_bzrdir(format)
 
85
            self._branch = bzrdir.BzrDir.create_branch_convenience(
 
86
                transport.base, format=format, force_new_tree=False)
76
87
        self._tree = None
77
88
 
78
89
    def build_commit(self, **commit_kwargs):
92
103
        finally:
93
104
            tree.unlock()
94
105
 
95
 
    def _do_commit(self, tree, message=None, **kwargs):
 
106
    def _do_commit(self, tree, message=None, message_callback=None, **kwargs):
96
107
        reporter = commit.NullCommitReporter()
97
 
        if message is None:
 
108
        if message is None and message_callback is None:
98
109
            message = u'commit %d' % (self._branch.revno() + 1,)
99
 
        return tree.commit(message,
 
110
        return tree.commit(message, message_callback=message_callback,
100
111
            reporter=reporter,
101
112
            **kwargs)
102
113
 
103
 
    def _move_branch_pointer(self, new_revision_id):
 
114
    def _move_branch_pointer(self, new_revision_id,
 
115
        allow_leftmost_as_ghost=False):
104
116
        """Point self._branch to a different revision id."""
105
117
        self._branch.lock_write()
106
118
        try:
107
119
            # We don't seem to have a simple set_last_revision(), so we
108
120
            # implement it here.
109
121
            cur_revno, cur_revision_id = self._branch.last_revision_info()
110
 
            g = self._branch.repository.get_graph()
111
 
            new_revno = g.find_distance_to_null(new_revision_id,
112
 
                                                [(cur_revision_id, cur_revno)])
113
 
            self._branch.set_last_revision_info(new_revno, new_revision_id)
 
122
            try:
 
123
                g = self._branch.repository.get_graph()
 
124
                new_revno = g.find_distance_to_null(new_revision_id,
 
125
                    [(cur_revision_id, cur_revno)])
 
126
                self._branch.set_last_revision_info(new_revno, new_revision_id)
 
127
            except errors.GhostRevisionsHaveNoRevno:
 
128
                if not allow_leftmost_as_ghost:
 
129
                    raise
 
130
                new_revno = 1
114
131
        finally:
115
132
            self._branch.unlock()
116
133
        if self._tree is not None:
144
161
        self._tree = None
145
162
 
146
163
    def build_snapshot(self, revision_id, parent_ids, actions,
147
 
                       message=None, timestamp=None):
 
164
        message=None, timestamp=None, allow_leftmost_as_ghost=False,
 
165
        committer=None, timezone=None, message_callback=None):
148
166
        """Build a commit, shaped in a specific way.
149
167
 
150
168
        :param revision_id: The handle for the new commit, can be None
157
175
            ('rename', ('orig-path', 'new-path'))
158
176
        :param message: An optional commit message, if not supplied, a default
159
177
            commit message will be written.
 
178
        :param message_callback: A message callback to use for the commit, as
 
179
            per mutabletree.commit.
160
180
        :param timestamp: If non-None, set the timestamp of the commit to this
161
181
            value.
 
182
        :param timezone: An optional timezone for timestamp.
 
183
        :param committer: An optional username to use for commit
 
184
        :param allow_leftmost_as_ghost: True if the leftmost parent should be
 
185
            permitted to be a ghost.
162
186
        :return: The revision_id of the new commit
163
187
        """
164
188
        if parent_ids is not None:
165
189
            base_id = parent_ids[0]
166
190
            if base_id != self._branch.last_revision():
167
 
                self._move_branch_pointer(base_id)
 
191
                self._move_branch_pointer(base_id,
 
192
                    allow_leftmost_as_ghost=allow_leftmost_as_ghost)
168
193
 
169
194
        if self._tree is not None:
170
195
            tree = self._tree
173
198
        tree.lock_write()
174
199
        try:
175
200
            if parent_ids is not None:
176
 
                tree.set_parent_ids(parent_ids)
 
201
                tree.set_parent_ids(parent_ids,
 
202
                    allow_leftmost_as_ghost=allow_leftmost_as_ghost)
177
203
            # Unfortunately, MemoryTree.add(directory) just creates an
178
204
            # inventory entry. And the only public function to create a
179
205
            # directory is MemoryTree.mkdir() which creates the directory, but
220
246
            for file_id, content in new_contents.iteritems():
221
247
                tree.put_file_bytes_non_atomic(file_id, content)
222
248
            return self._do_commit(tree, message=message, rev_id=revision_id,
223
 
                timestamp=timestamp)
 
249
                timestamp=timestamp, timezone=timezone, committer=committer,
 
250
                message_callback=message_callback)
224
251
        finally:
225
252
            tree.unlock()
226
253