/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 transportgit.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
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
 
 
17
 
"""A Git repository implementation that uses a Bazaar transport."""
18
 
 
19
 
 
20
 
from dulwich.errors import (
21
 
    NotGitRepository,
22
 
    NoIndexPresent,
23
 
    )
24
 
from dulwich.objects import (
25
 
    ShaFile,
26
 
    )
27
 
from dulwich.object_store import (
28
 
    PackBasedObjectStore,
29
 
    PACKDIR,
30
 
    )
31
 
from dulwich.pack import (
32
 
    PackData,
33
 
    Pack,
34
 
    load_pack_index_file,
35
 
    )
36
 
from dulwich.repo import (
37
 
    BaseRepo,
38
 
    DictRefsContainer,
39
 
    OBJECTDIR,
40
 
    read_info_refs,
41
 
    )
42
 
 
43
 
from bzrlib.errors import (
44
 
    NoSuchFile,
45
 
    )
46
 
 
47
 
 
48
 
class TransportRepo(BaseRepo):
49
 
 
50
 
    def __init__(self, transport):
51
 
        self.transport = transport
52
 
        try:
53
 
            if self.transport.has(".git/info/refs"):
54
 
                self.bare = False
55
 
                self._controltransport = self.transport.clone('.git')
56
 
            elif self.transport.has("info/refs"):
57
 
                self.bare = True
58
 
                self._controltransport = self.transport
59
 
            else:
60
 
                raise NotGitRepository(self.transport)
61
 
        except NoSuchFile:
62
 
            raise NotGitRepository(self.transport)
63
 
        object_store = TransportObjectStore(
64
 
            self._controltransport.clone(OBJECTDIR))
65
 
        refs = {}
66
 
        refs["HEAD"] = self._controltransport.get_bytes("HEAD").rstrip("\n")
67
 
        refs.update(read_info_refs(self._controltransport.get('info/refs')))
68
 
        super(TransportRepo, self).__init__(object_store, 
69
 
                DictRefsContainer(refs))
70
 
 
71
 
    def get_named_file(self, path):
72
 
        """Get a file from the control dir with a specific name.
73
 
 
74
 
        Although the filename should be interpreted as a filename relative to
75
 
        the control dir in a disk-baked Repo, the object returned need not be
76
 
        pointing to a file in that location.
77
 
 
78
 
        :param path: The path to the file, relative to the control dir.
79
 
        :return: An open file object, or None if the file does not exist.
80
 
        """
81
 
        try:
82
 
            return self._controltransport.get(path.lstrip('/'))
83
 
        except NoSuchFile:
84
 
            return None
85
 
 
86
 
    def open_index(self):
87
 
        """Open the index for this repository."""
88
 
        raise NoIndexPresent()
89
 
 
90
 
    def __repr__(self):
91
 
        return "<TransportRepo for %r>" % self.transport
92
 
 
93
 
 
94
 
class TransportObjectStore(PackBasedObjectStore):
95
 
    """Git-style object store that exists on disk."""
96
 
 
97
 
    def __init__(self, transport):
98
 
        """Open an object store.
99
 
 
100
 
        :param transport: Transport to open data from
101
 
        """
102
 
        super(TransportObjectStore, self).__init__()
103
 
        self.transport = transport
104
 
        self.pack_transport = self.transport.clone(PACKDIR)
105
 
 
106
 
    def _load_packs(self):
107
 
        ret = []
108
 
        for line in self.transport.get('info/packs').readlines():
109
 
            line = line.rstrip("\n")
110
 
            if not line:
111
 
                continue
112
 
            (kind, name) = line.split(" ", 1)
113
 
            if kind != "P":
114
 
                continue
115
 
            if name.startswith("pack-") and name.endswith(".pack"):
116
 
                pd = PackData(name, self.pack_transport.get(name))
117
 
                idxname = name.replace(".pack", ".idx")
118
 
                idx = load_pack_index_file(idxname, self.pack_transport.get(idxname))
119
 
                ret.append(Pack.from_objects(pd, idx))
120
 
        return ret
121
 
 
122
 
    def _iter_loose_objects(self):
123
 
        for base in self.transport.list_dir('.'):
124
 
            if len(base) != 2:
125
 
                continue
126
 
            for rest in self.transport.list_dir(base):
127
 
                yield base+rest
128
 
 
129
 
    def _split_loose_object(self, sha):
130
 
        return (sha[:2], sha[2:])
131
 
 
132
 
    def _get_loose_object(self, sha):
133
 
        path = '%s/%s' % self._split_loose_object(sha)
134
 
        try:
135
 
            return ShaFile._parse_file(self.transport.get(path).read())
136
 
        except NoSuchFile:
137
 
            return None
138
 
 
139
 
    def add_object(self, obj):
140
 
        """Add a single object to this object store.
141
 
 
142
 
        :param obj: Object to add
143
 
        """
144
 
        (dir, file) = self._split_loose_object(obj.id)
145
 
        self.transport.mkdir(dir)
146
 
        path = "%s/%s" % (dir, file)
147
 
        if self.transport.has(path):
148
 
            return # Already there, no need to write again
149
 
        self.transport.put_bytes(path, obj.as_legacy_object())
150
 
 
151
 
    def add_pack(self):
152
 
        """Add a new pack to this object store. 
153
 
 
154
 
        :return: Fileobject to write to and a commit function to 
155
 
            call when the pack is finished.
156
 
        """
157
 
        raise NotImplementedError(self.add_pack)