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