/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_IFREG = 32768
33
S_IFLNK = 40960
34
S_IFDIR = 16384
35
S_IFGITLINK = 0160000
36
37
#S_IFREG | 0755
38
#S_IFREG | 0655
39
#(a bit dodgey)
40
#S_IFREG | 0664
41
0.217.32 by John Carr
Dirtyness to help pass tests
42
0.217.1 by John Carr
Start stubbing out rewritten git-serve
43
class BzrBackend(Backend):
44
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
    def __init__(self, directory):
46
        self.directory = directory
0.217.7 by John Carr
Create tips
47
        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.
48
0.217.1 by John Carr
Start stubbing out rewritten git-serve
49
    def get_refs(self):
50
        """ return a dict of all tags and branches in repository (and shas) """
0.217.12 by John Carr
Support ls-remote against bazaar
51
        ret = {}
52
        repo_dir = BzrDir.open(self.directory)
53
        repo = repo_dir.open_repository()
54
        for branch in repo.find_branches(using=True):
55
            #FIXME: Need to get branch path relative to its repository and use this instead of nick
56
            ret["refs/heads/"+branch.nick] = self.mapping.revision_id_bzr_to_foreign(branch.last_revision())
57
        return ret
0.217.1 by John Carr
Start stubbing out rewritten git-serve
58
59
    def apply_pack(self, refs, read):
60
        """ apply pack from client to current repository """
0.217.4 by John Carr
Easy bits of git pushing to bazaar
61
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)
62
        fd, path = tempfile.mkstemp(suffix=".pack")
63
        f = os.fdopen(fd, 'w')
0.217.6 by John Carr
Fix typos
64
        f.write(read())
0.217.5 by John Carr
Add a temporary hack to test pushing form git to bazaar
65
        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)
66
67
        p = PackData(path)
68
        entries = p.sorted_entries()
69
        write_pack_index_v2(path[:-5]+".idx", entries, p.calculate_checksum())
70
71
        def get_objects():
72
            pack = Pack(path[:-5])
73
            for obj in pack.iterobjects():
74
                yield obj
75
76
        target = Repository.open(self.directory)
77
78
        target.lock_write()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
79
        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)
80
            target.start_write_group()
81
            try:
82
                import_git_objects(target, self.mapping, iter(get_objects()))
83
            finally:
84
                target.commit_write_group()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
85
        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)
86
            target.unlock()
0.217.4 by John Carr
Easy bits of git pushing to bazaar
87
0.217.7 by John Carr
Create tips
88
        for oldsha, sha, ref in refs:
89
            if ref[:11] == 'refs/heads/':
90
                branch_nick = ref[11:]
91
92
                try:
93
                    target_dir = BzrDir.open(self.directory + "/" + branch_nick)
94
                except:
95
                    target_dir = BzrDir.create(self.directory + "/" + branch_nick)
96
97
                try:
98
                    target_branch = target_dir.open_branch()
99
                except:
100
                    target_branch = target_dir.create_branch()
0.217.22 by John Carr
Fix whitespace
101
0.217.7 by John Carr
Create tips
102
                rev_id = self.mapping.revision_id_foreign_to_bzr(sha)
0.217.22 by John Carr
Fix whitespace
103
                target_branch.generate_revision_history(rev_id)
0.217.7 by John Carr
Create tips
104
0.217.1 by John Carr
Start stubbing out rewritten git-serve
105
    def fetch_objects(self, determine_wants, graph_walker, progress):
106
        """ yield git objects to send to client """
0.217.12 by John Carr
Support ls-remote against bazaar
107
        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
108
        commits_to_send = set([self.mapping.revision_id_foreign_to_bzr(w) for w in wants])
109
        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.
110
        obj_sent = set()
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
111
112
        repo = Repository.open(self.directory)
0.217.22 by John Carr
Fix whitespace
113
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
114
        repo.lock_read()
115
        try:
116
            have = graph_walker.next()
117
            while have:
118
                rev_done.add(have)
119
                if repo.has_revision(self.mapping.revision_id_foregin_to_bzr(sha)):
120
                    graph_walker.ack(have)
121
                have = graph_walker.next()
122
123
            while commits_to_send:
0.217.15 by John Carr
Start traversing commits and inventories
124
                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
125
                if commit in rev_done:
126
                    continue
127
                rev_done.add(commit)
128
0.217.15 by John Carr
Start traversing commits and inventories
129
                rev = repo.get_revision(commit)
130
131
                commits_to_send.update([p for p in rev.parent_ids if not p in rev_done])
