##// END OF EJS Templates
dirstate: Move more methods to the _dirstatemapcommon base class...
Simon Sapin -
r49034:e7b5e8ba default
parent child Browse files
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