Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/dulwich/bundle.py: 35%
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# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
5# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
6# General Public License as public by the Free Software Foundation; version 2.0
7# or (at your option) any later version. You can redistribute it and/or
8# modify it under the terms of either of these two licenses.
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16# You should have received a copy of the licenses; if not, see
17# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
18# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
19# License, Version 2.0.
20#
22"""Bundle format support."""
24from typing import BinaryIO, Optional
26from .pack import PackData, write_pack_data
29class Bundle:
30 version: Optional[int]
32 capabilities: dict[str, Optional[str]]
33 prerequisites: list[tuple[bytes, str]]
34 references: dict[bytes, bytes]
35 pack_data: PackData
37 def __repr__(self) -> str:
38 return (
39 f"<{type(self).__name__}(version={self.version}, "
40 f"capabilities={self.capabilities}, "
41 f"prerequisites={self.prerequisites}, "
42 f"references={self.references})>"
43 )
45 def __eq__(self, other: object) -> bool:
46 if not isinstance(other, type(self)):
47 return False
48 if self.version != other.version:
49 return False
50 if self.capabilities != other.capabilities:
51 return False
52 if self.prerequisites != other.prerequisites:
53 return False
54 if self.references != other.references:
55 return False
56 if self.pack_data != other.pack_data:
57 return False
58 return True
61def _read_bundle(f: BinaryIO, version: int) -> Bundle:
62 capabilities = {}
63 prerequisites = []
64 references = {}
65 line = f.readline()
66 if version >= 3:
67 while line.startswith(b"@"):
68 line = line[1:].rstrip(b"\n")
69 try:
70 key, value_bytes = line.split(b"=", 1)
71 value = value_bytes.decode("utf-8")
72 except ValueError:
73 key = line
74 value = None
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: BinaryIO) -> Bundle:
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: BinaryIO, bundle: Bundle) -> None:
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(f"unknown version {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 )