Show More
@@ -395,7 +395,6 class changelog(revlog.revlog): | |||||
395 | ``concurrencychecker`` will be passed to the revlog init function, see |
|
395 | ``concurrencychecker`` will be passed to the revlog init function, see | |
396 | the documentation there. |
|
396 | the documentation there. | |
397 | """ |
|
397 | """ | |
398 |
|
||||
399 | revlog.revlog.__init__( |
|
398 | revlog.revlog.__init__( | |
400 | self, |
|
399 | self, | |
401 | opener, |
|
400 | opener, | |
@@ -484,6 +483,8 class changelog(revlog.revlog): | |||||
484 | def _writepending(self, tr): |
|
483 | def _writepending(self, tr): | |
485 | """create a file containing the unfinalized state for |
|
484 | """create a file containing the unfinalized state for | |
486 | pretxnchangegroup""" |
|
485 | pretxnchangegroup""" | |
|
486 | if self._docket: | |||
|
487 | return self._docket.write(tr, pending=True) | |||
487 | if self._delaybuf: |
|
488 | if self._delaybuf: | |
488 | # make a temporary copy of the index |
|
489 | # make a temporary copy of the index | |
489 | fp1 = self._realopener(self._indexfile) |
|
490 | fp1 = self._realopener(self._indexfile) |
@@ -1150,7 +1150,6 coreconfigitem( | |||||
1150 | ) |
|
1150 | ) | |
1151 | # "out of experimental" todo list. |
|
1151 | # "out of experimental" todo list. | |
1152 | # |
|
1152 | # | |
1153 | # * expose transaction content hooks during pre-commit validation |
|
|||
1154 | # * include management of a persistent nodemap in the main docket |
|
1153 | # * include management of a persistent nodemap in the main docket | |
1155 | # * enforce a "no-truncate" policy for mmap safety |
|
1154 | # * enforce a "no-truncate" policy for mmap safety | |
1156 | # - for censoring operation |
|
1155 | # - for censoring operation |
@@ -529,7 +529,9 class revlog(object): | |||||
529 | if self._initempty: |
|
529 | if self._initempty: | |
530 | self._docket = docketutil.default_docket(self, header) |
|
530 | self._docket = docketutil.default_docket(self, header) | |
531 | else: |
|
531 | else: | |
532 |
self._docket = docketutil.parse_docket( |
|
532 | self._docket = docketutil.parse_docket( | |
|
533 | self, entry_data, use_pending=self._trypending | |||
|
534 | ) | |||
533 | self._indexfile = self._docket.index_filepath() |
|
535 | self._indexfile = self._docket.index_filepath() | |
534 | index_data = b'' |
|
536 | index_data = b'' | |
535 | index_size = self._docket.index_end |
|
537 | index_size = self._docket.index_end |
@@ -19,6 +19,10 from __future__ import absolute_import | |||||
19 |
|
19 | |||
20 | import struct |
|
20 | import struct | |
21 |
|
21 | |||
|
22 | from .. import ( | |||
|
23 | error, | |||
|
24 | ) | |||
|
25 | ||||
22 | from . import ( |
|
26 | from . import ( | |
23 | constants, |
|
27 | constants, | |
24 | ) |
|
28 | ) | |
@@ -29,19 +33,35 from . import ( | |||||
29 | # | This is mandatory as docket must be compatible with the previous |
|
33 | # | This is mandatory as docket must be compatible with the previous | |
30 | # | revlog index header. |
|
34 | # | revlog index header. | |
31 | # * 8 bytes: size of index data |
|
35 | # * 8 bytes: size of index data | |
32 | S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'L') |
|
36 | # * 8 bytes: pending size of index data | |
|
37 | S_HEADER = struct.Struct(constants.INDEX_HEADER.format + 'LL') | |||
33 |
|
38 | |||
34 |
|
39 | |||
35 | class RevlogDocket(object): |
|
40 | class RevlogDocket(object): | |
36 | """metadata associated with revlog""" |
|
41 | """metadata associated with revlog""" | |
37 |
|
42 | |||
38 | def __init__(self, revlog, version_header=None, index_end=0): |
|
43 | def __init__( | |
|
44 | self, | |||
|
45 | revlog, | |||
|
46 | use_pending=False, | |||
|
47 | version_header=None, | |||
|
48 | index_end=0, | |||
|
49 | pending_index_end=0, | |||
|
50 | ): | |||
39 | self._version_header = version_header |
|
51 | self._version_header = version_header | |
|
52 | self._read_only = bool(use_pending) | |||
40 | self._dirty = False |
|
53 | self._dirty = False | |
41 | self._radix = revlog.radix |
|
54 | self._radix = revlog.radix | |
42 | self._path = revlog._docket_file |
|
55 | self._path = revlog._docket_file | |
43 | self._opener = revlog.opener |
|
56 | self._opener = revlog.opener | |
44 | self._index_end = index_end |
|
57 | # this assert should be True as long as we have a single index filename | |
|
58 | assert index_end <= pending_index_end | |||
|
59 | self._initial_index_end = index_end | |||
|
60 | self._pending_index_end = pending_index_end | |||
|
61 | if use_pending: | |||
|
62 | self._index_end = self._pending_index_end | |||
|
63 | else: | |||
|
64 | self._index_end = self._initial_index_end | |||
45 |
|
65 | |||
46 | def index_filepath(self): |
|
66 | def index_filepath(self): | |
47 | """file path to the current index file associated to this docket""" |
|
67 | """file path to the current index file associated to this docket""" | |
@@ -58,22 +78,38 class RevlogDocket(object): | |||||
58 | self._index_end = new_size |
|
78 | self._index_end = new_size | |
59 | self._dirty = True |
|
79 | self._dirty = True | |
60 |
|
80 | |||
61 | def write(self, transaction, stripping=False): |
|
81 | def write(self, transaction, pending=False, stripping=False): | |
62 | """write the modification of disk if any |
|
82 | """write the modification of disk if any | |
63 |
|
83 | |||
64 | This make the new content visible to all process""" |
|
84 | This make the new content visible to all process""" | |
65 | if self._dirty: |
|
85 | if not self._dirty: | |
|
86 | return False | |||
|
87 | else: | |||
|
88 | if self._read_only: | |||
|
89 | msg = b'writing read-only docket: %s' | |||
|
90 | msg %= self._path | |||
|
91 | raise error.ProgrammingError(msg) | |||
66 | if not stripping: |
|
92 | if not stripping: | |
67 | # XXX we could, leverage the docket while stripping. However it |
|
93 | # XXX we could, leverage the docket while stripping. However it | |
68 | # is not powerfull enough at the time of this comment |
|
94 | # is not powerfull enough at the time of this comment | |
69 | transaction.addbackup(self._path, location=b'store') |
|
95 | transaction.addbackup(self._path, location=b'store') | |
70 | with self._opener(self._path, mode=b'w', atomictemp=True) as f: |
|
96 | with self._opener(self._path, mode=b'w', atomictemp=True) as f: | |
71 | f.write(self._serialize()) |
|
97 | f.write(self._serialize(pending=pending)) | |
72 | self._dirty = False |
|
98 | # if pending we still need to the write final data eventually | |
|
99 | self._dirty = pending | |||
|
100 | return True | |||
73 |
|
101 | |||
74 | def _serialize(self): |
|
102 | def _serialize(self, pending=False): | |
|
103 | if pending: | |||
|
104 | official_index_end = self._initial_index_end | |||
|
105 | else: | |||
|
106 | official_index_end = self._index_end | |||
|
107 | ||||
|
108 | # this assert should be True as long as we have a single index filename | |||
|
109 | assert official_index_end <= self._index_end | |||
75 | data = ( |
|
110 | data = ( | |
76 | self._version_header, |
|
111 | self._version_header, | |
|
112 | official_index_end, | |||
77 | self._index_end, |
|
113 | self._index_end, | |
78 | ) |
|
114 | ) | |
79 | return S_HEADER.pack(*data) |
|
115 | return S_HEADER.pack(*data) | |
@@ -88,13 +124,15 def default_docket(revlog, version_heade | |||||
88 | return docket |
|
124 | return docket | |
89 |
|
125 | |||
90 |
|
126 | |||
91 | def parse_docket(revlog, data): |
|
127 | def parse_docket(revlog, data, use_pending=False): | |
92 | """given some docket data return a docket object for the given revlog""" |
|
128 | """given some docket data return a docket object for the given revlog""" | |
93 | header = S_HEADER.unpack(data[: S_HEADER.size]) |
|
129 | header = S_HEADER.unpack(data[: S_HEADER.size]) | |
94 | version_header, index_size = header |
|
130 | version_header, index_size, pending_index_size = header | |
95 | docket = RevlogDocket( |
|
131 | docket = RevlogDocket( | |
96 | revlog, |
|
132 | revlog, | |
|
133 | use_pending=use_pending, | |||
97 | version_header=version_header, |
|
134 | version_header=version_header, | |
98 | index_end=index_size, |
|
135 | index_end=index_size, | |
|
136 | pending_index_end=pending_index_size, | |||
99 | ) |
|
137 | ) | |
100 | return docket |
|
138 | return docket |
@@ -46,13 +46,13 synchronisation+output script: | |||||
46 | $ cat << EOF > script/external.sh |
|
46 | $ cat << EOF > script/external.sh | |
47 | > #!/bin/sh |
|
47 | > #!/bin/sh | |
48 | > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_UNLOCK $HG_TEST_FILE_EXT_WAITING |
|
48 | > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_UNLOCK $HG_TEST_FILE_EXT_WAITING | |
49 |
> hg log --rev 'tip' -T 'external: {rev} {desc}\n' > $TESTTMP/output/external.out |
|
49 | > hg log --rev 'tip' -T 'external: {rev} {desc}\n' > $TESTTMP/output/external.out | |
50 | > touch $HG_TEST_FILE_EXT_DONE |
|
50 | > touch $HG_TEST_FILE_EXT_DONE | |
51 | > EOF |
|
51 | > EOF | |
52 | $ chmod +x script/external.sh |
|
52 | $ chmod +x script/external.sh | |
53 | $ cat << EOF > script/internal.sh |
|
53 | $ cat << EOF > script/internal.sh | |
54 | > #!/bin/sh |
|
54 | > #!/bin/sh | |
55 |
> hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > $TESTTMP/output/internal.out |
|
55 | > hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > $TESTTMP/output/internal.out | |
56 | > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_DONE $HG_TEST_FILE_EXT_UNLOCK |
|
56 | > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_DONE $HG_TEST_FILE_EXT_UNLOCK | |
57 | > EOF |
|
57 | > EOF | |
58 | $ chmod +x script/internal.sh |
|
58 | $ chmod +x script/internal.sh | |
@@ -124,8 +124,7 the repository should still be inline (f | |||||
124 | $ make_one_commit first |
|
124 | $ make_one_commit first | |
125 | pre-commit: -1 |
|
125 | pre-commit: -1 | |
126 | external: -1 |
|
126 | external: -1 | |
127 |
internal: 0 first |
|
127 | internal: 0 first | |
128 | internal: -1 (revlogv2 known-bad-output !) |
|
|||
129 | post-tr: 0 first |
|
128 | post-tr: 0 first | |
130 |
|
129 | |||
131 | #if revlogv1 |
|
130 | #if revlogv1 | |
@@ -150,8 +149,7 the repository should still be inline (f | |||||
150 | $ make_one_commit second |
|
149 | $ make_one_commit second | |
151 | pre-commit: 0 first |
|
150 | pre-commit: 0 first | |
152 | external: 0 first |
|
151 | external: 0 first | |
153 |
internal: 1 second |
|
152 | internal: 1 second | |
154 | internal: 0 first (revlogv2 known-bad-output !) |
|
|||
155 | post-tr: 1 second |
|
153 | post-tr: 1 second | |
156 |
|
154 | |||
157 | #if revlogv1 |
|
155 | #if revlogv1 | |
@@ -177,8 +175,7 the repository should still be inline (f | |||||
177 | pre-commit: 1 second |
|
175 | pre-commit: 1 second | |
178 | warning: repository is unrelated |
|
176 | warning: repository is unrelated | |
179 | external: 1 second |
|
177 | external: 1 second | |
180 |
internal: 5 r3 |
|
178 | internal: 5 r3 | |
181 | internal: 1 second (revlogv2 known-bad-output !) |
|
|||
182 | post-tr: 5 r3 |
|
179 | post-tr: 5 r3 | |
183 |
|
180 | |||
184 | #if revlogv1 |
|
181 | #if revlogv1 | |
@@ -203,8 +200,7 the repository should no longer be inlin | |||||
203 | $ make_one_pull 400 |
|
200 | $ make_one_pull 400 | |
204 | pre-commit: 5 r3 |
|
201 | pre-commit: 5 r3 | |
205 | external: 5 r3 |
|
202 | external: 5 r3 | |
206 |
internal: 402 r400 |
|
203 | internal: 402 r400 | |
207 | internal: 5 r3 (revlogv2 known-bad-output !) |
|
|||
208 | post-tr: 402 r400 |
|
204 | post-tr: 402 r400 | |
209 |
|
205 | |||
210 | #if revlogv1 |
|
206 | #if revlogv1 | |
@@ -229,8 +225,7 the repository should no longer be inlin | |||||
229 | $ make_one_commit third |
|
225 | $ make_one_commit third | |
230 | pre-commit: 402 r400 |
|
226 | pre-commit: 402 r400 | |
231 | external: 402 r400 |
|
227 | external: 402 r400 | |
232 |
internal: 403 third |
|
228 | internal: 403 third | |
233 | internal: 402 r400 (revlogv2 known-bad-output !) |
|
|||
234 | post-tr: 403 third |
|
229 | post-tr: 403 third | |
235 |
|
230 | |||
236 | #if revlogv1 |
|
231 | #if revlogv1 | |
@@ -256,8 +251,7 the repository should no longer be inlin | |||||
256 | $ make_one_pull tip |
|
251 | $ make_one_pull tip | |
257 | pre-commit: 403 third |
|
252 | pre-commit: 403 third | |
258 | external: 403 third |
|
253 | external: 403 third | |
259 |
internal: 503 r500 |
|
254 | internal: 503 r500 | |
260 | internal: 403 third (revlogv2 known-bad-output !) |
|
|||
261 | post-tr: 503 r500 |
|
255 | post-tr: 503 r500 | |
262 |
|
256 | |||
263 | #if revlogv1 |
|
257 | #if revlogv1 |
General Comments 0
You need to be logged in to leave comments.
Login now