Show More
@@ -56,6 +56,7 class _dirstatemapcommon(object): | |||
|
56 | 56 | self._nodelen = 20 # Also update Rust code when changing this! |
|
57 | 57 | self._parents = None |
|
58 | 58 | self._dirtyparents = False |
|
59 | self._docket = None | |
|
59 | 60 | |
|
60 | 61 | # for consistent view between _pl() and _read() invocations |
|
61 | 62 | self._pendingmode = None |
@@ -208,6 +209,93 class _dirstatemapcommon(object): | |||
|
208 | 209 | ) |
|
209 | 210 | self._insert_entry(filename, entry) |
|
210 | 211 | |
|
212 | ### disk interaction | |
|
213 | ||
|
214 | def _opendirstatefile(self): | |
|
215 | fp, mode = txnutil.trypending(self._root, self._opener, self._filename) | |
|
216 | if self._pendingmode is not None and self._pendingmode != mode: | |
|
217 | fp.close() | |
|
218 | raise error.Abort( | |
|
219 | _(b'working directory state may be changed parallelly') | |
|
220 | ) | |
|
221 | self._pendingmode = mode | |
|
222 | return fp | |
|
223 | ||
|
224 | def _readdirstatefile(self, size=-1): | |
|
225 | try: | |
|
226 | with self._opendirstatefile() as fp: | |
|
227 | return fp.read(size) | |
|
228 | except IOError as err: | |
|
229 | if err.errno != errno.ENOENT: | |
|
230 | raise | |
|
231 | # File doesn't exist, so the current state is empty | |
|
232 | return b'' | |
|
233 | ||
|
234 | @property | |
|
235 | def docket(self): | |
|
236 | if not self._docket: | |
|
237 | if not self._use_dirstate_v2: | |
|
238 | raise error.ProgrammingError( | |
|
239 | b'dirstate only has a docket in v2 format' | |
|
240 | ) | |
|
241 | self._docket = docketmod.DirstateDocket.parse( | |
|
242 | self._readdirstatefile(), self._nodeconstants | |
|
243 | ) | |
|
244 | return self._docket | |
|
245 | ||
|
246 | def write_v2_no_append(self, tr, st, meta, packed): | |
|
247 | old_docket = self.docket | |
|
248 | new_docket = docketmod.DirstateDocket.with_new_uuid( | |
|
249 | self.parents(), len(packed), meta | |
|
250 | ) | |
|
251 | data_filename = new_docket.data_filename() | |
|
252 | if tr: | |
|
253 | tr.add(data_filename, 0) | |
|
254 | self._opener.write(data_filename, packed) | |
|
255 | # Write the new docket after the new data file has been | |
|
256 | # written. Because `st` was opened with `atomictemp=True`, | |
|
257 | # the actual `.hg/dirstate` file is only affected on close. | |
|
258 | st.write(new_docket.serialize()) | |
|
259 | st.close() | |
|
260 | # Remove the old data file after the new docket pointing to | |
|
261 | # the new data file was written. | |
|
262 | if old_docket.uuid: | |
|
263 | data_filename = old_docket.data_filename() | |
|
264 | unlink = lambda _tr=None: self._opener.unlink(data_filename) | |
|
265 | if tr: | |
|
266 | category = b"dirstate-v2-clean-" + old_docket.uuid | |
|
267 | tr.addpostclose(category, unlink) | |
|
268 | else: | |
|
269 | unlink() | |
|
270 | self._docket = new_docket | |
|
271 | ||
|
272 | ### reading/setting parents | |
|
273 | ||
|
274 | def parents(self): | |
|
275 | if not self._parents: | |
|
276 | if self._use_dirstate_v2: | |
|
277 | self._parents = self.docket.parents | |
|
278 | else: | |
|
279 | read_len = self._nodelen * 2 | |
|
280 | st = self._readdirstatefile(read_len) | |
|
281 | l = len(st) | |
|
282 | if l == read_len: | |
|
283 | self._parents = ( | |
|
284 | st[: self._nodelen], | |
|
285 | st[self._nodelen : 2 * self._nodelen], | |
|
286 | ) | |
|
287 | elif l == 0: | |
|
288 | self._parents = ( | |
|
289 | self._nodeconstants.nullid, | |
|
290 | self._nodeconstants.nullid, | |
|
291 | ) | |
|
292 | else: | |
|
293 | raise error.Abort( | |
|
294 | _(b'working directory state appears damaged!') | |
|
295 | ) | |
|
296 | ||
|
297 | return self._parents | |
|
298 | ||
|
211 | 299 | |
|
212 | 300 | class dirstatemap(_dirstatemapcommon): |
|
213 | 301 | """Map encapsulating the dirstate's contents. |
@@ -295,36 +383,6 class dirstatemap(_dirstatemapcommon): | |||
|
295 | 383 | |
|
296 | 384 | ### reading/setting parents |
|
297 | 385 | |
|
298 | def parents(self): | |
|
299 | if not self._parents: | |
|
300 | try: | |
|
301 | fp = self._opendirstatefile() | |
|
302 | st = fp.read(2 * self._nodelen) | |
|
303 | fp.close() | |
|
304 | except IOError as err: | |
|
305 | if err.errno != errno.ENOENT: | |
|
306 | raise | |
|
307 | # File doesn't exist, so the current state is empty | |
|
308 | st = b'' | |
|
309 | ||
|
310 | l = len(st) | |
|
311 | if l == self._nodelen * 2: | |
|
312 | self._parents = ( | |
|
313 | st[: self._nodelen], | |
|
314 | st[self._nodelen : 2 * self._nodelen], | |
|
315 | ) | |
|
316 | elif l == 0: | |
|
317 | self._parents = ( | |
|
318 | self._nodeconstants.nullid, | |
|
319 | self._nodeconstants.nullid, | |
|
320 | ) | |
|
321 | else: | |
|
322 | raise error.Abort( | |
|
323 | _(b'working directory state appears damaged!') | |
|
324 | ) | |
|
325 | ||
|
326 | return self._parents | |
|
327 | ||
|
328 | 386 | def setparents(self, p1, p2, fold_p2=False): |
|
329 | 387 | self._parents = (p1, p2) |
|
330 | 388 | self._dirtyparents = True |
@@ -397,16 +455,6 class dirstatemap(_dirstatemapcommon): | |||
|
397 | 455 | st.close() |
|
398 | 456 | self._dirtyparents = False |
|
399 | 457 | |
|
400 | def _opendirstatefile(self): | |
|
401 | fp, mode = txnutil.trypending(self._root, self._opener, self._filename) | |
|
402 | if self._pendingmode is not None and self._pendingmode != mode: | |
|
403 | fp.close() | |
|
404 | raise error.Abort( | |
|
405 | _(b'working directory state may be changed parallelly') | |
|
406 | ) | |
|
407 | self._pendingmode = mode | |
|
408 | return fp | |
|
409 | ||
|
410 | 458 | @propertycache |
|
411 | 459 | def identity(self): |
|
412 | 460 | self._map |
@@ -506,26 +554,9 class dirstatemap(_dirstatemapcommon): | |||
|
506 | 554 | if rustmod is not None: |
|
507 | 555 | |
|
508 | 556 | class dirstatemap(_dirstatemapcommon): |
|
509 | def __init__(self, ui, opener, root, nodeconstants, use_dirstate_v2): | |
|
510 | super(dirstatemap, self).__init__( | |
|
511 | ui, opener, root, nodeconstants, use_dirstate_v2 | |
|
512 | ) | |
|
513 | self._docket = None | |
|
514 | 557 | |
|
515 | 558 | ### Core data storage and access |
|
516 | 559 | |
|
517 | @property | |
|
518 | def docket(self): | |
|
519 | if not self._docket: | |
|
520 | if not self._use_dirstate_v2: | |
|
521 | raise error.ProgrammingError( | |
|
522 | b'dirstate only has a docket in v2 format' | |
|
523 | ) | |
|
524 | self._docket = docketmod.DirstateDocket.parse( | |
|
525 | self._readdirstatefile(), self._nodeconstants | |
|
526 | ) | |
|
527 | return self._docket | |
|
528 | ||
|
529 | 560 | @propertycache |
|
530 | 561 | def _map(self): |
|
531 | 562 | """ |
@@ -616,31 +647,6 if rustmod is not None: | |||
|
616 | 647 | rust_map.set_dirstate_item(f, e) |
|
617 | 648 | return copies |
|
618 | 649 | |
|
619 | def parents(self): | |
|
620 | if not self._parents: | |
|
621 | if self._use_dirstate_v2: | |
|
622 | self._parents = self.docket.parents | |
|
623 | else: | |
|
624 | read_len = self._nodelen * 2 | |
|
625 | st = self._readdirstatefile(read_len) | |
|
626 | l = len(st) | |
|
627 | if l == read_len: | |
|
628 | self._parents = ( | |
|
629 | st[: self._nodelen], | |
|
630 | st[self._nodelen : 2 * self._nodelen], | |
|
631 | ) | |
|
632 | elif l == 0: | |
|
633 | self._parents = ( | |
|
634 | self._nodeconstants.nullid, | |
|
635 | self._nodeconstants.nullid, | |
|
636 | ) | |
|
637 | else: | |
|
638 | raise error.Abort( | |
|
639 | _(b'working directory state appears damaged!') | |
|
640 | ) | |
|
641 | ||
|
642 | return self._parents | |
|
643 | ||
|
644 | 650 | ### disk interaction |
|
645 | 651 | |
|
646 | 652 | @propertycache |
@@ -677,56 +683,11 if rustmod is not None: | |||
|
677 | 683 | st.write(docket.serialize()) |
|
678 | 684 | st.close() |
|
679 | 685 | else: |
|
680 | old_docket = self.docket | |
|
681 | new_docket = docketmod.DirstateDocket.with_new_uuid( | |
|
682 | self.parents(), len(packed), meta | |
|
683 | ) | |
|
684 | data_filename = new_docket.data_filename() | |
|
685 | if tr: | |
|
686 | tr.add(data_filename, 0) | |
|
687 | self._opener.write(data_filename, packed) | |
|
688 | # Write the new docket after the new data file has been | |
|
689 | # written. Because `st` was opened with `atomictemp=True`, | |
|
690 | # the actual `.hg/dirstate` file is only affected on close. | |
|
691 | st.write(new_docket.serialize()) | |
|
692 | st.close() | |
|
693 | # Remove the old data file after the new docket pointing to | |
|
694 | # the new data file was written. | |
|
695 | if old_docket.uuid: | |
|
696 | data_filename = old_docket.data_filename() | |
|
697 | unlink = lambda _tr=None: self._opener.unlink(data_filename) | |
|
698 | if tr: | |
|
699 | category = b"dirstate-v2-clean-" + old_docket.uuid | |
|
700 | tr.addpostclose(category, unlink) | |
|
701 | else: | |
|
702 | unlink() | |
|
703 | self._docket = new_docket | |
|
686 | self.write_v2_no_append(tr, st, meta, packed) | |
|
704 | 687 | # Reload from the newly-written file |
|
705 | 688 | util.clearcachedproperty(self, b"_map") |
|
706 | 689 | self._dirtyparents = False |
|
707 | 690 | |
|
708 | def _opendirstatefile(self): | |
|
709 | fp, mode = txnutil.trypending( | |
|
710 | self._root, self._opener, self._filename | |
|
711 | ) | |
|
712 | if self._pendingmode is not None and self._pendingmode != mode: | |
|
713 | fp.close() | |
|
714 | raise error.Abort( | |
|
715 | _(b'working directory state may be changed parallelly') | |
|
716 | ) | |
|
717 | self._pendingmode = mode | |
|
718 | return fp | |
|
719 | ||
|
720 | def _readdirstatefile(self, size=-1): | |
|
721 | try: | |
|
722 | with self._opendirstatefile() as fp: | |
|
723 | return fp.read(size) | |
|
724 | except IOError as err: | |
|
725 | if err.errno != errno.ENOENT: | |
|
726 | raise | |
|
727 | # File doesn't exist, so the current state is empty | |
|
728 | return b'' | |
|
729 | ||
|
730 | 691 | ### code related to maintaining and accessing "extra" property |
|
731 | 692 | # (e.g. "has_dir") |
|
732 | 693 |
General Comments 0
You need to be logged in to leave comments.
Login now