Show More
@@ -56,6 +56,7 b' class _dirstatemapcommon(object):' | |||||
56 | self._nodelen = 20 # Also update Rust code when changing this! |
|
56 | self._nodelen = 20 # Also update Rust code when changing this! | |
57 | self._parents = None |
|
57 | self._parents = None | |
58 | self._dirtyparents = False |
|
58 | self._dirtyparents = False | |
|
59 | self._docket = None | |||
59 |
|
60 | |||
60 | # for consistent view between _pl() and _read() invocations |
|
61 | # for consistent view between _pl() and _read() invocations | |
61 | self._pendingmode = None |
|
62 | self._pendingmode = None | |
@@ -208,6 +209,93 b' class _dirstatemapcommon(object):' | |||||
208 | ) |
|
209 | ) | |
209 | self._insert_entry(filename, entry) |
|
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 | class dirstatemap(_dirstatemapcommon): |
|
300 | class dirstatemap(_dirstatemapcommon): | |
213 | """Map encapsulating the dirstate's contents. |
|
301 | """Map encapsulating the dirstate's contents. | |
@@ -295,36 +383,6 b' class dirstatemap(_dirstatemapcommon):' | |||||
295 |
|
383 | |||
296 | ### reading/setting parents |
|
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 | def setparents(self, p1, p2, fold_p2=False): |
|
386 | def setparents(self, p1, p2, fold_p2=False): | |
329 | self._parents = (p1, p2) |
|
387 | self._parents = (p1, p2) | |
330 | self._dirtyparents = True |
|
388 | self._dirtyparents = True | |
@@ -397,16 +455,6 b' class dirstatemap(_dirstatemapcommon):' | |||||
397 | st.close() |
|
455 | st.close() | |
398 | self._dirtyparents = False |
|
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 | @propertycache |
|
458 | @propertycache | |
411 | def identity(self): |
|
459 | def identity(self): | |
412 | self._map |
|
460 | self._map | |
@@ -506,26 +554,9 b' class dirstatemap(_dirstatemapcommon):' | |||||
506 | if rustmod is not None: |
|
554 | if rustmod is not None: | |
507 |
|
555 | |||
508 | class dirstatemap(_dirstatemapcommon): |
|
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 | ### Core data storage and access |
|
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 | @propertycache |
|
560 | @propertycache | |
530 | def _map(self): |
|
561 | def _map(self): | |
531 | """ |
|
562 | """ | |
@@ -616,31 +647,6 b' if rustmod is not None:' | |||||
616 | rust_map.set_dirstate_item(f, e) |
|
647 | rust_map.set_dirstate_item(f, e) | |
617 | return copies |
|
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 | ### disk interaction |
|
650 | ### disk interaction | |
645 |
|
651 | |||
646 | @propertycache |
|
652 | @propertycache | |
@@ -677,56 +683,11 b' if rustmod is not None:' | |||||
677 | st.write(docket.serialize()) |
|
683 | st.write(docket.serialize()) | |
678 | st.close() |
|
684 | st.close() | |
679 | else: |
|
685 | else: | |
680 | old_docket = self.docket |
|
686 | self.write_v2_no_append(tr, st, meta, packed) | |
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 |
|
|||
704 | # Reload from the newly-written file |
|
687 | # Reload from the newly-written file | |
705 | util.clearcachedproperty(self, b"_map") |
|
688 | util.clearcachedproperty(self, b"_map") | |
706 | self._dirtyparents = False |
|
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 | ### code related to maintaining and accessing "extra" property |
|
691 | ### code related to maintaining and accessing "extra" property | |
731 | # (e.g. "has_dir") |
|
692 | # (e.g. "has_dir") | |
732 |
|
693 |
General Comments 0
You need to be logged in to leave comments.
Login now