/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to push.py

Set refs/heads/master if no ref is set yet.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
 
1
# Copyright (C) 2009-2010 Jelmer Vernooij <jelmer@samba.org>
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
"""Push implementation that simply prints message saying push is not supported."""
18
18
 
19
19
from bzrlib import (
 
20
    errors,
20
21
    ui,
21
22
    )
 
23
from bzrlib.graph import (
 
24
    PendingAncestryResult,
 
25
    )
22
26
from bzrlib.repository import (
23
27
    InterRepository,
24
28
    )
29
33
from bzrlib.plugins.git.errors import (
30
34
    NoPushSupport,
31
35
    )
32
 
from bzrlib.plugins.git.mapping import (
33
 
    extract_unusual_modes,
34
 
    )
35
36
from bzrlib.plugins.git.object_store import (
36
37
    BazaarObjectStore,
37
38
    )
56
57
        """
57
58
        self.source = source
58
59
        self._object_store = store
59
 
        self._revids = set()
60
 
        self._sent_shas = set()
61
60
        self._pending = []
62
61
        self.pb = pb
63
62
 
64
 
    def import_revisions(self, revids):
65
 
        self._revids.update(revids)
 
63
    def import_revisions(self, revids, roundtrip):
66
64
        for i, revid in enumerate(revids):
67
65
            if self.pb:
68
66
                self.pb.update("pushing revisions", i, len(revids))
69
 
            git_commit = self.import_revision(revid)
 
67
            git_commit = self.import_revision(revid, roundtrip)
70
68
            yield (revid, git_commit)
71
69
 
72
 
    def need_sha(self, sha):
73
 
        if sha in self._sent_shas:
74
 
            return False
75
 
        (type, (fileid, revid)) = self._object_store._idmap.lookup_git_sha(sha)
76
 
        assert type in ("blob", "tree")
77
 
        if revid in self._revids:
78
 
            # Not sent yet, and part of the set of revisions to send
79
 
            return True
80
 
        # Not changed in the revisions to send, so either not necessary
81
 
        # or already present remotely (as git doesn't do ghosts)
82
 
        return False
83
 
 
84
 
    def queue(self, sha, obj, path, ie=None, inv=None):
85
 
        if obj is None:
86
 
            obj = (ie, inv)
87
 
        self._pending.append((obj, path))
88
 
        self._sent_shas.add(sha)
89
 
 
90
 
    def import_revision(self, revid):
 
70
    def import_revision(self, revid, roundtrip):
91
71
        """Import the gist of a revision into this Git repository.
92
72
 
