/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
1
# Copyright (C) 2007 Canonical Ltd
0.200.252 by Jelmer Vernooij
Clarify history, copyright.
2
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
"""An adapter between a Git Branch and a Bazaar Branch"""
19
0.200.261 by Jelmer Vernooij
More formatting fixes.
20
from dulwich.objects import (
21
    Commit,
22
    Tag,
23
    )
24
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
25
from bzrlib import (
26
    branch,
27
    config,
0.200.327 by Jelmer Vernooij
merge new bzr-foreign.
28
    foreign,
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
29
    repository,
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
30
    revision,
0.200.82 by Jelmer Vernooij
Support listing tags.
31
    tag,
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
32
    transport,
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
33
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
34
from bzrlib.decorators import (
35
    needs_read_lock,
36
    )
37
from bzrlib.trace import (
38
    mutter,
39
    )
40
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
41
from bzrlib.plugins.git.errors import (
42
    NoSuchRef,
43
    )
0.200.261 by Jelmer Vernooij
More formatting fixes.
44
45
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
46
class GitPullResult(branch.PullResult):
47
48
    def _lookup_revno(self, revid):
49
        assert isinstance(revid, str), "was %r" % revid
50
        # Try in source branch first, it'll be faster
51
        return self.target_branch.revision_id_to_revno(revid)
52
53
    @property
54
    def old_revno(self):
55
        return self._lookup_revno(self.old_revid)
56
57
    @property
58
    def new_revno(self):
59
        return self._lookup_revno(self.new_revid)
60
61
0.200.261 by Jelmer Vernooij
More formatting fixes.
62
class LocalGitTagDict(tag.BasicTags):
63
    """Dictionary with tags in a local repository."""
0.200.82 by Jelmer Vernooij
Support listing tags.
64
0.200.89 by Jelmer Vernooij
Support sprouting branches.
65
    def __init__(self, branch):
66
        self.branch = branch
67
        self.repository = branch.repository
0.200.82 by Jelmer Vernooij
Support listing tags.
68
69
    def get_tag_dict(self):
70
        ret = {}
0.200.180 by Jelmer Vernooij
Simplify tag handling.
71
        for k,v in self.repository._git.tags.iteritems():
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
72
            obj = self.repository._git.get_object(v)
73
            while isinstance(obj, Tag):
74
                v = obj.object[1]
75
                obj = self.repository._git.get_object(v)
76
            if not isinstance(obj, Commit):
0.200.261 by Jelmer Vernooij
More formatting fixes.
77
                mutter("Tag %s points at object %r that is not a commit, "
78
                       "ignoring", k, obj)
0.200.194 by Jelmer Vernooij
Look for commit object in heavyweight tags.
79
                continue
0.200.180 by Jelmer Vernooij
Simplify tag handling.
80
            ret[k] = self.branch.mapping.revision_id_foreign_to_bzr(v)
0.200.82 by Jelmer Vernooij
Support listing tags.
81
        return ret
82
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
83
    def set_tag(self, name, revid):
0.200.181 by Jelmer Vernooij
Support setting tags.
84
        self.repository._git.tags[name] = revid
0.200.86 by Jelmer Vernooij
Clearer error when setting tags.
85
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
86
87
class GitBranchConfig(config.BranchConfig):
88
    """BranchConfig that uses locations.conf in place of branch.conf"""
89
90
    def __init__(self, branch):
91
        config.BranchConfig.__init__(self, branch)
92
        # do not provide a BranchDataConfig
93
        self.option_sources = self.option_sources[0], self.option_sources[2]
94
0.200.261 by Jelmer Vernooij
More formatting fixes.
95
    def set_user_option(self, name, value, store=config.STORE_BRANCH,
96
            warn_masked=False):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
97
        """Force local to True"""
0.200.261 by Jelmer Vernooij
More formatting fixes.
98
        config.BranchConfig.set_user_option(self, name, value,
99
            store=config.STORE_LOCATION, warn_masked=warn_masked)
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
100
101
102
class GitBranchFormat(branch.BranchFormat):
103
0.200.70 by Jelmer Vernooij
Implement GitBranchFormat.get_format_description.
104
    def get_format_description(self):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
105
        return 'Git Branch'
106
0.200.82 by Jelmer Vernooij
Support listing tags.
107
    def supports_tags(self):
108
        return True
109
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
110
    def make_tags(self, branch):
0.228.3 by Jelmer Vernooij
Fix tags when fetching from remotes.
111
        if getattr(branch.repository, "get_refs", None) is not None:
112
            from bzrlib.plugins.git.remote import RemoteGitTagDict
113
            return RemoteGitTagDict(branch)
0.200.261 by Jelmer Vernooij
More formatting fixes.
114
        else:
115
            return LocalGitTagDict(branch)
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
116
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
117
0.200.327 by Jelmer Vernooij
merge new bzr-foreign.
118
class GitBranch(foreign.ForeignBranch):
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
119
    """An adapter to git repositories for bzr Branch objects."""
120
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
121
    def __init__(self, bzrdir, repository, name, head, lockfiles):
0.200.82 by Jelmer Vernooij
Support listing tags.
122
        self.repository = repository
0.200.246 by Jelmer Vernooij
Cope with API changes in 1.13.
123
        self._format = GitBranchFormat()
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
124
        self.control_files = lockfiles
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
125
        self.bzrdir = bzrdir
0.231.1 by Jelmer Vernooij
Check that regenerated objects have the expected sha1.
126
        super(GitBranch, self).__init__(repository.get_mapping())
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
127
        self.name = name
0.200.57 by Jelmer Vernooij
Fix more tests.
128
        self.head = head
0.200.143 by Jelmer Vernooij
Reoncile InterGitRepository objects.
129
        self.base = bzrdir.transport.base
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
130
0.200.293 by Jelmer Vernooij
Fix branch nicks.
131
    def _get_nick(self, local=False, possible_master_transports=None):
132
        """Find the nick name for this branch.
133
134
        :return: Branch nick
135
        """
136
        return self.name
137
0.200.331 by Jelmer Vernooij
Add stub for setting nick function.
138
    def _set_nick(self, nick):
139
        raise NotImplementedError
140
141
    nick = property(_get_nick, _set_nick)
0.200.293 by Jelmer Vernooij
Fix branch nicks.
142
0.200.211 by Jelmer Vernooij
Add basic infrastructure for dpush.
143
    def dpull(self, source, stop_revision=None):
144
        if stop_revision is None:
145
            stop_revision = source.last_revision()
146
        # FIXME: Check for diverged branches
147
        revidmap = self.repository.dfetch(source.repository, stop_revision)
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
148
        if revidmap != {}:
149
            self.generate_revision_history(revidmap[stop_revision])
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
150
        return revidmap
151
152
    def generate_revision_history(self, revid, old_revid=None):
153
        # FIXME: Check that old_revid is in the ancestry of revid
154
        newhead, self.mapping = self.mapping.revision_id_bzr_to_foreign(revid)
155
        self._set_head(newhead)
156
157
    def _set_head(self, head):
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
158
        self.head = head
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
159
        self.repository._git.set_ref(self.name, self.head)
0.200.211 by Jelmer Vernooij
Add basic infrastructure for dpush.
160
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
161
    def lock_write(self):
162
        self.control_files.lock_write()
163
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
164
    def get_stacked_on_url(self):
165
        # Git doesn't do stacking (yet...)
166
        return None
167
168
    def get_parent(self):
169
        """See Branch.get_parent()."""
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
170
        # FIXME: Set "origin" url from .git/config ?
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
171
        return None
172
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
173
    def set_parent(self, url):
0.200.312 by Jelmer Vernooij
Add notes about parent locations.
174
        # FIXME: Set "origin" url in .git/config ?
0.200.175 by Jelmer Vernooij
Add optimized handling when fetching from git to git.
175
        pass
176
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
177
    def lock_read(self):
178
        self.control_files.lock_read()
179
180
    def unlock(self):
181
        self.control_files.unlock()
182
183
    def get_physical_lock_status(self):
184
        return False
185
186
 
187
class LocalGitBranch(GitBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
188
    """A local Git branch."""
0.200.139 by Jelmer Vernooij
Share more code between local and remote classes, support opening remote branches.
189
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
190
    @needs_read_lock
191
    def last_revision(self):
192
        # perhaps should escape this ?
0.200.57 by Jelmer Vernooij
Fix more tests.
193
        if self.head is None:
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
194
            return revision.NULL_REVISION
0.200.112 by Jelmer Vernooij
Fix the build.
195
        return self.mapping.revision_id_foreign_to_bzr(self.head)
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
196
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
197
    def _get_checkout_format(self):
198
        """Return the most suitable metadir for a checkout of this branch.
199
        Weaves are used if this branch's repository uses weaves.
200
        """
201
        format = self.repository.bzrdir.checkout_metadir()
202
        format.set_branch_format(self._format)
203
        return format
204
0.200.261 by Jelmer Vernooij
More formatting fixes.
205
    def create_checkout(self, to_location, revision_id=None, lightweight=False,
206
        accelerator_tree=None, hardlink=False):
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
207
        if lightweight:
0.230.1 by Jelmer Vernooij
Support lightweight checkouts.
208
            t = transport.get_transport(to_location)
209
            t.ensure_base()
210
            format = self._get_checkout_format()
211
            checkout = format.initialize_on_transport(t)
212
            from_branch = branch.BranchReferenceFormat().initialize(checkout, 
213
                self)
214
            tree = checkout.create_workingtree(revision_id,
215
                from_branch=from_branch, hardlink=hardlink)
216
            return tree
217
        else:
218
            return self._create_heavyweight_checkout(to_location, revision_id,
0.200.261 by Jelmer Vernooij
More formatting fixes.
219
            hardlink)
0.200.210 by Jelmer Vernooij
properly error out about not support lightweight checkouts.
220
221
    def _create_heavyweight_checkout(self, to_location, revision_id=None, 
222
                                     hardlink=False):
223
        """Create a new heavyweight checkout of this branch.
224
225
        :param to_location: URL of location to create the new checkout in.
226
        :param revision_id: Revision that should be the tip of the checkout.
227
        :param hardlink: Whether to hardlink
228
        :return: WorkingTree object of checkout.
229
        """
230
        checkout_branch = BzrDir.create_branch_convenience(
231
            to_location, force_new_tree=False, format=get_rich_root_format())
232
        checkout = checkout_branch.bzrdir
233
        checkout_branch.bind(self)
234
        # pull up to the specified revision_id to set the initial 
235
        # branch tip correctly, and seed it with history.
236
        checkout_branch.pull(self, stop_revision=revision_id)
237
        return checkout.create_workingtree(revision_id, hardlink=hardlink)
238
0.200.57 by Jelmer Vernooij
Fix more tests.
239
    def _gen_revision_history(self):
0.200.58 by Jelmer Vernooij
Fix remaining tests.
240
        if self.head is None:
241
            return []
0.200.261 by Jelmer Vernooij
More formatting fixes.
242
        ret = list(self.repository.iter_reverse_revision_history(
243
            self.last_revision()))
0.200.59 by Jelmer Vernooij
Add more tests, fix revision history.
244
        ret.reverse()
0.200.57 by Jelmer Vernooij
Fix more tests.
245
        return ret
0.200.18 by John Arbash Meinel
Start splitting up the Git{Branch,Dir,Repository} into separate modules, etc.
246
247
    def get_config(self):
248
        return GitBranchConfig(self)
249
250
    def get_push_location(self):
251
        """See Branch.get_push_location."""
252
        push_loc = self.get_config().get_user_option('push_location')
253
        return push_loc
254
255
    def set_push_location(self, location):
256
        """See Branch.set_push_location."""
0.200.19 by John Arbash Meinel
More refactoring. Add some direct tests for GitModel.
257
        self.get_config().set_user_option('push_location', location,
0.217.54 by John Carr
set_user_option breaks - doesnt have a local option in BranchConfig. Follow the bzr.dev syntax instead.
258
                                          store=config.STORE_LOCATION)
0.200.43 by David Allouche
Ultra-experimental support for "bzr pull". No test. No sanity.
259
260
    def supports_tags(self):
0.200.82 by Jelmer Vernooij
Support listing tags.
261
        return True
0.200.96 by Jelmer Vernooij
Fix branch.
262
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
263
264
class InterGitGenericBranch(branch.InterBranch):
0.200.261 by Jelmer Vernooij
More formatting fixes.
265
    """InterBranch implementation that pulls from Git into bzr."""
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
266
267
    @classmethod
268
    def is_compatible(self, source, target):
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
269
        return (isinstance(source, GitBranch) and 
270
                not isinstance(target, GitBranch))
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
271
272
    def update_revisions(self, stop_revision=None, overwrite=False,
273
        graph=None):
274
        """See InterBranch.update_revisions()."""
0.226.2 by Jelmer Vernooij
Cope with new fetch_spec argument.
275
        interrepo = repository.InterRepository.get(self.source.repository, 
276
            self.target.repository)
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
277
        self._last_revid = None
278
        def determine_wants(heads):
279
            if not self.source.name in heads:
0.200.278 by Jelmer Vernooij
Update branch head appropriately during dpull.
280
                raise NoSuchRef(self.source.name, heads.keys())
0.200.314 by Jelmer Vernooij
Support stop_revision.
281
            if stop_revision is not None:
282
                self._last_revid = stop_revision
0.200.316 by Jelmer Vernooij
Fix formatting.
283
                head, mapping = self.source.repository.lookup_git_revid(
284
                    stop_revision)
0.200.314 by Jelmer Vernooij
Support stop_revision.
285
            else:
286
                head = heads[self.source.name]
0.200.316 by Jelmer Vernooij
Fix formatting.
287
                self._last_revid = \
288
                    self.source.mapping.revision_id_foreign_to_bzr(head)
0.200.226 by Jelmer Vernooij
Merge thin-pack work.
289
            if self.target.repository.has_revision(self._last_revid):
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
290
                return []
291
            return [head]
292
        interrepo.fetch_objects(determine_wants, self.source.mapping)
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
293
        if overwrite:
0.200.314 by Jelmer Vernooij
Support stop_revision.
294
            prev_last_revid = None
0.200.313 by Jelmer Vernooij
Support overwrite parameter.
295
        else:
0.200.314 by Jelmer Vernooij
Support stop_revision.
296
            prev_last_revid = self.target.last_revision()
297
        self.target.generate_revision_history(self._last_revid, prev_last_revid)
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
298
0.200.338 by Jelmer Vernooij
Fix dpushing without changes necessary.
299
    def pull(self, overwrite=False, stop_revision=None,
300
             possible_transports=None, _hook_master=None, run_hooks=True,
301
             _override_hook_target=None):
302
        """See Branch.pull.
303
304
        :param _hook_master: Private parameter - set the branch to
305
            be supplied as the master to pull hooks.
306
        :param run_hooks: Private parameter - if false, this branch
307
            is being called because it's the master of the primary branch,
308
            so it should not run its hooks.
309
        :param _override_hook_target: Private parameter - set the branch to be
310
            supplied as the target_branch to pull hooks.
311
        """
312
        result = branch.PullResult()
313
        result.source_branch = self.source
314
        if _override_hook_target is None:
315
            result.target_branch = self.target
316
        else:
317
            result.target_branch = _override_hook_target
318
        self.source.lock_read()
319
        try:
320
            # We assume that during 'pull' the target repository is closer than
321
            # the source one.
322
            graph = self.target.repository.get_graph(self.source.repository)
323
            result.old_revno, result.old_revid = \
324
                self.target.last_revision_info()
325
            self.target.update_revisions(self.source, stop_revision,
326
                overwrite=overwrite, graph=graph)
327
            result.tag_conflicts = self.source.tags.merge_to(self.target.tags,
328
                overwrite)
329
            result.new_revno, result.new_revid = self.target.last_revision_info()
330
            if _hook_master:
331
                result.master_branch = _hook_master
332
                result.local_branch = result.target_branch
333
            else:
334
                result.master_branch = result.target_branch
335
                result.local_branch = None
336
            if run_hooks:
337
                for hook in branch.Branch.hooks['post_pull']:
338
                    hook(result)
339
        finally:
340
            self.source.unlock()
341
        return result
342
343
344
0.200.225 by Jelmer Vernooij
Implement custom InterBranch to support fetching from remote git branches.
345
346
branch.InterBranch.register_optimiser(InterGitGenericBranch)
0.200.334 by Jelmer Vernooij
Support pulling from git to git.
347
348
349
class InterGitRemoteLocalBranch(branch.InterBranch):
350
    """InterBranch implementation that pulls between Git branches."""
351
352
    @classmethod
353
    def is_compatible(self, source, target):
354
        from bzrlib.plugins.git.remote import RemoteGitBranch
355
        return (isinstance(source, RemoteGitBranch) and 
356
                isinstance(target, LocalGitBranch))
357
358
    def pull(self, stop_revision=None, overwrite=False, 
359
        possible_transports=None):
360
        result = GitPullResult()
361
        result.source_branch = self.source
362
        result.target_branch = self.target
363
        interrepo = repository.InterRepository.get(self.source.repository, 
364
            self.target.repository)
365
        result.old_revid = self.target.last_revision()
366
        if stop_revision is None:
367
            stop_revision = self.source.last_revision()
368
        interrepo.fetch(revision_id=stop_revision)
369
        self.target.generate_revision_history(stop_revision, result.old_revid)
370
        result.new_revid = self.target.last_revision()
371
        return result
372
373
374
branch.InterBranch.register_optimiser(InterGitRemoteLocalBranch)