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): |