93
73
        """
94
 
        inv = self.source.get_inventory(revid)
 
74
        tree = self._object_store.tree_cache.revision_tree(revid)
95
75
        rev = self.source.get_revision(revid)
96
 
        unusual_modes = extract_unusual_modes(rev)
97
 
        todo = [inv.root]
98
 
        tree_sha = None
99
 
        while todo:
100
 
            ie = todo.pop()
101
 
            (sha, object) = self._object_store._get_ie_object_or_sha1(ie, inv, unusual_modes)
102
 
            if ie.parent_id is None:
103
 
                tree_sha = sha
104
 
            if not self.need_sha(sha):
105
 
                continue
106
 
            self.queue(sha, object, inv.id2path(ie.file_id), ie, inv)
107
 
            if ie.kind == "directory":
108
 
                todo.extend(ie.children.values())
109
 
        assert tree_sha is not None
110
 
        commit = self._object_store._get_commit(rev, tree_sha)
111
 
        self.queue(commit.id, commit, None)
 
76
        commit = None
 
77
        for path, obj, ie in self._object_store._revision_to_objects(rev, tree,
 
78
            roundtrip):
 
79
            if obj.type_name == "commit":
 
80
                commit = obj
 
81
            self._pending.append((obj, path))
112
82
        return commit.id
113
83
 
114
84
    def __len__(self):
115
85
        return len(self._pending)
116
86
 
117
87
    def __iter__(self):
118
 
        for i, (object, path) in enumerate(self._pending):
119
 
            if self.pb:
120
 
                self.pb.update("writing pack objects", i, len(self))
121
 
            if isinstance(object, tuple):
122
 
                object = self._object_store._get_ie_object(*object)
123
 
            yield (object, path)   
 
88
        return iter(self._pending)
124
89
 
125
90
 
126
91
class InterToGitRepository(InterRepository):
141
106
        """See InterRepository.copy_content."""
142
107
        self.fetch(revision_id, pb, find_ghosts=False)
143
108
 
144
 
    def fetch(self, revision_id=None, pb=None, find_ghosts=False, 
145
 
            fetch_spec=None):
146
 
        raise NoPushSupport()
147
 
 
148
109
 
149
110
class InterToLocalGitRepository(InterToGitRepository):
150
111
 
 
112
    def __init__(self, source, target):
 
113
        super(InterToLocalGitRepository, self).__init__(source, target)
 
114
        self.target_store = self.target._git.object_store
 
115
        self.target_refs = self.target._git.refs
 
116
 
151
117
    def missing_revisions(self, stop_revisions, check_revid):
152
118
        missing = []
 
119
        graph = self.source.get_graph()
153
120
        pb = ui.ui_factory.nested_progress_bar()
154
121
        try:
155
 
            graph = self.source.get_graph()
156
122
            for revid, _ in graph.iter_ancestry(stop_revisions):
157
123
                pb.update("determining revisions to fetch", len(missing))
158
124
                if not check_revid(revid):
159
125
                    missing.append(revid)
160
 
            return graph.iter_topo_order(missing)
161
126
        finally:
162
127
            pb.finished()
 
128
        return graph.iter_topo_order(missing)
 
129
 
 
130
    def fetch_refs(self, refs):
 
131
        fetch_spec = PendingAncestryResult(refs.values(), self.source)
 
132
        self.fetch(fetch_spec=fetch_spec)
163
133
 
164
134
    def dfetch_refs(self, refs):
165
 
        new_refs = {}
 
135
        old_refs = self.target._git.get_refs()
 
136
        new_refs = dict(old_refs)
166
137
        revidmap, gitidmap = self.dfetch(refs.values())
167
138
        for name, revid in refs.iteritems():
168
 
            if revid in gitidmap:
 
139
            try:
169
140
                gitid = gitidmap[revid]
170
 
            else:
 
141
            except KeyError:
171
142
                gitid = self.source_store._lookup_revision_sha1(revid)
172
143
            self.target._git.refs[name] = gitid
173
144
            new_refs[name] = gitid
174
 
        return revidmap, new_refs
 
145
        return revidmap, old_refs, new_refs
 
146
 
 
147
    def _find_missing_revs(self, stop_revisions):
 
148
        def check_revid(revid):
 
149
            if revid == NULL_REVISION:
 
150
                return True
 
151
            sha_id = self.source_store._lookup_revision_sha1(revid)
 
152
            try:
 
153
                return (sha_id in self.target_store)
 
154
            except errors.NoSuchRevision:
 
155
                # Ghost, can't push
 
156
                return True
 
157
        return list(self.missing_revisions(stop_revisions, check_revid))
175
158
 
176
159
    def dfetch(self, stop_revisions):
177
160
        """Import the gist of the ancestry of a particular revision."""
179
162
        revidmap = {}
180
163
        self.source.lock_read()
181
164
        try:
182
 
            target_store = self.target._git.object_store
183
 
            def check_revid(revid):
184
 
                if revid == NULL_REVISION:
185
 
                    return True
186
 
                return (self.source_store._lookup_revision_sha1(revid) in target_store)
187
 
            todo = list(self.missing_revisions(stop_revisions, check_revid))
 
165
            todo = self._find_missing_revs(stop_revisions)
188
166
            pb = ui.ui_factory.nested_progress_bar()
189
167
            try:
190
 
                object_generator = MissingObjectsIterator(self.source_store, self.source, pb)
 
168
                object_generator = MissingObjectsIterator(self.source_store,
 
169
                    self.source, pb)
191
170
                for old_bzr_revid, git_commit in object_generator.import_revisions(
192
 
                    todo):
 
171
                    todo, roundtrip=False):
193
172
                    new_bzr_revid = self.mapping.revision_id_foreign_to_bzr(git_commit)
194
173
                    revidmap[old_bzr_revid] = new_bzr_revid
195
174
                    gitidmap[old_bzr_revid] = git_commit
196
 
                target_store.add_objects(object_generator) 
 
175
                self.target_store.add_objects(object_generator)
197
176
            finally:
198
177
                pb.finished()
199
178
        finally:
200
179
            self.source.unlock()
201
180
        return revidmap, gitidmap
202
181
 
 
182
    def fetch(self, revision_id=None, pb=None, find_ghosts=False,
 
183
            fetch_spec=None):
 
184
        if revision_id is not None:
 
185
            stop_revisions = [revision_id]
 
186
        elif fetch_spec is not None:
 
187
            stop_revisions = fetch_spec.heads
 
188
        else:
 
189
            stop_revisions = self.source.all_revision_ids()
 
190
        self.source.lock_read()
 
191
        try:
 
192
            todo = self._find_missing_revs(stop_revisions)
 
193
            pb = ui.ui_factory.nested_progress_bar()
 
194
            try:
 
195
                object_generator = MissingObjectsIterator(self.source_store,
 
196
                    self.source, pb)
 
197
                for (revid, git_sha) in object_generator.import_revisions(
 
198
                    todo, roundtrip=True):
 
199
                    try:
 
200
                        self.mapping.revision_id_bzr_to_foreign(revid)
 
201
                    except errors.InvalidRevisionId:
 
202
                        self.target_refs[self.mapping.revid_as_refname(revid)] = git_sha
 
203
                self.target_store.add_objects(object_generator)
 
204
            finally:
 
205
                pb.finished()
 
206
        finally:
 
207
            self.source.unlock()
 
208
 
203
209
    @staticmethod
204
210
    def is_compatible(source, target):
205
211
        """Be compatible with GitRepository."""
206
 
        return (not isinstance(source, GitRepository) and 
 
212
        return (not isinstance(source, GitRepository) and
207
213
                isinstance(target, LocalGitRepository))
208
214
 
209
215
 
212
218
    def dfetch_refs(self, new_refs):
213
219
        """Import the gist of the ancestry of a particular revision."""
214
220
        revidmap = {}
 
221
        old_refs = {}
215
222
        def determine_wants(refs):
216
223
            ret = {}
 
224
            old_refs.update(new_refs)
217
225
            for name, revid in new_refs.iteritems():
218
226
                ret[name] = self.source_store._lookup_revision_sha1(revid)
219
227
            return ret
220
228
        self.source.lock_read()
221
229
        try:
222
230
            new_refs = self.target.send_pack(determine_wants,
223
 
                    self.source_store.generate_pack_contents)
 
231
                    self.source_store.generate_lossy_pack_contents)
224
232
        finally:
225
233
            self.source.unlock()
226
 
        return revidmap, new_refs
 
234
        return revidmap, old_refs, new_refs
 
235
 
 
236
    def fetch(self, revision_id=None, pb=None, find_ghosts=False,
 
237
            fetch_spec=None):
 
238
        raise NoPushSupport()
227
239
 
228
240
    @staticmethod
229
241
    def is_compatible(source, target):
230
242
        """Be compatible with GitRepository."""
231
 
        return (not isinstance(source, GitRepository) and 
 
243
        return (not isinstance(source, GitRepository) and
232
244
                isinstance(target, RemoteGitRepository))