Status: | Merged |
---|---|
Approved by: | Jelmer Vernooij |
Approved revision: | no longer in the source branch. |
Merged at revision: | 7730 |
Proposed branch: | lp:~jelmer/brz/reforma |
Merge into: | lp:brz |
Diff against target: |
3235 lines (+982/-492) 57 files modified
.bzrignore (+1/-0) Makefile (+6/-0) breezy/bzr/chk_map.py (+2/-3) breezy/bzr/dirstate.py (+3/-8) breezy/bzr/groupcompress.py (+3/-2) breezy/bzr/smart/repository.py (+2/-2) breezy/bzr/tests/test_chk_map.py (+2/-1) breezy/bzr/tests/test_rio.py (+4/-3) breezy/bzr/weave.py (+1/-1) breezy/git/interrepo.py (+5/-4) breezy/git/refs.py (+3/-1) breezy/graph.py (+1/-1) breezy/log.py (+2/-3) breezy/main.rs (+1/-2) breezy/merge_directive.py (+3/-7) breezy/osutils.py (+6/-4) breezy/patch.py (+2/-1) breezy/patches.py (+2/-1) breezy/plugins/launchpad/lp_directory.py (+1/-1) breezy/repository.py (+4/-2) breezy/revisiontree.py (+1/-1) breezy/tests/test_patches.py (+3/-3) breezy/tests/test_timestamp.py (+1/-1) breezy/textfile.py (+2/-2) breezy/transport/http/urllib.py (+1/-1) breezy/tsort.py (+1/-1) breezy/version_info_formats/__init__.py (+1/-1) crates/bazaar/src/filters.rs (+16/-13) crates/chk-map-py/src/lib.rs (+5/-3) crates/chk-map/src/lib.rs (+5/-4) crates/dirstate-py/src/lib.rs (+48/-16) crates/dirstate/src/lib.rs (+21/-13) crates/graph-py/src/lib.rs (+15/-15) crates/graph/src/tsort.rs (+17/-5) crates/groupcompress-py/src/lib.rs (+16/-5) crates/groupcompress/src/lib.rs (+10/-2) crates/hashcache-py/src/lib.rs (+37/-12) crates/hashcache/src/lib.rs (+60/-37) crates/osutils-py/src/lib.rs (+195/-95) crates/osutils/src/file.rs (+4/-4) crates/osutils/src/iterablefile.rs (+46/-8) crates/osutils/src/lib.rs (+13/-9) crates/osutils/src/path.rs (+34/-10) crates/osutils/src/sha.rs (+1/-1) crates/osutils/src/tests.rs (+4/-1) crates/osutils/src/textfile.rs (+1/-1) crates/osutils/src/time.rs (+56/-16) crates/patch-py/src/lib.rs (+113/-44) crates/patch/src/invoke.rs (+58/-41) crates/patch/src/parse.rs (+18/-8) crates/rio-py/src/lib.rs (+59/-29) crates/rio/src/rio.rs (+14/-18) crates/rio/src/tests.rs (+39/-10) crates/zlib-util-py/src/lib.rs (+7/-7) crates/zlib-util/src/estimator.rs (+4/-6) crates/zlib-util/src/lib.rs (+1/-1) tarmac.conf (+1/-1) |
To merge this branch: | bzr merge lp:~jelmer/brz/reforma |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jelmer Vernooij | Approve | ||
Review via email: mp+441178@code.launchpad.net |
Commit message
Format-check rust files
Description of the change
Format-check rust files
Jelmer Vernooij (jelmer) : | # |
The Breezy Bot (the-breezy-bot) wrote : | # |
The Breezy Bot (the-breezy-bot) wrote : | # |
The attempt to merge lp:~jelmer/brz/reforma into lp:brz failed. Command exited with 1.
Below is the output from the failed tests.
Collecting setuptools-gettext
Downloading setuptools_
Requirement already satisfied: setuptools>=46.1 in ./lib/python3.
Installing collected packages: setuptools-gettext
Successfully installed setuptools-
Obtaining file://
Installing build dependencies: started
Installing build dependencies: finished with status 'done'
Checking if build backend supports build_editable: started
Checking if build backend supports build_editable: finished with status 'done'
Getting requirements to build editable: started
Getting requirements to build editable: finished with status 'done'
Installing backend dependencies: started
Installing backend dependencies: finished with status 'done'
Preparing editable metadata (pyproject.toml): started
Preparing editable metadata (pyproject.toml): finished with status 'done'
Requirement already satisfied: configobj in /usr/lib/
Requirement already satisfied: fastbencode in /usr/lib/
Requirement already satisfied: patiencediff in /usr/lib/
Requirement already satisfied: merge3 in /usr/lib/
Collecting dulwich>=0.21.3
Downloading dulwich-
━━
Requirement already satisfied: urllib3>=1.24.1 in /usr/lib/
Requirement already satisfied: pyyaml in /usr/lib/
Collecting testtools
Downloading testtools-
━━
Collecting testscenarios
Downloading testscenarios-
Collecting python-subunit
Downloading python_
━━
Requirement already satisfied: flake8 in /usr/lib/
Collecting cython>=0.29
Using cached Cython-
Collecting docutils
Downloading docutils-
━━
Requirement already satisfied: setuptools in ./lib/python3.
Collecting sphinx
Downloading sphinx-
━━
Collecting sphinx-epytext
Downloading sphinx-
Preparing metadata (setup.py): started
Preparing metadata (setup.py): finished with statu...
- 7729. By Jelmer Vernooij
-
Port MergeSorter to rust
by jelmer review by jelmer
- 7730. By Jelmer Vernooij
-
Format-check rust files
by jelmer review by jelmer
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2023-04-14 10:23:02 +0000 |
3 | +++ .bzrignore 2023-04-17 11:56:43 +0000 |
4 | @@ -80,3 +80,4 @@ |
5 | ./target |
6 | ./brz |
7 | *.so |
8 | +.pytest_cache |
9 | |
10 | === modified file 'Makefile' |
11 | --- Makefile 2023-02-06 23:24:27 +0000 |
12 | +++ Makefile 2023-04-17 11:56:43 +0000 |
13 | @@ -74,6 +74,11 @@ |
14 | flake8: |
15 | flake8 breezy |
16 | |
17 | +fmt-check: |
18 | + find . -name '*.rs' | xargs rustfmt --check |
19 | + flake8 breezy |
20 | + isort --check-only |
21 | + |
22 | mypy: |
23 | mypy breezy |
24 | |
25 | @@ -317,3 +322,4 @@ |
26 | |
27 | reformat: |
28 | isort . |
29 | + find . -name '*.rs' | xargs rustfmt |
30 | |
31 | === modified file 'breezy/bzr/chk_map.py' |
32 | --- breezy/bzr/chk_map.py 2023-04-05 18:13:47 +0000 |
33 | +++ breezy/bzr/chk_map.py 2023-04-17 11:56:43 +0000 |
34 | @@ -1710,15 +1710,14 @@ |
35 | return iterator.process() |
36 | |
37 | |
38 | -from ._chk_map_rs import _search_key_16, _search_key_255, _bytes_to_text_key |
39 | +from ._chk_map_rs import _bytes_to_text_key, _search_key_16, _search_key_255 |
40 | |
41 | try: |
42 | from ._chk_map_pyx import (_deserialise_internal_node, |
43 | _deserialise_leaf_node) |
44 | except ImportError as e: |
45 | osutils.failed_to_load_extension(e) |
46 | - from ._chk_map_py import (_deserialise_internal_node, |
47 | - _deserialise_leaf_node) |
48 | + from ._chk_map_py import _deserialise_internal_node, _deserialise_leaf_node |
49 | search_key_registry.register(b'hash-16-way', _search_key_16) |
50 | search_key_registry.register(b'hash-255-way', _search_key_255) |
51 | |
52 | |
53 | === modified file 'breezy/bzr/dirstate.py' |
54 | --- breezy/bzr/dirstate.py 2023-04-11 06:38:51 +0000 |
55 | +++ breezy/bzr/dirstate.py 2023-04-17 11:56:43 +0000 |
56 | @@ -4316,14 +4316,9 @@ |
57 | return dir_info |
58 | |
59 | |
60 | -from ._dirstate_rs import ( |
61 | - lt_by_dirs, |
62 | - bisect_path_left, |
63 | - bisect_path_right, |
64 | - bisect_dirblock, |
65 | - DefaultSHA1Provider, |
66 | - pack_stat, |
67 | - ) |
68 | +from ._dirstate_rs import (DefaultSHA1Provider, bisect_dirblock, |
69 | + bisect_path_left, bisect_path_right, lt_by_dirs, |
70 | + pack_stat) |
71 | |
72 | # Try to load the compiled form if possible |
73 | try: |
74 | |
75 | === modified file 'breezy/bzr/groupcompress.py' |
76 | --- breezy/bzr/groupcompress.py 2023-04-07 21:31:19 +0000 |
77 | +++ breezy/bzr/groupcompress.py 2023-04-17 11:56:43 +0000 |
78 | @@ -2234,9 +2234,10 @@ |
79 | GroupCompressor: Type[_CommonGroupCompressor] |
80 | |
81 | |
82 | -from ._groupcompress_rs import decode_base128_int, encode_base128_int, decode_copy_instruction, apply_delta, apply_delta_to_source |
83 | - |
84 | from ._groupcompress_py import LinesDeltaIndex |
85 | +from ._groupcompress_rs import (apply_delta, apply_delta_to_source, |
86 | + decode_base128_int, decode_copy_instruction, |
87 | + encode_base128_int) |
88 | |
89 | try: |
90 | from ._groupcompress_pyx import DeltaIndex |
91 | |
92 | === modified file 'breezy/bzr/smart/repository.py' |
93 | --- breezy/bzr/smart/repository.py 2023-04-13 22:19:43 +0000 |
94 | +++ breezy/bzr/smart/repository.py 2023-04-17 11:56:43 +0000 |
95 | @@ -27,9 +27,9 @@ |
96 | |
97 | import fastbencode as bencode |
98 | |
99 | -from ... import errors, zlib_util, osutils |
100 | +from ... import errors, osutils |
101 | from ... import revision as _mod_revision |
102 | -from ... import trace, ui |
103 | +from ... import trace, ui, zlib_util |
104 | from ...repository import _strip_NULL_ghosts, network_format_registry |
105 | from .. import inventory as _mod_inventory |
106 | from .. import inventory_delta, pack, vf_search |
107 | |
108 | === modified file 'breezy/bzr/tests/test_chk_map.py' |
109 | --- breezy/bzr/tests/test_chk_map.py 2023-04-05 18:13:47 +0000 |
110 | +++ breezy/bzr/tests/test_chk_map.py 2023-04-17 11:56:43 +0000 |
111 | @@ -18,7 +18,8 @@ |
112 | |
113 | from ... import errors, osutils, tests |
114 | from .. import chk_map, groupcompress |
115 | -from ..chk_map import CHKMap, InternalNode, LeafNode, Node, _search_key_16, _search_key_255, _bytes_to_text_key |
116 | +from ..chk_map import (CHKMap, InternalNode, LeafNode, Node, |
117 | + _bytes_to_text_key, _search_key_16, _search_key_255) |
118 | from ..static_tuple import StaticTuple |
119 | |
120 | stuple = StaticTuple |
121 | |
122 | === modified file 'breezy/bzr/tests/test_rio.py' |
123 | --- breezy/bzr/tests/test_rio.py 2023-04-14 13:31:48 +0000 |
124 | +++ breezy/bzr/tests/test_rio.py 2023-04-17 11:56:43 +0000 |
125 | @@ -27,10 +27,11 @@ |
126 | |
127 | from breezy.tests import TestCase |
128 | |
129 | +from ...osutils import IterableFile |
130 | from .. import rio |
131 | -from ...osutils import IterableFile |
132 | -from ..rio import RioReader, Stanza, read_stanza, read_stanzas, rio_iter # type: ignore |
133 | -from ..rio_patch import to_patch_lines, read_patch_stanza |
134 | +from ..rio import (RioReader, Stanza, read_stanza, # type: ignore |
135 | + read_stanzas, rio_iter) |
136 | +from ..rio_patch import read_patch_stanza, to_patch_lines |
137 | |
138 | |
139 | def rio_file(stanzas): |
140 | |
141 | === modified file 'breezy/bzr/weave.py' |
142 | --- breezy/bzr/weave.py 2023-04-08 18:48:50 +0000 |
143 | +++ breezy/bzr/weave.py 2023-04-17 11:56:43 +0000 |
144 | @@ -64,11 +64,11 @@ |
145 | |
146 | # FIXME: the conflict markers should be *7* characters |
147 | |
148 | +import hashlib |
149 | import os |
150 | from copy import copy |
151 | from io import BytesIO |
152 | |
153 | -import hashlib |
154 | import patiencediff |
155 | |
156 | from ..lazy_import import lazy_import |
157 | |
158 | === modified file 'breezy/git/interrepo.py' |
159 | --- breezy/git/interrepo.py 2023-03-31 22:01:18 +0000 |
160 | +++ breezy/git/interrepo.py 2023-04-17 11:56:43 +0000 |
161 | @@ -17,25 +17,27 @@ |
162 | """InterRepository operations.""" |
163 | |
164 | import itertools |
165 | -from typing import Callable, Dict, Tuple, Optional |
166 | +from typing import Callable, Dict, Optional, Tuple |
167 | |
168 | from dulwich.errors import NotCommitError |
169 | +from dulwich.object_store import ObjectStoreGraphWalker |
170 | from dulwich.objects import ObjectID |
171 | -from dulwich.object_store import ObjectStoreGraphWalker |
172 | from dulwich.pack import PACK_SPOOL_FILE_MAX_SIZE |
173 | from dulwich.protocol import CAPABILITY_THIN_PACK, ZERO_SHA |
174 | from dulwich.refs import SYMREF |
175 | + |
176 | try: |
177 | from dulwich.refs import PEELED_TAG_SUFFIX |
178 | except ImportError: # dulwich < 0.21.3 |
179 | from dulwich.refs import ANNOTATED_TAG_SUFFIX as PEELED_TAG_SUFFIX |
180 | + |
181 | from dulwich.walk import Walker |
182 | |
183 | from .. import config, trace, ui |
184 | from ..errors import (DivergedBranches, FetchLimitUnsupported, |
185 | InvalidRevisionId, LossyPushToSameVCS, |
186 | NoRoundtrippingSupport, NoSuchRevision) |
187 | -from ..repository import FetchResult, InterRepository, AbstractSearchResult |
188 | +from ..repository import AbstractSearchResult, FetchResult, InterRepository |
189 | from ..revision import NULL_REVISION, RevisionID |
190 | from .errors import NoPushSupport |
191 | from .fetch import DetermineWantsRecorder, import_git_objects |
192 | @@ -47,7 +49,6 @@ |
193 | from .repository import GitRepository, GitRepositoryFormat, LocalGitRepository |
194 | from .unpeel_map import UnpeelMap |
195 | |
196 | - |
197 | EitherId = Tuple[Optional[RevisionID], Optional[ObjectID]] |
198 | EitherRefDict = Dict[bytes, EitherId] |
199 | RevidMap = Dict[RevisionID, Tuple[ObjectID, RevisionID]] |
200 | |
201 | === modified file 'breezy/git/refs.py' |
202 | --- breezy/git/refs.py 2023-04-07 22:04:39 +0000 |
203 | +++ breezy/git/refs.py 2023-04-17 11:56:43 +0000 |
204 | @@ -17,11 +17,13 @@ |
205 | """Conversion between refs and Bazaar revision pointers.""" |
206 | |
207 | from dulwich.objects import Tag, object_class |
208 | -from dulwich.refs import (LOCAL_BRANCH_PREFIX, LOCAL_TAG_PREFIX) |
209 | +from dulwich.refs import LOCAL_BRANCH_PREFIX, LOCAL_TAG_PREFIX |
210 | + |
211 | try: |
212 | from dulwich.refs import PEELED_TAG_SUFFIX |
213 | except ImportError: |
214 | from dulwich.refs import ANNOTATED_TAG_SUFFIX as PEELED_TAG_SUFFIX |
215 | + |
216 | from dulwich.repo import RefsContainer |
217 | |
218 | from .. import controldir, errors, osutils |
219 | |
220 | === modified file 'breezy/graph.py' |
221 | --- breezy/graph.py 2023-04-16 03:18:03 +0000 |
222 | +++ breezy/graph.py 2023-04-17 11:56:43 +0000 |
223 | @@ -1582,7 +1582,7 @@ |
224 | return revs, ghosts |
225 | |
226 | |
227 | -from ._graph_rs import invert_parent_map, collapse_linear_regions |
228 | +from ._graph_rs import collapse_linear_regions, invert_parent_map |
229 | |
230 | |
231 | class GraphThunkIdsToKeys: |
232 | |
233 | === modified file 'breezy/log.py' |
234 | --- breezy/log.py 2023-04-13 21:30:33 +0000 |
235 | +++ breezy/log.py 2023-04-17 11:56:43 +0000 |
236 | @@ -73,11 +73,10 @@ |
237 | from . import revision as _mod_revision |
238 | from . import revisionspec, trace |
239 | from . import transport as _mod_transport |
240 | -from .osutils import (format_date, |
241 | +from .osutils import (UnsupportedTimezoneFormat, format_date, |
242 | format_date_with_offset_in_original_timezone, |
243 | get_diff_header_encoding, get_terminal_encoding, |
244 | - is_inside, terminal_width, |
245 | - UnsupportedTimezoneFormat) |
246 | + is_inside, terminal_width) |
247 | from .tree import InterTree |
248 | |
249 | |
250 | |
251 | === modified file 'breezy/main.rs' |
252 | --- breezy/main.rs 2023-04-15 03:34:42 +0000 |
253 | +++ breezy/main.rs 2023-04-17 11:56:43 +0000 |
254 | @@ -2,7 +2,6 @@ |
255 | use pyo3::types::*; |
256 | use std::path::*; |
257 | |
258 | - |
259 | fn check_version(py: Python<'_>) -> PyResult<()> { |
260 | let major: u32 = env!("CARGO_PKG_VERSION_MAJOR").parse::<u32>().unwrap(); |
261 | let minor: u32 = env!("CARGO_PKG_VERSION_MINOR").parse::<u32>().unwrap(); |
262 | @@ -66,7 +65,7 @@ |
263 | fn update_path(py: Python<'_>) -> PyResult<()> { |
264 | let mut path = std::env::current_exe()?; |
265 | |
266 | - path.pop(); // Drop executable name |
267 | + path.pop(); // Drop executable name |
268 | |
269 | let mut package_path = path.clone(); |
270 | package_path.push("breezy"); |
271 | |
272 | === modified file 'breezy/merge_directive.py' |
273 | --- breezy/merge_directive.py 2023-04-14 21:30:07 +0000 |
274 | +++ breezy/merge_directive.py 2023-04-17 11:56:43 +0000 |
275 | @@ -38,13 +38,9 @@ |
276 | serializer as bundle_serializer, |
277 | ) |
278 | """) |
279 | -from . import ( |
280 | - branch as _mod_branch, |
281 | - errors, |
282 | - hooks, |
283 | - registry, |
284 | - revision as _mod_revision, |
285 | -) |
286 | +from . import branch as _mod_branch |
287 | +from . import errors, hooks, registry |
288 | +from . import revision as _mod_revision |
289 | |
290 | |
291 | class IllegalMergeDirectivePayload(errors.BzrError): |
292 | |
293 | === modified file 'breezy/osutils.py' |
294 | --- breezy/osutils.py 2023-04-16 11:47:42 +0000 |
295 | +++ breezy/osutils.py 2023-04-17 11:56:43 +0000 |
296 | @@ -22,7 +22,7 @@ |
297 | import sys |
298 | import time |
299 | from functools import partial |
300 | -from typing import Dict, List, Iterable |
301 | +from typing import Dict, Iterable, List |
302 | |
303 | from .lazy_import import lazy_import |
304 | |
305 | @@ -49,7 +49,7 @@ |
306 | |
307 | import breezy |
308 | |
309 | -from . import errors, _osutils_rs |
310 | +from . import _osutils_rs, errors |
311 | |
312 | # On win32, O_BINARY is used to indicate the file should |
313 | # be opened in binary mode, rather than text mode. |
314 | @@ -73,7 +73,6 @@ |
315 | |
316 | from ._osutils_rs import get_umask, kind_marker, quotefn |
317 | |
318 | - |
319 | lexists = getattr(os.path, 'lexists', None) |
320 | if lexists is None: |
321 | def lexists(f): |
322 | @@ -646,7 +645,10 @@ |
323 | # https://bugs.launchpad.net/bzr/+bug/430529 |
324 | |
325 | |
326 | -from ._osutils_rs import chunks_to_lines, chunks_to_lines_iter, normalized_filename, _inaccessible_normalized_filename, _accessible_normalized_filename, normalizes_filenames, split_lines |
327 | +from ._osutils_rs import (_accessible_normalized_filename, |
328 | + _inaccessible_normalized_filename, chunks_to_lines, |
329 | + chunks_to_lines_iter, normalized_filename, |
330 | + normalizes_filenames, split_lines) |
331 | |
332 | |
333 | def hardlinks_good(): |
334 | |
335 | === modified file 'breezy/patch.py' |
336 | --- breezy/patch.py 2023-04-14 18:25:48 +0000 |
337 | +++ breezy/patch.py 2023-04-17 11:56:43 +0000 |
338 | @@ -17,7 +17,8 @@ |
339 | |
340 | """Diff and patch functionality""" |
341 | |
342 | -from ._patch_rs import patch, diff3, iter_patched_from_hunks, run_patch, PatchInvokeError, PatchFailed |
343 | +from ._patch_rs import (PatchFailed, PatchInvokeError, diff3, |
344 | + iter_patched_from_hunks, patch, run_patch) |
345 | |
346 | |
347 | def patch_tree(tree, patches, strip=0, reverse=False, dry_run=False, |
348 | |
349 | === modified file 'breezy/patches.py' |
350 | --- breezy/patches.py 2023-04-16 01:30:53 +0000 |
351 | +++ breezy/patches.py 2023-04-17 11:56:43 +0000 |
352 | @@ -57,7 +57,8 @@ |
353 | self.line = line |
354 | |
355 | |
356 | -from ._patch_rs import get_patch_names, BinaryFiles, MalformedPatchHeader, iter_lines_handle_nl, parse_range, difference_index |
357 | +from ._patch_rs import (BinaryFiles, MalformedPatchHeader, difference_index, |
358 | + get_patch_names, iter_lines_handle_nl, parse_range) |
359 | |
360 | |
361 | def hunk_from_header(line): |
362 | |
363 | === modified file 'breezy/plugins/launchpad/lp_directory.py' |
364 | --- breezy/plugins/launchpad/lp_directory.py 2023-03-31 15:00:34 +0000 |
365 | +++ breezy/plugins/launchpad/lp_directory.py 2023-04-17 11:56:43 +0000 |
366 | @@ -20,7 +20,7 @@ |
367 | |
368 | from ... import debug, errors, trace, transport |
369 | from ...i18n import gettext |
370 | -from ...urlutils import InvalidURL, split, join |
371 | +from ...urlutils import InvalidURL, join, split |
372 | from .account import get_lp_login |
373 | from .uris import DEFAULT_INSTANCE, LAUNCHPAD_DOMAINS, LPNET_SERVICE_ROOT |
374 | |
375 | |
376 | === modified file 'breezy/repository.py' |
377 | --- breezy/repository.py 2023-03-09 13:47:07 +0000 |
378 | +++ breezy/repository.py 2023-04-17 11:56:43 +0000 |
379 | @@ -16,7 +16,7 @@ |
380 | |
381 | __docformat__ = "google" |
382 | |
383 | -from typing import List, Type, TYPE_CHECKING, Optional, Iterable |
384 | +from typing import TYPE_CHECKING, Iterable, List, Optional, Type |
385 | |
386 | from .lazy_import import lazy_import |
387 | |
388 | @@ -30,7 +30,9 @@ |
389 | from breezy.i18n import gettext |
390 | """) |
391 | |
392 | -from . import controldir, debug, errors, graph, registry, revision as _mod_revision, ui |
393 | +from . import controldir, debug, errors, graph, registry |
394 | +from . import revision as _mod_revision |
395 | +from . import ui |
396 | from .decorators import only_raises |
397 | from .inter import InterObject |
398 | from .lock import LogicalLockResult, _RelockDebugMixin |
399 | |
400 | === modified file 'breezy/revisiontree.py' |
401 | --- breezy/revisiontree.py 2023-04-13 16:25:22 +0000 |
402 | +++ breezy/revisiontree.py 2023-04-17 11:56:43 +0000 |
403 | @@ -16,7 +16,7 @@ |
404 | |
405 | """RevisionTree - a Tree implementation backed by repository data for a revision.""" |
406 | |
407 | -from . import lock, revision, tree, osutils |
408 | +from . import lock, osutils, revision, tree |
409 | |
410 | |
411 | class RevisionTree(tree.Tree): |
412 | |
413 | === modified file 'breezy/tests/test_patches.py' |
414 | --- breezy/tests/test_patches.py 2023-04-15 03:34:42 +0000 |
415 | +++ breezy/tests/test_patches.py 2023-04-17 11:56:43 +0000 |
416 | @@ -22,9 +22,9 @@ |
417 | ContextLine, InsertLine, MalformedHunkHeader, |
418 | MalformedLine, MalformedPatchHeader, Patch, |
419 | RemoveLine, difference_index, get_patch_names, |
420 | - hunk_from_header, iter_patched, |
421 | - iter_patched_from_hunks, parse_line, parse_patch, |
422 | - parse_patches, iter_lines_handle_nl) |
423 | + hunk_from_header, iter_lines_handle_nl, |
424 | + iter_patched, iter_patched_from_hunks, parse_line, |
425 | + parse_patch, parse_patches) |
426 | from breezy.tests import TestCase, TestCaseWithTransport |
427 | |
428 | |
429 | |
430 | === modified file 'breezy/tests/test_timestamp.py' |
431 | --- breezy/tests/test_timestamp.py 2023-04-13 22:28:22 +0000 |
432 | +++ breezy/tests/test_timestamp.py 2023-04-17 11:56:43 +0000 |
433 | @@ -18,7 +18,7 @@ |
434 | import time |
435 | |
436 | from breezy import tests, timestamp |
437 | -from breezy.osutils import local_time_offset, format_date |
438 | +from breezy.osutils import format_date, local_time_offset |
439 | |
440 | |
441 | class TestPatchHeader(tests.TestCase): |
442 | |
443 | === modified file 'breezy/textfile.py' |
444 | --- breezy/textfile.py 2023-04-13 17:46:12 +0000 |
445 | +++ breezy/textfile.py 2023-04-17 11:56:43 +0000 |
446 | @@ -18,9 +18,9 @@ |
447 | |
448 | from itertools import chain |
449 | |
450 | +from . import _osutils_rs |
451 | from .errors import BinaryFile |
452 | -from .osutils import file_iterator, IterableFile |
453 | -from . import _osutils_rs |
454 | +from .osutils import IterableFile, file_iterator |
455 | |
456 | |
457 | def text_file(input): |
458 | |
459 | === modified file 'breezy/transport/http/urllib.py' |
460 | --- breezy/transport/http/urllib.py 2023-04-08 18:48:50 +0000 |
461 | +++ breezy/transport/http/urllib.py 2023-04-17 11:56:43 +0000 |
462 | @@ -24,8 +24,8 @@ |
463 | import base64 |
464 | import cgi |
465 | import errno |
466 | +import hashlib |
467 | import http.client |
468 | -import hashlib |
469 | import os |
470 | import re |
471 | import socket |
472 | |
473 | === modified file 'breezy/tsort.py' |
474 | --- breezy/tsort.py 2023-04-17 00:37:30 +0000 |
475 | +++ breezy/tsort.py 2023-04-17 11:56:43 +0000 |
476 | @@ -23,7 +23,7 @@ |
477 | |
478 | __all__ = ["topo_sort", "TopoSorter", "merge_sort", "MergeSorter"] |
479 | |
480 | -from ._graph_rs import TopoSorter, MergeSorter, merge_sort |
481 | +from ._graph_rs import MergeSorter, TopoSorter, merge_sort |
482 | |
483 | |
484 | def topo_sort(graph): |
485 | |
486 | === modified file 'breezy/version_info_formats/__init__.py' |
487 | --- breezy/version_info_formats/__init__.py 2023-04-14 10:04:16 +0000 |
488 | +++ breezy/version_info_formats/__init__.py 2023-04-17 11:56:43 +0000 |
489 | @@ -16,8 +16,8 @@ |
490 | |
491 | """Routines for extracting all version information from a bzr branch.""" |
492 | |
493 | +import time |
494 | from contextlib import ExitStack |
495 | -import time |
496 | from typing import Type |
497 | |
498 | from breezy import registry |
499 | |
500 | === modified file 'crates/bazaar/src/filters.rs' |
501 | --- crates/bazaar/src/filters.rs 2023-04-10 22:48:06 +0000 |
502 | +++ crates/bazaar/src/filters.rs 2023-04-17 11:56:43 +0000 |
503 | @@ -1,8 +1,8 @@ |
504 | -use std::path::Path; |
505 | +use breezy_osutils::sha::sha_chunks; |
506 | use std::fs::File; |
507 | +use std::io::Error; |
508 | use std::io::Read; |
509 | -use std::io::Error; |
510 | -use breezy_osutils::sha::sha_chunks; |
511 | +use std::path::Path; |
512 | |
513 | pub type ContentFilterProvider = dyn Fn(&Path, u64) -> Box<dyn ContentFilter> + Send; |
514 | |
515 | @@ -20,7 +20,7 @@ |
516 | fn sha1_file(&self, path: &Path) -> Result<String, std::io::Error> { |
517 | let mut file = File::open(path)?; |
518 | let chunk_iter = std::iter::from_fn(move || { |
519 | - let mut buf= vec![0; 128 << 10]; |
520 | + let mut buf = vec![0; 128 << 10]; |
521 | let bytes_read = file.read(&mut buf); |
522 | if let Err(e) = bytes_read { |
523 | return Some(Err(e)); |
524 | @@ -55,7 +55,7 @@ |
525 | filters: Vec<Box<dyn ContentFilter>>, |
526 | } |
527 | |
528 | -impl From <Vec<Box<dyn ContentFilter>>> for ContentFilterStack { |
529 | +impl From<Vec<Box<dyn ContentFilter>>> for ContentFilterStack { |
530 | fn from(filters: Vec<Box<dyn ContentFilter>>) -> Self { |
531 | Self { filters } |
532 | } |
533 | @@ -63,7 +63,9 @@ |
534 | |
535 | impl ContentFilterStack { |
536 | pub fn new() -> Self { |
537 | - Self { filters: Vec::new() } |
538 | + Self { |
539 | + filters: Vec::new(), |
540 | + } |
541 | } |
542 | |
543 | pub fn add_filter(&mut self, filter: Box<dyn ContentFilter>) { |
544 | @@ -75,17 +77,18 @@ |
545 | fn reader( |
546 | &self, |
547 | input: Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send>, |
548 | - ) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send> |
549 | - { |
550 | - self.filters.iter().fold(input, |input, filter| filter.reader(input)) |
551 | + ) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send> { |
552 | + self.filters |
553 | + .iter() |
554 | + .fold(input, |input, filter| filter.reader(input)) |
555 | } |
556 | |
557 | fn writer( |
558 | &self, |
559 | input: Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send>, |
560 | - ) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send> |
561 | - { |
562 | - self.filters.iter().fold(input, |input, filter| filter.writer(input)) |
563 | + ) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send> { |
564 | + self.filters |
565 | + .iter() |
566 | + .fold(input, |input, filter| filter.writer(input)) |
567 | } |
568 | - |
569 | } |
570 | |
571 | === modified file 'crates/chk-map-py/src/lib.rs' |
572 | --- crates/chk-map-py/src/lib.rs 2023-04-05 19:09:07 +0000 |
573 | +++ crates/chk-map-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
574 | @@ -1,11 +1,11 @@ |
575 | use pyo3::prelude::*; |
576 | +use pyo3::types::PyBytes; |
577 | use pyo3::wrap_pyfunction; |
578 | -use pyo3::types::PyBytes; |
579 | |
580 | use bazaar_chk_map; |
581 | |
582 | #[pyfunction] |
583 | -fn _search_key_16(py: Python, key: Vec<Vec<u8>>) -> Py<PyBytes>{ |
584 | +fn _search_key_16(py: Python, key: Vec<Vec<u8>>) -> Py<PyBytes> { |
585 | let key = key.iter().map(|v| v.as_slice()).collect::<Vec<&[u8]>>(); |
586 | let ret = bazaar_chk_map::search_key_16(key.as_slice()); |
587 | PyBytes::new(py, &ret).into_py(py) |
588 | @@ -22,7 +22,9 @@ |
589 | fn _bytes_to_text_key(py: Python, key: Vec<u8>) -> PyResult<(&PyBytes, &PyBytes)> { |
590 | let ret = bazaar_chk_map::bytes_to_text_key(key.as_slice()); |
591 | if ret.is_err() { |
592 | - return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>("Invalid key")); |
593 | + return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
594 | + "Invalid key", |
595 | + )); |
596 | } |
597 | let ret = ret.unwrap(); |
598 | Ok((PyBytes::new(py, &ret.0), PyBytes::new(py, &ret.1))) |
599 | |
600 | === modified file 'crates/chk-map/src/lib.rs' |
601 | --- crates/chk-map/src/lib.rs 2023-04-06 18:50:17 +0000 |
602 | +++ crates/chk-map/src/lib.rs 2023-04-17 11:56:43 +0000 |
603 | @@ -25,15 +25,16 @@ |
604 | result.push(0x00); |
605 | } |
606 | result.pop(); |
607 | - result.iter().map(|b| if *b == 0x0A { b'_'} else { *b }).collect() |
608 | + result |
609 | + .iter() |
610 | + .map(|b| if *b == 0x0A { b'_' } else { *b }) |
611 | + .collect() |
612 | } |
613 | |
614 | pub fn bytes_to_text_key(data: &[u8]) -> Result<(&[u8], &[u8]), String> { |
615 | let sections: Vec<&[u8]> = data.split(|&byte| byte == b'\n').collect(); |
616 | |
617 | - let delimiter_position = sections[0] |
618 | - .windows(2) |
619 | - .position(|window| window == b": "); |
620 | + let delimiter_position = sections[0].windows(2).position(|window| window == b": "); |
621 | |
622 | if delimiter_position.is_none() { |
623 | return Err("Invalid key file".to_string()); |
624 | |
625 | === modified file 'crates/dirstate-py/src/lib.rs' |
626 | --- crates/dirstate-py/src/lib.rs 2023-04-13 18:17:29 +0000 |
627 | +++ crates/dirstate-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
628 | @@ -1,13 +1,13 @@ |
629 | #![allow(non_snake_case)] |
630 | |
631 | +use pyo3::exceptions::PyTypeError; |
632 | use pyo3::prelude::*; |
633 | +use pyo3::types::{PyBytes, PyDict, PyList, PyString, PyTuple}; |
634 | use pyo3::wrap_pyfunction; |
635 | -use std::path::{Path,PathBuf}; |
636 | -use pyo3::types::{PyBytes, PyDict, PyList, PyTuple, PyString}; |
637 | -use pyo3::exceptions::PyTypeError; |
638 | -use std::os::unix::fs::{PermissionsExt, MetadataExt}; |
639 | use std::ffi::OsString; |
640 | use std::os::unix::ffi::OsStringExt; |
641 | +use std::os::unix::fs::{MetadataExt, PermissionsExt}; |
642 | +use std::path::{Path, PathBuf}; |
643 | |
644 | use bazaar_dirstate; |
645 | |
646 | @@ -79,10 +79,18 @@ |
647 | #[pyfunction] |
648 | fn bisect_path_left(paths: Vec<&PyAny>, path: &PyAny) -> PyResult<usize> { |
649 | let path = extract_path(path)?; |
650 | - let paths = paths.iter().map(|x| extract_path(x).unwrap()).collect::<Vec<PathBuf>>(); |
651 | + let paths = paths |
652 | + .iter() |
653 | + .map(|x| extract_path(x).unwrap()) |
654 | + .collect::<Vec<PathBuf>>(); |
655 | let offset = bazaar_dirstate::bisect_path_left( |
656 | - paths.iter().map(|x| x.as_path()).collect::<Vec<&Path>>().as_slice(), |
657 | - &path); |
658 | + paths |
659 | + .iter() |
660 | + .map(|x| x.as_path()) |
661 | + .collect::<Vec<&Path>>() |
662 | + .as_slice(), |
663 | + &path, |
664 | + ); |
665 | Ok(offset) |
666 | } |
667 | |
668 | @@ -107,10 +115,18 @@ |
669 | #[pyfunction] |
670 | fn bisect_path_right(paths: Vec<&PyAny>, path: &PyAny) -> PyResult<usize> { |
671 | let path = extract_path(path)?; |
672 | - let paths = paths.iter().map(|x| extract_path(x).unwrap()).collect::<Vec<PathBuf>>(); |
673 | + let paths = paths |
674 | + .iter() |
675 | + .map(|x| extract_path(x).unwrap()) |
676 | + .collect::<Vec<PathBuf>>(); |
677 | let offset = bazaar_dirstate::bisect_path_right( |
678 | - paths.iter().map(|x| x.as_path()).collect::<Vec<&Path>>().as_slice(), |
679 | - &path); |
680 | + paths |
681 | + .iter() |
682 | + .map(|x| x.as_path()) |
683 | + .collect::<Vec<&Path>>() |
684 | + .as_slice(), |
685 | + &path, |
686 | + ); |
687 | Ok(offset) |
688 | } |
689 | |
690 | @@ -201,15 +217,25 @@ |
691 | |
692 | #[getter] |
693 | fn st_mtime(&self) -> PyResult<u64> { |
694 | - let modified = self.metadata.modified().map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
695 | - let since_epoch = modified.duration_since(std::time::UNIX_EPOCH).map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e.to_string()))?; |
696 | + let modified = self |
697 | + .metadata |
698 | + .modified() |
699 | + .map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
700 | + let since_epoch = modified |
701 | + .duration_since(std::time::UNIX_EPOCH) |
702 | + .map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e.to_string()))?; |
703 | Ok(since_epoch.as_secs()) |
704 | } |
705 | |
706 | #[getter] |
707 | fn st_ctime(&self) -> PyResult<u64> { |
708 | - let created = self.metadata.created().map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
709 | - let since_epoch = created.duration_since(std::time::UNIX_EPOCH).map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e.to_string()))?; |
710 | + let created = self |
711 | + .metadata |
712 | + .created() |
713 | + .map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
714 | + let since_epoch = created |
715 | + .duration_since(std::time::UNIX_EPOCH) |
716 | + .map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e.to_string()))?; |
717 | Ok(since_epoch.as_secs()) |
718 | } |
719 | |
720 | @@ -240,7 +266,10 @@ |
721 | impl SHA1Provider { |
722 | fn sha1(&mut self, py: Python, path: &PyAny) -> PyResult<PyObject> { |
723 | let path = extract_path(path)?; |
724 | - let sha1 = self.provider.sha1(&path).map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
725 | + let sha1 = self |
726 | + .provider |
727 | + .sha1(&path) |
728 | + .map_err(|e| PyErr::new::<pyo3::exceptions::PyOSError, _>(e))?; |
729 | Ok(PyBytes::new(py, sha1.as_bytes()).to_object(py)) |
730 | } |
731 | |
732 | @@ -248,7 +277,10 @@ |
733 | let path = extract_path(path)?; |
734 | let (md, sha1) = self.provider.stat_and_sha1(&path)?; |
735 | let pmd = StatResult { metadata: md }; |
736 | - Ok((pmd.into_py(py), PyBytes::new(py, sha1.as_bytes()).to_object(py))) |
737 | + Ok(( |
738 | + pmd.into_py(py), |
739 | + PyBytes::new(py, sha1.as_bytes()).to_object(py), |
740 | + )) |
741 | } |
742 | } |
743 | |
744 | |
745 | === modified file 'crates/dirstate/src/lib.rs' |
746 | --- crates/dirstate/src/lib.rs 2023-04-17 09:12:14 +0000 |
747 | +++ crates/dirstate/src/lib.rs 2023-04-17 11:56:43 +0000 |
748 | @@ -1,12 +1,12 @@ |
749 | use base64; |
750 | +use breezy_osutils::sha::{sha_file, sha_file_by_name}; |
751 | use std::cmp::Ordering; |
752 | -use std::path::Path; |
753 | -use breezy_osutils::sha::{sha_file_by_name,sha_file}; |
754 | use std::fs::File; |
755 | use std::fs::Metadata; |
756 | use std::os::unix::fs::MetadataExt; |
757 | +use std::path::Path; |
758 | |
759 | -pub trait SHA1Provider : Send + Sync { |
760 | +pub trait SHA1Provider: Send + Sync { |
761 | fn sha1(&self, path: &Path) -> std::io::Result<String>; |
762 | |
763 | fn stat_and_sha1(&self, path: &Path) -> std::io::Result<(Metadata, String)>; |
764 | @@ -47,13 +47,11 @@ |
765 | (None, None) => return false, |
766 | (None, Some(_)) => return true, |
767 | (Some(_), None) => return false, |
768 | - (Some(part1), Some(part2)) => { |
769 | - match part1.cmp(&part2) { |
770 | - Ordering::Equal => continue, |
771 | - Ordering::Less => return true, |
772 | - Ordering::Greater => return false, |
773 | - } |
774 | - } |
775 | + (Some(part1), Some(part2)) => match part1.cmp(&part2) { |
776 | + Ordering::Equal => continue, |
777 | + Ordering::Less => return true, |
778 | + Ordering::Greater => return false, |
779 | + }, |
780 | } |
781 | } |
782 | } |
783 | @@ -100,11 +98,21 @@ |
784 | pub fn pack_stat_metadata(metadata: &Metadata) -> String { |
785 | pack_stat( |
786 | metadata.len(), |
787 | - metadata.modified().unwrap().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(), |
788 | - metadata.created().unwrap().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(), |
789 | + metadata |
790 | + .modified() |
791 | + .unwrap() |
792 | + .duration_since(std::time::UNIX_EPOCH) |
793 | + .unwrap() |
794 | + .as_secs(), |
795 | + metadata |
796 | + .created() |
797 | + .unwrap() |
798 | + .duration_since(std::time::UNIX_EPOCH) |
799 | + .unwrap() |
800 | + .as_secs(), |
801 | metadata.dev(), |
802 | metadata.ino(), |
803 | - metadata.mode() |
804 | + metadata.mode(), |
805 | ) |
806 | } |
807 | |
808 | |
809 | === modified file 'crates/graph-py/src/lib.rs' |
810 | --- crates/graph-py/src/lib.rs 2023-04-17 09:32:41 +0000 |
811 | +++ crates/graph-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
812 | @@ -1,12 +1,12 @@ |
813 | #![allow(non_snake_case)] |
814 | |
815 | +use breezy_graph::RevnoVec; |
816 | use pyo3::import_exception; |
817 | use pyo3::prelude::*; |
818 | -use pyo3::types::{PyDict, PyList, PyTuple}; |
819 | +use pyo3::types::{PyDict, PyIterator, PyList, PyTuple}; |
820 | use pyo3::wrap_pyfunction; |
821 | use std::collections::{HashMap, HashSet}; |
822 | use std::hash::Hash; |
823 | -use breezy_graph::RevnoVec; |
824 | |
825 | import_exception!(breezy.errors, GraphCycleError); |
826 | |
827 | @@ -342,20 +342,20 @@ |
828 | fn __next__(&mut self, py: Python) -> PyResult<Option<PyObject>> { |
829 | match self.sorter.next() { |
830 | None => Ok(None), |
831 | - Some(Ok((sequence_number, node, merge_depth, None, end_of_merge))) => Ok(Some(( |
832 | - sequence_number, |
833 | - node.into_py(py), |
834 | - merge_depth, |
835 | - end_of_merge, |
836 | - ).into_py(py))), |
837 | + Some(Ok((sequence_number, node, merge_depth, None, end_of_merge))) => Ok(Some( |
838 | + (sequence_number, node.into_py(py), merge_depth, end_of_merge).into_py(py), |
839 | + )), |
840 | |
841 | - Some(Ok((sequence_number, node, merge_depth, Some(revno), end_of_merge))) => Ok(Some(( |
842 | - sequence_number, |
843 | - node.into_py(py), |
844 | - merge_depth, |
845 | - revno_vec_to_py(py, revno), |
846 | - end_of_merge, |
847 | - ).into_py(py))), |
848 | + Some(Ok((sequence_number, node, merge_depth, Some(revno), end_of_merge))) => Ok(Some( |
849 | + ( |
850 | + sequence_number, |
851 | + node.into_py(py), |
852 | + merge_depth, |
853 | + revno_vec_to_py(py, revno), |
854 | + end_of_merge, |
855 | + ) |
856 | + .into_py(py), |
857 | + )), |
858 | Some(Err(breezy_graph::tsort::Error::Cycle(e))) => Err(GraphCycleError::new_err(e)), |
859 | } |
860 | } |
861 | |
862 | === modified file 'crates/graph/src/tsort.rs' |
863 | --- crates/graph/src/tsort.rs 2023-04-17 10:49:20 +0000 |
864 | +++ crates/graph/src/tsort.rs 2023-04-17 11:56:43 +0000 |
865 | @@ -57,7 +57,9 @@ |
866 | /// |
867 | /// After finishing iteration the sorter is empty and you cannot continue |
868 | /// iteration. |
869 | - pub fn iter_topo_order(&mut self) -> impl Iterator<Item = std::result::Result<K, Error<K>>> + '_ { |
870 | + pub fn iter_topo_order( |
871 | + &mut self, |
872 | + ) -> impl Iterator<Item = std::result::Result<K, Error<K>>> + '_ { |
873 | self |
874 | } |
875 | } |
876 | @@ -371,7 +373,9 @@ |
877 | /// Sort the graph and return as a list. |
878 | /// |
879 | /// After calling this the sorter is empty and you must create a new one. |
880 | - pub fn sorted(&mut self) -> std::result::Result<Vec<(usize, K, usize, Option<RevnoVec>, bool)>, Error<K>> { |
881 | + pub fn sorted( |
882 | + &mut self, |
883 | + ) -> std::result::Result<Vec<(usize, K, usize, Option<RevnoVec>, bool)>, Error<K>> { |
884 | self.iter_topo_order().collect() |
885 | } |
886 | |
887 | @@ -380,7 +384,8 @@ |
888 | /// iteration. |
889 | pub fn iter_topo_order( |
890 | &mut self, |
891 | - ) -> impl Iterator<Item = std::result::Result<(usize, K, usize, Option<RevnoVec>, bool), Error<K>>> + '_ { |
892 | + ) -> impl Iterator<Item = std::result::Result<(usize, K, usize, Option<RevnoVec>, bool), Error<K>>> |
893 | + + '_ { |
894 | self |
895 | } |
896 | |
897 | @@ -484,7 +489,12 @@ |
898 | *self.left_subtree_pushed_stack.last_mut().unwrap() = true; |
899 | // recurse depth first into the primary parent |
900 | } else { |
901 | - next_node_name = self.pending_parents_stack.last_mut().unwrap().pop().unwrap(); |
902 | + next_node_name = self |
903 | + .pending_parents_stack |
904 | + .last_mut() |
905 | + .unwrap() |
906 | + .pop() |
907 | + .unwrap(); |
908 | is_left_subtree = false; |
909 | // place any merges in right-to-left order for scheduling |
910 | // which gives us left-to-right order after we reverse |
911 | @@ -537,7 +547,9 @@ |
912 | |
913 | impl<K: Eq + Hash + std::fmt::Debug + Clone> Iterator for MergeSorter<K> { |
914 | type Item = std::result::Result<(usize, K, usize, Option<RevnoVec>, bool), Error<K>>; |
915 | - fn next(&mut self) -> Option<std::result::Result<(usize, K, usize, Option<RevnoVec>, bool), Error<K>>> { |
916 | + fn next( |
917 | + &mut self, |
918 | + ) -> Option<std::result::Result<(usize, K, usize, Option<RevnoVec>, bool), Error<K>>> { |
919 | if let Err(err) = self.build() { |
920 | return Some(Err(err)); |
921 | } |
922 | |
923 | === modified file 'crates/groupcompress-py/src/lib.rs' |
924 | --- crates/groupcompress-py/src/lib.rs 2023-04-05 19:55:41 +0000 |
925 | +++ crates/groupcompress-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
926 | @@ -1,6 +1,6 @@ |
927 | use pyo3::prelude::*; |
928 | +use pyo3::types::PyBytes; |
929 | use pyo3::wrap_pyfunction; |
930 | -use pyo3::types::PyBytes; |
931 | |
932 | use bazaar_groupcompress; |
933 | |
934 | @@ -19,7 +19,9 @@ |
935 | fn apply_delta(py: Python, basis: Vec<u8>, delta: Vec<u8>) -> PyResult<&PyBytes> { |
936 | let ret = bazaar_groupcompress::apply_delta(&basis, &delta); |
937 | if ret.is_err() { |
938 | - return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>("Invalid delta")); |
939 | + return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
940 | + "Invalid delta", |
941 | + )); |
942 | } |
943 | Ok(PyBytes::new(py, &ret.unwrap())) |
944 | } |
945 | @@ -28,7 +30,9 @@ |
946 | fn decode_copy_instruction(data: Vec<u8>, cmd: u8, pos: usize) -> PyResult<(usize, usize, usize)> { |
947 | let ret = bazaar_groupcompress::decode_copy_instruction(&data, cmd, pos); |
948 | if ret.is_err() { |
949 | - return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>("Invalid copy instruction")); |
950 | + return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
951 | + "Invalid copy instruction", |
952 | + )); |
953 | } |
954 | let ret = ret.unwrap(); |
955 | |
956 | @@ -36,10 +40,17 @@ |
957 | } |
958 | |
959 | #[pyfunction] |
960 | -fn apply_delta_to_source(py: Python, source: &[u8], delta_start: usize, delta_end: usize) -> PyResult<PyObject> { |
961 | +fn apply_delta_to_source( |
962 | + py: Python, |
963 | + source: &[u8], |
964 | + delta_start: usize, |
965 | + delta_end: usize, |
966 | +) -> PyResult<PyObject> { |
967 | let ret = bazaar_groupcompress::apply_delta_to_source(source, delta_start, delta_end); |
968 | if ret.is_err() { |
969 | - return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>("Invalid delta")); |
970 | + return Err(PyErr::new::<pyo3::exceptions::PyValueError, _>( |
971 | + "Invalid delta", |
972 | + )); |
973 | } |
974 | let ret = ret.unwrap(); |
975 | Ok(PyBytes::new(py, &ret).to_object(py)) |
976 | |
977 | === modified file 'crates/groupcompress/src/lib.rs' |
978 | --- crates/groupcompress/src/lib.rs 2023-04-05 19:55:41 +0000 |
979 | +++ crates/groupcompress/src/lib.rs 2023-04-17 11:56:43 +0000 |
980 | @@ -26,7 +26,11 @@ |
981 | |
982 | pub type CopyInstruction = (usize, usize, usize); |
983 | |
984 | -pub fn decode_copy_instruction(data: &[u8], cmd: u8, pos: usize) -> Result<CopyInstruction, String> { |
985 | +pub fn decode_copy_instruction( |
986 | + data: &[u8], |
987 | + cmd: u8, |
988 | + pos: usize, |
989 | +) -> Result<CopyInstruction, String> { |
990 | if cmd & 0x80 != 0x80 { |
991 | return Err("copy instructions must have bit 0x80 set".to_string()); |
992 | } |
993 | @@ -106,7 +110,11 @@ |
994 | Ok(lines) |
995 | } |
996 | |
997 | -pub fn apply_delta_to_source(source: &[u8], delta_start: usize, delta_end: usize) -> Result<Vec<u8>, String> { |
998 | +pub fn apply_delta_to_source( |
999 | + source: &[u8], |
1000 | + delta_start: usize, |
1001 | + delta_end: usize, |
1002 | +) -> Result<Vec<u8>, String> { |
1003 | let source_size = source.len(); |
1004 | if delta_start >= source_size { |
1005 | return Err("delta starts after source".to_string()); |
1006 | |
1007 | === modified file 'crates/hashcache-py/src/lib.rs' |
1008 | --- crates/hashcache-py/src/lib.rs 2023-04-13 17:29:19 +0000 |
1009 | +++ crates/hashcache-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
1010 | @@ -1,10 +1,10 @@ |
1011 | +use bazaar::filters::ContentFilter; |
1012 | use pyo3::prelude::*; |
1013 | +use pyo3::types::PyBytes; |
1014 | use std::fs::Permissions; |
1015 | +use std::io::Error; |
1016 | use std::os::unix::fs::PermissionsExt; |
1017 | -use std::io::Error; |
1018 | use std::path::Path; |
1019 | -use pyo3::types::PyBytes; |
1020 | -use bazaar::filters::ContentFilter; |
1021 | |
1022 | #[pyclass] |
1023 | struct HashCache { |
1024 | @@ -43,7 +43,7 @@ |
1025 | fn _impl( |
1026 | &self, |
1027 | input: Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send>, |
1028 | - worker: &str |
1029 | + worker: &str, |
1030 | ) -> Box<dyn Iterator<Item = Result<Vec<u8>, Error>> + Send> { |
1031 | Python::with_gil(|py| { |
1032 | let worker = self.content_filter.getattr(py, worker); |
1033 | @@ -73,7 +73,6 @@ |
1034 | } |
1035 | } |
1036 | |
1037 | - |
1038 | impl ContentFilter for PyContentFilter { |
1039 | fn reader( |
1040 | &self, |
1041 | @@ -90,11 +89,18 @@ |
1042 | } |
1043 | } |
1044 | |
1045 | -fn content_filter_to_fn(content_filter_provider: PyObject) -> Box<dyn Fn(&Path, u64) -> Box<dyn ContentFilter> + Send> { |
1046 | +fn content_filter_to_fn( |
1047 | + content_filter_provider: PyObject, |
1048 | +) -> Box<dyn Fn(&Path, u64) -> Box<dyn ContentFilter> + Send> { |
1049 | Box::new(move |path, ctime| { |
1050 | Python::with_gil(|py| { |
1051 | let content_filter_provider = content_filter_provider.to_object(py); |
1052 | - Box::new(PyContentFilter { content_filter: content_filter_provider.call1(py, (path, ctime)).unwrap().to_object(py) }) |
1053 | + Box::new(PyContentFilter { |
1054 | + content_filter: content_filter_provider |
1055 | + .call1(py, (path, ctime)) |
1056 | + .unwrap() |
1057 | + .to_object(py), |
1058 | + }) |
1059 | }) |
1060 | }) |
1061 | } |
1062 | @@ -105,16 +111,28 @@ |
1063 | } else if let Ok(val) = obj.extract::<f64>() { |
1064 | Ok(val as i64) |
1065 | } else { |
1066 | - Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>("Expected int or float")) |
1067 | + Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>( |
1068 | + "Expected int or float", |
1069 | + )) |
1070 | } |
1071 | } |
1072 | |
1073 | #[pymethods] |
1074 | impl HashCache { |
1075 | #[new] |
1076 | - fn new(root: &str, cache_file_name: &str, mode: Option<u32>, content_filter_provider: Option<PyObject>) -> Self { |
1077 | + fn new( |
1078 | + root: &str, |
1079 | + cache_file_name: &str, |
1080 | + mode: Option<u32>, |
1081 | + content_filter_provider: Option<PyObject>, |
1082 | + ) -> Self { |
1083 | Self { |
1084 | - hashcache: Box::new(bazaar_hashcache::HashCache::new(Path::new(root), Path::new(cache_file_name), mode.map(Permissions::from_mode), content_filter_provider.map(content_filter_to_fn))) |
1085 | + hashcache: Box::new(bazaar_hashcache::HashCache::new( |
1086 | + Path::new(root), |
1087 | + Path::new(cache_file_name), |
1088 | + mode.map(Permissions::from_mode), |
1089 | + content_filter_provider.map(content_filter_to_fn), |
1090 | + )), |
1091 | } |
1092 | } |
1093 | |
1094 | @@ -130,7 +148,12 @@ |
1095 | self.hashcache.scan(); |
1096 | } |
1097 | |
1098 | - fn get_sha1(&mut self, py: Python, path: &str, stat_value: Option<&PyAny>) -> PyResult<PyObject> { |
1099 | + fn get_sha1( |
1100 | + &mut self, |
1101 | + py: Python, |
1102 | + path: &str, |
1103 | + stat_value: Option<&PyAny>, |
1104 | + ) -> PyResult<PyObject> { |
1105 | let sha1; |
1106 | if let Some(stat_value) = stat_value { |
1107 | let fp = bazaar_hashcache::Fingerprint { |
1108 | @@ -141,7 +164,9 @@ |
1109 | dev: stat_value.getattr("st_dev")?.extract()?, |
1110 | mode: stat_value.getattr("st_mode")?.extract()?, |
1111 | }; |
1112 | - sha1 = self.hashcache.get_sha1_by_fingerprint(Path::new(path), &fp)?; |
1113 | + sha1 = self |
1114 | + .hashcache |
1115 | + .get_sha1_by_fingerprint(Path::new(path), &fp)?; |
1116 | } else { |
1117 | let ret = self.hashcache.get_sha1(Path::new(path), None)?; |
1118 | if let Some(s) = ret { |
1119 | |
1120 | === modified file 'crates/hashcache/src/lib.rs' |
1121 | --- crates/hashcache/src/lib.rs 2023-04-12 23:51:31 +0000 |
1122 | +++ crates/hashcache/src/lib.rs 2023-04-17 11:56:43 +0000 |
1123 | @@ -1,15 +1,15 @@ |
1124 | +use bazaar::filters::{ContentFilter, ContentFilterProvider, ContentFilterStack}; |
1125 | +use breezy_osutils::sha::sha_string; |
1126 | +use log::{debug, info}; |
1127 | +use std::collections::HashMap; |
1128 | +use std::fs; |
1129 | +use std::fs::{File, Metadata, Permissions}; |
1130 | +use std::io; |
1131 | use std::io::prelude::*; |
1132 | +use std::io::BufReader; |
1133 | use std::os::unix::fs::MetadataExt; |
1134 | -use std::path::{Path,PathBuf}; |
1135 | +use std::path::{Path, PathBuf}; |
1136 | use std::time::{SystemTime, UNIX_EPOCH}; |
1137 | -use std::io; |
1138 | -use std::io::{BufReader}; |
1139 | -use std::fs; |
1140 | -use std::fs::{File,Metadata,Permissions}; |
1141 | -use std::collections::HashMap; |
1142 | -use log::{debug, info}; |
1143 | -use breezy_osutils::sha::sha_string; |
1144 | -use bazaar::filters::{ContentFilterStack, ContentFilter, ContentFilterProvider}; |
1145 | use tempfile::NamedTempFile; |
1146 | |
1147 | /// TODO: Up-front, stat all files in order and remove those which are deleted or |
1148 | @@ -56,7 +56,7 @@ |
1149 | /// miss_count |
1150 | /// number of misses (times files have been completely re-read) |
1151 | |
1152 | -#[derive(Debug,PartialEq,Default,Clone)] |
1153 | +#[derive(Debug, PartialEq, Default, Clone)] |
1154 | pub struct Fingerprint { |
1155 | pub size: u64, |
1156 | pub mtime: i64, |
1157 | @@ -66,15 +66,15 @@ |
1158 | pub mode: u32, |
1159 | } |
1160 | |
1161 | -impl From <Metadata> for Fingerprint { |
1162 | - fn from (meta: Metadata) -> Fingerprint { |
1163 | +impl From<Metadata> for Fingerprint { |
1164 | + fn from(meta: Metadata) -> Fingerprint { |
1165 | Fingerprint { |
1166 | size: meta.size(), |
1167 | mtime: meta.mtime(), |
1168 | ctime: meta.ctime(), |
1169 | ino: meta.ino(), |
1170 | dev: meta.dev(), |
1171 | - mode: meta.mode() |
1172 | + mode: meta.mode(), |
1173 | } |
1174 | } |
1175 | } |
1176 | @@ -109,8 +109,7 @@ |
1177 | root: &Path, |
1178 | cache_file_name: &Path, |
1179 | permissions: Option<Permissions>, |
1180 | - content_filter_provider: Option<Box<ContentFilterProvider>, |
1181 | - >, |
1182 | + content_filter_provider: Option<Box<ContentFilterProvider>>, |
1183 | ) -> Self { |
1184 | HashCache { |
1185 | root: root.to_path_buf(), |
1186 | @@ -161,7 +160,11 @@ |
1187 | /// since the entry was inserted. |
1188 | pub fn scan(&mut self) { |
1189 | let mut keys_to_remove = Vec::new(); |
1190 | - let mut by_inode = self.cache.iter().map(|(k, v)| (v.1.ino, k, v)).collect::<Vec<_>>(); |
1191 | + let mut by_inode = self |
1192 | + .cache |
1193 | + .iter() |
1194 | + .map(|(k, v)| (v.1.ino, k, v)) |
1195 | + .collect::<Vec<_>>(); |
1196 | by_inode.sort_by_key(|x| x.0); |
1197 | for (_inode, path, cache_val) in by_inode { |
1198 | let abspath = self.root.join(path); |
1199 | @@ -183,10 +186,15 @@ |
1200 | pub fn get_sha1_by_fingerprint( |
1201 | &mut self, |
1202 | path: &Path, |
1203 | - file_fp: &Fingerprint) -> io::Result<String> { |
1204 | + file_fp: &Fingerprint, |
1205 | + ) -> io::Result<String> { |
1206 | let abspath = self.root.join(path); |
1207 | |
1208 | - let (cache_sha1, cache_fp) = self.cache.get(path).cloned().unwrap_or((Default::default(), Default::default())); |
1209 | + let (cache_sha1, cache_fp) = self |
1210 | + .cache |
1211 | + .get(path) |
1212 | + .cloned() |
1213 | + .unwrap_or((Default::default(), Default::default())); |
1214 | |
1215 | if cache_fp == *file_fp { |
1216 | self.hit_count += 1; |
1217 | @@ -196,11 +204,12 @@ |
1218 | |
1219 | match file_fp.mode & libc::S_IFMT { |
1220 | libc::S_IFREG => { |
1221 | - let filters: Box<dyn ContentFilter> = if let Some(filter_provider) = self.filter_provider.as_ref() { |
1222 | - filter_provider(path, file_fp.ctime as u64) |
1223 | - } else { |
1224 | - Box::new(ContentFilterStack::new()) |
1225 | - }; |
1226 | + let filters: Box<dyn ContentFilter> = |
1227 | + if let Some(filter_provider) = self.filter_provider.as_ref() { |
1228 | + filter_provider(path, file_fp.ctime as u64) |
1229 | + } else { |
1230 | + Box::new(ContentFilterStack::new()) |
1231 | + }; |
1232 | let digest = filters.sha1_file(&abspath)?; |
1233 | |
1234 | // window of 3 seconds to allow for 2s resolution on windows, |
1235 | @@ -226,7 +235,8 @@ |
1236 | } else { |
1237 | self.update_count += 1; |
1238 | self.needs_write = true; |
1239 | - self.cache.insert(path.to_owned(), (digest.clone(), file_fp.clone())); |
1240 | + self.cache |
1241 | + .insert(path.to_owned(), (digest.clone(), file_fp.clone())); |
1242 | } |
1243 | |
1244 | Ok(digest) |
1245 | @@ -234,17 +244,16 @@ |
1246 | libc::S_IFLNK => { |
1247 | let target = fs::read_link(&abspath)?; |
1248 | let digest = sha_string(target.to_string_lossy().as_bytes()); |
1249 | - self.cache.insert(path.to_owned(), (digest.clone(), file_fp.clone())); |
1250 | + self.cache |
1251 | + .insert(path.to_owned(), (digest.clone(), file_fp.clone())); |
1252 | self.update_count += 1; |
1253 | self.needs_write = true; |
1254 | Ok(digest) |
1255 | } |
1256 | - _ => { |
1257 | - Err(io::Error::new( |
1258 | - io::ErrorKind::InvalidData, |
1259 | - format!("unknown file stat mode: {:o}", file_fp.mode), |
1260 | - )) |
1261 | - } |
1262 | + _ => Err(io::Error::new( |
1263 | + io::ErrorKind::InvalidData, |
1264 | + format!("unknown file stat mode: {:o}", file_fp.mode), |
1265 | + )), |
1266 | } |
1267 | } |
1268 | } |
1269 | @@ -296,9 +305,15 @@ |
1270 | } |
1271 | outf.persist(self.cache_file_name())?; |
1272 | self.needs_write = false; |
1273 | - debug!("write hash cache: {} hits={} misses={} stat={} recent={} updates={}", |
1274 | - self.cache_file_name().display(), self.hit_count, self.miss_count, |
1275 | - self.stat_count, self.danger_count, self.update_count); |
1276 | + debug!( |
1277 | + "write hash cache: {} hits={} misses={} stat={} recent={} updates={}", |
1278 | + self.cache_file_name().display(), |
1279 | + self.hit_count, |
1280 | + self.miss_count, |
1281 | + self.stat_count, |
1282 | + self.danger_count, |
1283 | + self.update_count |
1284 | + ); |
1285 | Ok(()) |
1286 | } |
1287 | |
1288 | @@ -312,7 +327,11 @@ |
1289 | self.cache = HashMap::new(); |
1290 | let file = File::open(self.cache_file_name()); |
1291 | if file.is_err() { |
1292 | - debug!("failed to open {}: {}", self.cache_file_name().display(), file.err().unwrap()); |
1293 | + debug!( |
1294 | + "failed to open {}: {}", |
1295 | + self.cache_file_name().display(), |
1296 | + file.err().unwrap() |
1297 | + ); |
1298 | self.needs_write = true; |
1299 | return Ok(()); |
1300 | } |
1301 | @@ -324,14 +343,18 @@ |
1302 | self.needs_write = true; |
1303 | return Err(std::io::Error::new( |
1304 | std::io::ErrorKind::InvalidData, |
1305 | - format!("cache header marker not found at top of {}; discarding cache", self.cache_file_name().display()), |
1306 | + format!( |
1307 | + "cache header marker not found at top of {}; discarding cache", |
1308 | + self.cache_file_name().display() |
1309 | + ), |
1310 | )); |
1311 | } |
1312 | } else { |
1313 | self.needs_write = true; |
1314 | return Err(std::io::Error::new( |
1315 | std::io::ErrorKind::InvalidData, |
1316 | - format!("error reading cache file header", ))); |
1317 | + format!("error reading cache file header",), |
1318 | + )); |
1319 | } |
1320 | for line in lines { |
1321 | let line = line?; |
1322 | |
1323 | === modified file 'crates/osutils-py/src/lib.rs' |
1324 | --- crates/osutils-py/src/lib.rs 2023-04-16 11:47:42 +0000 |
1325 | +++ crates/osutils-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
1326 | @@ -1,21 +1,25 @@ |
1327 | #![allow(non_snake_case)] |
1328 | +use memchr; |
1329 | +use pyo3::create_exception; |
1330 | +use pyo3::exceptions::{PyIOError, PyTypeError, PyValueError}; |
1331 | use pyo3::prelude::*; |
1332 | +use pyo3::types::{PyBytes, PyIterator, PyList}; |
1333 | use pyo3::wrap_pyfunction; |
1334 | -use std::path::{Path,PathBuf}; |
1335 | +use pyo3::PyErr; |
1336 | use pyo3_file::PyFileLikeObject; |
1337 | -use pyo3::types::{PyBytes, PyIterator, PyList}; |
1338 | -use pyo3::exceptions::{PyTypeError,PyValueError,PyIOError}; |
1339 | use std::collections::HashSet; |
1340 | +use std::ffi::OsString; |
1341 | +use std::fs::Permissions; |
1342 | +use std::io::{BufRead, Read}; |
1343 | use std::iter::Iterator; |
1344 | -use std::ffi::OsString; |
1345 | -use std::io::{Read, BufRead}; |
1346 | use std::os::unix::ffi::OsStringExt; |
1347 | -use memchr; |
1348 | -use pyo3::PyErr; |
1349 | -use pyo3::create_exception; |
1350 | -use std::fs::Permissions; |
1351 | +use std::path::{Path, PathBuf}; |
1352 | |
1353 | -create_exception!(breezy_osutils, UnsupportedTimezoneFormat, pyo3::exceptions::PyException); |
1354 | +create_exception!( |
1355 | + breezy_osutils, |
1356 | + UnsupportedTimezoneFormat, |
1357 | + pyo3::exceptions::PyException |
1358 | +); |
1359 | |
1360 | #[pyclass] |
1361 | struct PyChunksToLinesIterator { |
1362 | @@ -27,7 +31,10 @@ |
1363 | impl PyChunksToLinesIterator { |
1364 | #[new] |
1365 | fn new(chunk_iter: PyObject) -> PyResult<Self> { |
1366 | - Ok(PyChunksToLinesIterator { chunk_iter, tail: None }) |
1367 | + Ok(PyChunksToLinesIterator { |
1368 | + chunk_iter, |
1369 | + tail: None, |
1370 | + }) |
1371 | } |
1372 | |
1373 | fn __iter__(slf: PyRef<Self>) -> Py<Self> { |
1374 | @@ -35,56 +42,53 @@ |
1375 | } |
1376 | |
1377 | fn __next__(&mut self) -> PyResult<Option<Py<PyAny>>> { |
1378 | - Python::with_gil(move |py| { |
1379 | - |
1380 | - loop { |
1381 | - if let Some(mut chunk) = self.tail.take() { |
1382 | - if let Some(newline) = memchr::memchr(b'\n', &chunk) { |
1383 | - if newline == chunk.len() - 1 { |
1384 | - assert!(!chunk.is_empty()); |
1385 | - return Ok(Some(PyBytes::new(py, chunk.as_slice()).to_object(py))); |
1386 | - } else { |
1387 | - assert!(!chunk.is_empty()); |
1388 | - self.tail = Some(chunk[newline + 1..].to_vec()); |
1389 | - let bytes = PyBytes::new(py, &chunk[..=newline]); |
1390 | - return Ok(Some(bytes.to_object(py))); |
1391 | - } |
1392 | + Python::with_gil(move |py| loop { |
1393 | + if let Some(mut chunk) = self.tail.take() { |
1394 | + if let Some(newline) = memchr::memchr(b'\n', &chunk) { |
1395 | + if newline == chunk.len() - 1 { |
1396 | + assert!(!chunk.is_empty()); |
1397 | + return Ok(Some(PyBytes::new(py, chunk.as_slice()).to_object(py))); |
1398 | } else { |
1399 | - if let Some(next_chunk) = self.chunk_iter.downcast::<PyIterator>(py)?.next() { |
1400 | - if let Err(e) = next_chunk { |
1401 | - return Err(e); |
1402 | - } |
1403 | - let next_chunk = next_chunk.unwrap(); |
1404 | - let next_chunk = next_chunk.extract::<&[u8]>()?; |
1405 | - chunk.extend_from_slice(next_chunk); |
1406 | - } else { |
1407 | - assert!(!chunk.is_empty()); |
1408 | - return Ok(Some(PyBytes::new(py, &chunk).to_object(py))); |
1409 | - } |
1410 | - if !chunk.is_empty() { |
1411 | - self.tail = Some(chunk); |
1412 | - } |
1413 | + assert!(!chunk.is_empty()); |
1414 | + self.tail = Some(chunk[newline + 1..].to_vec()); |
1415 | + let bytes = PyBytes::new(py, &chunk[..=newline]); |
1416 | + return Ok(Some(bytes.to_object(py))); |
1417 | } |
1418 | } else { |
1419 | if let Some(next_chunk) = self.chunk_iter.downcast::<PyIterator>(py)?.next() { |
1420 | if let Err(e) = next_chunk { |
1421 | return Err(e); |
1422 | } |
1423 | - let next_chunk_py = next_chunk.unwrap(); |
1424 | - let next_chunk = next_chunk_py.extract::<&[u8]>()?; |
1425 | - if let Some(newline) = memchr::memchr(b'\n', &next_chunk) { |
1426 | - if newline == next_chunk.len() - 1 { |
1427 | - let line = next_chunk_py.downcast::<PyBytes>()?; |
1428 | - return Ok(Some(line.to_object(py))); |
1429 | - } |
1430 | - } |
1431 | - |
1432 | - if !next_chunk.is_empty() { |
1433 | - self.tail = Some(next_chunk.to_vec()); |
1434 | - } |
1435 | + let next_chunk = next_chunk.unwrap(); |
1436 | + let next_chunk = next_chunk.extract::<&[u8]>()?; |
1437 | + chunk.extend_from_slice(next_chunk); |
1438 | } else { |
1439 | - return Ok(None); |
1440 | - } |
1441 | + assert!(!chunk.is_empty()); |
1442 | + return Ok(Some(PyBytes::new(py, &chunk).to_object(py))); |
1443 | + } |
1444 | + if !chunk.is_empty() { |
1445 | + self.tail = Some(chunk); |
1446 | + } |
1447 | + } |
1448 | + } else { |
1449 | + if let Some(next_chunk) = self.chunk_iter.downcast::<PyIterator>(py)?.next() { |
1450 | + if let Err(e) = next_chunk { |
1451 | + return Err(e); |
1452 | + } |
1453 | + let next_chunk_py = next_chunk.unwrap(); |
1454 | + let next_chunk = next_chunk_py.extract::<&[u8]>()?; |
1455 | + if let Some(newline) = memchr::memchr(b'\n', &next_chunk) { |
1456 | + if newline == next_chunk.len() - 1 { |
1457 | + let line = next_chunk_py.downcast::<PyBytes>()?; |
1458 | + return Ok(Some(line.to_object(py))); |
1459 | + } |
1460 | + } |
1461 | + |
1462 | + if !next_chunk.is_empty() { |
1463 | + self.tail = Some(next_chunk.to_vec()); |
1464 | + } |
1465 | + } else { |
1466 | + return Ok(None); |
1467 | } |
1468 | } |
1469 | }) |
1470 | @@ -155,7 +159,8 @@ |
1471 | #[pyfunction] |
1472 | fn sha_strings(py: Python, strings: &PyAny) -> PyResult<PyObject> { |
1473 | let iter = strings.iter()?; |
1474 | - let digest = breezy_osutils::sha::sha_chunks(iter.map(|x| x.unwrap().extract::<Vec<u8>>().unwrap())); |
1475 | + let digest = |
1476 | + breezy_osutils::sha::sha_chunks(iter.map(|x| x.unwrap().extract::<Vec<u8>>().unwrap())); |
1477 | Ok(PyBytes::new(py, digest.as_bytes()).into_py(py)) |
1478 | } |
1479 | |
1480 | @@ -192,7 +197,9 @@ |
1481 | #[pyfunction] |
1482 | fn _inaccessible_normalized_filename(filename: &PyAny) -> PyResult<(PathBuf, bool)> { |
1483 | let filename = extract_path(&filename)?; |
1484 | - if let Some(filename) = breezy_osutils::path::inaccessible_normalized_filename(filename.as_path()) { |
1485 | + if let Some(filename) = |
1486 | + breezy_osutils::path::inaccessible_normalized_filename(filename.as_path()) |
1487 | + { |
1488 | Ok(filename) |
1489 | } else { |
1490 | Ok((filename, true)) |
1491 | @@ -201,8 +208,9 @@ |
1492 | |
1493 | #[pyfunction] |
1494 | fn _accessible_normalized_filename(filename: &PyAny) -> PyResult<(PathBuf, bool)> { |
1495 | - let filename= extract_path(&filename)?; |
1496 | - if let Some(filename) = breezy_osutils::path::accessible_normalized_filename(filename.as_path()) { |
1497 | + let filename = extract_path(&filename)?; |
1498 | + if let Some(filename) = breezy_osutils::path::accessible_normalized_filename(filename.as_path()) |
1499 | + { |
1500 | Ok(filename) |
1501 | } else { |
1502 | Ok((filename, false)) |
1503 | @@ -218,7 +226,10 @@ |
1504 | fn is_inside(path: &PyAny, parent: &PyAny) -> PyResult<bool> { |
1505 | let path = extract_path(path)?; |
1506 | let parent = extract_path(parent)?; |
1507 | - Ok(breezy_osutils::path::is_inside(path.as_path(), parent.as_path())) |
1508 | + Ok(breezy_osutils::path::is_inside( |
1509 | + path.as_path(), |
1510 | + parent.as_path(), |
1511 | + )) |
1512 | } |
1513 | |
1514 | #[pyfunction] |
1515 | @@ -228,7 +239,13 @@ |
1516 | for dir in dir_list.iter()? { |
1517 | c_dir_list.push(extract_path(dir?)?); |
1518 | } |
1519 | - Ok(breezy_osutils::path::is_inside_any(&c_dir_list.iter().map(|p| p.as_path()).collect::<Vec<&Path>>(), path.as_path())) |
1520 | + Ok(breezy_osutils::path::is_inside_any( |
1521 | + &c_dir_list |
1522 | + .iter() |
1523 | + .map(|p| p.as_path()) |
1524 | + .collect::<Vec<&Path>>(), |
1525 | + path.as_path(), |
1526 | + )) |
1527 | } |
1528 | |
1529 | #[pyfunction] |
1530 | @@ -238,7 +255,13 @@ |
1531 | for dir in dir_list.iter()? { |
1532 | c_dir_list.push(extract_path(dir?)?); |
1533 | } |
1534 | - Ok(breezy_osutils::path::is_inside_or_parent_of_any(&c_dir_list.iter().map(|p| p.as_path()).collect::<Vec<&Path>>(), path.as_path())) |
1535 | + Ok(breezy_osutils::path::is_inside_or_parent_of_any( |
1536 | + &c_dir_list |
1537 | + .iter() |
1538 | + .map(|p| p.as_path()) |
1539 | + .collect::<Vec<&Path>>(), |
1540 | + path.as_path(), |
1541 | + )) |
1542 | } |
1543 | |
1544 | #[pyfunction] |
1545 | @@ -247,8 +270,16 @@ |
1546 | for path in paths.iter()? { |
1547 | path_set.insert(extract_path(path?)?); |
1548 | } |
1549 | - let paths = breezy_osutils::path::minimum_path_selection(path_set.iter().map(|p| p.as_path()).collect::<HashSet<&Path>>()); |
1550 | - Ok(paths.iter().map(|x| x.to_string_lossy().to_string()).collect()) |
1551 | + let paths = breezy_osutils::path::minimum_path_selection( |
1552 | + path_set |
1553 | + .iter() |
1554 | + .map(|p| p.as_path()) |
1555 | + .collect::<HashSet<&Path>>(), |
1556 | + ); |
1557 | + Ok(paths |
1558 | + .iter() |
1559 | + .map(|x| x.to_string_lossy().to_string()) |
1560 | + .collect()) |
1561 | } |
1562 | |
1563 | #[pyfunction] |
1564 | @@ -282,7 +313,7 @@ |
1565 | fn available_backup_name(py: Python, path: &PyAny, exists: PyObject) -> PyResult<PathBuf> { |
1566 | let path = extract_path(path)?; |
1567 | let exists = |p: &Path| -> PyResult<bool> { |
1568 | - let ret = exists.call1(py, (p, ))?; |
1569 | + let ret = exists.call1(py, (p,))?; |
1570 | ret.extract::<bool>(py) |
1571 | }; |
1572 | |
1573 | @@ -311,7 +342,14 @@ |
1574 | } |
1575 | |
1576 | #[pyfunction] |
1577 | -fn format_local_date(py: Python, t: PyObject, offset: Option<i32>, timezone: Option<&str>, date_format: Option<&str>, show_offset: Option<bool>) -> PyResult<String> { |
1578 | +fn format_local_date( |
1579 | + py: Python, |
1580 | + t: PyObject, |
1581 | + offset: Option<i32>, |
1582 | + timezone: Option<&str>, |
1583 | + date_format: Option<&str>, |
1584 | + show_offset: Option<bool>, |
1585 | +) -> PyResult<String> { |
1586 | let t = if let Ok(t) = t.extract::<f64>(py) { |
1587 | t as i64 |
1588 | } else if let Ok(t) = t.extract::<i64>(py) { |
1589 | @@ -324,7 +362,13 @@ |
1590 | return Err(UnsupportedTimezoneFormat::new_err("Unsupported timezone")); |
1591 | } |
1592 | let timezone = timezone.unwrap(); |
1593 | - Ok(breezy_osutils::time::format_local_date(t, offset, timezone, date_format, show_offset.unwrap_or(true))) |
1594 | + Ok(breezy_osutils::time::format_local_date( |
1595 | + t, |
1596 | + offset, |
1597 | + timezone, |
1598 | + date_format, |
1599 | + show_offset.unwrap_or(true), |
1600 | + )) |
1601 | } |
1602 | |
1603 | #[pyfunction] |
1604 | @@ -334,18 +378,25 @@ |
1605 | |
1606 | #[pyclass] |
1607 | struct PyIterableFile { |
1608 | - inner: breezy_osutils::iterablefile::IterableFile<Box<dyn Iterator<Item=std::io::Result<Vec<u8>>> + Send>>, |
1609 | + inner: breezy_osutils::iterablefile::IterableFile< |
1610 | + Box<dyn Iterator<Item = std::io::Result<Vec<u8>>> + Send>, |
1611 | + >, |
1612 | closed: bool, |
1613 | } |
1614 | |
1615 | #[pymethods] |
1616 | impl PyIterableFile { |
1617 | - |
1618 | fn __enter__(slf: PyRef<Self>) -> Py<Self> { |
1619 | slf.into() |
1620 | } |
1621 | |
1622 | - fn __exit__(&mut self, _py: Python, _exc_type: &PyAny, _exc_value: &PyAny, _traceback: &PyAny) -> PyResult<bool> { |
1623 | + fn __exit__( |
1624 | + &mut self, |
1625 | + _py: Python, |
1626 | + _exc_type: &PyAny, |
1627 | + _exc_value: &PyAny, |
1628 | + _traceback: &PyAny, |
1629 | + ) -> PyResult<bool> { |
1630 | self.check_closed(_py)?; |
1631 | Ok(false) |
1632 | } |
1633 | @@ -368,7 +419,9 @@ |
1634 | } else { |
1635 | self.inner.read_to_end(&mut buf) |
1636 | }; |
1637 | - if PyErr::occurred(py) { return Err(PyErr::fetch(py)); } |
1638 | + if PyErr::occurred(py) { |
1639 | + return Err(PyErr::fetch(py)); |
1640 | + } |
1641 | buf.truncate(read?); |
1642 | Ok(PyBytes::new(py, &buf).to_object(py)) |
1643 | } |
1644 | @@ -399,7 +452,9 @@ |
1645 | self.check_closed(py)?; |
1646 | let mut buf = Vec::new(); |
1647 | let read = self.inner.read_until(b'\n', &mut buf); |
1648 | - if PyErr::occurred(py) { return Err(PyErr::fetch(py)); } |
1649 | + if PyErr::occurred(py) { |
1650 | + return Err(PyErr::fetch(py)); |
1651 | + } |
1652 | let read = read?; |
1653 | if read == 0 { |
1654 | return Ok(None); |
1655 | @@ -413,27 +468,43 @@ |
1656 | fn IterableFile(py_iterable: PyObject) -> PyResult<PyObject> { |
1657 | Python::with_gil(|py| { |
1658 | let py_iter = py_iterable.call_method0(py, "__iter__")?; |
1659 | - let line_iter: Box<dyn Iterator<Item = std::io::Result<Vec<u8>>> + Send> = Box::new(std::iter::from_fn(move || -> Option<std::io::Result<Vec<u8>>> { |
1660 | - Python::with_gil(|py| { |
1661 | - match py_iter.downcast::<PyIterator>(py).unwrap().next() { |
1662 | - None => None, |
1663 | - Some(Err(err)) => { |
1664 | - PyErr::restore(err.clone_ref(py), py); |
1665 | - Some(Err(std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))) |
1666 | + let line_iter: Box<dyn Iterator<Item = std::io::Result<Vec<u8>>> + Send> = Box::new( |
1667 | + std::iter::from_fn(move || -> Option<std::io::Result<Vec<u8>>> { |
1668 | + Python::with_gil( |
1669 | + |py| match py_iter.downcast::<PyIterator>(py).unwrap().next() { |
1670 | + None => None, |
1671 | + Some(Err(err)) => { |
1672 | + PyErr::restore(err.clone_ref(py), py); |
1673 | + Some(Err(std::io::Error::new( |
1674 | + std::io::ErrorKind::Other, |
1675 | + err.to_string(), |
1676 | + ))) |
1677 | + } |
1678 | + Some(Ok(obj)) => match obj.downcast::<PyBytes>() { |
1679 | + Err(err) => { |
1680 | + PyErr::restore( |
1681 | + PyTypeError::new_err("unable to convert to bytes"), |
1682 | + py, |
1683 | + ); |
1684 | + Some(Err(std::io::Error::new( |
1685 | + std::io::ErrorKind::Other, |
1686 | + err.to_string(), |
1687 | + ))) |
1688 | + } |
1689 | + Ok(bytes) => Some(Ok(bytes.as_bytes().to_vec().into())), |
1690 | + }, |
1691 | }, |
1692 | - Some(Ok(obj)) => { |
1693 | - match obj.downcast::<PyBytes>() { |
1694 | - Err(err) => { PyErr::restore(PyTypeError::new_err("unable to convert to bytes"), py); Some(Err(std::io::Error::new(std::io::ErrorKind::Other, err.to_string()))) }, |
1695 | - Ok(bytes) => Some(Ok(bytes.as_bytes().to_vec().into())), |
1696 | - } |
1697 | - } |
1698 | - } |
1699 | - }) |
1700 | - })); |
1701 | + ) |
1702 | + }), |
1703 | + ); |
1704 | |
1705 | let f = breezy_osutils::iterablefile::IterableFile::new(line_iter); |
1706 | |
1707 | - Ok(PyIterableFile { inner: f, closed: false }.into_py(py)) |
1708 | + Ok(PyIterableFile { |
1709 | + inner: f, |
1710 | + closed: false, |
1711 | + } |
1712 | + .into_py(py)) |
1713 | }) |
1714 | } |
1715 | |
1716 | @@ -450,7 +521,10 @@ |
1717 | let line = py_iter.next(); |
1718 | match line { |
1719 | Some(Ok(line)) => Some(line.extract::<Vec<u8>>().unwrap()), |
1720 | - Some(Err(err)) => { PyErr::restore(err, py); None } |
1721 | + Some(Err(err)) => { |
1722 | + PyErr::restore(err, py); |
1723 | + None |
1724 | + } |
1725 | None => None, |
1726 | } |
1727 | }); |
1728 | @@ -475,7 +549,11 @@ |
1729 | } |
1730 | |
1731 | #[pyfunction] |
1732 | -fn format_date_with_offset_in_original_timezone(py: Python, date: PyObject, offset: Option<PyObject>) -> PyResult<String> { |
1733 | +fn format_date_with_offset_in_original_timezone( |
1734 | + py: Python, |
1735 | + date: PyObject, |
1736 | + offset: Option<PyObject>, |
1737 | +) -> PyResult<String> { |
1738 | let date = if let Ok(date) = date.extract::<f64>(py) { |
1739 | date as i64 |
1740 | } else if let Ok(date) = date.extract::<i64>(py) { |
1741 | @@ -498,7 +576,14 @@ |
1742 | } |
1743 | |
1744 | #[pyfunction] |
1745 | -fn format_date(py: Python, t: PyObject, offset: Option<PyObject>, timezone: Option<&str>, date_fmt: Option<&str>, show_offset: Option<bool>) -> PyResult<String> { |
1746 | +fn format_date( |
1747 | + py: Python, |
1748 | + t: PyObject, |
1749 | + offset: Option<PyObject>, |
1750 | + timezone: Option<&str>, |
1751 | + date_fmt: Option<&str>, |
1752 | + show_offset: Option<bool>, |
1753 | +) -> PyResult<String> { |
1754 | let t = if let Ok(t) = t.extract::<f64>(py) { |
1755 | t as i64 |
1756 | } else if let Ok(t) = t.extract::<i64>(py) { |
1757 | @@ -522,7 +607,13 @@ |
1758 | None |
1759 | }; |
1760 | let timezone = timezone.unwrap(); |
1761 | - Ok(breezy_osutils::time::format_date(t, offset, timezone, date_fmt, show_offset.unwrap_or(true))) |
1762 | + Ok(breezy_osutils::time::format_date( |
1763 | + t, |
1764 | + offset, |
1765 | + timezone, |
1766 | + date_fmt, |
1767 | + show_offset.unwrap_or(true), |
1768 | + )) |
1769 | } |
1770 | |
1771 | #[pyfunction] |
1772 | @@ -550,7 +641,8 @@ |
1773 | |
1774 | #[pyfunction] |
1775 | fn unpack_highres_date(date: &str) -> PyResult<(f64, i32)> { |
1776 | - breezy_osutils::time::unpack_highres_date(date).map_err(|e| PyValueError::new_err(e.to_string())) |
1777 | + breezy_osutils::time::unpack_highres_date(date) |
1778 | + .map_err(|e| PyValueError::new_err(e.to_string())) |
1779 | } |
1780 | |
1781 | #[pyfunction] |
1782 | @@ -589,7 +681,10 @@ |
1783 | #[pyfunction] |
1784 | fn chmod_if_possible(path: PathBuf, mode: u32) -> PyResult<()> { |
1785 | use std::os::unix::fs::PermissionsExt; |
1786 | - Ok(breezy_osutils::file::chmod_if_possible(path, Permissions::from_mode(mode))?) |
1787 | + Ok(breezy_osutils::file::chmod_if_possible( |
1788 | + path, |
1789 | + Permissions::from_mode(mode), |
1790 | + )?) |
1791 | } |
1792 | |
1793 | #[pyfunction] |
1794 | @@ -626,7 +721,9 @@ |
1795 | m.add_wrapped(wrap_pyfunction!(check_text_path))?; |
1796 | m.add_wrapped(wrap_pyfunction!(check_text_lines))?; |
1797 | m.add_wrapped(wrap_pyfunction!(format_delta))?; |
1798 | - m.add_wrapped(wrap_pyfunction!(format_date_with_offset_in_original_timezone))?; |
1799 | + m.add_wrapped(wrap_pyfunction!( |
1800 | + format_date_with_offset_in_original_timezone |
1801 | + ))?; |
1802 | m.add_wrapped(wrap_pyfunction!(format_date))?; |
1803 | m.add_wrapped(wrap_pyfunction!(format_highres_date))?; |
1804 | m.add_wrapped(wrap_pyfunction!(unpack_highres_date))?; |
1805 | @@ -639,6 +736,9 @@ |
1806 | m.add_wrapped(wrap_pyfunction!(quotefn))?; |
1807 | #[cfg(unix)] |
1808 | m.add_wrapped(wrap_pyfunction!(get_umask))?; |
1809 | - m.add("UnsupportedTimezoneFormat", py.get_type::<UnsupportedTimezoneFormat>())?; |
1810 | + m.add( |
1811 | + "UnsupportedTimezoneFormat", |
1812 | + py.get_type::<UnsupportedTimezoneFormat>(), |
1813 | + )?; |
1814 | Ok(()) |
1815 | } |
1816 | |
1817 | === modified file 'crates/osutils/src/file.rs' |
1818 | --- crates/osutils/src/file.rs 2023-04-16 11:47:42 +0000 |
1819 | +++ crates/osutils/src/file.rs 2023-04-17 11:56:43 +0000 |
1820 | @@ -1,8 +1,8 @@ |
1821 | -use std::path::Path; |
1822 | +use log::debug; |
1823 | +use std::fs::{set_permissions, Permissions}; |
1824 | use std::io::Result; |
1825 | -use std::fs::{Permissions, set_permissions}; |
1826 | use std::os::unix::fs::PermissionsExt; |
1827 | -use log::debug; |
1828 | +use std::path::Path; |
1829 | |
1830 | pub fn make_writable<P: AsRef<Path>>(path: P) -> Result<()> { |
1831 | let path = path.as_ref(); |
1832 | @@ -39,7 +39,7 @@ |
1833 | debug!("ignore error on chmod of {:?}: {:?}", path.as_ref(), e); |
1834 | Ok(()) |
1835 | } |
1836 | - _ => Err(e) |
1837 | + _ => Err(e), |
1838 | } |
1839 | } else { |
1840 | Ok(()) |
1841 | |
1842 | === modified file 'crates/osutils/src/iterablefile.rs' |
1843 | --- crates/osutils/src/iterablefile.rs 2023-04-13 16:25:22 +0000 |
1844 | +++ crates/osutils/src/iterablefile.rs 2023-04-17 11:56:43 +0000 |
1845 | @@ -1,4 +1,4 @@ |
1846 | -use std::io::{self, Read, Seek, SeekFrom, BufRead}; |
1847 | +use std::io::{self, BufRead, Read, Seek, SeekFrom}; |
1848 | |
1849 | pub struct IterableFile<I: Iterator<Item = io::Result<Vec<u8>>> + Send> { |
1850 | iter: I, |
1851 | @@ -85,7 +85,12 @@ |
1852 | |
1853 | #[test] |
1854 | fn test_read_all() { |
1855 | - let content: Vec<Vec<u8>> = vec![b"This ".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.".to_vec()]; |
1856 | + let content: Vec<Vec<u8>> = vec![ |
1857 | + b"This ".to_vec(), |
1858 | + b"is ".to_vec(), |
1859 | + b"a ".to_vec(), |
1860 | + b"test.".to_vec(), |
1861 | + ]; |
1862 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1863 | let mut buf = Vec::new(); |
1864 | let read = file.read_to_end(&mut buf).unwrap(); |
1865 | @@ -95,7 +100,12 @@ |
1866 | |
1867 | #[test] |
1868 | fn test_read_n() { |
1869 | - let content: Vec<Vec<u8>> = vec![b"This ".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.".to_vec()]; |
1870 | + let content: Vec<Vec<u8>> = vec![ |
1871 | + b"This ".to_vec(), |
1872 | + b"is ".to_vec(), |
1873 | + b"a ".to_vec(), |
1874 | + b"test.".to_vec(), |
1875 | + ]; |
1876 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1877 | let mut buf = [0u8; 8]; |
1878 | file.read_exact(&mut buf).unwrap(); |
1879 | @@ -104,7 +114,12 @@ |
1880 | |
1881 | #[test] |
1882 | fn test_read_to() { |
1883 | - let content: Vec<Vec<u8>> = vec![b"This\n".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.\n".to_vec()]; |
1884 | + let content: Vec<Vec<u8>> = vec![ |
1885 | + b"This\n".to_vec(), |
1886 | + b"is ".to_vec(), |
1887 | + b"a ".to_vec(), |
1888 | + b"test.\n".to_vec(), |
1889 | + ]; |
1890 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1891 | let mut buf = Vec::new(); |
1892 | file.read_until(b'\n', &mut buf).unwrap(); |
1893 | @@ -117,7 +132,13 @@ |
1894 | |
1895 | #[test] |
1896 | fn test_readline() { |
1897 | - let content: Vec<Vec<u8>> = vec![b"".to_vec(), b"This\n".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.\n".to_vec()]; |
1898 | + let content: Vec<Vec<u8>> = vec![ |
1899 | + b"".to_vec(), |
1900 | + b"This\n".to_vec(), |
1901 | + b"is ".to_vec(), |
1902 | + b"a ".to_vec(), |
1903 | + b"test.\n".to_vec(), |
1904 | + ]; |
1905 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1906 | let mut buf = String::new(); |
1907 | let read = file.read_line(&mut buf).unwrap(); |
1908 | @@ -127,7 +148,13 @@ |
1909 | |
1910 | #[test] |
1911 | fn test_readlines() { |
1912 | - let content: Vec<Vec<u8>> = vec![b"This\n".to_vec(), b"is ".to_vec(), b"".to_vec(), b"a ".to_vec(), b"test.\n".to_vec()]; |
1913 | + let content: Vec<Vec<u8>> = vec![ |
1914 | + b"This\n".to_vec(), |
1915 | + b"is ".to_vec(), |
1916 | + b"".to_vec(), |
1917 | + b"a ".to_vec(), |
1918 | + b"test.\n".to_vec(), |
1919 | + ]; |
1920 | let file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1921 | let lines: Vec<String> = file.lines().map(|line| line.unwrap()).collect(); |
1922 | assert_eq!(lines, vec!["This", "is a test."]); |
1923 | @@ -135,7 +162,13 @@ |
1924 | |
1925 | #[test] |
1926 | fn test_fillbuf() { |
1927 | - let content: Vec<Vec<u8>> = vec![b"This ".to_vec(), b"".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.".to_vec()]; |
1928 | + let content: Vec<Vec<u8>> = vec![ |
1929 | + b"This ".to_vec(), |
1930 | + b"".to_vec(), |
1931 | + b"is ".to_vec(), |
1932 | + b"a ".to_vec(), |
1933 | + b"test.".to_vec(), |
1934 | + ]; |
1935 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1936 | assert_eq!(file.fill_buf().unwrap(), b"This "); |
1937 | file.consume(5); |
1938 | @@ -150,7 +183,12 @@ |
1939 | |
1940 | #[test] |
1941 | fn test_drain() { |
1942 | - let content: Vec<Vec<u8>> = vec![b"This ".to_vec(), b"is ".to_vec(), b"a ".to_vec(), b"test.".to_vec()]; |
1943 | + let content: Vec<Vec<u8>> = vec![ |
1944 | + b"This ".to_vec(), |
1945 | + b"is ".to_vec(), |
1946 | + b"a ".to_vec(), |
1947 | + b"test.".to_vec(), |
1948 | + ]; |
1949 | let mut file = IterableFile::new(content.iter().map(|x| Ok(x.to_vec()))); |
1950 | let buf = file.fill_buf().unwrap(); |
1951 | assert_eq!(buf, b"This "); |
1952 | |
1953 | === modified file 'crates/osutils/src/lib.rs' |
1954 | --- crates/osutils/src/lib.rs 2023-04-16 11:47:42 +0000 |
1955 | +++ crates/osutils/src/lib.rs 2023-04-17 11:56:43 +0000 |
1956 | @@ -1,11 +1,12 @@ |
1957 | +#[cfg(unix)] |
1958 | +use libc; |
1959 | use memchr::memchr; |
1960 | use rand::Rng; |
1961 | -#[cfg(unix)] |
1962 | -use libc; |
1963 | |
1964 | pub fn chunks_to_lines<'a, I, E>(mut chunks: I) -> impl Iterator<Item = Result<Vec<u8>, E>> |
1965 | where |
1966 | - I: Iterator<Item = Result<&'a [u8], E>> + 'a, E: std::fmt::Debug |
1967 | + I: Iterator<Item = Result<&'a [u8], E>> + 'a, |
1968 | + E: std::fmt::Debug, |
1969 | { |
1970 | let mut tail: Option<Vec<u8>> = None; |
1971 | |
1972 | @@ -58,7 +59,10 @@ |
1973 | }) |
1974 | } |
1975 | |
1976 | -pub fn set_or_unset_env(env_variable: &str, value: Option<&str>) -> Result<Option<String>, std::env::VarError> { |
1977 | +pub fn set_or_unset_env( |
1978 | + env_variable: &str, |
1979 | + value: Option<&str>, |
1980 | +) -> Result<Option<String>, std::env::VarError> { |
1981 | let orig_val = std::env::var(env_variable); |
1982 | let ret: Option<String>; |
1983 | if let Err(std::env::VarError::NotPresent) = orig_val { |
1984 | @@ -73,7 +77,7 @@ |
1985 | ret = Some(orig_val.unwrap()); |
1986 | match value { |
1987 | None => std::env::remove_var(env_variable), |
1988 | - Some(val) => std::env::set_var(env_variable, val) |
1989 | + Some(val) => std::env::set_var(env_variable, val), |
1990 | } |
1991 | } |
1992 | Ok(ret) |
1993 | @@ -113,12 +117,12 @@ |
1994 | } |
1995 | } |
1996 | |
1997 | +pub mod file; |
1998 | +pub mod iterablefile; |
1999 | +pub mod path; |
2000 | pub mod sha; |
2001 | -pub mod path; |
2002 | +pub mod textfile; |
2003 | pub mod time; |
2004 | -pub mod iterablefile; |
2005 | -pub mod textfile; |
2006 | -pub mod file; |
2007 | |
2008 | #[cfg(test)] |
2009 | mod tests; |
2010 | |
2011 | === modified file 'crates/osutils/src/path.rs' |
2012 | --- crates/osutils/src/path.rs 2023-04-16 11:47:42 +0000 |
2013 | +++ crates/osutils/src/path.rs 2023-04-17 11:56:43 +0000 |
2014 | @@ -1,9 +1,9 @@ |
2015 | -use std::path::{Path,PathBuf}; |
2016 | +use lazy_static::lazy_static; |
2017 | +use regex::Regex; |
2018 | use std::collections::HashSet; |
2019 | use std::os::unix::fs::PermissionsExt; |
2020 | -use unicode_normalization::{UnicodeNormalization,is_nfc}; |
2021 | -use regex::Regex; |
2022 | -use lazy_static::lazy_static; |
2023 | +use std::path::{Path, PathBuf}; |
2024 | +use unicode_normalization::{is_nfc, UnicodeNormalization}; |
2025 | |
2026 | pub fn is_inside(dir: &Path, fname: &Path) -> bool { |
2027 | fname.starts_with(&dir) |
2028 | @@ -51,14 +51,33 @@ |
2029 | use winreg::enums::{HKEY_LOCAL_MACHINE, KEY_QUERY_VALUE}; |
2030 | use winreg::RegKey; |
2031 | let exts = env::var("PATHEXT").unwrap_or_default(); |
2032 | - let exts = exts.split(';').map(|ext| ext.to_lowercase()).collect::<Vec<_>>(); |
2033 | + let exts = exts |
2034 | + .split(';') |
2035 | + .map(|ext| ext.to_lowercase()) |
2036 | + .collect::<Vec<_>>(); |
2037 | let (name, exts) = { |
2038 | let mut path = PathBuf::from(name); |
2039 | - let ext = path.extension().and_then(|ext| ext.to_str()).unwrap_or_default().to_lowercase(); |
2040 | + let ext = path |
2041 | + .extension() |
2042 | + .and_then(|ext| ext.to_str()) |
2043 | + .unwrap_or_default() |
2044 | + .to_lowercase(); |
2045 | if !exts.is_empty() && !exts.contains(&ext) { |
2046 | - (path.file_stem().unwrap_or_default().to_str().unwrap_or_default(), vec![ext]) |
2047 | + ( |
2048 | + path.file_stem() |
2049 | + .unwrap_or_default() |
2050 | + .to_str() |
2051 | + .unwrap_or_default(), |
2052 | + vec![ext], |
2053 | + ) |
2054 | } else { |
2055 | - (path.file_stem().unwrap_or_default().to_str().unwrap_or_default(), exts) |
2056 | + ( |
2057 | + path.file_stem() |
2058 | + .unwrap_or_default() |
2059 | + .to_str() |
2060 | + .unwrap_or_default(), |
2061 | + exts, |
2062 | + ) |
2063 | } |
2064 | }; |
2065 | let paths = env::var("PATH").unwrap_or_default(); |
2066 | @@ -71,7 +90,9 @@ |
2067 | } |
2068 | } |
2069 | } |
2070 | - if let Ok(reg_key) = RegKey::predef(HKEY_LOCAL_MACHINE).open_subkey(r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths") { |
2071 | + if let Ok(reg_key) = RegKey::predef(HKEY_LOCAL_MACHINE) |
2072 | + .open_subkey(r"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths") |
2073 | + { |
2074 | if let Ok(value) = reg_key.get_value(name) { |
2075 | if let Some(value) = value.as_string() { |
2076 | return Some(value); |
2077 | @@ -97,7 +118,10 @@ |
2078 | }) |
2079 | } |
2080 | |
2081 | -pub fn available_backup_name<'a, E>(path: &Path, exists: &'a dyn Fn(&Path) -> Result<bool, E>) -> Result<PathBuf, E> { |
2082 | +pub fn available_backup_name<'a, E>( |
2083 | + path: &Path, |
2084 | + exists: &'a dyn Fn(&Path) -> Result<bool, E>, |
2085 | +) -> Result<PathBuf, E> { |
2086 | let mut counter = 0; |
2087 | let mut next = || { |
2088 | counter += 1; |
2089 | |
2090 | === modified file 'crates/osutils/src/sha.rs' |
2091 | --- crates/osutils/src/sha.rs 2023-04-10 19:43:24 +0000 |
2092 | +++ crates/osutils/src/sha.rs 2023-04-17 11:56:43 +0000 |
2093 | @@ -1,7 +1,7 @@ |
2094 | +use sha1::{Digest, Sha1}; |
2095 | use std::fs::File; |
2096 | use std::io::Read; |
2097 | use std::path::Path; |
2098 | -use sha1::{Digest, Sha1}; |
2099 | |
2100 | pub fn sha_file(f: &mut dyn Read) -> Result<String, std::io::Error> { |
2101 | let mut s = Sha1::new(); |
2102 | |
2103 | === modified file 'crates/osutils/src/tests.rs' |
2104 | --- crates/osutils/src/tests.rs 2023-04-12 22:24:34 +0000 |
2105 | +++ crates/osutils/src/tests.rs 2023-04-17 11:56:43 +0000 |
2106 | @@ -5,7 +5,10 @@ |
2107 | fn assert_chunks_to_lines(input: Vec<&str>, expected: Vec<&str>) { |
2108 | let iter = input.iter().map(|l| Ok::<&[u8], String>(l.as_bytes())); |
2109 | let got = chunks_to_lines(iter); |
2110 | - let got = got.map(|l| String::from_utf8(l.unwrap())).collect::<Result<Vec<_>, _>>().unwrap(); |
2111 | + let got = got |
2112 | + .map(|l| String::from_utf8(l.unwrap())) |
2113 | + .collect::<Result<Vec<_>, _>>() |
2114 | + .unwrap(); |
2115 | assert_eq!(got, expected); |
2116 | } |
2117 | |
2118 | |
2119 | === modified file 'crates/osutils/src/textfile.rs' |
2120 | --- crates/osutils/src/textfile.rs 2023-04-13 19:24:39 +0000 |
2121 | +++ crates/osutils/src/textfile.rs 2023-04-17 11:56:43 +0000 |
2122 | @@ -1,5 +1,5 @@ |
2123 | use std::fs::File; |
2124 | -use std::io::{Read,Error}; |
2125 | +use std::io::{Error, Read}; |
2126 | use std::path::Path; |
2127 | |
2128 | /// Return false if the supplied lines contain NULs. |
2129 | |
2130 | === modified file 'crates/osutils/src/time.rs' |
2131 | --- crates/osutils/src/time.rs 2023-04-16 11:47:42 +0000 |
2132 | +++ crates/osutils/src/time.rs 2023-04-17 11:56:43 +0000 |
2133 | @@ -1,5 +1,5 @@ |
2134 | +use chrono::{DateTime, FixedOffset, Local, NaiveDateTime, TimeZone, Utc}; |
2135 | use std::time::UNIX_EPOCH; |
2136 | -use chrono::{DateTime, NaiveDateTime, Local, TimeZone, Utc, FixedOffset, Datelike, Timelike}; |
2137 | |
2138 | const DEFAULT_DATE_FORMAT: &str = "%a %Y-%m-%d %H:%M:%S"; |
2139 | |
2140 | @@ -115,18 +115,33 @@ |
2141 | let offset_hours = offset / 3600; |
2142 | let offset_minutes = (offset % 3600) / 60; |
2143 | |
2144 | - let dt = DateTime::<Utc>::from(UNIX_EPOCH + std::time::Duration::from_secs(t as u64) + std::time::Duration::from_secs(offset as u64)); |
2145 | + let dt = DateTime::<Utc>::from( |
2146 | + UNIX_EPOCH |
2147 | + + std::time::Duration::from_secs(t as u64) |
2148 | + + std::time::Duration::from_secs(offset as u64), |
2149 | + ); |
2150 | let date_str = dt.format(DEFAULT_DATE_FORMAT).to_string(); |
2151 | let offset_str = format!(" {:+03}{:02}", offset_hours, offset_minutes); |
2152 | |
2153 | date_str + &offset_str |
2154 | } |
2155 | |
2156 | -pub fn format_date(t: i64, offset: Option<i64>, timezone: Timezone, date_fmt: Option<&str>, show_offset: bool) -> String { |
2157 | +pub fn format_date( |
2158 | + t: i64, |
2159 | + offset: Option<i64>, |
2160 | + timezone: Timezone, |
2161 | + date_fmt: Option<&str>, |
2162 | + show_offset: bool, |
2163 | +) -> String { |
2164 | let (dt, offset_str) = match timezone { |
2165 | Timezone::Utc => ( |
2166 | DateTime::from_utc(NaiveDateTime::from_timestamp(t, 0), Utc), |
2167 | - if show_offset { " +0000".to_owned() } else { "".to_owned() }), |
2168 | + if show_offset { |
2169 | + " +0000".to_owned() |
2170 | + } else { |
2171 | + "".to_owned() |
2172 | + }, |
2173 | + ), |
2174 | Timezone::Original => { |
2175 | let offset = offset.unwrap_or(0); |
2176 | let offset_str = if show_offset { |
2177 | @@ -137,8 +152,11 @@ |
2178 | } else { |
2179 | "".to_owned() |
2180 | }; |
2181 | - (DateTime::from_utc(NaiveDateTime::from_timestamp(t + offset, 0), Utc), offset_str) |
2182 | - }, |
2183 | + ( |
2184 | + DateTime::from_utc(NaiveDateTime::from_timestamp(t + offset, 0), Utc), |
2185 | + offset_str, |
2186 | + ) |
2187 | + } |
2188 | Timezone::Local => { |
2189 | let local = Local.timestamp(t, 0); |
2190 | let offset = local.offset().local_minus_utc(); |
2191 | @@ -151,9 +169,11 @@ |
2192 | "".to_owned() |
2193 | }; |
2194 | (local.with_timezone(&Utc), offset_str) |
2195 | - }, |
2196 | + } |
2197 | }; |
2198 | - dt.format(date_fmt.unwrap_or(DEFAULT_DATE_FORMAT)).to_string() + &offset_str |
2199 | + dt.format(date_fmt.unwrap_or(DEFAULT_DATE_FORMAT)) |
2200 | + .to_string() |
2201 | + + &offset_str |
2202 | } |
2203 | |
2204 | pub fn format_highres_date(t: f64, offset: Option<i32>) -> String { |
2205 | @@ -161,7 +181,12 @@ |
2206 | let datetime = Utc.timestamp_opt(t as i64 + offset as i64, 0).unwrap(); |
2207 | let highres_seconds = format!("{:.9}", t - t.floor())[1..].to_string(); |
2208 | let offset_str = format!(" {:+03}{:02}", offset / 3600, (offset / 60) % 60); |
2209 | - format!("{}{}{}", datetime.format(DEFAULT_DATE_FORMAT), highres_seconds, offset_str) |
2210 | + format!( |
2211 | + "{}{}{}", |
2212 | + datetime.format(DEFAULT_DATE_FORMAT), |
2213 | + highres_seconds, |
2214 | + offset_str |
2215 | + ) |
2216 | } |
2217 | |
2218 | const WEEKDAYS: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; |
2219 | @@ -169,15 +194,24 @@ |
2220 | pub fn unpack_highres_date(date: &str) -> Result<(f64, i32), String> { |
2221 | let space_loc = date.find(' '); |
2222 | if space_loc.is_none() { |
2223 | - return Err(format!("date string does not contain a day of week: {}", date)); |
2224 | + return Err(format!( |
2225 | + "date string does not contain a day of week: {}", |
2226 | + date |
2227 | + )); |
2228 | } |
2229 | let weekday = &date[..space_loc.unwrap()]; |
2230 | if WEEKDAYS.iter().find(|&&d| d == weekday).is_none() { |
2231 | - return Err(format!("date string does not contain a valid day of week: {}", date)); |
2232 | + return Err(format!( |
2233 | + "date string does not contain a valid day of week: {}", |
2234 | + date |
2235 | + )); |
2236 | } |
2237 | let dot_loc = date.find('.'); |
2238 | if dot_loc.is_none() { |
2239 | - return Err(format!("Date string does not contain high-precision seconds: {}", date)); |
2240 | + return Err(format!( |
2241 | + "Date string does not contain high-precision seconds: {}", |
2242 | + date |
2243 | + )); |
2244 | } |
2245 | let base_time_str = &date[space_loc.unwrap() + 1..dot_loc.unwrap()]; |
2246 | let offset_loc = date[dot_loc.unwrap()..].find(' '); |
2247 | @@ -187,13 +221,19 @@ |
2248 | let fract_seconds_str = &date[dot_loc.unwrap()..dot_loc.unwrap() + offset_loc.unwrap()]; |
2249 | let offset_str = &date[dot_loc.unwrap() + 1 + offset_loc.unwrap()..]; |
2250 | |
2251 | - let base_time = Utc.datetime_from_str(base_time_str, "%Y-%m-%d %H:%M:%S") |
2252 | + let base_time = Utc |
2253 | + .datetime_from_str(base_time_str, "%Y-%m-%d %H:%M:%S") |
2254 | .map_err(|e| format!("Failed to parse datetime string ({}): {}", base_time_str, e))?; |
2255 | |
2256 | - let fract_seconds = fract_seconds_str.parse::<f64>() |
2257 | - .map_err(|e| format!("Failed to parse high-precision seconds({}) : {}", fract_seconds_str, e))?; |
2258 | + let fract_seconds = fract_seconds_str.parse::<f64>().map_err(|e| { |
2259 | + format!( |
2260 | + "Failed to parse high-precision seconds({}) : {}", |
2261 | + fract_seconds_str, e |
2262 | + ) |
2263 | + })?; |
2264 | |
2265 | - let offset = offset_str.parse::<i32>() |
2266 | + let offset = offset_str |
2267 | + .parse::<i32>() |
2268 | .map_err(|e| format!("Failed to parse offset ({}): {}", offset_str, e))?; |
2269 | |
2270 | let offset_hours = offset / 100; |
2271 | |
2272 | === modified file 'crates/patch-py/src/lib.rs' |
2273 | --- crates/patch-py/src/lib.rs 2023-04-16 01:30:53 +0000 |
2274 | +++ crates/patch-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
2275 | @@ -1,53 +1,91 @@ |
2276 | +use pyo3::create_exception; |
2277 | +use pyo3::exceptions::PyValueError; |
2278 | +use pyo3::import_exception; |
2279 | use pyo3::prelude::*; |
2280 | +use pyo3::types::{PyBytes, PyIterator, PyList}; |
2281 | use pyo3::wrap_pyfunction; |
2282 | -use pyo3::types::{PyBytes, PyList, PyIterator}; |
2283 | -use pyo3::exceptions::PyValueError; |
2284 | -use pyo3::create_exception; |
2285 | -use pyo3::import_exception; |
2286 | use pyo3_file::PyFileLikeObject; |
2287 | -use std::path::PathBuf; |
2288 | +use std::ffi::OsString; |
2289 | use std::io::Write; |
2290 | -use std::ffi::OsString; |
2291 | use std::os::unix::ffi::OsStringExt; |
2292 | +use std::path::PathBuf; |
2293 | |
2294 | create_exception!(_patch_rs, PatchInvokeError, pyo3::exceptions::PyException); |
2295 | create_exception!(_patch_rs, PatchFailed, pyo3::exceptions::PyException); |
2296 | create_exception!(_patch_rs, BinaryFiles, pyo3::exceptions::PyException); |
2297 | create_exception!(_patch_rs, PatchSyntax, pyo3::exceptions::PyException); |
2298 | -create_exception!(_patch_rs, MalformedPatchHeader, pyo3::exceptions::PyException); |
2299 | +create_exception!( |
2300 | + _patch_rs, |
2301 | + MalformedPatchHeader, |
2302 | + pyo3::exceptions::PyException |
2303 | +); |
2304 | import_exception!(breezy.errors, BinaryFile); |
2305 | |
2306 | #[pyfunction] |
2307 | -fn patch(patch_contents: Vec<Vec<u8>>, filename: PathBuf, output_filename: Option<PathBuf>, reverse: Option<bool>) -> PyResult<i32> { |
2308 | +fn patch( |
2309 | + patch_contents: Vec<Vec<u8>>, |
2310 | + filename: PathBuf, |
2311 | + output_filename: Option<PathBuf>, |
2312 | + reverse: Option<bool>, |
2313 | +) -> PyResult<i32> { |
2314 | let output_path = output_filename.as_ref().map(|x| x.as_path()); |
2315 | - breezy_patch::invoke::patch(patch_contents.iter().map(|x| x.as_slice()), filename.as_path(), output_path, reverse.unwrap_or(false)) |
2316 | - .map_err(invoke_err_to_py_err) |
2317 | -} |
2318 | - |
2319 | -#[pyfunction] |
2320 | -fn diff3(out_file: PathBuf, mine_path: PathBuf, older_path: PathBuf, yours_path: PathBuf) -> PyResult<i32> { |
2321 | - breezy_patch::invoke::diff3(out_file.as_path(), mine_path.as_path(), older_path.as_path(), yours_path.as_path()) |
2322 | - .map_err(invoke_err_to_py_err) |
2323 | -} |
2324 | - |
2325 | -#[pyfunction] |
2326 | -fn run_patch(directory: PathBuf, patches: Vec<Vec<u8>>, strip: Option<u32>, reverse: Option<bool>, dry_run: Option<bool>, quiet: Option<bool>, target_file: Option<&str>, out: Option<PyObject>, _patch_cmd: Option<&str>) -> PyResult<()> { |
2327 | + breezy_patch::invoke::patch( |
2328 | + patch_contents.iter().map(|x| x.as_slice()), |
2329 | + filename.as_path(), |
2330 | + output_path, |
2331 | + reverse.unwrap_or(false), |
2332 | + ) |
2333 | + .map_err(invoke_err_to_py_err) |
2334 | +} |
2335 | + |
2336 | +#[pyfunction] |
2337 | +fn diff3( |
2338 | + out_file: PathBuf, |
2339 | + mine_path: PathBuf, |
2340 | + older_path: PathBuf, |
2341 | + yours_path: PathBuf, |
2342 | +) -> PyResult<i32> { |
2343 | + breezy_patch::invoke::diff3( |
2344 | + out_file.as_path(), |
2345 | + mine_path.as_path(), |
2346 | + older_path.as_path(), |
2347 | + yours_path.as_path(), |
2348 | + ) |
2349 | + .map_err(invoke_err_to_py_err) |
2350 | +} |
2351 | + |
2352 | +#[pyfunction] |
2353 | +fn run_patch( |
2354 | + directory: PathBuf, |
2355 | + patches: Vec<Vec<u8>>, |
2356 | + strip: Option<u32>, |
2357 | + reverse: Option<bool>, |
2358 | + dry_run: Option<bool>, |
2359 | + quiet: Option<bool>, |
2360 | + target_file: Option<&str>, |
2361 | + out: Option<PyObject>, |
2362 | + _patch_cmd: Option<&str>, |
2363 | +) -> PyResult<()> { |
2364 | let mut out: Box<dyn Write> = if let Some(obj) = out { |
2365 | - Box::new(PyFileLikeObject::with_requirements(obj, false, true, false)?) |
2366 | + Box::new(PyFileLikeObject::with_requirements( |
2367 | + obj, false, true, false, |
2368 | + )?) |
2369 | } else { |
2370 | Box::new(std::io::stdout()) |
2371 | }; |
2372 | |
2373 | breezy_patch::invoke::run_patch( |
2374 | - directory.as_path(), |
2375 | - patches.iter().map(|x| x.as_slice()), |
2376 | - strip.unwrap_or(0), |
2377 | - reverse.unwrap_or(false), |
2378 | - dry_run.unwrap_or(false), |
2379 | - quiet.unwrap_or(true), |
2380 | - target_file, &mut out, |
2381 | - _patch_cmd) |
2382 | - .map_err(invoke_err_to_py_err) |
2383 | + directory.as_path(), |
2384 | + patches.iter().map(|x| x.as_slice()), |
2385 | + strip.unwrap_or(0), |
2386 | + reverse.unwrap_or(false), |
2387 | + dry_run.unwrap_or(false), |
2388 | + quiet.unwrap_or(true), |
2389 | + target_file, |
2390 | + &mut out, |
2391 | + _patch_cmd, |
2392 | + ) |
2393 | + .map_err(invoke_err_to_py_err) |
2394 | } |
2395 | |
2396 | fn invoke_err_to_py_err(err: breezy_patch::invoke::Error) -> PyErr { |
2397 | @@ -56,18 +94,26 @@ |
2398 | breezy_patch::invoke::Error::BinaryFile(path) => BinaryFile::new_err(path), |
2399 | breezy_patch::invoke::Error::PatchInvokeError(errstr, stderr, inner) => { |
2400 | PatchInvokeError::new_err((errstr, stderr, inner.map(|x| x.to_string()))) |
2401 | - }, |
2402 | - breezy_patch::invoke::Error::PatchFailed(exitcode, stderr) => PatchFailed::new_err((exitcode, stderr)), |
2403 | + } |
2404 | + breezy_patch::invoke::Error::PatchFailed(exitcode, stderr) => { |
2405 | + PatchFailed::new_err((exitcode, stderr)) |
2406 | + } |
2407 | } |
2408 | } |
2409 | |
2410 | #[pyfunction] |
2411 | -fn iter_patched_from_hunks(py: Python, orig_lines: PyObject, hunks: PyObject) -> PyResult<PyObject> { |
2412 | +fn iter_patched_from_hunks( |
2413 | + py: Python, |
2414 | + orig_lines: PyObject, |
2415 | + hunks: PyObject, |
2416 | +) -> PyResult<PyObject> { |
2417 | let orig_lines = orig_lines.extract::<Vec<Vec<u8>>>(py)?; |
2418 | let hunks = hunks.extract::<Vec<Vec<u8>>>(py)?; |
2419 | let patched_lines = breezy_patch::invoke::iter_patched_from_hunks( |
2420 | orig_lines.iter().map(|x| x.as_slice()), |
2421 | - hunks.iter().map(|x| x.as_slice())).map_err(invoke_err_to_py_err)?; |
2422 | + hunks.iter().map(|x| x.as_slice()), |
2423 | + ) |
2424 | + .map_err(invoke_err_to_py_err)?; |
2425 | |
2426 | let pl = vec![PyBytes::new(py, &patched_lines)]; |
2427 | Ok(PyList::new(py, &pl).into()) |
2428 | @@ -75,34 +121,54 @@ |
2429 | |
2430 | fn parse_err_to_py_err(err: breezy_patch::parse::Error) -> PyErr { |
2431 | match err { |
2432 | - breezy_patch::parse::Error::BinaryFiles(path1, path2) => BinaryFiles::new_err((PathBuf::from(OsString::from_vec(path1)), PathBuf::from(OsString::from_vec(path2)))), |
2433 | + breezy_patch::parse::Error::BinaryFiles(path1, path2) => BinaryFiles::new_err(( |
2434 | + PathBuf::from(OsString::from_vec(path1)), |
2435 | + PathBuf::from(OsString::from_vec(path2)), |
2436 | + )), |
2437 | breezy_patch::parse::Error::PatchSyntax(err, _line) => PatchSyntax::new_err(err), |
2438 | - breezy_patch::parse::Error::MalformedPatchHeader(err, line) => MalformedPatchHeader::new_err(err), |
2439 | + breezy_patch::parse::Error::MalformedPatchHeader(err, line) => { |
2440 | + MalformedPatchHeader::new_err(err) |
2441 | + } |
2442 | } |
2443 | } |
2444 | |
2445 | #[pyfunction] |
2446 | -fn get_patch_names(py: Python, patch_contents: PyObject) -> PyResult<((PyObject, Option<PyObject>), (PyObject, Option<PyObject>))> { |
2447 | +fn get_patch_names( |
2448 | + py: Python, |
2449 | + patch_contents: PyObject, |
2450 | +) -> PyResult<((PyObject, Option<PyObject>), (PyObject, Option<PyObject>))> { |
2451 | let names = breezy_patch::parse::get_patch_names( |
2452 | - patch_contents.downcast::<PyIterator>(py)?.map(|x| x.unwrap().extract::<Vec<u8>>().unwrap())).map_err(parse_err_to_py_err)?; |
2453 | + patch_contents |
2454 | + .downcast::<PyIterator>(py)? |
2455 | + .map(|x| x.unwrap().extract::<Vec<u8>>().unwrap()), |
2456 | + ) |
2457 | + .map_err(parse_err_to_py_err)?; |
2458 | |
2459 | - let py_orig = (PyBytes::new(py, &names.0.0).to_object(py), names.0.1.map(|x| PyBytes::new(py, &x).to_object(py))); |
2460 | - let py_mod = (PyBytes::new(py, &names.1.0).to_object(py), names.1.1.map(|x| PyBytes::new(py, &x).to_object(py))); |
2461 | + let py_orig = ( |
2462 | + PyBytes::new(py, &names.0 .0).to_object(py), |
2463 | + names.0 .1.map(|x| PyBytes::new(py, &x).to_object(py)), |
2464 | + ); |
2465 | + let py_mod = ( |
2466 | + PyBytes::new(py, &names.1 .0).to_object(py), |
2467 | + names.1 .1.map(|x| PyBytes::new(py, &x).to_object(py)), |
2468 | + ); |
2469 | Ok((py_orig, py_mod)) |
2470 | } |
2471 | |
2472 | #[pyfunction] |
2473 | fn iter_lines_handle_nl(py: Python, iter_lines: PyObject) -> PyResult<PyObject> { |
2474 | let py_iter = iter_lines.as_ref(py).iter()?; |
2475 | - let lines = breezy_patch::parse::iter_lines_handle_nl(py_iter.map(|x| x.unwrap().extract::<Vec<u8>>().unwrap())); |
2476 | + let lines = breezy_patch::parse::iter_lines_handle_nl( |
2477 | + py_iter.map(|x| x.unwrap().extract::<Vec<u8>>().unwrap()), |
2478 | + ); |
2479 | let pl = lines.map(|x| PyBytes::new(py, &x)).collect::<Vec<_>>(); |
2480 | Ok(PyList::new(py, &pl).as_ref().iter()?.to_object(py)) |
2481 | } |
2482 | |
2483 | #[pyfunction] |
2484 | fn parse_range(textrange: &str) -> PyResult<(i32, i32)> { |
2485 | - breezy_patch::parse::parse_range(textrange).map_err( |
2486 | - |err| PyValueError::new_err(format!("Invalid range: {}", err))) |
2487 | + breezy_patch::parse::parse_range(textrange) |
2488 | + .map_err(|err| PyValueError::new_err(format!("Invalid range: {}", err))) |
2489 | } |
2490 | |
2491 | #[pyfunction] |
2492 | @@ -123,7 +189,10 @@ |
2493 | m.add("PatchInvokeError", py.get_type::<PatchInvokeError>())?; |
2494 | m.add("PatchFailed", py.get_type::<PatchFailed>())?; |
2495 | m.add("PatchSyntax", py.get_type::<PatchSyntax>())?; |
2496 | - m.add("MalformedPatchHeader", py.get_type::<MalformedPatchHeader>())?; |
2497 | + m.add( |
2498 | + "MalformedPatchHeader", |
2499 | + py.get_type::<MalformedPatchHeader>(), |
2500 | + )?; |
2501 | m.add("BinaryFiles", py.get_type::<BinaryFiles>())?; |
2502 | Ok(()) |
2503 | } |
2504 | |
2505 | === modified file 'crates/patch/src/invoke.rs' |
2506 | --- crates/patch/src/invoke.rs 2023-04-15 03:34:42 +0000 |
2507 | +++ crates/patch/src/invoke.rs 2023-04-17 11:56:43 +0000 |
2508 | @@ -1,27 +1,35 @@ |
2509 | +use breezy_osutils::textfile::check_text_path; |
2510 | use std::ffi::OsString; |
2511 | +use std::io::{BufWriter, Write}; |
2512 | use std::path::Path; |
2513 | -use std::io::{Write,BufWriter}; |
2514 | use std::process::{Command, Stdio}; |
2515 | -use breezy_osutils::textfile::check_text_path; |
2516 | use tempfile::NamedTempFile; |
2517 | |
2518 | pub enum Error { |
2519 | - PatchInvokeError(String, String, Option<Box<dyn std::error::Error + Send + Sync>>), |
2520 | + PatchInvokeError( |
2521 | + String, |
2522 | + String, |
2523 | + Option<Box<dyn std::error::Error + Send + Sync>>, |
2524 | + ), |
2525 | PatchFailed(i32, String), |
2526 | BinaryFile(std::path::PathBuf), |
2527 | Io(std::io::Error), |
2528 | } |
2529 | |
2530 | -impl From <std::io::Error> for Error { |
2531 | +impl From<std::io::Error> for Error { |
2532 | fn from(e: std::io::Error) -> Self { |
2533 | Error::Io(e) |
2534 | } |
2535 | } |
2536 | |
2537 | /// Invoke a command with the given arguments, passing `input` to its stdin. |
2538 | -fn write_to_cmd<'a, I>(command: &str, args: &[OsString], input: I) -> std::io::Result<(Vec<u8>, Vec<u8>, i32)> |
2539 | +fn write_to_cmd<'a, I>( |
2540 | + command: &str, |
2541 | + args: &[OsString], |
2542 | + input: I, |
2543 | +) -> std::io::Result<(Vec<u8>, Vec<u8>, i32)> |
2544 | where |
2545 | - I: IntoIterator<Item = &'a [u8]> |
2546 | + I: IntoIterator<Item = &'a [u8]>, |
2547 | { |
2548 | let mut cmd = Command::new(command); |
2549 | cmd.args(args) |
2550 | @@ -29,7 +37,7 @@ |
2551 | .stdout(Stdio::piped()) |
2552 | .stderr(Stdio::piped()); |
2553 | let mut child = cmd.spawn()?; |
2554 | - if let Some(mut stdin) = child.stdin.take() { |
2555 | + if let Some(mut stdin) = child.stdin.take() { |
2556 | for chunk in input { |
2557 | stdin.write_all(chunk)?; |
2558 | } |
2559 | @@ -42,9 +50,14 @@ |
2560 | } |
2561 | |
2562 | /// Apply a patch to a file, producing another output file. |
2563 | -pub fn patch<'a, I>(patch_contents: I, filename: &Path, output_filename: Option<&Path>, reverse: bool) -> Result<i32, Error> |
2564 | +pub fn patch<'a, I>( |
2565 | + patch_contents: I, |
2566 | + filename: &Path, |
2567 | + output_filename: Option<&Path>, |
2568 | + reverse: bool, |
2569 | +) -> Result<i32, Error> |
2570 | where |
2571 | - I: Iterator<Item = &'a [u8]> |
2572 | + I: Iterator<Item = &'a [u8]>, |
2573 | { |
2574 | let mut args: Vec<OsString> = vec![ |
2575 | "-f".into(), |
2576 | @@ -60,20 +73,29 @@ |
2577 | } |
2578 | args.push(filename.into()); |
2579 | let (stdout, stderr, status) = write_to_cmd("patch", &args, patch_contents) |
2580 | - .map_err(|e| Error::PatchInvokeError( |
2581 | - e.to_string(), |
2582 | - String::new(), |
2583 | - Some(Box::new(e)), |
2584 | - ))?; |
2585 | + .map_err(|e| Error::PatchInvokeError(e.to_string(), String::new(), Some(Box::new(e))))?; |
2586 | if status < 0 { |
2587 | - let err = if output_filename.is_some() { assert!(stderr.is_empty()); &stdout } else { &stderr }; |
2588 | - return Err(Error::PatchFailed(status, String::from_utf8_lossy(err).to_string())); |
2589 | + let err = if output_filename.is_some() { |
2590 | + assert!(stderr.is_empty()); |
2591 | + &stdout |
2592 | + } else { |
2593 | + &stderr |
2594 | + }; |
2595 | + return Err(Error::PatchFailed( |
2596 | + status, |
2597 | + String::from_utf8_lossy(err).to_string(), |
2598 | + )); |
2599 | } |
2600 | Ok(status) |
2601 | } |
2602 | |
2603 | /// Apply a three-way merge using `diff3`. |
2604 | -pub fn diff3(out_file: &Path, mine_path: &Path, older_path: &Path, yours_path: &Path) -> Result<i32, Error> { |
2605 | +pub fn diff3( |
2606 | + out_file: &Path, |
2607 | + mine_path: &Path, |
2608 | + older_path: &Path, |
2609 | + yours_path: &Path, |
2610 | +) -> Result<i32, Error> { |
2611 | fn add_label(args: &mut Vec<OsString>, label: &str) { |
2612 | args.extend(vec!["-L".into(), label.into()]); |
2613 | } |
2614 | @@ -82,24 +104,17 @@ |
2615 | return Err(Error::BinaryFile(path.to_path_buf())); |
2616 | } |
2617 | } |
2618 | - let mut args = vec![ |
2619 | - "-E".into(), |
2620 | - "--merge".into(), |
2621 | - ]; |
2622 | + let mut args = vec!["-E".into(), "--merge".into()]; |
2623 | add_label(&mut args, "TREE"); |
2624 | add_label(&mut args, "ANCESTOR"); |
2625 | add_label(&mut args, "MERGE-SOURCE"); |
2626 | - args.extend(vec![ |
2627 | - mine_path.into(), |
2628 | - older_path.into(), |
2629 | - yours_path.into(), |
2630 | - ]); |
2631 | + args.extend(vec![mine_path.into(), older_path.into(), yours_path.into()]); |
2632 | let (output, stderr, status) = write_to_cmd("diff3", &args, std::iter::once::<&[u8]>(&[]))?; |
2633 | if status != 0 && status != 1 { |
2634 | return Err(Error::PatchInvokeError( |
2635 | format!("diff3 exited with status {}", status), |
2636 | String::from_utf8_lossy(&stderr).to_string(), |
2637 | - None |
2638 | + None, |
2639 | )); |
2640 | } |
2641 | std::fs::write(out_file, &output)?; |
2642 | @@ -118,7 +133,7 @@ |
2643 | patch_cmd: Option<&str>, |
2644 | ) -> Result<(), Error> |
2645 | where |
2646 | - I: Iterator<Item = &'a [u8]> |
2647 | + I: Iterator<Item = &'a [u8]>, |
2648 | { |
2649 | let mut args: Vec<OsString> = vec![ |
2650 | "-d".into(), |
2651 | @@ -147,15 +162,14 @@ |
2652 | args.push(target_file.into()); |
2653 | } |
2654 | let mut process = Command::new(patch_cmd.unwrap_or("patch")); |
2655 | - process.args(&args) |
2656 | + process |
2657 | + .args(&args) |
2658 | .stdin(Stdio::piped()) |
2659 | .stdout(Stdio::piped()) |
2660 | .stderr(Stdio::piped()); |
2661 | - let mut child = process.spawn().map_err(|e| Error::PatchInvokeError( |
2662 | - e.to_string(), |
2663 | - String::new(), |
2664 | - Some(Box::new(e)), |
2665 | - ))?; |
2666 | + let mut child = process |
2667 | + .spawn() |
2668 | + .map_err(|e| Error::PatchInvokeError(e.to_string(), String::new(), Some(Box::new(e))))?; |
2669 | if let Some(mut stdin) = child.stdin.take() { |
2670 | for patch in patches { |
2671 | stdin.write_all(patch)?; |
2672 | @@ -172,7 +186,10 @@ |
2673 | let status = output.status.code().unwrap_or(-1); |
2674 | assert!(output.stderr.is_empty()); |
2675 | if status != 0 { |
2676 | - return Err(Error::PatchFailed(status, String::from_utf8_lossy(&output.stdout).to_string())); |
2677 | + return Err(Error::PatchFailed( |
2678 | + status, |
2679 | + String::from_utf8_lossy(&output.stdout).to_string(), |
2680 | + )); |
2681 | } |
2682 | out.write_all(&output.stdout)?; |
2683 | Ok(()) |
2684 | @@ -184,7 +201,7 @@ |
2685 | pub fn iter_patched_from_hunks<'a, I, H>(orig_lines: I, hunks: H) -> Result<Vec<u8>, Error> |
2686 | where |
2687 | I: IntoIterator<Item = &'a [u8]>, |
2688 | - H: Iterator<Item = &'a [u8]> |
2689 | + H: Iterator<Item = &'a [u8]>, |
2690 | { |
2691 | let temp_file = NamedTempFile::new()?; |
2692 | let mut f = BufWriter::new(temp_file); |
2693 | @@ -204,12 +221,12 @@ |
2694 | temp_file_path.as_os_str().into(), |
2695 | ]; |
2696 | let (stdout, stderr, status) = write_to_cmd("patch", &args, hunks) |
2697 | - .map_err(|e| Error::PatchInvokeError( |
2698 | - e.to_string(), |
2699 | - String::new(), |
2700 | - Some(Box::new(e))))?; |
2701 | + .map_err(|e| Error::PatchInvokeError(e.to_string(), String::new(), Some(Box::new(e))))?; |
2702 | if status != 0 { |
2703 | - return Err(Error::PatchFailed(status, String::from_utf8_lossy(&stderr).to_string())); |
2704 | + return Err(Error::PatchFailed( |
2705 | + status, |
2706 | + String::from_utf8_lossy(&stderr).to_string(), |
2707 | + )); |
2708 | } |
2709 | assert!(stderr.is_empty()); |
2710 | Ok(stdout) |
2711 | |
2712 | === modified file 'crates/patch/src/parse.rs' |
2713 | --- crates/patch/src/parse.rs 2023-04-16 01:30:53 +0000 |
2714 | +++ crates/patch/src/parse.rs 2023-04-17 11:56:43 +0000 |
2715 | @@ -1,5 +1,5 @@ |
2716 | +use lazy_static::lazy_static; |
2717 | use regex::bytes::Regex; |
2718 | -use lazy_static::lazy_static; |
2719 | use std::num::ParseIntError; |
2720 | |
2721 | pub enum Error { |
2722 | @@ -12,10 +12,13 @@ |
2723 | mut iter_lines: T, |
2724 | ) -> Result<((Vec<u8>, Option<Vec<u8>>), (Vec<u8>, Option<Vec<u8>>)), Error> { |
2725 | lazy_static! { |
2726 | - static ref BINARY_FILES_RE: Regex = Regex::new(r"^Binary files (.+) and (.+) differ").unwrap(); |
2727 | + static ref BINARY_FILES_RE: Regex = |
2728 | + Regex::new(r"^Binary files (.+) and (.+) differ").unwrap(); |
2729 | } |
2730 | |
2731 | - let line = iter_lines.next().ok_or_else(||Error::PatchSyntax("No input", vec![]))?; |
2732 | + let line = iter_lines |
2733 | + .next() |
2734 | + .ok_or_else(|| Error::PatchSyntax("No input", vec![]))?; |
2735 | |
2736 | let (orig_name, orig_ts) = match BINARY_FILES_RE.captures(&line) { |
2737 | Some(captures) => { |
2738 | @@ -25,9 +28,12 @@ |
2739 | } |
2740 | None => { |
2741 | let orig_name = line |
2742 | - .strip_prefix(b"--- ").ok_or_else(||Error::MalformedPatchHeader("No orig name", line.to_vec()))? |
2743 | - .strip_suffix(b"\n").ok_or_else(|| Error::PatchSyntax("missing newline", line.to_vec()))?; |
2744 | - let (orig_name, orig_ts) = match orig_name.split(|&c| c == b'\t').collect::<Vec<_>>()[..] { |
2745 | + .strip_prefix(b"--- ") |
2746 | + .ok_or_else(|| Error::MalformedPatchHeader("No orig name", line.to_vec()))? |
2747 | + .strip_suffix(b"\n") |
2748 | + .ok_or_else(|| Error::PatchSyntax("missing newline", line.to_vec()))?; |
2749 | + let (orig_name, orig_ts) = match orig_name.split(|&c| c == b'\t').collect::<Vec<_>>()[..] |
2750 | + { |
2751 | [name, ts] => (name.to_vec(), Some(ts.to_vec())), |
2752 | [name] => (name.to_vec(), None), |
2753 | _ => return Err(Error::MalformedPatchHeader("No orig line", line.to_vec())), |
2754 | @@ -36,11 +42,15 @@ |
2755 | } |
2756 | }; |
2757 | |
2758 | - let line = iter_lines.next().ok_or_else(||Error::PatchSyntax("No input", vec![]))?; |
2759 | + let line = iter_lines |
2760 | + .next() |
2761 | + .ok_or_else(|| Error::PatchSyntax("No input", vec![]))?; |
2762 | |
2763 | let (mod_name, mod_ts) = match line.strip_prefix(b"+++ ") { |
2764 | Some(line) => { |
2765 | - let mod_name = line.strip_suffix(b"\n").ok_or_else(|| Error::PatchSyntax("missing newline", line.to_vec()))?; |
2766 | + let mod_name = line |
2767 | + .strip_suffix(b"\n") |
2768 | + .ok_or_else(|| Error::PatchSyntax("missing newline", line.to_vec()))?; |
2769 | let (mod_name, mod_ts) = match mod_name.split(|&c| c == b'\t').collect::<Vec<_>>()[..] { |
2770 | [name, ts] => (name.to_vec(), Some(ts.to_vec())), |
2771 | [name] => (name.to_vec(), None), |
2772 | |
2773 | === modified file 'crates/rio-py/src/lib.rs' |
2774 | --- crates/rio-py/src/lib.rs 2023-04-10 12:31:50 +0000 |
2775 | +++ crates/rio-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
2776 | @@ -2,8 +2,8 @@ |
2777 | |
2778 | use pyo3::wrap_pyfunction; |
2779 | |
2780 | -use pyo3::types::{PyDict,PyType,PyBytes,PyList,PyIterator,PyString}; |
2781 | -use pyo3::exceptions::{PyTypeError, PyValueError, PyNotImplementedError, PyIOError}; |
2782 | +use pyo3::exceptions::{PyIOError, PyNotImplementedError, PyTypeError, PyValueError}; |
2783 | +use pyo3::types::{PyBytes, PyDict, PyIterator, PyList, PyString, PyType}; |
2784 | |
2785 | use pyo3::class::basic::CompareOp; |
2786 | |
2787 | @@ -50,9 +50,12 @@ |
2788 | if other_stanza.is_err() { |
2789 | Ok(false.into_py(other.py())) |
2790 | } else { |
2791 | - Ok(self.stanza.eq(&other_stanza.unwrap().stanza).into_py(other.py())) |
2792 | + Ok(self |
2793 | + .stanza |
2794 | + .eq(&other_stanza.unwrap().stanza) |
2795 | + .into_py(other.py())) |
2796 | } |
2797 | - }, |
2798 | + } |
2799 | _ => Err(PyErr::new::<PyNotImplementedError, _>("Not implemented")), |
2800 | } |
2801 | } |
2802 | @@ -64,8 +67,12 @@ |
2803 | fn get(&self, tag: &str, py: Python) -> PyResult<Option<PyObject>> { |
2804 | if let Some(value) = self.stanza.get(tag) { |
2805 | match value { |
2806 | - bazaar_rio::rio::StanzaValue::String(v) => Ok(Some(PyString::new(py, v).into_py(py))), |
2807 | - bazaar_rio::rio::StanzaValue::Stanza(v) => Ok(Some(Stanza { stanza: *v.clone() }.into_py(py))), |
2808 | + bazaar_rio::rio::StanzaValue::String(v) => { |
2809 | + Ok(Some(PyString::new(py, v).into_py(py))) |
2810 | + } |
2811 | + bazaar_rio::rio::StanzaValue::Stanza(v) => { |
2812 | + Ok(Some(Stanza { stanza: *v.clone() }.into_py(py))) |
2813 | + } |
2814 | } |
2815 | } else { |
2816 | Ok(None) |
2817 | @@ -107,17 +114,27 @@ |
2818 | // Otherwise, if the type of value is Stanza, then extract it as a Stanza and add it to the stanza. |
2819 | // Otherwise, return an error. |
2820 | let ret = if let Ok(val) = value.extract::<String>() { |
2821 | - self.stanza.add(tag.to_string(), bazaar_rio::rio::StanzaValue::String(val)) |
2822 | + self.stanza |
2823 | + .add(tag.to_string(), bazaar_rio::rio::StanzaValue::String(val)) |
2824 | } else if let Ok(val) = value.extract::<Stanza>() { |
2825 | - self.stanza.add(tag.to_string(), bazaar_rio::rio::StanzaValue::Stanza(Box::new(val.stanza))) |
2826 | + self.stanza.add( |
2827 | + tag.to_string(), |
2828 | + bazaar_rio::rio::StanzaValue::Stanza(Box::new(val.stanza)), |
2829 | + ) |
2830 | } else { |
2831 | - return Err(PyErr::new::<PyTypeError, _>(format!("Invalid value: {}", value.repr()?))); |
2832 | + return Err(PyErr::new::<PyTypeError, _>(format!( |
2833 | + "Invalid value: {}", |
2834 | + value.repr()? |
2835 | + ))); |
2836 | }; |
2837 | if let Err(e) = ret { |
2838 | if let bazaar_rio::rio::Error::Io(e) = e { |
2839 | return Err(PyErr::new::<PyIOError, _>(format!("IO error: {}", e))); |
2840 | } else { |
2841 | - return Err(PyErr::new::<PyValueError, _>(format!("Invalid value: {}", value.repr()?))); |
2842 | + return Err(PyErr::new::<PyValueError, _>(format!( |
2843 | + "Invalid value: {}", |
2844 | + value.repr()? |
2845 | + ))); |
2846 | } |
2847 | } |
2848 | Ok(()) |
2849 | @@ -138,7 +155,9 @@ |
2850 | let ret = PyList::empty(py); |
2851 | for (tag, value) in self.stanza.iter_pairs() { |
2852 | match value { |
2853 | - bazaar_rio::rio::StanzaValue::String(v) => ret.append((tag.to_string(), v.to_string()))?, |
2854 | + bazaar_rio::rio::StanzaValue::String(v) => { |
2855 | + ret.append((tag.to_string(), v.to_string()))? |
2856 | + } |
2857 | bazaar_rio::rio::StanzaValue::Stanza(v) => { |
2858 | let sub: Stanza = Stanza { stanza: *v.clone() }; |
2859 | ret.append((tag.to_string(), sub.into_py(py)))?; |
2860 | @@ -185,7 +204,7 @@ |
2861 | |
2862 | #[pyclass] |
2863 | struct RioWriter { |
2864 | - writer: bazaar_rio::rio::RioWriter<PyFileLikeObject> |
2865 | + writer: bazaar_rio::rio::RioWriter<PyFileLikeObject>, |
2866 | } |
2867 | |
2868 | #[pymethods] |
2869 | @@ -209,11 +228,11 @@ |
2870 | |
2871 | let mut reader = BufReader::new(reader); |
2872 | |
2873 | - let stanza = bazaar_rio::rio::read_stanza_file(&mut reader).map_err(|e| { |
2874 | - match e { |
2875 | - bazaar_rio::rio::Error::Io(e) => PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)), |
2876 | - _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file", )), |
2877 | + let stanza = bazaar_rio::rio::read_stanza_file(&mut reader).map_err(|e| match e { |
2878 | + bazaar_rio::rio::Error::Io(e) => { |
2879 | + PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)) |
2880 | } |
2881 | + _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file",)), |
2882 | })?; |
2883 | |
2884 | if let Some(stanza) = stanza { |
2885 | @@ -231,13 +250,17 @@ |
2886 | let line = py_iter.next()?; |
2887 | if let Err(e) = line { |
2888 | pyerr = Some(e); |
2889 | - return Some(Err(bazaar_rio::rio::Error::Other("Python error".to_string()))); |
2890 | + return Some(Err(bazaar_rio::rio::Error::Other( |
2891 | + "Python error".to_string(), |
2892 | + ))); |
2893 | } else { |
2894 | let line = line.unwrap(); |
2895 | let line = line.extract::<Vec<u8>>(); |
2896 | if let Err(e) = line { |
2897 | pyerr = Some(e); |
2898 | - return Some(Err(bazaar_rio::rio::Error::Other("invalid input".to_string()))); |
2899 | + return Some(Err(bazaar_rio::rio::Error::Other( |
2900 | + "invalid input".to_string(), |
2901 | + ))); |
2902 | } else { |
2903 | Some(Ok(line.unwrap())) |
2904 | } |
2905 | @@ -249,8 +272,10 @@ |
2906 | return e; |
2907 | } |
2908 | match e { |
2909 | - bazaar_rio::rio::Error::Io(e) => PyErr::new::<PyIOError, _>(format!("Error reading stanza: {}", e)), |
2910 | - _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza", )), |
2911 | + bazaar_rio::rio::Error::Io(e) => { |
2912 | + PyErr::new::<PyIOError, _>(format!("Error reading stanza: {}", e)) |
2913 | + } |
2914 | + _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza",)), |
2915 | } |
2916 | })?; |
2917 | |
2918 | @@ -269,11 +294,11 @@ |
2919 | |
2920 | let mut reader = BufReader::new(reader); |
2921 | |
2922 | - let stanzas = bazaar_rio::rio::read_stanzas(&mut reader).map_err(|e| { |
2923 | - match e { |
2924 | - bazaar_rio::rio::Error::Io(e) => PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)), |
2925 | - _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file: ", )), |
2926 | + let stanzas = bazaar_rio::rio::read_stanzas(&mut reader).map_err(|e| match e { |
2927 | + bazaar_rio::rio::Error::Io(e) => { |
2928 | + PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)) |
2929 | } |
2930 | + _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file: ",)), |
2931 | })?; |
2932 | for stanza in stanzas { |
2933 | ret.append((Stanza { stanza }).into_py(py))?; |
2934 | @@ -302,13 +327,18 @@ |
2935 | Python::with_gil(|py| { |
2936 | let ret = PyList::empty(py); |
2937 | for stanza in self.reader.iter() { |
2938 | - let stanza = stanza.map_err(|e| { |
2939 | - match e { |
2940 | - bazaar_rio::rio::Error::Io(e) => PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)), |
2941 | - _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file: ", )), |
2942 | + let stanza = stanza.map_err(|e| match e { |
2943 | + bazaar_rio::rio::Error::Io(e) => { |
2944 | + PyErr::new::<PyIOError, _>(format!("Error reading stanza file: {}", e)) |
2945 | } |
2946 | + _ => PyErr::new::<PyValueError, _>(format!("Error reading stanza file: ",)), |
2947 | })?; |
2948 | - ret.append((Stanza { stanza: stanza.unwrap() }).into_py(py))?; |
2949 | + ret.append( |
2950 | + (Stanza { |
2951 | + stanza: stanza.unwrap(), |
2952 | + }) |
2953 | + .into_py(py), |
2954 | + )?; |
2955 | } |
2956 | Ok(PyIterator::from_object(py, ret)?.into()) |
2957 | }) |
2958 | |
2959 | === modified file 'crates/rio/src/rio.rs' |
2960 | --- crates/rio/src/rio.rs 2023-04-14 08:57:25 +0000 |
2961 | +++ crates/rio/src/rio.rs 2023-04-17 11:56:43 +0000 |
2962 | @@ -1,4 +1,3 @@ |
2963 | - |
2964 | /// The RIO file format |
2965 | /// |
2966 | /// Copyright (C) 2023 Jelmer Vernooij <jelmer@jelmer.uk> |
2967 | @@ -22,9 +21,9 @@ |
2968 | /// stream representation of an object and vice versa, and that this relation |
2969 | /// will continue to hold for future versions of bzr. |
2970 | use regex::Regex; |
2971 | -use std::io::{BufRead,Write}; |
2972 | +use std::collections::HashMap; |
2973 | +use std::io::{BufRead, Write}; |
2974 | use std::iter::Iterator; |
2975 | -use std::collections::HashMap; |
2976 | use std::result::Result; |
2977 | use std::str; |
2978 | |
2979 | @@ -87,9 +86,7 @@ |
2980 | } |
2981 | |
2982 | pub fn iter(&mut self) -> RioReaderIter<R> { |
2983 | - RioReaderIter { |
2984 | - reader: self |
2985 | - } |
2986 | + RioReaderIter { reader: self } |
2987 | } |
2988 | } |
2989 | |
2990 | @@ -175,13 +172,14 @@ |
2991 | } |
2992 | |
2993 | pub fn iter_pairs(&self) -> impl Iterator<Item = (&str, &StanzaValue)> { |
2994 | - self.items |
2995 | - .iter() |
2996 | - .map(|(tag, value)| (tag.as_str(), value)) |
2997 | + self.items.iter().map(|(tag, value)| (tag.as_str(), value)) |
2998 | } |
2999 | |
3000 | pub fn to_bytes_lines(&self) -> Vec<Vec<u8>> { |
3001 | - self.to_lines().iter().map(|s| s.as_bytes().to_vec()).collect() |
3002 | + self.to_lines() |
3003 | + .iter() |
3004 | + .map(|s| s.as_bytes().to_vec()) |
3005 | + .collect() |
3006 | } |
3007 | |
3008 | pub fn to_lines(&self) -> Vec<String> { |
3009 | @@ -207,11 +205,7 @@ |
3010 | result.push(format!("\t{}\n", line)); |
3011 | } |
3012 | } else { |
3013 | - result.push(format!( |
3014 | - "{}: {}\n", |
3015 | - String::from_utf8_lossy(tag), |
3016 | - value |
3017 | - )); |
3018 | + result.push(format!("{}: {}\n", String::from_utf8_lossy(tag), value)); |
3019 | } |
3020 | } |
3021 | result |
3022 | @@ -243,7 +237,8 @@ |
3023 | } |
3024 | |
3025 | pub fn get_all(&self, tag: &str) -> Vec<&StanzaValue> { |
3026 | - self.items.iter() |
3027 | + self.items |
3028 | + .iter() |
3029 | .filter(|(t, _)| t == tag) |
3030 | .map(|(_, v)| v) |
3031 | .collect() |
3032 | @@ -276,7 +271,8 @@ |
3033 | |
3034 | pub fn read_stanza<I>(lines: I) -> Result<Option<Stanza>, Error> |
3035 | where |
3036 | - I: Iterator<Item = Result<Vec<u8>, Error>> { |
3037 | + I: Iterator<Item = Result<Vec<u8>, Error>>, |
3038 | +{ |
3039 | let mut stanza = Stanza::new(); |
3040 | let mut tag: Option<String> = None; |
3041 | let mut accum_value: Option<Vec<String>> = None; |
3042 | @@ -299,7 +295,7 @@ |
3043 | // new tag:value line |
3044 | if let Some(tag) = tag.take() { |
3045 | let value = accum_value.take().map_or_else(String::new, |v| v.join("")); |
3046 | - stanza.add(tag, StanzaValue::String(value)); |
3047 | + stanza.add(tag, StanzaValue::String(value))?; |
3048 | } |
3049 | let colon_index = match line.windows(2).position(|window| window.eq(b": ")) { |
3050 | Some(index) => index, |
3051 | |
3052 | === modified file 'crates/rio/src/tests.rs' |
3053 | --- crates/rio/src/tests.rs 2023-04-10 12:01:30 +0000 |
3054 | +++ crates/rio/src/tests.rs 2023-04-17 11:56:43 +0000 |
3055 | @@ -1,5 +1,5 @@ |
3056 | use crate::rio::valid_tag; |
3057 | -use crate::rio::{Stanza,StanzaValue,read_stanza}; |
3058 | +use crate::rio::{read_stanza, Stanza, StanzaValue}; |
3059 | |
3060 | #[test] |
3061 | fn test_valid_tag() { |
3062 | @@ -18,8 +18,14 @@ |
3063 | assert!(!s.contains("42")); |
3064 | |
3065 | // Verify that the s.get() function works |
3066 | - assert_eq!(s.get("number"), Some(&StanzaValue::String("42".to_string()))); |
3067 | - assert_eq!(s.get("name"), Some(&StanzaValue::String("fred".to_string()))); |
3068 | + assert_eq!( |
3069 | + s.get("number"), |
3070 | + Some(&StanzaValue::String("42".to_string())) |
3071 | + ); |
3072 | + assert_eq!( |
3073 | + s.get("name"), |
3074 | + Some(&StanzaValue::String("fred".to_string())) |
3075 | + ); |
3076 | assert_eq!(s.get("color"), None); |
3077 | |
3078 | // Verify that iter_pairs() works |
3079 | @@ -45,7 +51,10 @@ |
3080 | |
3081 | #[test] |
3082 | fn test_empty_value() { |
3083 | - let s = Stanza::from_pairs(vec![("empty".to_string(), StanzaValue::String("".to_string()))]); |
3084 | + let s = Stanza::from_pairs(vec![( |
3085 | + "empty".to_string(), |
3086 | + StanzaValue::String("".to_string()), |
3087 | + )]); |
3088 | assert_eq!(s.to_string(), "empty: \n"); |
3089 | } |
3090 | |
3091 | @@ -54,12 +63,26 @@ |
3092 | let s = Stanza::from_pairs(vec![ |
3093 | ("number".to_string(), StanzaValue::String("42".to_string())), |
3094 | ("name".to_string(), StanzaValue::String("fred".to_string())), |
3095 | - ("field-with-newlines".to_string(), StanzaValue::String("foo\nbar\nblah".to_string())), |
3096 | - ("special-characters".to_string(), StanzaValue::String(" \t\r\\\n ".to_string())), |
3097 | + ( |
3098 | + "field-with-newlines".to_string(), |
3099 | + StanzaValue::String("foo\nbar\nblah".to_string()), |
3100 | + ), |
3101 | + ( |
3102 | + "special-characters".to_string(), |
3103 | + StanzaValue::String(" \t\r\\\n ".to_string()), |
3104 | + ), |
3105 | ]); |
3106 | assert_eq!( |
3107 | s.to_lines(), |
3108 | - vec!["number: 42\n".to_string(), "name: fred\n".to_string(), "field-with-newlines: foo\n".to_string(), "\tbar\n".to_string(), "\tblah\n".to_string(), "special-characters: \t\r\\\n".to_string(), "\t \n".to_string()], |
3109 | + vec![ |
3110 | + "number: 42\n".to_string(), |
3111 | + "name: fred\n".to_string(), |
3112 | + "field-with-newlines: foo\n".to_string(), |
3113 | + "\tbar\n".to_string(), |
3114 | + "\tblah\n".to_string(), |
3115 | + "special-characters: \t\r\\\n".to_string(), |
3116 | + "\t \n".to_string() |
3117 | + ], |
3118 | ); |
3119 | } |
3120 | |
3121 | @@ -71,11 +94,17 @@ |
3122 | \tbar |
3123 | \tblah |
3124 | |
3125 | -".split(|c| *c == b'\n').map(|s| s.to_vec()); |
3126 | - let s = read_stanza(lines.map(|l|Ok(l))).unwrap().unwrap(); |
3127 | +" |
3128 | + .split(|c| *c == b'\n') |
3129 | + .map(|s| s.to_vec()); |
3130 | + let s = read_stanza(lines.map(|l| Ok(l))).unwrap().unwrap(); |
3131 | let expected = Stanza::from_pairs(vec![ |
3132 | ("number".to_string(), StanzaValue::String("42".to_string())), |
3133 | ("name".to_string(), StanzaValue::String("fred".to_string())), |
3134 | - ("field-with-newlines".to_string(), StanzaValue::String("foo\nbar\nblah".to_string()))]); |
3135 | + ( |
3136 | + "field-with-newlines".to_string(), |
3137 | + StanzaValue::String("foo\nbar\nblah".to_string()), |
3138 | + ), |
3139 | + ]); |
3140 | assert_eq!(s, expected); |
3141 | } |
3142 | |
3143 | === modified file 'crates/zlib-util-py/src/lib.rs' |
3144 | --- crates/zlib-util-py/src/lib.rs 2023-04-14 10:24:19 +0000 |
3145 | +++ crates/zlib-util-py/src/lib.rs 2023-04-17 11:56:43 +0000 |
3146 | @@ -1,6 +1,6 @@ |
3147 | #![allow(non_snake_case)] |
3148 | +use pyo3::exceptions::PyValueError; |
3149 | use pyo3::prelude::*; |
3150 | -use pyo3::exceptions::PyValueError; |
3151 | |
3152 | #[pyclass] |
3153 | struct ZLibEstimator { |
3154 | @@ -27,15 +27,15 @@ |
3155 | } |
3156 | |
3157 | fn add_content(&mut self, content: &[u8]) -> PyResult<()> { |
3158 | - self.estimator.add_content(content).map_err(|e| { |
3159 | - PyValueError::new_err(format!("Failed to add content: {}", e)) |
3160 | - }) |
3161 | + self.estimator |
3162 | + .add_content(content) |
3163 | + .map_err(|e| PyValueError::new_err(format!("Failed to add content: {}", e))) |
3164 | } |
3165 | |
3166 | fn full(&mut self) -> PyResult<bool> { |
3167 | - self.estimator.full().map_err(|e| { |
3168 | - PyValueError::new_err(format!("Failed to check if full: {}", e)) |
3169 | - }) |
3170 | + self.estimator |
3171 | + .full() |
3172 | + .map_err(|e| PyValueError::new_err(format!("Failed to check if full: {}", e))) |
3173 | } |
3174 | } |
3175 | |
3176 | |
3177 | === modified file 'crates/zlib-util/src/estimator.rs' |
3178 | --- crates/zlib-util/src/estimator.rs 2023-04-14 10:24:19 +0000 |
3179 | +++ crates/zlib-util/src/estimator.rs 2023-04-17 11:56:43 +0000 |
3180 | @@ -1,6 +1,6 @@ |
3181 | +use crate::python_default_deflate_encoder; |
3182 | use flate2::write::DeflateEncoder; |
3183 | use std::io::Write; |
3184 | -use crate::python_default_deflate_encoder; |
3185 | |
3186 | pub struct ZLibEstimator { |
3187 | target_size: usize, |
3188 | @@ -50,8 +50,8 @@ |
3189 | self.unflushed_size_added = 0; |
3190 | // So far we've read X uncompressed bytes, and written Y compressed |
3191 | // bytes. We should have a decent estimate of the final compression. |
3192 | - self.estimated_compression = (self.uncompressed_size_added as f32) |
3193 | - / (self.compressed_size_added as f32); |
3194 | + self.estimated_compression = |
3195 | + (self.uncompressed_size_added as f32) / (self.compressed_size_added as f32); |
3196 | } |
3197 | |
3198 | pub fn full(&mut self) -> std::io::Result<bool> { |
3199 | @@ -60,8 +60,7 @@ |
3200 | let remaining_size = self.target_size - self.compressed_size_added; |
3201 | // Estimate how much compressed content the unflushed data will |
3202 | // consume |
3203 | - let est_z_size = (self.unflushed_size_added as f32) |
3204 | - / self.estimated_compression; |
3205 | + let est_z_size = (self.unflushed_size_added as f32) / self.estimated_compression; |
3206 | if est_z_size >= remaining_size as f32 { |
3207 | // We estimate we are close to remaining |
3208 | self.compressor.flush()?; |
3209 | @@ -74,4 +73,3 @@ |
3210 | Ok(self.compressed_size_added >= self.target_size) |
3211 | } |
3212 | } |
3213 | - |
3214 | |
3215 | === modified file 'crates/zlib-util/src/lib.rs' |
3216 | --- crates/zlib-util/src/lib.rs 2023-04-13 22:19:43 +0000 |
3217 | +++ crates/zlib-util/src/lib.rs 2023-04-17 11:56:43 +0000 |
3218 | @@ -1,5 +1,5 @@ |
3219 | +use flate2::write::DeflateEncoder; |
3220 | use flate2::Compression; |
3221 | -use flate2::write::DeflateEncoder; |
3222 | use std::io::Write; |
3223 | |
3224 | pub fn python_default_deflate_encoder<I: Write>(input: I) -> DeflateEncoder<I> { |
3225 | |
3226 | === modified file 'tarmac.conf' |
3227 | --- tarmac.conf 2023-01-29 22:40:48 +0000 |
3228 | +++ tarmac.conf 2023-04-17 11:56:43 +0000 |
3229 | @@ -1,6 +1,6 @@ |
3230 | [Tarmac] |
3231 | setup_command = sudo apt -y update && sudo apt -y install cargo rustc python3-venv python3-gpg libpython3-dev make python3-setuptools-rust openssh-client patch mypy flake8 |
3232 | -verify_command = python3 -m venv --system-site-packages . && . bin/activate && ./bin/pip3 install setuptools-gettext && ./bin/pip3 install -e .[dev,doc,pgp,fastimport,launchpad,git,paramiko] && make extensions docs mypy flake8 PYTHON=$PWD/bin/python && BRZ_PLUGIN_PATH=-site:-user ./bin/python -m breezy selftest -v |
3233 | +verify_command = python3 -m venv --system-site-packages . && . bin/activate && ./bin/pip3 install setuptools-gettext && ./bin/pip3 install -e .[dev,doc,pgp,fastimport,launchpad,git,paramiko] && make extensions docs mypy fmt-check PYTHON=$PWD/bin/python && BRZ_PLUGIN_PATH=-site:-user ./bin/python -m breezy selftest -v |
3234 | verify_command_output_timeout = 1800 |
3235 | commit_message_template = <commit_message> |
3236 |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.