Mercurial > hg
comparison mercurial/dirstate.py @ 48793:6e559391f96e
tracked-key: remove the dual write and rename to tracked-hint
The dual-write approach was mostly useless. As explained in the previous version
of the help, the key had to be read twice before we could cache a value.
However this "read twice" limitation actually also apply to any usage of the
key. If some operation wants to rely of the "same value == same tracked set"
property it would need to read the value before, and after running that
operation (or at least, after, in all cases). So it cannot be sure the operation
it did is "valid" until checking the key after the operation. As a resultat such
operation can only be read-only or rollbackable.
This reduce the utility of the "same value == same tracked set" a lot.
So it seems simpler to drop the double write and to update the documentation to
highlight that this file does not garantee race-free operation. As a result the
"key" is demoted to a "hint".
Documentation is updated accordingly.
Differential Revision: https://phab.mercurial-scm.org/D12201
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Thu, 17 Feb 2022 07:34:49 +0100 |
parents | 5ba24e886cec |
children | 6000f5b25c9b |
comparison
equal
deleted
inserted
replaced
48792:8bbb1abb9d19 | 48793:6e559391f96e |
---|---|
99 root, | 99 root, |
100 validate, | 100 validate, |
101 sparsematchfn, | 101 sparsematchfn, |
102 nodeconstants, | 102 nodeconstants, |
103 use_dirstate_v2, | 103 use_dirstate_v2, |
104 use_tracked_key=False, | 104 use_tracked_hint=False, |
105 ): | 105 ): |
106 """Create a new dirstate object. | 106 """Create a new dirstate object. |
107 | 107 |
108 opener is an open()-like callable that can be used to open the | 108 opener is an open()-like callable that can be used to open the |
109 dirstate file; root is the root of the directory tracked by | 109 dirstate file; root is the root of the directory tracked by |
110 the dirstate. | 110 the dirstate. |
111 """ | 111 """ |
112 self._use_dirstate_v2 = use_dirstate_v2 | 112 self._use_dirstate_v2 = use_dirstate_v2 |
113 self._use_tracked_key = use_tracked_key | 113 self._use_tracked_hint = use_tracked_hint |
114 self._nodeconstants = nodeconstants | 114 self._nodeconstants = nodeconstants |
115 self._opener = opener | 115 self._opener = opener |
116 self._validate = validate | 116 self._validate = validate |
117 self._root = root | 117 self._root = root |
118 self._sparsematchfn = sparsematchfn | 118 self._sparsematchfn = sparsematchfn |
125 self._dirty_tracked_set = False | 125 self._dirty_tracked_set = False |
126 self._ui = ui | 126 self._ui = ui |
127 self._filecache = {} | 127 self._filecache = {} |
128 self._parentwriters = 0 | 128 self._parentwriters = 0 |
129 self._filename = b'dirstate' | 129 self._filename = b'dirstate' |
130 self._filename_tk = b'dirstate-tracked-key' | 130 self._filename_th = b'dirstate-tracked-hint' |
131 self._pendingfilename = b'%s.pending' % self._filename | 131 self._pendingfilename = b'%s.pending' % self._filename |
132 self._plchangecallbacks = {} | 132 self._plchangecallbacks = {} |
133 self._origpl = None | 133 self._origpl = None |
134 self._mapcls = dirstatemap.dirstatemap | 134 self._mapcls = dirstatemap.dirstatemap |
135 # Access and cache cwd early, so we don't access it for the first time | 135 # Access and cache cwd early, so we don't access it for the first time |
719 | 719 |
720 def write(self, tr): | 720 def write(self, tr): |
721 if not self._dirty: | 721 if not self._dirty: |
722 return | 722 return |
723 | 723 |
724 write_key = self._use_tracked_key and self._dirty_tracked_set | 724 write_key = self._use_tracked_hint and self._dirty_tracked_set |
725 if tr: | 725 if tr: |
726 # delay writing in-memory changes out | 726 # delay writing in-memory changes out |
727 if write_key: | |
728 tr.addfilegenerator( | |
729 b'dirstate-0-key-pre', | |
730 (self._filename_tk,), | |
731 lambda f: self._write_tracked_key(tr, f), | |
732 location=b'plain', | |
733 post_finalize=True, | |
734 ) | |
735 tr.addfilegenerator( | 727 tr.addfilegenerator( |
736 b'dirstate-1-main', | 728 b'dirstate-1-main', |
737 (self._filename,), | 729 (self._filename,), |
738 lambda f: self._writedirstate(tr, f), | 730 lambda f: self._writedirstate(tr, f), |
739 location=b'plain', | 731 location=b'plain', |
740 post_finalize=True, | 732 post_finalize=True, |
741 ) | 733 ) |
742 if write_key: | 734 if write_key: |
743 tr.addfilegenerator( | 735 tr.addfilegenerator( |
744 b'dirstate-2-key-post', | 736 b'dirstate-2-key-post', |
745 (self._filename_tk,), | 737 (self._filename_th,), |
746 lambda f: self._write_tracked_key(tr, f), | 738 lambda f: self._write_tracked_hint(tr, f), |
747 location=b'plain', | 739 location=b'plain', |
748 post_finalize=True, | 740 post_finalize=True, |
749 ) | 741 ) |
750 return | 742 return |
751 | 743 |
752 file = lambda f: self._opener(f, b"w", atomictemp=True, checkambig=True) | 744 file = lambda f: self._opener(f, b"w", atomictemp=True, checkambig=True) |
753 if write_key: | |
754 # we change the key-file before changing the dirstate to make sure | |
755 # reading invalidate there cache before we start writing | |
756 with file(self._filename_tk) as f: | |
757 self._write_tracked_key(tr, f) | |
758 with file(self._filename) as f: | 745 with file(self._filename) as f: |
759 self._writedirstate(tr, f) | 746 self._writedirstate(tr, f) |
760 if write_key: | 747 if write_key: |
761 # we update the key-file after writing to make sure reader have a | 748 # we update the key-file after writing to make sure reader have a |
762 # key that match the newly written content | 749 # key that match the newly written content |
763 with file(self._filename_tk) as f: | 750 with file(self._filename_th) as f: |
764 self._write_tracked_key(tr, f) | 751 self._write_tracked_hint(tr, f) |
765 | 752 |
766 def delete_tracked_key(self): | 753 def delete_tracked_hint(self): |
767 """remove the tracked_key file | 754 """remove the tracked_hint file |
768 | 755 |
769 To be used by format downgrades operation""" | 756 To be used by format downgrades operation""" |
770 self._opener.unlink(self._filename_tk) | 757 self._opener.unlink(self._filename_th) |
771 self._use_tracked_key = False | 758 self._use_tracked_hint = False |
772 | 759 |
773 def addparentchangecallback(self, category, callback): | 760 def addparentchangecallback(self, category, callback): |
774 """add a callback to be called when the wd parents are changed | 761 """add a callback to be called when the wd parents are changed |
775 | 762 |
776 Callback will be called with the following arguments: | 763 Callback will be called with the following arguments: |
791 self._origpl = None | 778 self._origpl = None |
792 self._map.write(tr, st) | 779 self._map.write(tr, st) |
793 self._dirty = False | 780 self._dirty = False |
794 self._dirty_tracked_set = False | 781 self._dirty_tracked_set = False |
795 | 782 |
796 def _write_tracked_key(self, tr, f): | 783 def _write_tracked_hint(self, tr, f): |
797 key = node.hex(uuid.uuid4().bytes) | 784 key = node.hex(uuid.uuid4().bytes) |
798 f.write(b"1\n%s\n" % key) # 1 is the format version | 785 f.write(b"1\n%s\n" % key) # 1 is the format version |
799 | 786 |
800 def _dirignore(self, f): | 787 def _dirignore(self, f): |
801 if self._ignore(f): | 788 if self._ignore(f): |