1
# Copyright (C) 2018 Jelmer Vernooij <jelmer@jelmer.uk>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
from __future__ import absolute_import
21
from dulwich.object_store import (
25
from .. import osutils
26
from ..bzr.versionedfile import UnavailableRepresentation
27
from ..errors import (
30
from ..graph import Graph
31
from ..revision import (
35
from .mapping import (
41
class GitBlobContentFactory(object):
42
"""Static data content factory.
44
This takes a fulltext when created and just returns that during
45
get_bytes_as('fulltext').
47
:ivar sha1: None, or the sha1 of the content fulltext.
48
:ivar storage_kind: The native storage kind of this factory. Always
50
:ivar key: The key of this content. Each key is a tuple with a single
52
:ivar parents: A tuple of parent keys for self.key. If the object has
53
no parent information, None (as opposed to () for an empty list of
57
def __init__(self, store, path, revision, blob_id):
58
"""Create a ContentFactory."""
60
self.key = (path, revision)
61
self.storage_kind = 'git-blob'
63
self.blob_id = blob_id
66
def get_bytes_as(self, storage_kind):
67
if storage_kind == 'fulltext':
68
return self.store[self.blob_id].as_raw_string()
69
elif storage_kind == 'lines':
70
return list(osutils.chunks_to_lines(self.store[self.blob_id].as_raw_chunks()))
71
elif storage_kind == 'chunked':
72
return self.store[self.blob_id].as_raw_chunks()
73
raise UnavailableRepresentation(self.key, storage_kind,
76
def iter_bytes_as(self, storage_kind):
77
if storage_kind == 'lines':
78
return iter(osutils.chunks_to_lines(self.store[self.blob_id].as_raw_chunks()))
79
elif storage_kind == 'chunked':
80
return iter(self.store[self.blob_id].as_raw_chunks())
81
raise UnavailableRepresentation(self.key, storage_kind,
85
class GitAbsentContentFactory(object):
86
"""Absent data content factory.
88
:ivar sha1: None, or the sha1 of the content fulltext.
89
:ivar storage_kind: The native storage kind of this factory. Always
91
:ivar key: The key of this content. Each key is a tuple with a single
93
:ivar parents: A tuple of parent keys for self.key. If the object has
94
no parent information, None (as opposed to () for an empty list of
98
def __init__(self, store, path, revision):
99
"""Create a ContentFactory."""
101
self.key = (path, revision)
102
self.storage_kind = 'absent'
106
def get_bytes_as(self, storage_kind):
109
def iter_bytes_as(self, storage_kind):
113
class AnnotateProvider(object):
115
def __init__(self, change_scanner):
116
self.change_scanner = change_scanner
117
self.store = self.change_scanner.repository._git.object_store
119
def _get_parents(self, path, text_revision):
120
commit_id, mapping = (
121
self.change_scanner.repository.lookup_bzr_revision_id(
124
path = encode_git_path(path)
125
for commit_parent in self.store[commit_id].parents:
127
(path, text_parent) = (
128
self.change_scanner.find_last_change_revision(
129
path, commit_parent))
132
if text_parent not in text_parents:
133
text_parents.append(text_parent)
135
(decode_git_path(path),
136
self.change_scanner.repository.lookup_foreign_revision_id(p))
137
for p in text_parents])
139
def get_parent_map(self, keys):
142
(path, text_revision) = key
143
if text_revision == NULL_REVISION:
147
ret[key] = self._get_parents(path, text_revision)
152
def get_record_stream(self, keys, ordering, include_delta_closure):
153
if ordering == 'topological':
155
keys = graph.iter_topo_order(keys)
156
store = self.change_scanner.repository._git.object_store
157
for (path, text_revision) in keys:
159
commit_id, mapping = (
160
self.change_scanner.repository.lookup_bzr_revision_id(
162
except NoSuchRevision:
163
yield GitAbsentContentFactory(store, path, text_revision)
167
tree_id = store[commit_id].tree
169
yield GitAbsentContentFactory(store, path, text_revision)
172
(mode, blob_sha) = tree_lookup_path(
173
store.__getitem__, tree_id, encode_git_path(path))
175
yield GitAbsentContentFactory(store, path, text_revision)
177
yield GitBlobContentFactory(
178
store, path, text_revision, blob_sha)