2086 dsize = self.end(r - 1) |
2086 dsize = self.end(r - 1) |
2087 dfh = None |
2087 dfh = None |
2088 if not self._inline: |
2088 if not self._inline: |
2089 try: |
2089 try: |
2090 dfh = self._datafp(b"r+") |
2090 dfh = self._datafp(b"r+") |
2091 dfh.seek(0, os.SEEK_END) |
2091 if self._docket is None: |
|
2092 dfh.seek(0, os.SEEK_END) |
|
2093 else: |
|
2094 dfh.seek(self._docket.data_end, os.SEEK_SET) |
2092 except IOError as inst: |
2095 except IOError as inst: |
2093 if inst.errno != errno.ENOENT: |
2096 if inst.errno != errno.ENOENT: |
2094 raise |
2097 raise |
2095 dfh = self._datafp(b"w+") |
2098 dfh = self._datafp(b"w+") |
2096 transaction.add(self._datafile, dsize) |
2099 transaction.add(self._datafile, dsize) |
2453 end of the data file within a transaction, you can have cases where, for |
2456 end of the data file within a transaction, you can have cases where, for |
2454 example, rev `n` does not have sidedata while rev `n - 1` does, leading |
2457 example, rev `n` does not have sidedata while rev `n - 1` does, leading |
2455 to `n - 1`'s sidedata being written after `n`'s data. |
2458 to `n - 1`'s sidedata being written after `n`'s data. |
2456 |
2459 |
2457 TODO cache this in a docket file before getting out of experimental.""" |
2460 TODO cache this in a docket file before getting out of experimental.""" |
2458 if self._format_version != REVLOGV2: |
2461 if self._docket is None: |
2459 return self.end(prev) |
2462 return self.end(prev) |
2460 |
2463 else: |
2461 offset = 0 |
2464 return self._docket.data_end |
2462 for rev, entry in enumerate(self.index): |
|
2463 sidedata_end = entry[8] + entry[9] |
|
2464 # Sidedata for a previous rev has potentially been written after |
|
2465 # this rev's end, so take the max. |
|
2466 offset = max(self.end(rev), offset, sidedata_end) |
|
2467 return offset |
|
2468 |
2465 |
2469 def _writeentry(self, transaction, entry, data, link, offset, sidedata): |
2466 def _writeentry(self, transaction, entry, data, link, offset, sidedata): |
2470 # Files opened in a+ mode have inconsistent behavior on various |
2467 # Files opened in a+ mode have inconsistent behavior on various |
2471 # platforms. Windows requires that a file positioning call be made |
2468 # platforms. Windows requires that a file positioning call be made |
2472 # when the file handle transitions between reads and writes. See |
2469 # when the file handle transitions between reads and writes. See |
2486 if self._docket is None: |
2483 if self._docket is None: |
2487 ifh.seek(0, os.SEEK_END) |
2484 ifh.seek(0, os.SEEK_END) |
2488 else: |
2485 else: |
2489 ifh.seek(self._docket.index_end, os.SEEK_SET) |
2486 ifh.seek(self._docket.index_end, os.SEEK_SET) |
2490 if dfh: |
2487 if dfh: |
2491 dfh.seek(0, os.SEEK_END) |
2488 if self._docket is None: |
|
2489 dfh.seek(0, os.SEEK_END) |
|
2490 else: |
|
2491 dfh.seek(self._docket.data_end, os.SEEK_SET) |
2492 |
2492 |
2493 curr = len(self) - 1 |
2493 curr = len(self) - 1 |
2494 if not self._inline: |
2494 if not self._inline: |
2495 transaction.add(self._datafile, offset) |
2495 transaction.add(self._datafile, offset) |
2496 transaction.add(self._indexfile, curr * len(entry)) |
2496 transaction.add(self._indexfile, curr * len(entry)) |
2509 if sidedata: |
2509 if sidedata: |
2510 ifh.write(sidedata) |
2510 ifh.write(sidedata) |
2511 self._enforceinlinesize(transaction) |
2511 self._enforceinlinesize(transaction) |
2512 if self._docket is not None: |
2512 if self._docket is not None: |
2513 self._docket.index_end = self._writinghandles[0].tell() |
2513 self._docket.index_end = self._writinghandles[0].tell() |
|
2514 self._docket.data_end = self._writinghandles[1].tell() |
2514 |
2515 |
2515 nodemaputil.setup_persistent_nodemap(transaction, self) |
2516 nodemaputil.setup_persistent_nodemap(transaction, self) |
2516 |
2517 |
2517 def addgroup( |
2518 def addgroup( |
2518 self, |
2519 self, |
2671 rev, _ = self.getstrippoint(minlink) |
2672 rev, _ = self.getstrippoint(minlink) |
2672 if rev == len(self): |
2673 if rev == len(self): |
2673 return |
2674 return |
2674 |
2675 |
2675 # first truncate the files on disk |
2676 # first truncate the files on disk |
2676 end = self.start(rev) |
2677 data_end = self.start(rev) |
2677 if not self._inline: |
2678 if not self._inline: |
2678 transaction.add(self._datafile, end) |
2679 transaction.add(self._datafile, data_end) |
2679 end = rev * self.index.entry_size |
2680 end = rev * self.index.entry_size |
2680 else: |
2681 else: |
2681 end += rev * self.index.entry_size |
2682 end = data_end + (rev * self.index.entry_size) |
2682 |
2683 |
2683 transaction.add(self._indexfile, end) |
2684 transaction.add(self._indexfile, end) |
2684 if self._docket is not None: |
2685 if self._docket is not None: |
2685 # XXX we could, leverage the docket while stripping. However it is |
2686 # XXX we could, leverage the docket while stripping. However it is |
2686 # not powerfull enough at the time of this comment |
2687 # not powerfull enough at the time of this comment |
2687 self._docket.index_end = end |
2688 self._docket.index_end = end |
|
2689 self._docket.data_end = data_end |
2688 self._docket.write(transaction, stripping=True) |
2690 self._docket.write(transaction, stripping=True) |
2689 |
2691 |
2690 # then reset internal state in memory to forget those revisions |
2692 # then reset internal state in memory to forget those revisions |
2691 self._revisioncache = None |
2693 self._revisioncache = None |
2692 self._chaininfocache = util.lrucachedict(500) |
2694 self._chaininfocache = util.lrucachedict(500) |
3208 |
3210 |
3209 new_entries = [] |
3211 new_entries = [] |
3210 # append the new sidedata |
3212 # append the new sidedata |
3211 with self._writing(transaction): |
3213 with self._writing(transaction): |
3212 ifh, dfh = self._writinghandles |
3214 ifh, dfh = self._writinghandles |
3213 dfh.seek(0, os.SEEK_END) |
3215 if self._docket is not None: |
|
3216 dfh.seek(self._docket.data_end, os.SEEK_SET) |
|
3217 else: |
|
3218 dfh.seek(0, os.SEEK_END) |
|
3219 |
3214 current_offset = dfh.tell() |
3220 current_offset = dfh.tell() |
3215 for rev in range(startrev, endrev + 1): |
3221 for rev in range(startrev, endrev + 1): |
3216 entry = self.index[rev] |
3222 entry = self.index[rev] |
3217 new_sidedata, flags = sidedatautil.run_sidedata_helpers( |
3223 new_sidedata, flags = sidedatautil.run_sidedata_helpers( |
3218 store=self, |
3224 store=self, |
3240 # the sidedata computation might have move the file cursors around |
3246 # the sidedata computation might have move the file cursors around |
3241 dfh.seek(current_offset, os.SEEK_SET) |
3247 dfh.seek(current_offset, os.SEEK_SET) |
3242 dfh.write(serialized_sidedata) |
3248 dfh.write(serialized_sidedata) |
3243 new_entries.append(entry) |
3249 new_entries.append(entry) |
3244 current_offset += len(serialized_sidedata) |
3250 current_offset += len(serialized_sidedata) |
|
3251 if self._docket is not None: |
|
3252 self._docket.data_end = dfh.tell() |
3245 |
3253 |
3246 # rewrite the new index entries |
3254 # rewrite the new index entries |
3247 ifh.seek(startrev * self.index.entry_size) |
3255 ifh.seek(startrev * self.index.entry_size) |
3248 for i, e in enumerate(new_entries): |
3256 for i, e in enumerate(new_entries): |
3249 rev = startrev + i |
3257 rev = startrev + i |