comparison mercurial/upgrade_utils/actions.py @ 47320:a43d256c041a

dirstate-v2: Add `hg debugupgraderepo` command support This command changes changes the file formats used inside an existing repository to what they would be in a new repository with the current config. For example: hg debugupgraderepo --config format.exp-dirstate-v2=1 --run hg debugupgraderepo --config format.exp-dirstate-v2=0 --run If a repository has a dirstate in v1 format, the first command would upgrade it to dirstate-v2. Conversely, if a repository has a dirstate in v2 format, the second command would downgrade it to v1. (Both may also run some unrelated upgrades.) Since `format.exp-dirstate-v2` is currently disabled by default, not specifying it in `--config` or any configuration file would result in the second command. Differential Revision: https://phab.mercurial-scm.org/D10769
author Simon Sapin <simon.sapin@octobus.net>
date Wed, 19 May 2021 18:35:43 +0200
parents e985a36c2aa3
children 4259a72fe528
comparison
equal deleted inserted replaced
47319:e985a36c2aa3 47320:a43d256c041a
78 78
79 # Message intended for humans which will be shown post an upgrade 79 # Message intended for humans which will be shown post an upgrade
80 # operation in which this improvement was removed 80 # operation in which this improvement was removed
81 postdowngrademessage = None 81 postdowngrademessage = None
82 82
83 # By default for now, we assume every improvement touches all the things 83 # By default we assume that every improvement touches requirements and all revlogs
84 84
85 # Whether this improvement touches filelogs 85 # Whether this improvement touches filelogs
86 touches_filelogs = True 86 touches_filelogs = True
87 87
88 # Whether this improvement touches manifests 88 # Whether this improvement touches manifests
91 # Whether this improvement touches changelog 91 # Whether this improvement touches changelog
92 touches_changelog = True 92 touches_changelog = True
93 93
94 # Whether this improvement changes repository requirements 94 # Whether this improvement changes repository requirements
95 touches_requirements = True 95 touches_requirements = True
96
97 # Whether this improvement touches the dirstate
98 touches_dirstate = False
96 99
97 100
98 allformatvariant = [] # type: List[Type['formatvariant']] 101 allformatvariant = [] # type: List[Type['formatvariant']]
99 102
100 103
162 upgrademessage = _( 165 upgrademessage = _(
163 b'repository will be more resilient to storing ' 166 b'repository will be more resilient to storing '
164 b'certain paths and performance of certain ' 167 b'certain paths and performance of certain '
165 b'operations should be improved' 168 b'operations should be improved'
166 ) 169 )
170
171
172 @registerformatvariant
173 class dirstatev2(requirementformatvariant):
174 name = b'dirstate-v2'
175 _requirement = requirements.DIRSTATE_V2_REQUIREMENT
176
177 default = False
178
179 description = _(
180 b'version 1 of the dirstate file format requires '
181 b'reading and parsing it all at once.'
182 )
183
184 upgrademessage = _(b'"hg status" will be faster')
185
186 touches_filelogs = False
187 touches_manifests = False
188 touches_changelog = False
189 touches_requirements = True
190 touches_dirstate = True
167 191
168 192
169 @registerformatvariant 193 @registerformatvariant
170 class dotencode(requirementformatvariant): 194 class dotencode(requirementformatvariant):
171 name = b'dotencode' 195 name = b'dotencode'
642 self.ui = ui 666 self.ui = ui
643 self.new_requirements = new_requirements 667 self.new_requirements = new_requirements
644 self.current_requirements = current_requirements 668 self.current_requirements = current_requirements
645 # list of upgrade actions the operation will perform 669 # list of upgrade actions the operation will perform
646 self.upgrade_actions = upgrade_actions 670 self.upgrade_actions = upgrade_actions
647 self._upgrade_actions_names = set([a.name for a in upgrade_actions])
648 self.removed_actions = removed_actions 671 self.removed_actions = removed_actions
649 self.revlogs_to_process = revlogs_to_process 672 self.revlogs_to_process = revlogs_to_process
650 # requirements which will be added by the operation 673 # requirements which will be added by the operation
651 self._added_requirements = ( 674 self._added_requirements = (
652 self.new_requirements - self.current_requirements 675 self.new_requirements - self.current_requirements
665 self.unused_optimizations = [ 688 self.unused_optimizations = [
666 i for i in all_optimizations if i not in self.upgrade_actions 689 i for i in all_optimizations if i not in self.upgrade_actions
667 ] 690 ]
668 691
669 # delta reuse mode of this upgrade operation 692 # delta reuse mode of this upgrade operation
693 upgrade_actions_names = self.upgrade_actions_names
670 self.delta_reuse_mode = revlog.revlog.DELTAREUSEALWAYS 694 self.delta_reuse_mode = revlog.revlog.DELTAREUSEALWAYS
671 if b're-delta-all' in self._upgrade_actions_names: 695 if b're-delta-all' in upgrade_actions_names:
672 self.delta_reuse_mode = revlog.revlog.DELTAREUSENEVER 696 self.delta_reuse_mode = revlog.revlog.DELTAREUSENEVER
673 elif b're-delta-parent' in self._upgrade_actions_names: 697 elif b're-delta-parent' in upgrade_actions_names:
674 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS 698 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
675 elif b're-delta-multibase' in self._upgrade_actions_names: 699 elif b're-delta-multibase' in upgrade_actions_names:
676 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS 700 self.delta_reuse_mode = revlog.revlog.DELTAREUSESAMEREVS
677 elif b're-delta-fulladd' in self._upgrade_actions_names: 701 elif b're-delta-fulladd' in upgrade_actions_names:
678 self.delta_reuse_mode = revlog.revlog.DELTAREUSEFULLADD 702 self.delta_reuse_mode = revlog.revlog.DELTAREUSEFULLADD
679 703
680 # should this operation force re-delta of both parents 704 # should this operation force re-delta of both parents
681 self.force_re_delta_both_parents = ( 705 self.force_re_delta_both_parents = (
682 b're-delta-multibase' in self._upgrade_actions_names 706 b're-delta-multibase' in upgrade_actions_names
683 ) 707 )
684 708
685 # should this operation create a backup of the store 709 # should this operation create a backup of the store
686 self.backup_store = backup_store 710 self.backup_store = backup_store
687 711
688 # whether the operation touches different revlogs at all or not 712 @property
689 self.touches_filelogs = self._touches_filelogs() 713 def upgrade_actions_names(self):
690 self.touches_manifests = self._touches_manifests() 714 return set([a.name for a in self.upgrade_actions])
691 self.touches_changelog = self._touches_changelog() 715
692 # whether the operation touches requirements file or not 716 @property
693 self.touches_requirements = self._touches_requirements() 717 def requirements_only(self):
694 self.touches_store = ( 718 # does the operation only touches repository requirement
695 self.touches_filelogs 719 return (
696 or self.touches_manifests 720 self.touches_requirements
697 or self.touches_changelog 721 and not self.touches_filelogs
722 and not self.touches_manifests
723 and not self.touches_changelog
724 and not self.touches_dirstate
698 ) 725 )
699 # does the operation only touches repository requirement 726
700 self.requirements_only = ( 727 @property
701 self.touches_requirements and not self.touches_store 728 def touches_filelogs(self):
702 )
703
704 def _touches_filelogs(self):
705 for a in self.upgrade_actions: 729 for a in self.upgrade_actions:
706 # in optimisations, we re-process the revlogs again 730 # in optimisations, we re-process the revlogs again
707 if a.type == OPTIMISATION: 731 if a.type == OPTIMISATION:
708 return True 732 return True
709 elif a.touches_filelogs: 733 elif a.touches_filelogs:
711 for a in self.removed_actions: 735 for a in self.removed_actions:
712 if a.touches_filelogs: 736 if a.touches_filelogs:
713 return True 737 return True
714 return False 738 return False
715 739
716 def _touches_manifests(self): 740 @property
741 def touches_manifests(self):
717 for a in self.upgrade_actions: 742 for a in self.upgrade_actions:
718 # in optimisations, we re-process the revlogs again 743 # in optimisations, we re-process the revlogs again
719 if a.type == OPTIMISATION: 744 if a.type == OPTIMISATION:
720 return True 745 return True
721 elif a.touches_manifests: 746 elif a.touches_manifests:
723 for a in self.removed_actions: 748 for a in self.removed_actions:
724 if a.touches_manifests: 749 if a.touches_manifests:
725 return True 750 return True
726 return False 751 return False
727 752
728 def _touches_changelog(self): 753 @property
754 def touches_changelog(self):
729 for a in self.upgrade_actions: 755 for a in self.upgrade_actions:
730 # in optimisations, we re-process the revlogs again 756 # in optimisations, we re-process the revlogs again
731 if a.type == OPTIMISATION: 757 if a.type == OPTIMISATION:
732 return True 758 return True
733 elif a.touches_changelog: 759 elif a.touches_changelog:
735 for a in self.removed_actions: 761 for a in self.removed_actions:
736 if a.touches_changelog: 762 if a.touches_changelog:
737 return True 763 return True
738 return False 764 return False
739 765
740 def _touches_requirements(self): 766 @property
767 def touches_requirements(self):
741 for a in self.upgrade_actions: 768 for a in self.upgrade_actions:
742 # optimisations are used to re-process revlogs and does not result 769 # optimisations are used to re-process revlogs and does not result
743 # in a requirement being added or removed 770 # in a requirement being added or removed
744 if a.type == OPTIMISATION: 771 if a.type == OPTIMISATION:
745 pass 772 pass
746 elif a.touches_requirements: 773 elif a.touches_requirements:
747 return True 774 return True
748 for a in self.removed_actions: 775 for a in self.removed_actions:
749 if a.touches_requirements: 776 if a.touches_requirements:
777 return True
778
779 @property
780 def touches_dirstate(self):
781 for a in self.upgrade_actions:
782 # revlog optimisations do not affect the dirstate
783 if a.type == OPTIMISATION:
784 pass
785 elif a.touches_dirstate:
786 return True
787 for a in self.removed_actions:
788 if a.touches_dirstate:
750 return True 789 return True
751 790
752 return False 791 return False
753 792
754 def _write_labeled(self, l, label): 793 def _write_labeled(self, l, label):
906 requirements.NODEMAP_REQUIREMENT, 945 requirements.NODEMAP_REQUIREMENT,
907 requirements.SHARESAFE_REQUIREMENT, 946 requirements.SHARESAFE_REQUIREMENT,
908 requirements.REVLOGV2_REQUIREMENT, 947 requirements.REVLOGV2_REQUIREMENT,
909 requirements.CHANGELOGV2_REQUIREMENT, 948 requirements.CHANGELOGV2_REQUIREMENT,
910 requirements.REVLOGV1_REQUIREMENT, 949 requirements.REVLOGV1_REQUIREMENT,
950 requirements.DIRSTATE_V2_REQUIREMENT,
911 } 951 }
912 for name in compression.compengines: 952 for name in compression.compengines:
913 engine = compression.compengines[name] 953 engine = compression.compengines[name]
914 if engine.available() and engine.revlogheader(): 954 if engine.available() and engine.revlogheader():
915 supported.add(b'exp-compression-%s' % name) 955 supported.add(b'exp-compression-%s' % name)
968 requirements.NODEMAP_REQUIREMENT, 1008 requirements.NODEMAP_REQUIREMENT,
969 requirements.SHARESAFE_REQUIREMENT, 1009 requirements.SHARESAFE_REQUIREMENT,
970 requirements.REVLOGV1_REQUIREMENT, 1010 requirements.REVLOGV1_REQUIREMENT,
971 requirements.REVLOGV2_REQUIREMENT, 1011 requirements.REVLOGV2_REQUIREMENT,
972 requirements.CHANGELOGV2_REQUIREMENT, 1012 requirements.CHANGELOGV2_REQUIREMENT,
1013 requirements.DIRSTATE_V2_REQUIREMENT,
973 } 1014 }
974 for name in compression.compengines: 1015 for name in compression.compengines:
975 engine = compression.compengines[name] 1016 engine = compression.compengines[name]
976 if engine.available() and engine.revlogheader(): 1017 if engine.available() and engine.revlogheader():
977 supported.add(b'exp-compression-%s' % name) 1018 supported.add(b'exp-compression-%s' % name)