Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/dulwich/bundle.py: 36%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# bundle.py -- Bundle format support
2# Copyright (C) 2020 Jelmer Vernooij <jelmer@jelmer.uk>
3#
4# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
5# General Public License as public by the Free Software Foundation; version 2.0
6# or (at your option) any later version. You can redistribute it and/or
7# modify it under the terms of either of these two licenses.
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15# You should have received a copy of the licenses; if not, see
16# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
17# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
18# License, Version 2.0.
19#
21"""Bundle format support."""
23from typing import Dict, List, Optional, Sequence, Tuple, Union
25from .pack import PackData, write_pack_data
28class Bundle:
29 version: Optional[int]
31 capabilities: Dict[str, str]
32 prerequisites: List[Tuple[bytes, str]]
33 references: Dict[str, bytes]
34 pack_data: Union[PackData, Sequence[bytes]]
36 def __repr__(self) -> str:
37 return (
38 f"<{type(self).__name__}(version={self.version}, "
39 f"capabilities={self.capabilities}, "
40 f"prerequisites={self.prerequisites}, "
41 f"references={self.references})>"
42 )
44 def __eq__(self, other):
45 if not isinstance(other, type(self)):
46 return False
47 if self.version != other.version:
48 return False
49 if self.capabilities != other.capabilities:
50 return False
51 if self.prerequisites != other.prerequisites:
52 return False
53 if self.references != other.references:
54 return False
55 if self.pack_data != other.pack_data:
56 return False
57 return True
60def _read_bundle(f, version):
61 capabilities = {}
62 prerequisites = []
63 references = {}
64 line = f.readline()
65 if version >= 3:
66 while line.startswith(b"@"):
67 line = line[1:].rstrip(b"\n")
68 try:
69 key, value = line.split(b"=", 1)
70 except ValueError:
71 key = line
72 value = None
73 else:
74 value = value.decode("utf-8")
75 capabilities[key.decode("utf-8")] = value
76 line = f.readline()
77 while line.startswith(b"-"):
78 (obj_id, comment) = line[1:].rstrip(b"\n").split(b" ", 1)
79 prerequisites.append((obj_id, comment.decode("utf-8")))
80 line = f.readline()
81 while line != b"\n":
82 (obj_id, ref) = line.rstrip(b"\n").split(b" ", 1)
83 references[ref] = obj_id
84 line = f.readline()
85 pack_data = PackData.from_file(f)
86 ret = Bundle()
87 ret.references = references
88 ret.capabilities = capabilities
89 ret.prerequisites = prerequisites
90 ret.pack_data = pack_data
91 ret.version = version
92 return ret
95def read_bundle(f):
96 """Read a bundle file."""
97 firstline = f.readline()
98 if firstline == b"# v2 git bundle\n":
99 return _read_bundle(f, 2)
100 if firstline == b"# v3 git bundle\n":
101 return _read_bundle(f, 3)
102 raise AssertionError(f"unsupported bundle format header: {firstline!r}")
105def write_bundle(f, bundle):
106 version = bundle.version
107 if version is None:
108 if bundle.capabilities:
109 version = 3
110 else:
111 version = 2
112 if version == 2:
113 f.write(b"# v2 git bundle\n")
114 elif version == 3:
115 f.write(b"# v3 git bundle\n")
116 else:
117 raise AssertionError("unknown version %d" % version)
118 if version == 3:
119 for key, value in bundle.capabilities.items():
120 f.write(b"@" + key.encode("utf-8"))
121 if value is not None:
122 f.write(b"=" + value.encode("utf-8"))
123 f.write(b"\n")
124 for obj_id, comment in bundle.prerequisites:
125 f.write(b"-%s %s\n" % (obj_id, comment.encode("utf-8")))
126 for ref, obj_id in bundle.references.items():
127 f.write(b"%s %s\n" % (obj_id, ref))
128 f.write(b"\n")
129 write_pack_data(
130 f.write,
131 num_records=len(bundle.pack_data),
132 records=bundle.pack_data.iter_unpacked(),
133 )