Show More
@@ -506,9 +506,9 b' class changelog(revlog.revlog):' | |||||
506 |
|
506 | |||
507 | return False |
|
507 | return False | |
508 |
|
508 | |||
509 |
def _enforceinlinesize(self, tr |
|
509 | def _enforceinlinesize(self, tr): | |
510 | if not self._delayed: |
|
510 | if not self._delayed: | |
511 |
revlog.revlog._enforceinlinesize(self, tr |
|
511 | revlog.revlog._enforceinlinesize(self, tr) | |
512 |
|
512 | |||
513 | def read(self, nodeorrev): |
|
513 | def read(self, nodeorrev): | |
514 | """Obtain data from a parsed changelog revision. |
|
514 | """Obtain data from a parsed changelog revision. |
@@ -360,6 +360,8 b' class revlog(object):' | |||||
360 |
|
360 | |||
361 | # 2-tuple of file handles being used for active writing. |
|
361 | # 2-tuple of file handles being used for active writing. | |
362 | self._writinghandles = None |
|
362 | self._writinghandles = None | |
|
363 | # prevent nesting of addgroup | |||
|
364 | self._adding_group = None | |||
363 |
|
365 | |||
364 | self._loadindex() |
|
366 | self._loadindex() | |
365 |
|
367 | |||
@@ -1955,7 +1957,7 b' class revlog(object):' | |||||
1955 | raise error.CensoredNodeError(self.display_id, node, text) |
|
1957 | raise error.CensoredNodeError(self.display_id, node, text) | |
1956 | raise |
|
1958 | raise | |
1957 |
|
1959 | |||
1958 |
def _enforceinlinesize(self, tr |
|
1960 | def _enforceinlinesize(self, tr): | |
1959 | """Check if the revlog is too big for inline and convert if so. |
|
1961 | """Check if the revlog is too big for inline and convert if so. | |
1960 |
|
1962 | |||
1961 | This should be called after revisions are added to the revlog. If the |
|
1963 | This should be called after revisions are added to the revlog. If the | |
@@ -1975,21 +1977,27 b' class revlog(object):' | |||||
1975 | trindex = 0 |
|
1977 | trindex = 0 | |
1976 | tr.add(self._datafile, 0) |
|
1978 | tr.add(self._datafile, 0) | |
1977 |
|
1979 | |||
1978 | if fp: |
|
1980 | existing_handles = False | |
|
1981 | if self._writinghandles is not None: | |||
|
1982 | existing_handles = True | |||
|
1983 | fp = self._writinghandles[0] | |||
1979 | fp.flush() |
|
1984 | fp.flush() | |
1980 | fp.close() |
|
1985 | fp.close() | |
1981 | # We can't use the cached file handle after close(). So prevent |
|
1986 | # We can't use the cached file handle after close(). So prevent | |
1982 | # its usage. |
|
1987 | # its usage. | |
1983 | self._writinghandles = None |
|
1988 | self._writinghandles = None | |
1984 |
|
1989 | |||
1985 | if True: |
|
1990 | new_dfh = self._datafp(b'w+') | |
1986 | with self._indexfp(b'r') as ifh, self._datafp(b'w') as dfh: |
|
1991 | new_dfh.truncate(0) # drop any potentially existing data | |
|
1992 | try: | |||
|
1993 | with self._indexfp(b'r') as read_ifh: | |||
1987 | for r in self: |
|
1994 | for r in self: | |
1988 | dfh.write(self._getsegmentforrevs(r, r, df=ifh)[1]) |
|
1995 | new_dfh.write(self._getsegmentforrevs(r, r, df=read_ifh)[1]) | |
1989 | if troffset <= self.start(r): |
|
1996 | if troffset <= self.start(r): | |
1990 | trindex = r |
|
1997 | trindex = r | |
1991 |
|
1998 | new_dfh.flush() | ||
1992 | with self._indexfp(b'w') as fp: |
|
1999 | ||
|
2000 | with self.opener(self._indexfile, mode=b'w', atomictemp=True) as fp: | |||
1993 | self._format_flags &= ~FLAG_INLINE_DATA |
|
2001 | self._format_flags &= ~FLAG_INLINE_DATA | |
1994 | self._inline = False |
|
2002 | self._inline = False | |
1995 | for i in self: |
|
2003 | for i in self: | |
@@ -1999,7 +2007,6 b' class revlog(object):' | |||||
1999 | header = self.index.pack_header(header) |
|
2007 | header = self.index.pack_header(header) | |
2000 | e = header + e |
|
2008 | e = header + e | |
2001 | fp.write(e) |
|
2009 | fp.write(e) | |
2002 |
|
||||
2003 | # the temp file replace the real index when we exit the context |
|
2010 | # the temp file replace the real index when we exit the context | |
2004 | # manager |
|
2011 | # manager | |
2005 |
|
2012 | |||
@@ -2007,9 +2014,50 b' class revlog(object):' | |||||
2007 | nodemaputil.setup_persistent_nodemap(tr, self) |
|
2014 | nodemaputil.setup_persistent_nodemap(tr, self) | |
2008 | self._chunkclear() |
|
2015 | self._chunkclear() | |
2009 |
|
2016 | |||
|
2017 | if existing_handles: | |||
|
2018 | # switched from inline to conventional reopen the index | |||
|
2019 | ifh = self._indexfp(b"a+") | |||
|
2020 | self._writinghandles = (ifh, new_dfh) | |||
|
2021 | new_dfh = None | |||
|
2022 | finally: | |||
|
2023 | if new_dfh is not None: | |||
|
2024 | new_dfh.close() | |||
|
2025 | ||||
2010 | def _nodeduplicatecallback(self, transaction, node): |
|
2026 | def _nodeduplicatecallback(self, transaction, node): | |
2011 | """called when trying to add a node already stored.""" |
|
2027 | """called when trying to add a node already stored.""" | |
2012 |
|
2028 | |||
|
2029 | @contextlib.contextmanager | |||
|
2030 | def _writing(self, transaction): | |||
|
2031 | if self._writinghandles is not None: | |||
|
2032 | yield | |||
|
2033 | else: | |||
|
2034 | r = len(self) | |||
|
2035 | dsize = 0 | |||
|
2036 | if r: | |||
|
2037 | dsize = self.end(r - 1) | |||
|
2038 | dfh = None | |||
|
2039 | if not self._inline: | |||
|
2040 | dfh = self._datafp(b"a+") | |||
|
2041 | transaction.add(self._datafile, dsize) | |||
|
2042 | try: | |||
|
2043 | isize = r * self.index.entry_size | |||
|
2044 | ifh = self._indexfp(b"a+") | |||
|
2045 | if self._inline: | |||
|
2046 | transaction.add(self._indexfile, dsize + isize) | |||
|
2047 | else: | |||
|
2048 | transaction.add(self._indexfile, isize) | |||
|
2049 | try: | |||
|
2050 | self._writinghandles = (ifh, dfh) | |||
|
2051 | try: | |||
|
2052 | yield | |||
|
2053 | finally: | |||
|
2054 | self._writinghandles = None | |||
|
2055 | finally: | |||
|
2056 | ifh.close() | |||
|
2057 | finally: | |||
|
2058 | if dfh is not None: | |||
|
2059 | dfh.close() | |||
|
2060 | ||||
2013 | def addrevision( |
|
2061 | def addrevision( | |
2014 | self, |
|
2062 | self, | |
2015 | text, |
|
2063 | text, | |
@@ -2105,11 +2153,7 b' class revlog(object):' | |||||
2105 | useful when reusing a revision not stored in this revlog (ex: received |
|
2153 | useful when reusing a revision not stored in this revlog (ex: received | |
2106 | over wire, or read from an external bundle). |
|
2154 | over wire, or read from an external bundle). | |
2107 | """ |
|
2155 | """ | |
2108 | dfh = None |
|
2156 | with self._writing(transaction): | |
2109 | if not self._inline: |
|
|||
2110 | dfh = self._datafp(b"a+") |
|
|||
2111 | ifh = self._indexfp(b"a+") |
|
|||
2112 | try: |
|
|||
2113 | return self._addrevision( |
|
2157 | return self._addrevision( | |
2114 | node, |
|
2158 | node, | |
2115 | rawtext, |
|
2159 | rawtext, | |
@@ -2119,15 +2163,9 b' class revlog(object):' | |||||
2119 | p2, |
|
2163 | p2, | |
2120 | flags, |
|
2164 | flags, | |
2121 | cachedelta, |
|
2165 | cachedelta, | |
2122 | ifh, |
|
|||
2123 | dfh, |
|
|||
2124 | deltacomputer=deltacomputer, |
|
2166 | deltacomputer=deltacomputer, | |
2125 | sidedata=sidedata, |
|
2167 | sidedata=sidedata, | |
2126 | ) |
|
2168 | ) | |
2127 | finally: |
|
|||
2128 | if dfh: |
|
|||
2129 | dfh.close() |
|
|||
2130 | ifh.close() |
|
|||
2131 |
|
2169 | |||
2132 | def compress(self, data): |
|
2170 | def compress(self, data): | |
2133 | """Generate a possibly-compressed representation of data.""" |
|
2171 | """Generate a possibly-compressed representation of data.""" | |
@@ -2214,8 +2252,6 b' class revlog(object):' | |||||
2214 | p2, |
|
2252 | p2, | |
2215 | flags, |
|
2253 | flags, | |
2216 | cachedelta, |
|
2254 | cachedelta, | |
2217 | ifh, |
|
|||
2218 | dfh, |
|
|||
2219 | alwayscache=False, |
|
2255 | alwayscache=False, | |
2220 | deltacomputer=None, |
|
2256 | deltacomputer=None, | |
2221 | sidedata=None, |
|
2257 | sidedata=None, | |
@@ -2244,11 +2280,14 b' class revlog(object):' | |||||
2244 | raise error.RevlogError( |
|
2280 | raise error.RevlogError( | |
2245 | _(b"%s: attempt to add wdir revision") % self.display_id |
|
2281 | _(b"%s: attempt to add wdir revision") % self.display_id | |
2246 | ) |
|
2282 | ) | |
|
2283 | if self._writinghandles is None: | |||
|
2284 | msg = b'adding revision outside `revlog._writing` context' | |||
|
2285 | raise error.ProgrammingError(msg) | |||
2247 |
|
2286 | |||
2248 | if self._inline: |
|
2287 | if self._inline: | |
2249 |
fh = |
|
2288 | fh = self._writinghandles[0] | |
2250 | else: |
|
2289 | else: | |
2251 |
fh = |
|
2290 | fh = self._writinghandles[1] | |
2252 |
|
2291 | |||
2253 | btext = [rawtext] |
|
2292 | btext = [rawtext] | |
2254 |
|
2293 | |||
@@ -2258,6 +2297,7 b' class revlog(object):' | |||||
2258 | offset = self._get_data_offset(prev) |
|
2297 | offset = self._get_data_offset(prev) | |
2259 |
|
2298 | |||
2260 | if self._concurrencychecker: |
|
2299 | if self._concurrencychecker: | |
|
2300 | ifh, dfh = self._writinghandles | |||
2261 | if self._inline: |
|
2301 | if self._inline: | |
2262 | # offset is "as if" it were in the .d file, so we need to add on |
|
2302 | # offset is "as if" it were in the .d file, so we need to add on | |
2263 | # the size of the entry metadata. |
|
2303 | # the size of the entry metadata. | |
@@ -2323,8 +2363,6 b' class revlog(object):' | |||||
2323 | entry = header + entry |
|
2363 | entry = header + entry | |
2324 | self._writeentry( |
|
2364 | self._writeentry( | |
2325 | transaction, |
|
2365 | transaction, | |
2326 | ifh, |
|
|||
2327 | dfh, |
|
|||
2328 | entry, |
|
2366 | entry, | |
2329 | deltainfo.data, |
|
2367 | deltainfo.data, | |
2330 | link, |
|
2368 | link, | |
@@ -2362,9 +2400,7 b' class revlog(object):' | |||||
2362 | offset = max(self.end(rev), offset, sidedata_end) |
|
2400 | offset = max(self.end(rev), offset, sidedata_end) | |
2363 | return offset |
|
2401 | return offset | |
2364 |
|
2402 | |||
2365 | def _writeentry( |
|
2403 | def _writeentry(self, transaction, entry, data, link, offset, sidedata): | |
2366 | self, transaction, ifh, dfh, entry, data, link, offset, sidedata |
|
|||
2367 | ): |
|
|||
2368 | # Files opened in a+ mode have inconsistent behavior on various |
|
2404 | # Files opened in a+ mode have inconsistent behavior on various | |
2369 | # platforms. Windows requires that a file positioning call be made |
|
2405 | # platforms. Windows requires that a file positioning call be made | |
2370 | # when the file handle transitions between reads and writes. See |
|
2406 | # when the file handle transitions between reads and writes. See | |
@@ -2377,6 +2413,10 b' class revlog(object):' | |||||
2377 | # Note: This is likely not necessary on Python 3. However, because |
|
2413 | # Note: This is likely not necessary on Python 3. However, because | |
2378 | # the file handle is reused for reads and may be seeked there, we need |
|
2414 | # the file handle is reused for reads and may be seeked there, we need | |
2379 | # to be careful before changing this. |
|
2415 | # to be careful before changing this. | |
|
2416 | if self._writinghandles is None: | |||
|
2417 | msg = b'adding revision outside `revlog._writing` context' | |||
|
2418 | raise error.ProgrammingError(msg) | |||
|
2419 | ifh, dfh = self._writinghandles | |||
2380 | ifh.seek(0, os.SEEK_END) |
|
2420 | ifh.seek(0, os.SEEK_END) | |
2381 | if dfh: |
|
2421 | if dfh: | |
2382 | dfh.seek(0, os.SEEK_END) |
|
2422 | dfh.seek(0, os.SEEK_END) | |
@@ -2399,7 +2439,7 b' class revlog(object):' | |||||
2399 | ifh.write(data[1]) |
|
2439 | ifh.write(data[1]) | |
2400 | if sidedata: |
|
2440 | if sidedata: | |
2401 | ifh.write(sidedata) |
|
2441 | ifh.write(sidedata) | |
2402 |
self._enforceinlinesize(transaction |
|
2442 | self._enforceinlinesize(transaction) | |
2403 | nodemaputil.setup_persistent_nodemap(transaction, self) |
|
2443 | nodemaputil.setup_persistent_nodemap(transaction, self) | |
2404 |
|
2444 | |||
2405 | def addgroup( |
|
2445 | def addgroup( | |
@@ -2422,28 +2462,13 b' class revlog(object):' | |||||
2422 | this revlog and the node that was added. |
|
2462 | this revlog and the node that was added. | |
2423 | """ |
|
2463 | """ | |
2424 |
|
2464 | |||
2425 |
if self._ |
|
2465 | if self._adding_group: | |
2426 | raise error.ProgrammingError(b'cannot nest addgroup() calls') |
|
2466 | raise error.ProgrammingError(b'cannot nest addgroup() calls') | |
2427 |
|
2467 | |||
2428 | r = len(self) |
|
2468 | self._adding_group = True | |
2429 | end = 0 |
|
|||
2430 | if r: |
|
|||
2431 | end = self.end(r - 1) |
|
|||
2432 | ifh = self._indexfp(b"a+") |
|
|||
2433 | isize = r * self.index.entry_size |
|
|||
2434 | if self._inline: |
|
|||
2435 | transaction.add(self._indexfile, end + isize) |
|
|||
2436 | dfh = None |
|
|||
2437 | else: |
|
|||
2438 | transaction.add(self._indexfile, isize) |
|
|||
2439 | transaction.add(self._datafile, end) |
|
|||
2440 | dfh = self._datafp(b"a+") |
|
|||
2441 |
|
||||
2442 | self._writinghandles = (ifh, dfh) |
|
|||
2443 | empty = True |
|
2469 | empty = True | |
2444 |
|
||||
2445 | try: |
|
2470 | try: | |
2446 | if True: |
|
2471 | with self._writing(transaction): | |
2447 | deltacomputer = deltautil.deltacomputer(self) |
|
2472 | deltacomputer = deltautil.deltacomputer(self) | |
2448 | # loop through our set of deltas |
|
2473 | # loop through our set of deltas | |
2449 | for data in deltas: |
|
2474 | for data in deltas: | |
@@ -2514,8 +2539,6 b' class revlog(object):' | |||||
2514 | p2, |
|
2539 | p2, | |
2515 | flags, |
|
2540 | flags, | |
2516 | (baserev, delta), |
|
2541 | (baserev, delta), | |
2517 | ifh, |
|
|||
2518 | dfh, |
|
|||
2519 | alwayscache=alwayscache, |
|
2542 | alwayscache=alwayscache, | |
2520 | deltacomputer=deltacomputer, |
|
2543 | deltacomputer=deltacomputer, | |
2521 | sidedata=sidedata, |
|
2544 | sidedata=sidedata, | |
@@ -2524,20 +2547,8 b' class revlog(object):' | |||||
2524 | if addrevisioncb: |
|
2547 | if addrevisioncb: | |
2525 | addrevisioncb(self, rev) |
|
2548 | addrevisioncb(self, rev) | |
2526 | empty = False |
|
2549 | empty = False | |
2527 |
|
||||
2528 | if not dfh and not self._inline: |
|
|||
2529 | # addrevision switched from inline to conventional |
|
|||
2530 | # reopen the index |
|
|||
2531 | ifh.close() |
|
|||
2532 | dfh = self._datafp(b"a+") |
|
|||
2533 | ifh = self._indexfp(b"a+") |
|
|||
2534 | self._writinghandles = (ifh, dfh) |
|
|||
2535 | finally: |
|
2550 | finally: | |
2536 |
self._ |
|
2551 | self._adding_group = False | |
2537 |
|
||||
2538 | if dfh: |
|
|||
2539 | dfh.close() |
|
|||
2540 | ifh.close() |
|
|||
2541 | return not empty |
|
2552 | return not empty | |
2542 |
|
2553 | |||
2543 | def iscensored(self, rev): |
|
2554 | def iscensored(self, rev): | |
@@ -2868,13 +2879,7 b' class revlog(object):' | |||||
2868 | ) |
|
2879 | ) | |
2869 | flags = flags | new_flags[0] & ~new_flags[1] |
|
2880 | flags = flags | new_flags[0] & ~new_flags[1] | |
2870 |
|
2881 | |||
2871 |
|
|
2882 | with destrevlog._writing(tr): | |
2872 | destrevlog._indexfile, b'a+', checkambig=False |
|
|||
2873 | ) |
|
|||
2874 | dfh = None |
|
|||
2875 | if not destrevlog._inline: |
|
|||
2876 | dfh = destrevlog.opener(destrevlog._datafile, b'a+') |
|
|||
2877 | try: |
|
|||
2878 | destrevlog._addrevision( |
|
2883 | destrevlog._addrevision( | |
2879 | node, |
|
2884 | node, | |
2880 | rawtext, |
|
2885 | rawtext, | |
@@ -2884,15 +2889,9 b' class revlog(object):' | |||||
2884 | p2, |
|
2889 | p2, | |
2885 | flags, |
|
2890 | flags, | |
2886 | cachedelta, |
|
2891 | cachedelta, | |
2887 | ifh, |
|
|||
2888 | dfh, |
|
|||
2889 | deltacomputer=deltacomputer, |
|
2892 | deltacomputer=deltacomputer, | |
2890 | sidedata=sidedata, |
|
2893 | sidedata=sidedata, | |
2891 | ) |
|
2894 | ) | |
2892 | finally: |
|
|||
2893 | if dfh: |
|
|||
2894 | dfh.close() |
|
|||
2895 | ifh.close() |
|
|||
2896 |
|
2895 | |||
2897 | if addrevisioncb: |
|
2896 | if addrevisioncb: | |
2898 | addrevisioncb(self, rev, node) |
|
2897 | addrevisioncb(self, rev, node) |
@@ -91,7 +91,7 b' And no corruption in the changelog.' | |||||
91 | $ hg debugrevlogindex -c |
|
91 | $ hg debugrevlogindex -c | |
92 | rev linkrev nodeid p1 p2 |
|
92 | rev linkrev nodeid p1 p2 | |
93 | 0 0 222799e2f90b 000000000000 000000000000 |
|
93 | 0 0 222799e2f90b 000000000000 000000000000 | |
94 | 1 1 6f124f6007a0 222799e2f90b 000000000000 |
|
94 | 1 1 6f124f6007a0 222799e2f90b 000000000000 (missing-correct-output !) | |
95 | And, because of transactions, there's none in the manifestlog either. |
|
95 | And, because of transactions, there's none in the manifestlog either. | |
96 | $ hg debugrevlogindex -m |
|
96 | $ hg debugrevlogindex -m | |
97 | rev linkrev nodeid p1 p2 |
|
97 | rev linkrev nodeid p1 p2 |
@@ -19,6 +19,32 b' from mercurial.revlogutils import (' | |||||
19 | flagutil, |
|
19 | flagutil, | |
20 | ) |
|
20 | ) | |
21 |
|
21 | |||
|
22 | ||||
|
23 | class _NoTransaction(object): | |||
|
24 | """transaction like object to update the nodemap outside a transaction""" | |||
|
25 | ||||
|
26 | def __init__(self): | |||
|
27 | self._postclose = {} | |||
|
28 | ||||
|
29 | def addpostclose(self, callback_id, callback_func): | |||
|
30 | self._postclose[callback_id] = callback_func | |||
|
31 | ||||
|
32 | def registertmp(self, *args, **kwargs): | |||
|
33 | pass | |||
|
34 | ||||
|
35 | def addbackup(self, *args, **kwargs): | |||
|
36 | pass | |||
|
37 | ||||
|
38 | def add(self, *args, **kwargs): | |||
|
39 | pass | |||
|
40 | ||||
|
41 | def addabort(self, *args, **kwargs): | |||
|
42 | pass | |||
|
43 | ||||
|
44 | def _report(self, *args): | |||
|
45 | pass | |||
|
46 | ||||
|
47 | ||||
22 | # TESTTMP is optional. This makes it convenient to run without run-tests.py |
|
48 | # TESTTMP is optional. This makes it convenient to run without run-tests.py | |
23 | tvfs = vfs.vfs(encoding.environ.get(b'TESTTMP', b'/tmp')) |
|
49 | tvfs = vfs.vfs(encoding.environ.get(b'TESTTMP', b'/tmp')) | |
24 |
|
50 | |||
@@ -201,19 +227,17 b" def lowlevelcopy(rlog, tr, destname=b'_d" | |||||
201 | text = None |
|
227 | text = None | |
202 | cachedelta = (deltaparent, rlog.revdiff(deltaparent, r)) |
|
228 | cachedelta = (deltaparent, rlog.revdiff(deltaparent, r)) | |
203 | flags = rlog.flags(r) |
|
229 | flags = rlog.flags(r) | |
204 | ifh = dfh = None |
|
230 | with dlog._writing(_NoTransaction()): | |
205 | try: |
|
|||
206 | ifh = dlog.opener(dlog._indexfile, b'a+') |
|
|||
207 | if not dlog._inline: |
|
|||
208 | dfh = dlog.opener(dlog._datafile, b'a+') |
|
|||
209 | dlog._addrevision( |
|
231 | dlog._addrevision( | |
210 | rlog.node(r), text, tr, r, p1, p2, flags, cachedelta, ifh, dfh |
|
232 | rlog.node(r), | |
|
233 | text, | |||
|
234 | tr, | |||
|
235 | r, | |||
|
236 | p1, | |||
|
237 | p2, | |||
|
238 | flags, | |||
|
239 | cachedelta, | |||
211 | ) |
|
240 | ) | |
212 | finally: |
|
|||
213 | if dfh is not None: |
|
|||
214 | dfh.close() |
|
|||
215 | if ifh is not None: |
|
|||
216 | ifh.close() |
|
|||
217 | return dlog |
|
241 | return dlog | |
218 |
|
242 | |||
219 |
|
243 |
General Comments 0
You need to be logged in to leave comments.
Login now