Mercurial > hg
comparison mercurial/dirstatemap.py @ 47692:e5fb14a07866
dirstate-map: move most of `dirstate.update_file` logic in the dsmap
A new `reset_state` method is introduced to deal with most of that logic. This
move things one layer lower, but the ultimate goal is to deal with most of this
at the DirstateItem level.
This reveal various imperfection with the data passed to update_file by
`mergestate.recordupdates`, however this is orthogonal to this patch and should
be dealt with at a higher level.
Differential Revision: https://phab.mercurial-scm.org/D11134
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Mon, 19 Jul 2021 07:23:55 +0200 |
parents | f2aef39abc14 |
children | b0314d8deee1 |
comparison
equal
deleted
inserted
replaced
47691:33beeb32f73a | 47692:e5fb14a07866 |
---|---|
217 if e.dm_nonnormal: | 217 if e.dm_nonnormal: |
218 self.nonnormalset.add(f) | 218 self.nonnormalset.add(f) |
219 if e.dm_otherparent: | 219 if e.dm_otherparent: |
220 self.otherparentset.add(f) | 220 self.otherparentset.add(f) |
221 | 221 |
222 def reset_state( | |
223 self, | |
224 filename, | |
225 wc_tracked, | |
226 p1_tracked, | |
227 p2_tracked=False, | |
228 merged=False, | |
229 clean_p1=False, | |
230 clean_p2=False, | |
231 possibly_dirty=False, | |
232 parentfiledata=None, | |
233 ): | |
234 """Set a entry to a given state, diregarding all previous state | |
235 | |
236 This is to be used by the part of the dirstate API dedicated to | |
237 adjusting the dirstate after a update/merge. | |
238 | |
239 note: calling this might result to no entry existing at all if the | |
240 dirstate map does not see any point at having one for this file | |
241 anymore. | |
242 """ | |
243 if merged and (clean_p1 or clean_p2): | |
244 msg = b'`merged` argument incompatible with `clean_p1`/`clean_p2`' | |
245 raise error.ProgrammingError(msg) | |
246 # copy information are now outdated | |
247 # (maybe new information should be in directly passed to this function) | |
248 self.copymap.pop(filename, None) | |
249 | |
250 if not (p1_tracked or p2_tracked or wc_tracked): | |
251 self.dropfile(filename) | |
252 elif merged: | |
253 # XXX might be merged and removed ? | |
254 entry = self.get(filename) | |
255 if entry is not None and entry.tracked: | |
256 # XXX mostly replicate dirstate.other parent. We should get | |
257 # the higher layer to pass us more reliable data where `merged` | |
258 # actually mean merged. Dropping the else clause will show | |
259 # failure in `test-graft.t` | |
260 self.addfile(filename, merged=True) | |
261 else: | |
262 self.addfile(filename, from_p2=True) | |
263 elif not (p1_tracked or p2_tracked) and wc_tracked: | |
264 self.addfile(filename, added=True, possibly_dirty=possibly_dirty) | |
265 elif (p1_tracked or p2_tracked) and not wc_tracked: | |
266 # XXX might be merged and removed ? | |
267 old_entry = self._map.get(filename) | |
268 self._dirs_decr(filename, old_entry=old_entry, remove_variant=True) | |
269 self._map[filename] = DirstateItem(b'r', 0, 0, 0) | |
270 self.nonnormalset.add(filename) | |
271 elif clean_p2 and wc_tracked: | |
272 if p1_tracked or self.get(filename) is not None: | |
273 # XXX the `self.get` call is catching some case in | |
274 # `test-merge-remove.t` where the file is tracked in p1, the | |
275 # p1_tracked argument is False. | |
276 # | |
277 # In addition, this seems to be a case where the file is marked | |
278 # as merged without actually being the result of a merge | |
279 # action. So thing are not ideal here. | |
280 self.addfile(filename, merged=True) | |
281 else: | |
282 self.addfile(filename, from_p2=True) | |
283 elif not p1_tracked and p2_tracked and wc_tracked: | |
284 self.addfile(filename, from_p2=True, possibly_dirty=possibly_dirty) | |
285 elif possibly_dirty: | |
286 self.addfile(filename, possibly_dirty=possibly_dirty) | |
287 elif wc_tracked: | |
288 # this is a "normal" file | |
289 if parentfiledata is None: | |
290 msg = b'failed to pass parentfiledata for a normal file: %s' | |
291 msg %= filename | |
292 raise error.ProgrammingError(msg) | |
293 mode, size, mtime = parentfiledata | |
294 self.addfile(filename, mode=mode, size=size, mtime=mtime) | |
295 self.nonnormalset.discard(filename) | |
296 else: | |
297 assert False, 'unreachable' | |
298 | |
222 def removefile(self, f, in_merge=False): | 299 def removefile(self, f, in_merge=False): |
223 """ | 300 """ |
224 Mark a file as removed in the dirstate. | 301 Mark a file as removed in the dirstate. |
225 | 302 |
226 The `size` parameter is used to store sentinel values that indicate | 303 The `size` parameter is used to store sentinel values that indicate |
497 merged, | 574 merged, |
498 from_p2, | 575 from_p2, |
499 possibly_dirty, | 576 possibly_dirty, |
500 ) | 577 ) |
501 | 578 |
579 def reset_state( | |
580 self, | |
581 filename, | |
582 wc_tracked, | |
583 p1_tracked, | |
584 p2_tracked=False, | |
585 merged=False, | |
586 clean_p1=False, | |
587 clean_p2=False, | |
588 possibly_dirty=False, | |
589 parentfiledata=None, | |
590 ): | |
591 """Set a entry to a given state, disregarding all previous state | |
592 | |
593 This is to be used by the part of the dirstate API dedicated to | |
594 adjusting the dirstate after a update/merge. | |
595 | |
596 note: calling this might result to no entry existing at all if the | |
597 dirstate map does not see any point at having one for this file | |
598 anymore. | |
599 """ | |
600 if merged and (clean_p1 or clean_p2): | |
601 msg = ( | |
602 b'`merged` argument incompatible with `clean_p1`/`clean_p2`' | |
603 ) | |
604 raise error.ProgrammingError(msg) | |
605 # copy information are now outdated | |
606 # (maybe new information should be in directly passed to this function) | |
607 self.copymap.pop(filename, None) | |
608 | |
609 if not (p1_tracked or p2_tracked or wc_tracked): | |
610 self.dropfile(filename) | |
611 elif merged: | |
612 # XXX might be merged and removed ? | |
613 entry = self.get(filename) | |
614 if entry is not None and entry.tracked: | |
615 # XXX mostly replicate dirstate.other parent. We should get | |
616 # the higher layer to pass us more reliable data where `merged` | |
617 # actually mean merged. Dropping the else clause will show | |
618 # failure in `test-graft.t` | |
619 self.addfile(filename, merged=True) | |
620 else: | |
621 self.addfile(filename, from_p2=True) | |
622 elif not (p1_tracked or p2_tracked) and wc_tracked: | |
623 self.addfile( | |
624 filename, added=True, possibly_dirty=possibly_dirty | |
625 ) | |
626 elif (p1_tracked or p2_tracked) and not wc_tracked: | |
627 # XXX might be merged and removed ? | |
628 self[filename] = DirstateItem(b'r', 0, 0, 0) | |
629 self.nonnormalset.add(filename) | |
630 elif clean_p2 and wc_tracked: | |
631 if p1_tracked or self.get(filename) is not None: | |
632 # XXX the `self.get` call is catching some case in | |
633 # `test-merge-remove.t` where the file is tracked in p1, the | |
634 # p1_tracked argument is False. | |
635 # | |
636 # In addition, this seems to be a case where the file is marked | |
637 # as merged without actually being the result of a merge | |
638 # action. So thing are not ideal here. | |
639 self.addfile(filename, merged=True) | |
640 else: | |
641 self.addfile(filename, from_p2=True) | |
642 elif not p1_tracked and p2_tracked and wc_tracked: | |
643 self.addfile( | |
644 filename, from_p2=True, possibly_dirty=possibly_dirty | |
645 ) | |
646 elif possibly_dirty: | |
647 self.addfile(filename, possibly_dirty=possibly_dirty) | |
648 elif wc_tracked: | |
649 # this is a "normal" file | |
650 if parentfiledata is None: | |
651 msg = b'failed to pass parentfiledata for a normal file: %s' | |
652 msg %= filename | |
653 raise error.ProgrammingError(msg) | |
654 mode, size, mtime = parentfiledata | |
655 self.addfile(filename, mode=mode, size=size, mtime=mtime) | |
656 self.nonnormalset.discard(filename) | |
657 else: | |
658 assert False, 'unreachable' | |
659 | |
502 def removefile(self, *args, **kwargs): | 660 def removefile(self, *args, **kwargs): |
503 return self._rustmap.removefile(*args, **kwargs) | 661 return self._rustmap.removefile(*args, **kwargs) |
504 | 662 |
505 def dropfile(self, *args, **kwargs): | 663 def dropfile(self, *args, **kwargs): |
506 return self._rustmap.dropfile(*args, **kwargs) | 664 return self._rustmap.dropfile(*args, **kwargs) |
746 f = {} | 904 f = {} |
747 normcase = util.normcase | 905 normcase = util.normcase |
748 for name in self._rustmap.tracked_dirs(): | 906 for name in self._rustmap.tracked_dirs(): |
749 f[normcase(name)] = name | 907 f[normcase(name)] = name |
750 return f | 908 return f |
909 | |
910 def __setitem__(self, key, value): | |
911 assert isinstance(value, DirstateItem) | |
912 self._rustmap.set_v1(key, value) |