132
0.217.33 by John Carr
Return real full texts
133
                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.
134
                    if sha not in obj_sent:
135
                        obj_sent.add(sha)
136
                        yield obj
0.217.15 by John Carr
Start traversing commits and inventories
137
0.217.28 by John Carr
Refactor to correctly yield shas and objects
138
                yield revision_to_commit(rev, self.mapping, sha)
0.217.15 by John Carr
Start traversing commits and inventories
139
0.217.14 by John Carr
Negotiate which revisions need to be sent to client, and iterate over them all
140
        finally:
141
            repo.unlock()
0.217.15 by John Carr
Start traversing commits and inventories
142
143
0.217.25 by John Carr
Lets test commit gen
144
def revision_to_commit(rev, mapping, tree_sha):
145
    """
146
    Turn a Bazaar revision in to a Git commit
147
    :param tree_sha: HACK parameter (until we can retrieve this from the mapping)
148
    :return dulwich.objects.Commit represent the revision:
149
    """
0.217.15 by John Carr
Start traversing commits and inventories
150
    commit = Commit()
0.217.26 by John Carr
Fix typos
151
    commit._tree = tree_sha
0.217.23 by John Carr
Reconstitute the commit object
152
    for p in rev.parent_ids:
0.217.26 by John Carr
Fix typos
153
        commit._parents.append(mapping.revision_id_bzr_to_foreign(p))
0.217.23 by John Carr
Reconstitute the commit object
154
    commit._message = rev.message
155
    commit._committer = rev.committer
156
    if 'author' in rev.properties:
157
        commit._author = rev.properties['author']
158
    else:
159
        commit._author = rev.committer
0.217.26 by John Carr
Fix typos
160
    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...
161
    commit.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
162
    print commit.sha().hexdigest()
0.217.15 by John Carr
Start traversing commits and inventories
163
    return commit
164
0.217.33 by John Carr
Return real full texts
165
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
166
    stack = []
167
    cur = ""
168
    tree = Tree()
0.217.15 by John Carr
Start traversing commits and inventories
169
0.217.33 by John Carr
Return real full texts
170
    inv = repo.get_inventory(revision_id)
171
0.217.15 by John Carr
Start traversing commits and inventories
172
    for path, entry in inv.iter_entries():
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
173
        while stack and not path.startswith(cur):
174
            tree.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
175
            sha = tree.sha().hexdigest()
176
            yield sha, tree
0.217.44 by John Carr
Use proper modes
177
            t = (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...
178
            cur, tree = stack.pop()
0.217.30 by John Carr
Typo
179
            tree.add(*t)
0.217.15 by John Carr
Start traversing commits and inventories
180
181
        if type(entry) == InventoryDirectory:
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
182
            stack.append((cur, tree))
183
            cur = path
184
            tree = Tree()
0.217.15 by John Carr
Start traversing commits and inventories
185
186
        if type(entry) == InventoryFile:
0.217.33 by John Carr
Return real full texts
187
            #FIXME: We can make potentially make this Lazy to avoid shaing lots of stuff
188
            # and having all these objects in memory at once
0.217.17 by John Carr
More gentle plumbing
189
            blob = Blob()
0.217.40 by John Carr
Use entry file_id
190
            _, 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
191
            sha = blob.sha().hexdigest()
192
            yield sha, blob
0.217.15 by John Carr
Start traversing commits and inventories
193
0.217.38 by John Carr
Fix encoding problem
194
            name = splitpath(path)[-1:][0].encode('UTF-8')
0.217.44 by John Carr
Use proper modes
195
            mode = S_IFREG | 0655
0.217.45 by John Carr
Restore +x flag is file is executable
196
            if mode & stat.S_IXUSR:
197
                mode |= 0100
0.217.38 by John Carr
Fix encoding problem
198
            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...
199
0.217.28 by John Carr
Refactor to correctly yield shas and objects
200
    while len(stack) > 1:
0.217.20 by John Carr
Refactor to track Tree objects as we iterate over inventory
201
        tree.serialize()
0.217.28 by John Carr
Refactor to correctly yield shas and objects
202
        sha = tree.sha().hexdigest()
203
        yield sha, tree
0.217.44 by John Carr
Use proper modes
204
        t = (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...
205
        cur, tree = stack.pop()
0.217.30 by John Carr
Typo
206
        tree.add(*t)
0.217.28 by John Carr
Refactor to correctly yield shas and objects
207
208
    tree.serialize()
209
    yield tree.sha().hexdigest(), tree
0.217.15 by John Carr
Start traversing commits and inventories
210