/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.217.1 by John Carr
Start stubbing out rewritten git-serve
1
# Copyright (C) 2008 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
0.217.7 by John Carr
Create tips
17
from bzrlib.bzrdir import BzrDir
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
18
from bzrlib.repository import Repository
0.217.15 by John Carr
Start traversing commits and inventories
19
from bzrlib.inventory import InventoryDirectory, InventoryFile
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
20
from bzrlib.osutils import splitpath
0.217.4 by John Carr
Easy bits of git pushing to bazaar
21
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
22
from bzrlib.plugins.git.fetch import import_git_objects
0.217.7 by John Carr
Create tips
23
from bzrlib.plugins.git.mapping import default_mapping
24
0.217.1 by John Carr
Start stubbing out rewritten git-serve
25
from dulwich.server import Backend
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
26
from dulwich.pack import Pack, PackData, write_pack_index_v2
0.217.17 by John Carr
More gentle plumbing
27
from dulwich.objects import ShaFile, Commit, Tree, Blob
0.217.5 by John Carr
Add a temporary hack to test pushing form git to bazaar
28
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
29
import os, tempfile
0.217.1 by John Carr
Start stubbing out rewritten git-serve
30
0.217.32 by John Carr
Dirtyness to help pass tests
31
# FIXME: Remove this in favor of something in the mapping...
32
_mode = -1
33
def get_umask():
0.220.1 by Ali Sabil
Fixed unpacking the return value from Repository.iter_files_bytes
34
    global _mode
0.217.32 by John Carr
Dirtyness to help pass tests
35
    if _mode == -1:
36
        _mode = os.umask(0)
37
        os.umask(_mode)
38
    return _mode
39
0.217.1 by John Carr
Start stubbing out rewritten git-serve
40
class BzrBackend(Backend):
41
0.217.2 by John Carr
Fix missing imports. Update TCPGitServer instantiation to latest. BzrBackend needs to know which directory its repo is in.
42
    def __init__(self, directory):
43
        self.directory = directory
0.217.7 by John Carr
Create tips
44
        self.mapping = default_mapping
0.217.2 by John Carr
Fix missing imports. Update TCPGitServer instantiation to latest. BzrBackend needs to know which directory its repo is in.
45
0.217.1 by John Carr
Start stubbing out rewritten git-serve
46
    def get_refs(self):
47
        """ return a dict of all tags and branches in repository (and shas) """
0.217.12 by John Carr
Support ls-remote against bazaar
48
        ret = {}
49
        repo_dir = BzrDir.open(self.directory)
50
        repo = repo_dir.open_repository()
51
        for branch in repo.find_branches(using=True):
52
            #FIXME: Need to get branch path relative to its repository and use this instead of nick
53
            ret["refs/heads/"+branch.nick] = self.mapping.revision_id_bzr_to_foreign(branch.last_revision())
54
        return ret
0.217.1 by John Carr
Start stubbing out rewritten git-serve
55
56
    def apply_pack(self, refs, read):
57
        """ apply pack from client to current repository """
0.217.4 by John Carr
Easy bits of git pushing to bazaar
58
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
59
        fd, path = tempfile.mkstemp(suffix=".pack")
60
        f = os.fdopen(fd, 'w')
0.217.6 by John Carr
Fix typos
61
        f.write(read())
0.217.5 by John Carr
Add a temporary hack to test pushing form git to bazaar
62
        f.close()
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
63
64
        p = PackData(path)
65
        entries = p.sorted_entries()
66
        write_pack_index_v2(path[:-5]+".idx", entries, p.calculate_checksum())
67
68
        def get_objects():
69
            pack = Pack(path[:-5])
70
            for obj in pack.iterobjects():
71
                yield obj
72
73
        target = Repository.open(self.directory)
74
75
        target.lock_write()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
76
        try:
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
77
            target.start_write_group()
78
            try:
79
                import_git_objects(target, self.mapping, iter(get_objects()))
80
            finally:
81
                target.commit_write_group()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
82
        finally:
0.217.8 by John Carr
Don't bother using InterRepo, use import_git_objects directly. Don't need a full repository (just operating on a pack and index)
83
            target.unlock()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
84
0.217.7 by John Carr
Create tips
85
        for oldsha, sha, ref in refs:
86
            if ref[:11] == 'refs/heads/':
87
                branch_nick = ref[11:]
88
89
                try:
90
                    target_dir = BzrDir.open(self.directory + "/" + branch_nick)
91
                except:
92
                    target_dir = BzrDir.create(self.directory + "/" + branch_nick)
93
94
                try:
95
                    target_branch = target_dir.open_branch()
96
                except:
97
                    target_branch = target_dir.create_branch()
0.217.22 by John Carr
Fix whitespace
98
0.217.7 by John Carr
Create tips
99
                rev_id = self.mapping.revision_id_foreign_to_bzr(sha)
0.217.22 by John Carr
Fix whitespace
100
                target_branch.generate_revision_history(rev_id)
0.217.7 by John Carr
Create tips
101
0.217.1 by John Carr
Start stubbing out rewritten git-serve
102
    def fetch_objects(self, determine_wants, graph_walker, progress):
103
        """ yield git objects to send to client """
0.217.12 by John Carr
Support ls-remote against bazaar
104
        wants = determine_wants(self.get_refs())
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
105
        commits_to_send = set([self.mapping.revision_id_foreign_to_bzr(w) for w in wants])
106
        rev_done = set()
0.217.31 by John Carr
At the moment, we have to convert an object to know its sha :\ - the same sha can be made multiple times... lets at least not add it the pack if its already there.
107
        obj_sent = set()
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
108
109
        repo = Repository.open(self.directory)
