annotate mercurial/pure/mpatch.py @ 51759:955084b4f74f stable

rhg: ignore readonly FS error when saving dirstate The error is already ignored when the .hg directory is read-only, so this is only fair. (the python hg is silent on readonly fs, too)
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Thu, 01 Aug 2024 13:04:38 +0100
parents 94a797032fc4
children d748fd2647f8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
1 # mpatch.py - Python implementation of mpatch.c
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
2 #
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 45942
diff changeset
3 # Copyright 2009 Olivia Mackall <olivia@selenic.com> and others
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7775
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 8225
diff changeset
6 # GNU General Public License version 2 or any later version.
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
7
27337
9a17576103a4 mpatch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 16683
diff changeset
8
48873
5aafc3c5bdec py3: use io.BytesIO directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 46819
diff changeset
9 import io
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
10 import struct
27337
9a17576103a4 mpatch: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 16683
diff changeset
11
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
12 from typing import (
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
13 List,
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
14 Tuple,
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
15 )
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
16
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
17
48873
5aafc3c5bdec py3: use io.BytesIO directly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 46819
diff changeset
18 stringio = io.BytesIO
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
19
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
20
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
21 class mpatchError(Exception):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 43077
diff changeset
22 """error raised when a delta cannot be decoded"""
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
23
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
24
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
25 # This attempts to apply a series of patches in time proportional to
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
26 # the total size of the patches, rather than patches * len(text). This
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
27 # means rather than shuffling strings around, we shuffle around
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
28 # pointers to fragments with fragment lists.
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
29 #
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
30 # When the fragment lists get too long, we collapse them. To do this
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
31 # efficiently, we do all our operations inside a buffer created by
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
32 # mmap and simply use memmove. This avoids creating a bunch of large
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
33 # temporary string buffers.
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
34
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
35
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
36 def _pull(
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
37 dst: List[Tuple[int, int]], src: List[Tuple[int, int]], l: int
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
38 ) -> None: # pull l bytes from src
28587
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
39 while l:
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
40 f = src.pop()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
41 if f[0] > l: # do we need to split?
28587
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
42 src.append((f[0] - l, f[1] + l))
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
43 dst.append((l, f[1]))
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
44 return
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
45 dst.append(f)
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
46 l -= f[0]
76d7cab13f04 mpatch: move pull() method to top level
Augie Fackler <augie@google.com>
parents: 27337
diff changeset
47
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
48
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
49 def _move(m: stringio, dest: int, src: int, count: int) -> None:
28588
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
50 """move count bytes from src to dest
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
51
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
52 The file pointer is left at the end of dest.
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
53 """
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
54 m.seek(src)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
55 buf = m.read(count)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
56 m.seek(dest)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
57 m.write(buf)
6546afde350e mpatch: un-nest the move() method
Augie Fackler <augie@google.com>
parents: 28587
diff changeset
58
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
59
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
60 def _collect(
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
61 m: stringio, buf: int, list: List[Tuple[int, int]]
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
62 ) -> Tuple[int, int]:
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
63 start = buf
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
64 for l, p in reversed(list):
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
65 _move(m, buf, p, l)
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
66 buf += l
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
67 return (buf - start, start)
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
68
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
69
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
70 def patches(a: bytes, bins: List[bytes]) -> bytes:
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
71 if not bins:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
72 return a
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
73
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
74 plens = [len(x) for x in bins]
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
75 pl = sum(plens)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
76 bl = len(a) + pl
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
77 tl = bl + bl + pl # enough for the patches and two working texts
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
78 b1, b2 = 0, bl
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
79
10282
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
80 if not tl:
08a0f04b56bd many, many trivial check-code fixups
Matt Mackall <mpm@selenic.com>
parents: 10263
diff changeset
81 return a
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
82
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28782
diff changeset
83 m = stringio()
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
84
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
85 # load our original text
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
86 m.write(a)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
87 frags = [(len(a), b1)]
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
88
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
89 # copy all the patches into our segment so we can memmove from them
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
90 pos = b2 + bl
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
91 m.seek(pos)
34435
5326e4ef1dab style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents: 32512
diff changeset
92 for p in bins:
5326e4ef1dab style: never put multiple statements on one line
Alex Gaynor <agaynor@mozilla.com>
parents: 32512
diff changeset
93 m.write(p)
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
94
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
95 for plen in plens:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
96 # if our list gets too long, execute it
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
97 if len(frags) > 128:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
98 b2, b1 = b1, b2
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
99 frags = [_collect(m, b1, frags)]
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
100
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
101 new = []
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
102 end = pos + plen
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
103 last = 0
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
104 while pos < end:
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
105 m.seek(pos)
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
106 try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
107 p1, p2, l = struct.unpack(b">lll", m.read(12))
28782
f736f98e16ca mpatch: unify mpatchError (issue5182)
timeless <timeless@mozdev.org>
parents: 28589
diff changeset
108 except struct.error:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
109 raise mpatchError(b"patch cannot be decoded")
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
110 _pull(new, frags, p1 - last) # what didn't change
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
111 _pull([], frags, p2 - p1) # what got deleted
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
112 new.append((l, pos + 12)) # what got added
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
113 pos += l + 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
114 last = p2
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
115 frags.extend(reversed(new)) # what was left at the end
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
116
28589
c4c7be9f0554 mpatch: move collect() to module level
Augie Fackler <augie@google.com>
parents: 28588
diff changeset
117 t = _collect(m, b2, frags)
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
118
7775
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
119 m.seek(t[1])
5280c39778b6 pure/mpatch: use StringIO instead of mmap (issue1493)
Martin Geisler <mg@daimi.au.dk>
parents: 7699
diff changeset
120 return m.read(t[0])
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
121
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
122
49599
94a797032fc4 typing: add type hints to mpatch implementations
Matt Harbison <matt_harbison@yahoo.com>
parents: 48875
diff changeset
123 def patchedsize(orig: int, delta: bytes) -> int:
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
124 outlen, last, bin = 0, 0, 0
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
125 binend = len(delta)
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
126 data = 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
127
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
128 while data <= binend:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 36958
diff changeset
129 decode = delta[bin : bin + 12]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
130 start, end, length = struct.unpack(b">lll", decode)
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
131 if start > end:
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
132 break
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
133 bin = data + length
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
134 data = bin + 12
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
135 outlen += start - last
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
136 last = end
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
137 outlen += length
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
138
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
139 if bin != binend:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
140 raise mpatchError(b"patch cannot be decoded")
7699
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
141
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
142 outlen += orig - last
fac054f84600 pure Python implementation of mpatch.c
Martin Geisler <mg@daimi.au.dk>
parents:
diff changeset
143 return outlen