/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.45 by John Carr
Restore +x flag is file is executable
31
import stat
0.217.44 by John Carr
Use proper modes
32
S_IFGITLINK = 0160000
33
0.217.46 by John Carr
Remove debug print. Fetch S_IF* foo from stat module. Fix file mode picker.
34
#S_IFREG | 0664 # *Might* see this; would fail fsck --strict
0.217.44 by John Carr
Use proper modes
35
0.217.32 by John Carr
Dirtyness to help pass tests
36
0.217.1 by John Carr
Start stubbing out rewritten git-serve
37
class BzrBackend(Backend):
38
0.217.2 by John Carr
Fix missing imports. Update TCPGitServer instantiation to latest. BzrBackend needs to know which directory its repo is in.
39
    def __init__(self, directory):
40
        self.directory = directory
0.217.7 by John Carr
Create tips
41
        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.
42
0.217.1 by John Carr
Start stubbing out rewritten git-serve
43
    def get_refs(self):
44
        """ return a dict of all tags and branches in repository (and shas) """
0.217.12 by John Carr
Support ls-remote against bazaar
45
        ret = {}
46
        repo_dir = BzrDir.open(self.directory)
47
        repo = repo_dir.open_repository()
48
        for branch in repo.find_branches(using=True):
49
            #FIXME: Need to get branch path relative to its repository and use this instead of nick
50
            ret["refs/heads/"+branch.nick] = self.mapping.revision_id_bzr_to_foreign(branch.last_revision())
51
        return ret
0.217.1 by John Carr
Start stubbing out rewritten git-serve
52
53
    def apply_pack(self, refs, read):
54
        """ apply pack from client to current repository """
0.217.4 by John Carr
Easy bits of git pushing to bazaar
55
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)
56
        fd, path = tempfile.mkstemp(suffix=".pack")
57
        f = os.fdopen(fd, 'w')
0.217.6 by John Carr
Fix typos
58
        f.write(read())
0.217.5 by John Carr
Add a temporary hack to test pushing form git to bazaar
59
        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)
60
61
        p = PackData(path)
62
        entries = p.sorted_entries()
63
        write_pack_index_v2(path[:-5]+".idx", entries, p.calculate_checksum())
64
65
        def get_objects():
66
            pack = Pack(path[:-5])
67
            for obj in pack.iterobjects():
68
                yield obj
69
70
        target = Repository.open(self.directory)
71
72
        target.lock_write()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
73
        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)
74
            target.start_write_group()
75
            try:
76
                import_git_objects(target, self.mapping, iter(get_objects()))
77
            finally:
78
                target.commit_write_group()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
79
        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)
80
            target.unlock()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
81
0.217.7 by John Carr
Create tips
82
        for oldsha, sha, ref in refs:
83
            if ref[:11] == 'refs/heads/':
84
                branch_nick = ref[11:]
85
86
                try:
87
                    target_dir = BzrDir.open(self.directory + "/" + branch_nick)
88
                except:
89
                    target_dir = BzrDir.create(self.directory + "/" + branch_nick)
90
91
                try:
92
                    target_branch = target_dir.open_branch()
93
                except:
94
                    target_branch = target_dir.create_branch()
0.217.22 by John Carr
Fix whitespace
95
0.217.7 by John Carr
Create tips
96
                rev_id = self.mapping.revision_id_foreign_to_bzr(sha)
0.217.22 by John Carr
Fix whitespace
97
                target_branch.generate_revision_history(rev_id)
0.217.7 by John Carr
Create tips
98
0.217.1 by John Carr
Start stubbing out rewritten git-serve
99
    def fetch_objects(self, determine_wants, graph_walker, progress):
100
        """ yield git objects to send to client """
0.217.12 by John Carr
Support ls-remote against bazaar
101
        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
102
        commits_to_send = set([self.mapping.revision_id_foreign_to_bzr(w) for w in wants])
103
        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.
104
        obj_sent = set()
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
105
106
        repo = Repository.open(self.directory)