0.217.22 by John Carr
Fix whitespace
110
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
111
        repo.lock_read()
112
        try:
113
            have = graph_walker.next()
114
            while have:
115
                rev_done.add(have)
116
                if repo.has_revision(self.mapping.revision_id_foregin_to_bzr(sha)):
117
                    graph_walker.ack(have)
118
                have = graph_walker.next()
119
120
            while commits_to_send:
0.217.15 by John Carr
Start traversing commits and inventories
121
                commit = commits_to_send.pop()
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
122
                if commit in rev_done:
123
                    continue
124
                rev_done.add(commit)
125
0.217.15 by John Carr
Start traversing commits and inventories
126
                rev = repo.get_revision(commit)
127
128
                commits_to_send.update([p for p in rev.parent_ids if not p in rev_done])
129
0.217.33 by John Carr
Return real full texts
130
                for sha, obj in inventory_to_tree_and_blobs(repo, self.mapping, commit):
0.217.31 by John Carr
At the moment, we have to convert an object to know its sha :\ - the same sha can be made multiple times... lets at least not add it the pack if its already there.
131
                    if sha not in obj_sent:
132
                        obj_sent.add(sha)
133
                        yield obj
0.217.15 by John Carr
Start traversing commits and inventories
134
0.217.28 by John Carr
Refactor to correctly yield shas and objects
135
                yield revision_to_commit(rev, self.mapping, sha)
0.217.15 by John Carr
Start traversing commits and inventories
136
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
137
        finally:
138
            repo.unlock()
0.217.15 by John Carr
Start traversing commits and inventories
139
140
0.217.25 by John Carr
Lets test commit gen
141
def revision_to_commit(rev, mapping, tree_sha):
142
    """
143
    Turn a Bazaar revision in to a Git commit
144
    :param tree_sha: HACK parameter (until we can retrieve this from the mapping)
145
    :return dulwich.objects.Commit represent the revision:
146
    """
0.217.15 by John Carr
Start traversing commits and inventories
147
    commit = Commit()
0.217.26 by John Carr
Fix typos
148
    commit._tree = tree_sha
0.217.23 by John Carr
Reconstitute the commit object
149
    for p in rev.parent_ids:
0.217.26 by John Carr
Fix typos
150
        commit._parents.append(mapping.revision_id_bzr_to_foreign(p))
0.217.23 by John Carr
Reconstitute the commit object
151
    commit._message = rev.message
152
    commit._committer = rev.committer
153
    if 'author' in rev.properties:
154
        commit._author = rev.properties['author']
155
    else:
156
        commit._author = rev.committer
0.217.26 by John Carr
Fix typos
157
    commit._commit_time = rev.timestamp
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
158
    commit.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
159
    print commit.sha().hexdigest()
0.217.15 by John Carr
Start traversing commits and inventories
160
    return commit
161
0.217.33 by John Carr
Return real full texts
162
def inventory_to_tree_and_blobs(repo, mapping, revision_id):
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
163
    stack = []
164
    cur = ""
165
    tree = Tree()
0.217.15 by John Carr
Start traversing commits and inventories
166
0.217.33 by John Carr
Return real full texts
167
    inv = repo.get_inventory(revision_id)
168
0.217.15 by John Carr
Start traversing commits and inventories
169
    for path, entry in inv.iter_entries():
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
170
        while stack and not path.startswith(cur):
171
            tree.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
172
            sha = tree.sha().hexdigest()
173
            yield sha, tree
0.217.38 by John Carr
Fix encoding problem
174
            t = (get_umask(), splitpath(cur)[-1:][0].encode('UTF-8'), sha)
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
175
            cur, tree = stack.pop()
0.217.30 by John Carr
Typo
176
            tree.add(*t)
0.217.15 by John Carr
Start traversing commits and inventories
177
178
        if type(entry) == InventoryDirectory:
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
179
            stack.append((cur, tree))
180
            cur = path
181
            tree = Tree()
0.217.15 by John Carr
Start traversing commits and inventories
182
183
        if type(entry) == InventoryFile:
0.217.33 by John Carr
Return real full texts
184
            #FIXME: We can make potentially make this Lazy to avoid shaing lots of stuff
185
            # and having all these objects in memory at once
0.217.17 by John Carr
More gentle plumbing
186
            blob = Blob()
0.217.40 by John Carr
Use entry file_id
187
            _, blob._text = repo.iter_files_bytes([(entry.file_id, revision_id, path)]).next()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
188
            sha = blob.sha().hexdigest()
189
            yield sha, blob
0.217.15 by John Carr
Start traversing commits and inventories
190
0.217.38 by John Carr
Fix encoding problem
191
            name = splitpath(path)[-1:][0].encode('UTF-8')
0.217.32 by John Carr
Dirtyness to help pass tests
192
            mode = get_umask()
0.217.38 by John Carr
Fix encoding problem
193
            tree.add(mode, name, sha)
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
194
0.217.28 by John Carr
Refactor to correctly yield shas and objects
195
    while len(stack) > 1:
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
196
        tree.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
197
        sha = tree.sha().hexdigest()
198
        yield sha, tree
0.217.38 by John Carr
Fix encoding problem
199
        t = (get_umask(), splitpath(cur)[-1:][0].encode('UTF-8'), sha)
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
200
        cur, tree = stack.pop()
0.217.30 by John Carr
Typo
201
        tree.add(*t)
0.217.28 by John Carr
Refactor to correctly yield shas and objects
202
203
    tree.serialize()
204
    yield tree.sha().hexdigest(), tree
0.217.15 by John Carr
Start traversing commits and inventories
205