0.217.22 by John Carr
Fix whitespace
107
0.200.188 by Jelmer Vernooij
Merge dulwich.
108
        objects = set()
109
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
110
        repo.lock_read()
111
        try:
112
            have = graph_walker.next()
113
            while have:
114
                rev_done.add(have)
115
                if repo.has_revision(self.mapping.revision_id_foregin_to_bzr(sha)):
116
                    graph_walker.ack(have)
117
                have = graph_walker.next()
118
119
            while commits_to_send:
0.217.15 by John Carr
Start traversing commits and inventories
120
                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
121
                if commit in rev_done:
122
                    continue
123
                rev_done.add(commit)
124
0.217.15 by John Carr
Start traversing commits and inventories
125
                rev = repo.get_revision(commit)
126
127
                commits_to_send.update([p for p in rev.parent_ids if not p in rev_done])
128
0.217.33 by John Carr
Return real full texts
129
                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.
130
                    if sha not in obj_sent:
131
                        obj_sent.add(sha)
0.200.188 by Jelmer Vernooij
Merge dulwich.
132
                        objects.add(obj)
0.217.15 by John Carr
Start traversing commits and inventories
133
0.200.188 by Jelmer Vernooij
Merge dulwich.
134
                objects.add(revision_to_commit(rev, self.mapping, sha))
0.217.15 by John Carr
Start traversing commits and inventories
135
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
136
        finally:
137
            repo.unlock()
0.217.15 by John Carr
Start traversing commits and inventories
138
0.200.188 by Jelmer Vernooij
Merge dulwich.
139
        return (len(objects), iter(objects))
140
0.217.15 by John Carr
Start traversing commits and inventories
141
0.217.25 by John Carr
Lets test commit gen
142
def revision_to_commit(rev, mapping, tree_sha):
143
    """
144
    Turn a Bazaar revision in to a Git commit
145
    :param tree_sha: HACK parameter (until we can retrieve this from the mapping)
146
    :return dulwich.objects.Commit represent the revision:
147
    """
0.217.15 by John Carr
Start traversing commits and inventories
148
    commit = Commit()
0.217.26 by John Carr
Fix typos
149
    commit._tree = tree_sha
0.217.23 by John Carr
Reconstitute the commit object
150
    for p in rev.parent_ids:
0.217.26 by John Carr
Fix typos
151
        commit._parents.append(mapping.revision_id_bzr_to_foreign(p))
0.217.23 by John Carr
Reconstitute the commit object
152
    commit._message = rev.message
153
    commit._committer = rev.committer
154
    if 'author' in rev.properties:
155
        commit._author = rev.properties['author']
156
    else:
157
        commit._author = rev.committer
0.217.47 by John Carr
Hmm, really don't want floats in our commit objects
158
    commit._commit_time = long(rev.timestamp)
0.217.21 by John Carr
This is oh so nearly the right logic, but it is so going to explode...
159
    commit.serialize()
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.46 by John Carr
Remove debug print. Fetch S_IF* foo from stat module. Fix file mode picker.
174
            t = (stat.S_IFDIR, 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.46 by John Carr
Remove debug print. Fetch S_IF* foo from stat module. Fix file mode picker.
192
            mode = stat.S_IFREG | 0644
193
            if entry.executable:
194
                mode |= 0111
0.217.38 by John Carr
Fix encoding problem
195
            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...
196
0.217.28 by John Carr
Refactor to correctly yield shas and objects
197
    while len(stack) > 1:
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
198
        tree.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
199
        sha = tree.sha().hexdigest()
200
        yield sha, tree
0.217.46 by John Carr
Remove debug print. Fetch S_IF* foo from stat module. Fix file mode picker.
201
        t = (stat.S_IFDIR, 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...
202
        cur, tree = stack.pop()
0.217.30 by John Carr
Typo
203
        tree.add(*t)
0.217.28 by John Carr
Refactor to correctly yield shas and objects
204
205
    tree.serialize()
206
    yield tree.sha().hexdigest(), tree
0.217.15 by John Carr
Start traversing commits and inventories
207